From 47245e8862f4e39a1dc113770f30d0a29eb4859b Mon Sep 17 00:00:00 2001 From: "Arvid E. Picciani" Date: Tue, 18 Apr 2017 14:17:33 +0200 Subject: [PATCH 001/327] respect DISPLAY on linux Signed-off-by: Arvid E. Picciani --- base/xdisplay_c.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/base/xdisplay_c.h b/base/xdisplay_c.h index c6874f3a..f2178f3f 100644 --- a/base/xdisplay_c.h +++ b/base/xdisplay_c.h @@ -4,7 +4,7 @@ static Display *mainDisplay = NULL; static int registered = 0; -static char *displayName = ":0.0"; +static char *displayName = NULL; static int hasDisplayNameChanged = 0; Display *XGetMainDisplay(void) @@ -24,6 +24,11 @@ Display *XGetMainDisplay(void) mainDisplay = XOpenDisplay(NULL); } + /* Fall back to the most likely :0.0*/ + if (mainDisplay == NULL) { + mainDisplay = XOpenDisplay(":0.0"); + } + if (mainDisplay == NULL) { fputs("Could not open main display\n", stderr); } else if (!registered) { From 37921d66789a65b3e9fb1ef06b2e2d171ee2a989 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 9 Jun 2020 11:02:01 -0400 Subject: [PATCH 002/327] Update README.md, add more examples --- README.md | 17 +++++++++++++++++ README_zh.md | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/README.md b/README.md index fb20294a..286f3f4a 100644 --- a/README.md +++ b/README.md @@ -230,6 +230,12 @@ import ( ) func main() { + add() + low() + event() +} + +func add() { fmt.Println("--- Please press ctrl + shift + q to stop hook ---") robotgo.EventHook(hook.KeyDown, []string{"q", "ctrl", "shift"}, func(e hook.Event) { fmt.Println("ctrl-shift-q") @@ -243,7 +249,18 @@ func main() { s := robotgo.EventStart() <-robotgo.EventProcess(s) +} + +func low() { + EvChan := hook.Start() + defer hook.End() + + for ev := range EvChan { + fmt.Println("hook: ", ev) + } +} +func event() { ok := robotgo.AddEvents("q", "ctrl", "shift") if ok { fmt.Println("add events...") diff --git a/README_zh.md b/README_zh.md index 91d7379f..830aac17 100644 --- a/README_zh.md +++ b/README_zh.md @@ -227,6 +227,12 @@ import ( ) func main() { + add() + low() + event() +} + +func add() { fmt.Println("--- Please press ctrl + shift + q to stop hook ---") robotgo.EventHook(hook.KeyDown, []string{"q", "ctrl", "shift"}, func(e hook.Event) { fmt.Println("ctrl-shift-q") @@ -240,7 +246,18 @@ func main() { s := robotgo.EventStart() <-robotgo.EventProcess(s) +} + +func low() { + EvChan := hook.Start() + defer hook.End() + + for ev := range EvChan { + fmt.Println("hook: ", ev) + } +} +func event() { ok := robotgo.AddEvents("q", "ctrl", "shift") if ok { fmt.Println("add events...") From fd840a1f7cdb7e4ab93d22e2c42fe8bf8ead44eb Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sat, 20 Jun 2020 10:43:05 -0400 Subject: [PATCH 003/327] move hook and event to gohook --- examples/{ => gohook}/event/main.go | 0 examples/{ => gohook}/hook/main.go | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename examples/{ => gohook}/event/main.go (100%) rename examples/{ => gohook}/hook/main.go (100%) diff --git a/examples/event/main.go b/examples/gohook/event/main.go similarity index 100% rename from examples/event/main.go rename to examples/gohook/event/main.go diff --git a/examples/hook/main.go b/examples/gohook/hook/main.go similarity index 100% rename from examples/hook/main.go rename to examples/gohook/hook/main.go From 6fa51928bfd3aed78829bf6ec7731bede93d49af Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sat, 20 Jun 2020 10:45:12 -0400 Subject: [PATCH 004/327] move cbitmap and bitmap-bytes to bitmap dir --- examples/{ => bitmap}/bitmap-bytes/main.go | 0 examples/{ => bitmap}/cbitmap/main.go | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename examples/{ => bitmap}/bitmap-bytes/main.go (100%) rename examples/{ => bitmap}/cbitmap/main.go (100%) diff --git a/examples/bitmap-bytes/main.go b/examples/bitmap/bitmap-bytes/main.go similarity index 100% rename from examples/bitmap-bytes/main.go rename to examples/bitmap/bitmap-bytes/main.go diff --git a/examples/cbitmap/main.go b/examples/bitmap/cbitmap/main.go similarity index 100% rename from examples/cbitmap/main.go rename to examples/bitmap/cbitmap/main.go From 5800de88713a9bdf197cc86575e79a6c596fe8b3 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 30 Jun 2020 11:18:57 -0400 Subject: [PATCH 005/327] update go mod pkg --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 6b5b788f..08f2d171 100644 --- a/go.mod +++ b/go.mod @@ -5,15 +5,15 @@ require ( github.com/lxn/win v0.0.0-20191128105842-2da648fda5b4 github.com/otiai10/curr v1.0.0 // indirect github.com/otiai10/gosseract v2.2.1+incompatible - github.com/robotn/gohook v0.30.2 + github.com/robotn/gohook v0.30.3 github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 github.com/vcaesar/gops v0.10.0 github.com/vcaesar/imgo v0.10.0 github.com/vcaesar/tt v0.10.0 - golang.org/x/image v0.0.0-20200430140353-33d19683fad8 + golang.org/x/image v0.0.0-20200618115811-c13761719519 golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7 // indirect - golang.org/x/sys v0.0.0-20200523222454-059865788121 // indirect + golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae // indirect ) // replace golang.org/x/sys => github.com/golang/sys v0.0.0-20190109145017-48ac38b7c8cb diff --git a/go.sum b/go.sum index f0e03695..d135abfa 100644 --- a/go.sum +++ b/go.sum @@ -20,8 +20,8 @@ github.com/otiai10/mint v1.3.0 h1:Ady6MKVezQwHBkGzLFbrsywyp09Ah7rkmfjV3Bcr5uc= github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/robotn/gohook v0.30.2 h1:PbG/N24ycg3lEfl6+UpGumC/jnuHL9gJCy2jMGbQKhA= -github.com/robotn/gohook v0.30.2/go.mod h1:cWEhn477y4+4/D1SXIDPhivGSNsZT4dcco3uLTVBa6g= +github.com/robotn/gohook v0.30.3 h1:JU72aZK3tny/5pmKp6YAK3IpaftF5IQHRu4v7PBpeoo= +github.com/robotn/gohook v0.30.3/go.mod h1:cWEhn477y4+4/D1SXIDPhivGSNsZT4dcco3uLTVBa6g= github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 h1:2lhSR8N3T6I30q096DT7/5AKEIcf1vvnnWAmS0wfnNY= github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934/go.mod h1:SxQhJskUJ4rleVU44YvnrdvxQr0tKy5SRSigBrCgyyQ= github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 h1:2uX8QRLkkxn2EpAQ6I3KhA79BkdRZfvugJUzJadiJwk= @@ -42,8 +42,8 @@ github.com/vcaesar/tt v0.10.0/go.mod h1:GHPxQYhn+7OgKakRusH7KJ0M5MhywoeLb8Fcffs/ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a h1:gHevYm0pO4QUbwy8Dmdr01R5r1BuKtfYqRqF0h/Cbh0= golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200430140353-33d19683fad8 h1:6WW6V3x1P/jokJBpRQYUJnMHRP6isStQwCozxnU7XQw= -golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200618115811-c13761719519 h1:1e2ufUJNM3lCHEY5jIgac/7UTjd6cgJNdatjPdFWf34= +golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7 h1:AeiKBIuRw3UomYXSbLy0Mc2dDLfdtbT/IVn4keq83P0= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -51,8 +51,8 @@ golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200113162924-86b910548bc1 h1:gZpLHxUX5BdYLA08Lj4YCJNN/jk7KtquiArPoeX0WvA= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121 h1:rITEj+UZHYC927n8GT97eC3zrpzXdb/voyeOuVKS46o= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae h1:Ih9Yo4hSPImZOpfGuA4bR/ORKTAbhZo2AbWNRCnevdo= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 69bfaf9806e0b662b92f8c8bfb4e399f0b2734ed Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 12 Jul 2020 14:02:56 -0400 Subject: [PATCH 006/327] Update README.md --- README_zh.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README_zh.md b/README_zh.md index 830aac17..73889671 100644 --- a/README_zh.md +++ b/README_zh.md @@ -145,14 +145,14 @@ import ( ) func main() { - robotgo.TypeStr("Hello World") - robotgo.TypeStr("测试") - // robotgo.TypeString("测试") + robotgo.TypeStr("Hello World. Winter is coming!") + robotgo.TypeStr("だんしゃり", 1.0) + // robotgo.TypeString("テストする") - robotgo.TypeStr("山达尔星新星军团, galaxy. こんにちは世界.") + robotgo.TypeStr("Hi galaxy. こんにちは世界.") robotgo.Sleep(1) - // ustr := uint32(robotgo.CharCodeAt("测试", 0)) + // ustr := uint32(robotgo.CharCodeAt("テストする", 0)) // robotgo.UnicodeType(ustr) robotgo.KeyTap("enter") @@ -162,7 +162,7 @@ func main() { arr := []string{"alt", "command"} robotgo.KeyTap("i", arr) - robotgo.WriteAll("测试") + robotgo.WriteAll("テストする") text, err := robotgo.ReadAll() if err == nil { fmt.Println(text) @@ -347,7 +347,7 @@ GOOS=windows GOARCH=amd64 CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64 ## Donate -支持 robotgo, [buy me a coffee](https://github.com/go-vgo/buy-me-a-coffee). + #### Paypal From a05e255abe2bc6a439944896f09efaa36fe59008 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Fri, 24 Jul 2020 09:33:40 -0400 Subject: [PATCH 007/327] update some name --- robotgo.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/robotgo.go b/robotgo.go index ca9098c6..8ae93230 100644 --- a/robotgo.go +++ b/robotgo.go @@ -765,8 +765,8 @@ func TypeStr(str string, args ...float64) { if runtime.GOOS == "linux" { strUc := toUC(str) for i := 0; i < len(strUc); i++ { - rstr := []rune(strUc[i]) - if len(rstr) <= 1 { + ru := []rune(strUc[i]) + if len(ru) <= 1 { ustr := uint32(CharCodeAt(strUc[i], 0)) UnicodeType(ustr) } else { From 698ab9de3909b9923f8e716554238958abc7f704 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sat, 25 Jul 2020 11:43:08 -0400 Subject: [PATCH 008/327] update dockerfile and appveyor.yml --- .circleci/images/primary/Dockerfile | 12 ++++++------ appveyor.yml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index fc0e4241..3728788f 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,23 +1,23 @@ # FROM golang:1.10.1 -FROM golang:1.14.4-stretch AS build +FROM golang:1.14.6-stretch AS build # FROM govgo/go:1.11.1 RUN apt-get update && apt-get install -y --no-install-recommends \ -# customize dependencies + # customize dependencies libx11-dev xorg-dev \ # libgtkglextmm-x11-dev # libghc6-x11-dev # libgl1-mesa-swx11-dev # xorg-dev libxtst-dev libpng++-dev \ -# Event: + # Event: xcb libxcb-xkb-dev \ x11-xkb-utils libx11-xcb-dev \ libxkbcommon-x11-dev libxkbcommon-dev \ -# Clipboard: + # Clipboard: xsel xclip && \ -# RUN apt-get install -y xclip -# + # RUN apt-get install -y xclip + # apt-get remove --purge --auto-remove && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* diff --git a/appveyor.yml b/appveyor.yml index 22040456..7679bed9 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,7 +34,7 @@ environment: PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% # - COMPILER: MINGW_W64 # ARCHITECTURE: x64 - GOVERSION: 1.14.4 + GOVERSION: 1.14.6 # GOPATH: c:\gopath # scripts that run after cloning repository From fbfe90a5d623dcc09656d3bf1acd26918794369f Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 5 Aug 2020 13:19:13 -0400 Subject: [PATCH 009/327] update go mod --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 08f2d171..994932e1 100644 --- a/go.mod +++ b/go.mod @@ -11,9 +11,9 @@ require ( github.com/vcaesar/gops v0.10.0 github.com/vcaesar/imgo v0.10.0 github.com/vcaesar/tt v0.10.0 - golang.org/x/image v0.0.0-20200618115811-c13761719519 + golang.org/x/image v0.0.0-20200801110659-972c09e46d76 golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7 // indirect - golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae // indirect + golang.org/x/sys v0.0.0-20200805065543-0cf7623e9dbd // indirect ) // replace golang.org/x/sys => github.com/golang/sys v0.0.0-20190109145017-48ac38b7c8cb diff --git a/go.sum b/go.sum index d135abfa..696d6d0d 100644 --- a/go.sum +++ b/go.sum @@ -42,8 +42,8 @@ github.com/vcaesar/tt v0.10.0/go.mod h1:GHPxQYhn+7OgKakRusH7KJ0M5MhywoeLb8Fcffs/ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a h1:gHevYm0pO4QUbwy8Dmdr01R5r1BuKtfYqRqF0h/Cbh0= golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200618115811-c13761719519 h1:1e2ufUJNM3lCHEY5jIgac/7UTjd6cgJNdatjPdFWf34= -golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200801110659-972c09e46d76 h1:U7GPaoQyQmX+CBRWXKrvRzWTbd+slqeSh8uARsIyhAw= +golang.org/x/image v0.0.0-20200801110659-972c09e46d76/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7 h1:AeiKBIuRw3UomYXSbLy0Mc2dDLfdtbT/IVn4keq83P0= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -51,8 +51,8 @@ golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200113162924-86b910548bc1 h1:gZpLHxUX5BdYLA08Lj4YCJNN/jk7KtquiArPoeX0WvA= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae h1:Ih9Yo4hSPImZOpfGuA4bR/ORKTAbhZo2AbWNRCnevdo= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200805065543-0cf7623e9dbd h1:wefLe/3g5tC0FcXw3NneLA5tHgbyouyZlfcSjNfOdgk= +golang.org/x/sys v0.0.0-20200805065543-0cf7623e9dbd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 27a8e625cd4847938839c12b6939ae0a57e4efab Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 6 Aug 2020 12:20:03 -0400 Subject: [PATCH 010/327] update clipboard code --- clipboard/clipboard_darwin.go | 1 + clipboard/clipboard_unix.go | 3 +++ clipboard/clipboard_windows.go | 7 +++++-- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/clipboard/clipboard_darwin.go b/clipboard/clipboard_darwin.go index 6f33078d..58d4a2da 100644 --- a/clipboard/clipboard_darwin.go +++ b/clipboard/clipboard_darwin.go @@ -48,5 +48,6 @@ func writeAll(text string) error { if err := in.Close(); err != nil { return err } + return copyCmd.Wait() } diff --git a/clipboard/clipboard_unix.go b/clipboard/clipboard_unix.go index 76d7611d..dcae8085 100644 --- a/clipboard/clipboard_unix.go +++ b/clipboard/clipboard_unix.go @@ -67,11 +67,13 @@ func readAll() (string, error) { if Unsupported { return "", errMissingCommands } + pasteCmd := getPasteCommand() out, err := pasteCmd.Output() if err != nil { return "", err } + return string(out), nil } @@ -94,5 +96,6 @@ func writeAll(text string) error { if err := in.Close(); err != nil { return err } + return copyCmd.Wait() } diff --git a/clipboard/clipboard_windows.go b/clipboard/clipboard_windows.go index 7111e817..406bb658 100644 --- a/clipboard/clipboard_windows.go +++ b/clipboard/clipboard_windows.go @@ -38,8 +38,10 @@ var ( func waitOpenClipboard() error { started := time.Now() limit := started.Add(time.Second) - var r uintptr - var err error + var ( + r uintptr + err error + ) for time.Now().Before(limit) { r, _, err = openClipboard.Call(0) if r != 0 { @@ -47,6 +49,7 @@ func waitOpenClipboard() error { } time.Sleep(time.Millisecond) } + return err } From 769fd0e29602e755bc05f03d8c959f567e057749 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 6 Aug 2020 12:23:05 -0400 Subject: [PATCH 011/327] update hook code --- hook.go | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/hook.go b/hook.go index 731f9c05..a499bafb 100644 --- a/hook.go +++ b/hook.go @@ -36,6 +36,22 @@ func EventEnd() { hook.End() } +// Start start global event hook +// return event channel +func Start() chan hook.Event { + return hook.Start() +} + +// End removes global event hook +func End() { + hook.End() +} + +// StopEvent stop event listener +func StopEvent() { + hook.StopEvent() +} + // EventProcess return go hook process func EventProcess(Events chan hook.Event) chan bool { return hook.Process(Events) @@ -84,22 +100,6 @@ func AddEvent(key string) bool { return false } -// StopEvent stop event listener -func StopEvent() { - hook.StopEvent() -} - -// Start start global event hook -// return event channel -func Start() chan hook.Event { - return hook.Start() -} - -// End removes global event hook -func End() { - hook.End() -} - // AddEvents add global event hook // // robotgo.AddEvents("q") From b152b7ed01f96169f2bbb0275469f5887590ab6d Mon Sep 17 00:00:00 2001 From: vcaesar Date: Fri, 7 Aug 2020 12:44:07 -0400 Subject: [PATCH 012/327] update dockerfile and appveyor.yml --- .circleci/images/primary/Dockerfile | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index 3728788f..c8c67fb1 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.14.6-stretch AS build +FROM golang:1.14.7-stretch AS build # FROM govgo/go:1.11.1 RUN apt-get update && apt-get install -y --no-install-recommends \ diff --git a/appveyor.yml b/appveyor.yml index 7679bed9..f8f25149 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,7 +34,7 @@ environment: PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% # - COMPILER: MINGW_W64 # ARCHITECTURE: x64 - GOVERSION: 1.14.6 + GOVERSION: 1.14.7 # GOPATH: c:\gopath # scripts that run after cloning repository From 2ce203af8f63ba96b74da391654ceb48d4b33162 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sat, 8 Aug 2020 11:11:23 -0400 Subject: [PATCH 013/327] optimize code and update version --- robotgo.go | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/robotgo.go b/robotgo.go index 8ae93230..a1e353ca 100644 --- a/robotgo.go +++ b/robotgo.go @@ -69,7 +69,7 @@ import ( const ( // Version get the robotgo version - Version = "v0.90.0.1050, MT. Rainier!" + Version = "v0.90.3.1072, MT. Rainier!" ) // GetVersion get the robotgo version @@ -89,8 +89,8 @@ type ( // Bitmap is Bitmap struct type Bitmap struct { ImgBuf *uint8 - Width int - Height int + Width, Height int + Bytewidth int BitsPixel uint8 BytesPerPixel uint8 @@ -306,9 +306,9 @@ func CaptureScreen(args ...int) C.MMBitmapRef { } else { x = 0 y = 0 + // Get screen size. - var displaySize C.MMSizeInt32 - displaySize = C.getMainDisplaySize() + displaySize := C.getMainDisplaySize() w = displaySize.w h = displaySize.h } @@ -638,7 +638,6 @@ func KeyTap(tapKey string, args ...interface{}) string { amod := C.CString(akey) amodt := C.CString(keyT) - str := C.key_tap(zkey, amod, amodt, C.int(keyDelay)) C.free(unsafe.Pointer(amod)) @@ -659,7 +658,6 @@ func KeyToggle(key string, args ...string) string { ckeyArr := make([](*C.char), 0) if len(args) > 3 { num := len(args) - for i := 0; i < num; i++ { ckeyArr = append(ckeyArr, (*C.char)(unsafe.Pointer(C.CString(args[i])))) } @@ -678,7 +676,6 @@ func KeyToggle(key string, args ...string) string { if len(args) > 1 { mKey = args[1] - if len(args) > 2 { mKeyT = args[2] } @@ -1536,7 +1533,7 @@ func internalActive(pid int32, hwnd int) { func ActiveName(name string) error { pids, err := FindIds(name) if err == nil && len(pids) > 0 { - ActivePID(pids[0]) + return ActivePID(pids[0]) } return err From d70fbf3fa99fe4f5e52b2a36241b5d058acef142 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 9 Aug 2020 08:40:20 -0400 Subject: [PATCH 014/327] add paste string err return and optimize code --- hook.go | 8 +------- robotgo.go | 16 ++++++++++------ 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/hook.go b/hook.go index a499bafb..63e55510 100644 --- a/hook.go +++ b/hook.go @@ -60,7 +60,6 @@ func EventProcess(Events chan hook.Event) chan bool { // EventHook register gohook event func EventHook(When uint8, keysPressed []string, Callback func(hook.Event)) { hook.Register(When, keysPressed, Callback) - return } // AddEvent add event listener, @@ -92,12 +91,7 @@ func AddEvent(key string) bool { geve := hook.AddEvent(key) // defer C.free(unsafe.Pointer(cs)) - - if geve == 0 { - return true - } - - return false + return geve == 0 } // AddEvents add global event hook diff --git a/robotgo.go b/robotgo.go index a1e353ca..e7faab3b 100644 --- a/robotgo.go +++ b/robotgo.go @@ -49,8 +49,9 @@ package robotgo import "C" import ( - // "fmt" + "fmt" "image" + // "os" "reflect" "runtime" @@ -577,9 +578,9 @@ func KeyTap(tapKey string, args ...interface{}) string { num int keyDelay = 10 ) + // var ckeyArr []*C.char ckeyArr := make([](*C.char), 0) - // zkey := C.CString(args[0]) zkey := C.CString(tapKey) defer C.free(unsafe.Pointer(zkey)) @@ -591,8 +592,8 @@ func KeyTap(tapKey string, args ...interface{}) string { ckeyArr = append(ckeyArr, (*C.char)(unsafe.Pointer(C.CString(s)))) } - str := C.key_Taps(zkey, (**C.char)(unsafe.Pointer(&ckeyArr[0])), - C.int(num), 0) + str := C.key_Taps(zkey, + (**C.char)(unsafe.Pointer(&ckeyArr[0])), C.int(num), 0) return C.GoString(str) } @@ -601,7 +602,6 @@ func KeyTap(tapKey string, args ...interface{}) string { keyArr = args[0].([]string) num = len(keyArr) - for i := 0; i < num; i++ { ckeyArr = append(ckeyArr, (*C.char)(unsafe.Pointer(C.CString(keyArr[i])))) } @@ -789,7 +789,11 @@ func TypeStr(str string, args ...float64) { // PasteStr paste a string, support UTF-8 func PasteStr(str string) string { - clipboard.WriteAll(str) + err := clipboard.WriteAll(str) + if err != nil { + return fmt.Sprint(err) + } + if runtime.GOOS == "darwin" { return KeyTap("v", "command") } From 1f047c8524f695f84a80f19e56fdac47147a6a0d Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 20 Aug 2020 12:17:10 -0400 Subject: [PATCH 015/327] update go.yml and travis.yml to go1.15 --- .github/workflows/go.yml | 4 ++-- .travis.yml | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 4e5bb5da..176b0e38 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -10,10 +10,10 @@ jobs: runs-on: ${{ matrix.os }} steps: - - name: Set up Go 1.14 + - name: Set up Go 1.15 uses: actions/setup-go@v1 with: - go-version: 1.14 + go-version: 1.15 id: go - name: Check out code into the Go module directory diff --git a/.travis.yml b/.travis.yml index c26c52dd..65a1c0d3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,8 @@ go: # - 1.11.x # - 1.12.x # - 1.13.x - - 1.14.x + # - 1.14.x + - 1.15.x # - tip addons: From 46870282e57b559f7f6e0c5fd65caf77a1ce6889 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 2 Sep 2020 08:10:29 -0400 Subject: [PATCH 016/327] Update Ubuntu apt-get to apt --- .circleci/config.yml | 4 ++-- .circleci/images/primary/Dockerfile | 8 ++++---- .travis.yml | 16 ++++++++-------- README.md | 10 +++++----- README_zh.md | 10 +++++----- 5 files changed, 24 insertions(+), 24 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index cedd39c1..963b3e33 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -9,8 +9,8 @@ jobs: steps: - checkout # specify any bash command here prefixed with `run: ` - - run: apt-get update - - run: apt-get -y install xvfb + - run: apt update + - run: apt -y install xvfb # # override: # './...' is a relative pattern which means all subdirectories diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index c8c67fb1..34a376b5 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -2,7 +2,7 @@ FROM golang:1.14.7-stretch AS build # FROM govgo/go:1.11.1 -RUN apt-get update && apt-get install -y --no-install-recommends \ +RUN apt update && apt install -y --no-install-recommends \ # customize dependencies libx11-dev xorg-dev \ # libgtkglextmm-x11-dev @@ -16,10 +16,10 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libxkbcommon-x11-dev libxkbcommon-dev \ # Clipboard: xsel xclip && \ - # RUN apt-get install -y xclip + # RUN apt install -y xclip # - apt-get remove --purge --auto-remove && \ - apt-get clean && \ + apt remove --purge --auto-remove && \ + apt clean && \ rm -rf /var/lib/apt/lists/* RUN go get -u github.com/go-vgo/robotgo \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 65a1c0d3..1ba8d5c1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,16 +29,16 @@ addons: # - xvfb # script: -# - sudo apt-get update -# - sudo apt-get install libx11-dev -# - sudo apt-get install xorg-dev -# - sudo apt-get install libxtst-dev libpng++-dev +# - sudo apt update +# - sudo apt install libx11-dev +# - sudo apt install xorg-dev +# - sudo apt install libxtst-dev libpng++-dev # # Event: -# - sudo apt-get install xcb libxcb-xkb-dev x11-xkb-utils libx11-xcb-dev libxkbcommon-x11-dev -# - sudo apt-get install libxkbcommon-dev +# - sudo apt install xcb libxcb-xkb-dev x11-xkb-utils libx11-xcb-dev libxkbcommon-x11-dev +# - sudo apt install libxkbcommon-dev # # Clipboard: -# - sudo apt-get install xsel -# - sudo apt-get install xclip +# - sudo apt install xsel +# - sudo apt install xclip # - go test -v . before_install: diff --git a/README.md b/README.md index 286f3f4a..ff19603b 100644 --- a/README.md +++ b/README.md @@ -80,14 +80,14 @@ xcb, xkb, libxkbcommon ##### Ubuntu: ```yml -sudo apt-get install gcc libc6-dev +sudo apt install gcc libc6-dev -sudo apt-get install libx11-dev xorg-dev libxtst-dev libpng++-dev +sudo apt install libx11-dev xorg-dev libxtst-dev libpng++-dev -sudo apt-get install xcb libxcb-xkb-dev x11-xkb-utils libx11-xcb-dev libxkbcommon-x11-dev -sudo apt-get install libxkbcommon-dev +sudo apt install xcb libxcb-xkb-dev x11-xkb-utils libx11-xcb-dev libxkbcommon-x11-dev +sudo apt install libxkbcommon-dev -sudo apt-get install xsel xclip +sudo apt install xsel xclip ``` #### Fedora: diff --git a/README_zh.md b/README_zh.md index 73889671..6a37b669 100644 --- a/README_zh.md +++ b/README_zh.md @@ -77,14 +77,14 @@ xcb, xkb, libxkbcommon ##### Ubuntu: ```yml -sudo apt-get install gcc libc6-dev +sudo apt install gcc libc6-dev -sudo apt-get install libx11-dev xorg-dev libxtst-dev libpng++-dev +sudo apt install libx11-dev xorg-dev libxtst-dev libpng++-dev -sudo apt-get install xcb libxcb-xkb-dev x11-xkb-utils libx11-xcb-dev libxkbcommon-x11-dev -sudo apt-get install libxkbcommon-dev +sudo apt install xcb libxcb-xkb-dev x11-xkb-utils libx11-xcb-dev libxkbcommon-x11-dev +sudo apt install libxkbcommon-dev -sudo apt-get install xsel xclip +sudo apt install xsel xclip ``` From ca32ffeb8672d882d7e15ed3939e3c77ebf98adf Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 2 Sep 2020 08:20:34 -0400 Subject: [PATCH 017/327] update dockerfile and appveyor.yml --- .circleci/images/primary/Dockerfile | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index 34a376b5..f8cf51c9 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.14.7-stretch AS build +FROM golang:1.15.1-stretch AS build # FROM govgo/go:1.11.1 RUN apt update && apt install -y --no-install-recommends \ diff --git a/appveyor.yml b/appveyor.yml index f8f25149..daa6f60b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,7 +34,7 @@ environment: PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% # - COMPILER: MINGW_W64 # ARCHITECTURE: x64 - GOVERSION: 1.14.7 + GOVERSION: 1.15.1 # GOPATH: c:\gopath # scripts that run after cloning repository From 10f23931235d9f2004ba04d86ef52069b1093290 Mon Sep 17 00:00:00 2001 From: T4O2M0 <41974915+T4O2M0@users.noreply.github.com> Date: Wed, 2 Sep 2020 22:50:42 -0700 Subject: [PATCH 018/327] Fixed Mouse buttons reversed left and right click were swapped so I changed that --- examples/gohook/main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/gohook/main.go b/examples/gohook/main.go index 31300b7f..38479aa5 100644 --- a/examples/gohook/main.go +++ b/examples/gohook/main.go @@ -36,9 +36,9 @@ func addEvent() { func addMouse() { fmt.Println("--- Please press left mouse button to see it's position and the right mouse button to exit ---") robotgo.EventHook(hook.MouseDown, []string{}, func(e hook.Event) { - if e.Button == hook.MouseMap["right"] { + if e.Button == hook.MouseMap["left"] { fmt.Printf("mleft @ %v - %v\n", e.X, e.Y) - } else if e.Button == hook.MouseMap["left"] { + } else if e.Button == hook.MouseMap["right"] { robotgo.EventEnd() } }) From 484e86d55fc19055a727ea73381d0f837f55634c Mon Sep 17 00:00:00 2001 From: vcaesar Date: Fri, 4 Sep 2020 09:22:11 -0400 Subject: [PATCH 019/327] Update README.md and log --- README.md | 2 +- README_zh.md | 2 +- examples/gohook/main.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ff19603b..95a3f1c7 100644 --- a/README.md +++ b/README.md @@ -223,7 +223,7 @@ func main() { package main import ( - "fmt" + "fmt" "github.com/go-vgo/robotgo" hook "github.com/robotn/gohook" diff --git a/README_zh.md b/README_zh.md index 6a37b669..b1db37c2 100644 --- a/README_zh.md +++ b/README_zh.md @@ -220,7 +220,7 @@ func main() { package main import ( - "fmt" + "fmt" "github.com/go-vgo/robotgo" hook "github.com/robotn/gohook" diff --git a/examples/gohook/main.go b/examples/gohook/main.go index 38479aa5..ab6c5a5c 100644 --- a/examples/gohook/main.go +++ b/examples/gohook/main.go @@ -37,7 +37,7 @@ func addMouse() { fmt.Println("--- Please press left mouse button to see it's position and the right mouse button to exit ---") robotgo.EventHook(hook.MouseDown, []string{}, func(e hook.Event) { if e.Button == hook.MouseMap["left"] { - fmt.Printf("mleft @ %v - %v\n", e.X, e.Y) + fmt.Printf("mouse left @ %v - %v\n", e.X, e.Y) } else if e.Button == hook.MouseMap["right"] { robotgo.EventEnd() } From 12fb240b56288f9602a601eecc01886481d18b75 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Tue, 8 Sep 2020 21:00:46 +0900 Subject: [PATCH 020/327] returns "Invalid key code specified." if specified character is not valid --- key/goKey.h | 2 ++ key/keycode_c.h | 16 ++++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/key/goKey.h b/key/goKey.h index 77c1927d..c66338da 100644 --- a/key/goKey.h +++ b/key/goKey.h @@ -143,6 +143,8 @@ int CheckKeyCodes(char* k, MMKeyCode *key){ if (strlen(k) == 1) { *key = keyCodeForChar(*k); + if (*key == K_NOT_A_KEY) + return -2; return 0; } diff --git a/key/keycode_c.h b/key/keycode_c.h index cb19f516..25891a65 100644 --- a/key/keycode_c.h +++ b/key/keycode_c.h @@ -79,7 +79,7 @@ MMKeyCode keyCodeForChar(const char c){ 128, &kCFCopyStringDictionaryKeyCallBacks, NULL); - if (charToCodeDict == NULL) return UINT16_MAX; + if (charToCodeDict == NULL) return K_NOT_A_KEY; /* Loop through every keycode (0 - 127) to find its current mapping. */ for (i = 0; i < 128; ++i) { @@ -100,9 +100,18 @@ MMKeyCode keyCodeForChar(const char c){ } CFRelease(charStr); + + if (code == UINT16_MAX) { + return K_NOT_A_KEY; + } + return (MMKeyCode)code; #elif defined(IS_WINDOWS) - return VkKeyScan(c); + CGKeyCode code; + code = VkKeyScan(c); + if (code == 0xFFFF) + return K_NOT_A_KEY; + return code; #elif defined(USE_X11) MMKeyCode code; @@ -125,6 +134,9 @@ MMKeyCode keyCodeForChar(const char c){ } } + if (code == NoSymbol) + return K_NOT_A_KEY; + return code; #endif } From 05e614891db2d62f28c7253bad00e69c2111d832 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Tue, 8 Sep 2020 21:18:59 +0900 Subject: [PATCH 021/327] add keyCodeForCharFallBack --- key/keycode_c.h | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/key/keycode_c.h b/key/keycode_c.h index 25891a65..f6c4c38b 100644 --- a/key/keycode_c.h +++ b/key/keycode_c.h @@ -10,6 +10,8 @@ * responsibility to release the returned object. */ CFStringRef createStringForKey(CGKeyCode keyCode); +MMKeyCode keyCodeForCharFallBack(const char c); + #elif defined(USE_X11) /* @@ -101,6 +103,11 @@ MMKeyCode keyCodeForChar(const char c){ CFRelease(charStr); + // TISGetInputSourceProperty may return nil so we need fallback + if (code == UINT16_MAX) { + code = keyCodeForCharFallBack(c); + } + if (code == UINT16_MAX) { return K_NOT_A_KEY; } @@ -174,4 +181,49 @@ CFStringRef createStringForKey(CGKeyCode keyCode){ return CFStringCreateWithCharacters(kCFAllocatorDefault, chars, 1); } +MMKeyCode keyCodeForCharFallBack(const char c) { + switch (c) { + case 'A': return kVK_ANSI_A; + case 'B': return kVK_ANSI_B; + case 'C': return kVK_ANSI_C; + case 'D': return kVK_ANSI_D; + case 'E': return kVK_ANSI_E; + case 'F': return kVK_ANSI_F; + case 'G': return kVK_ANSI_G; + case 'H': return kVK_ANSI_H; + case 'I': return kVK_ANSI_I; + case 'J': return kVK_ANSI_J; + case 'K': return kVK_ANSI_K; + case 'L': return kVK_ANSI_L; + case 'M': return kVK_ANSI_M; + case 'N': return kVK_ANSI_N; + case 'O': return kVK_ANSI_O; + case 'P': return kVK_ANSI_P; + case 'Q': return kVK_ANSI_Q; + case 'R': return kVK_ANSI_R; + case 'S': return kVK_ANSI_S; + case 'T': return kVK_ANSI_T; + case 'U': return kVK_ANSI_U; + case 'V': return kVK_ANSI_V; + case 'W': return kVK_ANSI_W; + case 'X': return kVK_ANSI_X; + case 'Y': return kVK_ANSI_Y; + case 'Z': return kVK_ANSI_Z; + + + case '0': return kVK_ANSI_0; + case '1': return kVK_ANSI_1; + case '2': return kVK_ANSI_2; + case '3': return kVK_ANSI_3; + case '4': return kVK_ANSI_4; + case '5': return kVK_ANSI_5; + case '6': return kVK_ANSI_6; + case '7': return kVK_ANSI_7; + case '8': return kVK_ANSI_8; + case '9': return kVK_ANSI_9; + } + + return K_NOT_A_KEY; +} + #endif From 272bb3bb2ad36ea1c86450257ec6691ea351c5e0 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Tue, 8 Sep 2020 21:36:30 +0900 Subject: [PATCH 022/327] fix for windows --- key/keycode_c.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/key/keycode_c.h b/key/keycode_c.h index f6c4c38b..413d8ce3 100644 --- a/key/keycode_c.h +++ b/key/keycode_c.h @@ -114,7 +114,7 @@ MMKeyCode keyCodeForChar(const char c){ return (MMKeyCode)code; #elif defined(IS_WINDOWS) - CGKeyCode code; + MMKeyCode code; code = VkKeyScan(c); if (code == 0xFFFF) return K_NOT_A_KEY; From ec1ff45b532c797a408002f40556e32d33344d5c Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 16 Sep 2020 08:36:01 -0400 Subject: [PATCH 023/327] update go version and key code --- .circleci/images/primary/Dockerfile | 2 +- appveyor.yml | 2 +- key/goKey.h | 4 +++- key/keycode_c.h | 8 ++++++-- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index f8cf51c9..af5839e9 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.15.1-stretch AS build +FROM golang:1.15.2-stretch AS build # FROM govgo/go:1.11.1 RUN apt update && apt install -y --no-install-recommends \ diff --git a/appveyor.yml b/appveyor.yml index daa6f60b..f8b33c5a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,7 +34,7 @@ environment: PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% # - COMPILER: MINGW_W64 # ARCHITECTURE: x64 - GOVERSION: 1.15.1 + GOVERSION: 1.15.2 # GOPATH: c:\gopath # scripts that run after cloning repository diff --git a/key/goKey.h b/key/goKey.h index c66338da..031162f0 100644 --- a/key/goKey.h +++ b/key/goKey.h @@ -143,8 +143,10 @@ int CheckKeyCodes(char* k, MMKeyCode *key){ if (strlen(k) == 1) { *key = keyCodeForChar(*k); - if (*key == K_NOT_A_KEY) + if (*key == K_NOT_A_KEY) { return -2; + } + return 0; } diff --git a/key/keycode_c.h b/key/keycode_c.h index 413d8ce3..9fd0d369 100644 --- a/key/keycode_c.h +++ b/key/keycode_c.h @@ -116,8 +116,10 @@ MMKeyCode keyCodeForChar(const char c){ #elif defined(IS_WINDOWS) MMKeyCode code; code = VkKeyScan(c); - if (code == 0xFFFF) + if (code == 0xFFFF) { return K_NOT_A_KEY; + } + return code; #elif defined(USE_X11) MMKeyCode code; @@ -135,14 +137,16 @@ MMKeyCode keyCodeForChar(const char c){ while (xs->name) { if (c == xs->name ) { code = xs->code; + // break; } xs++; } } - if (code == NoSymbol) + if (code == NoSymbol) { return K_NOT_A_KEY; + } return code; #endif From 9a856a039bc1dcb2bcae79a80b783b58d032778a Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 24 Sep 2020 11:34:37 -0400 Subject: [PATCH 024/327] update test code and go mod --- clipboard/clipboard_test.go | 28 ++++++++++++++-------------- go.mod | 6 +++--- go.sum | 10 ++++++---- 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/clipboard/clipboard_test.go b/clipboard/clipboard_test.go index 0da4ffcd..4ffee8bf 100644 --- a/clipboard/clipboard_test.go +++ b/clipboard/clipboard_test.go @@ -10,23 +10,23 @@ import ( "github.com/go-vgo/robotgo/clipboard" ) -// func TestCopyAndPaste(t *testing.T) { -// expected := "日本語" +func TestCopyAndPaste(t *testing.T) { + expected := "日本語" -// err := clipboard.WriteAll(expected) -// if err != nil { -// t.Fatal(err) -// } + err := clipboard.WriteAll(expected) + if err != nil { + t.Fatal(err) + } -// actual, err := clipboard.ReadAll() -// if err != nil { -// t.Fatal(err) -// } + actual, err := clipboard.ReadAll() + if err != nil { + t.Fatal(err) + } -// if actual != expected { -// t.Errorf("want %s, got %s", expected, actual) -// } -// } + if actual != expected { + t.Errorf("want %s, got %s", expected, actual) + } +} // func TestMultiCopyAndPaste(t *testing.T) { // expected1 := "French: éèêëàùœç" diff --git a/go.mod b/go.mod index 994932e1..64cda932 100644 --- a/go.mod +++ b/go.mod @@ -10,10 +10,10 @@ require ( github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 github.com/vcaesar/gops v0.10.0 github.com/vcaesar/imgo v0.10.0 - github.com/vcaesar/tt v0.10.0 - golang.org/x/image v0.0.0-20200801110659-972c09e46d76 + github.com/vcaesar/tt v0.11.0 + golang.org/x/image v0.0.0-20200924062109-4578eab98f00 golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7 // indirect - golang.org/x/sys v0.0.0-20200805065543-0cf7623e9dbd // indirect + golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d // indirect ) // replace golang.org/x/sys => github.com/golang/sys v0.0.0-20190109145017-48ac38b7c8cb diff --git a/go.sum b/go.sum index 696d6d0d..d438a294 100644 --- a/go.sum +++ b/go.sum @@ -39,11 +39,13 @@ github.com/vcaesar/imgo v0.10.0 h1:6TOWsQFHdxIq7UVijeKBnhOymO+lDuRJwuP7VhSeR9U= github.com/vcaesar/imgo v0.10.0/go.mod h1:52+3yYrTNjWKh+CkQozNRCLWCE/X666yAWPGbYC3DZI= github.com/vcaesar/tt v0.10.0 h1:jPtFiRRnCOXVakd5ujCed2dwWwTs91wh8W1iHeUIfc0= github.com/vcaesar/tt v0.10.0/go.mod h1:GHPxQYhn+7OgKakRusH7KJ0M5MhywoeLb8Fcffs/Gtg= +github.com/vcaesar/tt v0.11.0 h1:obQecjgbnAxxC6OYGY6yDvhGRW2PR5wD8Ma2uJH3WGA= +github.com/vcaesar/tt v0.11.0/go.mod h1:GHPxQYhn+7OgKakRusH7KJ0M5MhywoeLb8Fcffs/Gtg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a h1:gHevYm0pO4QUbwy8Dmdr01R5r1BuKtfYqRqF0h/Cbh0= golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200801110659-972c09e46d76 h1:U7GPaoQyQmX+CBRWXKrvRzWTbd+slqeSh8uARsIyhAw= -golang.org/x/image v0.0.0-20200801110659-972c09e46d76/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200924062109-4578eab98f00 h1:9VSII+GM7HSMYSWsMcnMnDHKcDv2agce+07ISbE3llQ= +golang.org/x/image v0.0.0-20200924062109-4578eab98f00/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7 h1:AeiKBIuRw3UomYXSbLy0Mc2dDLfdtbT/IVn4keq83P0= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -51,8 +53,8 @@ golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200113162924-86b910548bc1 h1:gZpLHxUX5BdYLA08Lj4YCJNN/jk7KtquiArPoeX0WvA= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200805065543-0cf7623e9dbd h1:wefLe/3g5tC0FcXw3NneLA5tHgbyouyZlfcSjNfOdgk= -golang.org/x/sys v0.0.0-20200805065543-0cf7623e9dbd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d h1:L/IKR6COd7ubZrs2oTnTi73IhgqJ71c9s80WsQnh0Es= +golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From b49f16ed0a323a6a4bd980e8c9a7eacc6c9e87b8 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 24 Sep 2020 11:43:49 -0400 Subject: [PATCH 025/327] Update README.md and test code --- cdeps/README.md | 2 +- clipboard/clipboard_test.go | 52 ++++++++++++++++++------------------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/cdeps/README.md b/cdeps/README.md index 3303cf77..caebabbb 100644 --- a/cdeps/README.md +++ b/cdeps/README.md @@ -1 +1 @@ -C language dependent package, better to compilation. \ No newline at end of file +C language dependent package, better to compilation. ( zlib and libpng ) \ No newline at end of file diff --git a/clipboard/clipboard_test.go b/clipboard/clipboard_test.go index 4ffee8bf..993d3432 100644 --- a/clipboard/clipboard_test.go +++ b/clipboard/clipboard_test.go @@ -28,36 +28,36 @@ func TestCopyAndPaste(t *testing.T) { } } -// func TestMultiCopyAndPaste(t *testing.T) { -// expected1 := "French: éèêëàùœç" -// expected2 := "Weird UTF-8: 💩☃" +func TestMultiCopyAndPaste(t *testing.T) { + expected1 := "French: éèêëàùœç" + expected2 := "Weird UTF-8: 💩☃" -// err := clipboard.WriteAll(expected1) -// if err != nil { -// t.Fatal(err) -// } + err := clipboard.WriteAll(expected1) + if err != nil { + t.Fatal(err) + } -// actual1, err := clipboard.ReadAll() -// if err != nil { -// t.Fatal(err) -// } -// if actual1 != expected1 { -// t.Errorf("want %s, got %s", expected1, actual1) -// } + actual1, err := clipboard.ReadAll() + if err != nil { + t.Fatal(err) + } + if actual1 != expected1 { + t.Errorf("want %s, got %s", expected1, actual1) + } -// err = clipboard.WriteAll(expected2) -// if err != nil { -// t.Fatal(err) -// } + err = clipboard.WriteAll(expected2) + if err != nil { + t.Fatal(err) + } -// actual2, err := clipboard.ReadAll() -// if err != nil { -// t.Fatal(err) -// } -// if actual2 != expected2 { -// t.Errorf("want %s, got %s", expected2, actual2) -// } -// } + actual2, err := clipboard.ReadAll() + if err != nil { + t.Fatal(err) + } + if actual2 != expected2 { + t.Errorf("want %s, got %s", expected2, actual2) + } +} func BenchmarkReadAll(b *testing.B) { for i := 0; i < b.N; i++ { From 39d2014c548f0954c4a06aa8b9cc7f6c3c32122c Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 6 Oct 2020 11:34:32 -0400 Subject: [PATCH 026/327] update go mod and fixed #290 --- go.mod | 8 ++++---- go.sum | 24 +++++++++++++----------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 64cda932..785d7c99 100644 --- a/go.mod +++ b/go.mod @@ -5,15 +5,15 @@ require ( github.com/lxn/win v0.0.0-20191128105842-2da648fda5b4 github.com/otiai10/curr v1.0.0 // indirect github.com/otiai10/gosseract v2.2.1+incompatible - github.com/robotn/gohook v0.30.3 + github.com/robotn/gohook v0.30.4 github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 github.com/vcaesar/gops v0.10.0 github.com/vcaesar/imgo v0.10.0 github.com/vcaesar/tt v0.11.0 - golang.org/x/image v0.0.0-20200924062109-4578eab98f00 - golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7 // indirect - golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d // indirect + golang.org/x/image v0.0.0-20200927104501-e162460cd6b5 + golang.org/x/net v0.0.0-20201002202402-0a1ea396d57c // indirect + golang.org/x/sys v0.0.0-20201005172224-997123666555 // indirect ) // replace golang.org/x/sys => github.com/golang/sys v0.0.0-20190109145017-48ac38b7c8cb diff --git a/go.sum b/go.sum index d438a294..e3768b7e 100644 --- a/go.sum +++ b/go.sum @@ -20,8 +20,8 @@ github.com/otiai10/mint v1.3.0 h1:Ady6MKVezQwHBkGzLFbrsywyp09Ah7rkmfjV3Bcr5uc= github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/robotn/gohook v0.30.3 h1:JU72aZK3tny/5pmKp6YAK3IpaftF5IQHRu4v7PBpeoo= -github.com/robotn/gohook v0.30.3/go.mod h1:cWEhn477y4+4/D1SXIDPhivGSNsZT4dcco3uLTVBa6g= +github.com/robotn/gohook v0.30.4 h1:MSGU6SGhvT//nERZBqZVlutb20ezIDhKrdYrFVQAAH0= +github.com/robotn/gohook v0.30.4/go.mod h1:WTp0iFJqlggobr3vz9HIpRMDPWAf5/JMnLU/M34VKQo= github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 h1:2lhSR8N3T6I30q096DT7/5AKEIcf1vvnnWAmS0wfnNY= github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934/go.mod h1:SxQhJskUJ4rleVU44YvnrdvxQr0tKy5SRSigBrCgyyQ= github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 h1:2uX8QRLkkxn2EpAQ6I3KhA79BkdRZfvugJUzJadiJwk= @@ -37,24 +37,26 @@ github.com/vcaesar/gops v0.10.0 h1:pVIwPfHNKdkHBFyMQu5x5patIPGE+R8kd3+4BIEU7sU= github.com/vcaesar/gops v0.10.0/go.mod h1:HDKiKqHeRYwEhBUTjgBHWT/PkwvLusticopFNbGO/eY= github.com/vcaesar/imgo v0.10.0 h1:6TOWsQFHdxIq7UVijeKBnhOymO+lDuRJwuP7VhSeR9U= github.com/vcaesar/imgo v0.10.0/go.mod h1:52+3yYrTNjWKh+CkQozNRCLWCE/X666yAWPGbYC3DZI= -github.com/vcaesar/tt v0.10.0 h1:jPtFiRRnCOXVakd5ujCed2dwWwTs91wh8W1iHeUIfc0= -github.com/vcaesar/tt v0.10.0/go.mod h1:GHPxQYhn+7OgKakRusH7KJ0M5MhywoeLb8Fcffs/Gtg= +github.com/vcaesar/tt v0.10.1/go.mod h1:GHPxQYhn+7OgKakRusH7KJ0M5MhywoeLb8Fcffs/Gtg= github.com/vcaesar/tt v0.11.0 h1:obQecjgbnAxxC6OYGY6yDvhGRW2PR5wD8Ma2uJH3WGA= github.com/vcaesar/tt v0.11.0/go.mod h1:GHPxQYhn+7OgKakRusH7KJ0M5MhywoeLb8Fcffs/Gtg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a h1:gHevYm0pO4QUbwy8Dmdr01R5r1BuKtfYqRqF0h/Cbh0= golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200924062109-4578eab98f00 h1:9VSII+GM7HSMYSWsMcnMnDHKcDv2agce+07ISbE3llQ= -golang.org/x/image v0.0.0-20200924062109-4578eab98f00/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7 h1:AeiKBIuRw3UomYXSbLy0Mc2dDLfdtbT/IVn4keq83P0= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/image v0.0.0-20200927104501-e162460cd6b5 h1:QelT11PB4FXiDEXucrfNckHoFxwt8USGY1ajP1ZF5lM= +golang.org/x/image v0.0.0-20200927104501-e162460cd6b5/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20201002202402-0a1ea396d57c h1:dk0ukUIHmGHqASjP0iue2261isepFCC6XRCSd1nHgDw= +golang.org/x/net v0.0.0-20201002202402-0a1ea396d57c/go.mod h1:iQL9McJNjoIa5mjH6nYTCTZXUN6RP+XW3eib7Ya3XcI= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1 h1:gZpLHxUX5BdYLA08Lj4YCJNN/jk7KtquiArPoeX0WvA= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d h1:L/IKR6COd7ubZrs2oTnTi73IhgqJ71c9s80WsQnh0Es= -golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201005172224-997123666555 h1:fihtqzYxy4E31W1yUlyRGveTZT1JIP0bmKaDZ2ceKAw= +golang.org/x/sys v0.0.0-20201005172224-997123666555/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From fdaa440f26cc3d5f3d87925fa04b47a857c32a5f Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 8 Oct 2020 11:11:03 -0400 Subject: [PATCH 027/327] update parameter name and version --- hook.go | 8 ++++---- robotgo.go | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/hook.go b/hook.go index 63e55510..f059c895 100644 --- a/hook.go +++ b/hook.go @@ -53,13 +53,13 @@ func StopEvent() { } // EventProcess return go hook process -func EventProcess(Events chan hook.Event) chan bool { - return hook.Process(Events) +func EventProcess(events chan hook.Event) chan bool { + return hook.Process(events) } // EventHook register gohook event -func EventHook(When uint8, keysPressed []string, Callback func(hook.Event)) { - hook.Register(When, keysPressed, Callback) +func EventHook(when uint8, keysPressed []string, callback func(hook.Event)) { + hook.Register(when, keysPressed, callback) } // AddEvent add event listener, diff --git a/robotgo.go b/robotgo.go index e7faab3b..ee291ef1 100644 --- a/robotgo.go +++ b/robotgo.go @@ -70,7 +70,7 @@ import ( const ( // Version get the robotgo version - Version = "v0.90.3.1072, MT. Rainier!" + Version = "v0.91.0.1089, MT. Rainier!" ) // GetVersion get the robotgo version From 08deeb3c737139a41ad4d914aaa5941a1677f43d Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 13 Oct 2020 09:29:00 -0400 Subject: [PATCH 028/327] Update README.md --- README.md | 9 --------- README_zh.md | 8 -------- 2 files changed, 17 deletions(-) diff --git a/README.md b/README.md index 95a3f1c7..28b8ddaf 100644 --- a/README.md +++ b/README.md @@ -350,15 +350,6 @@ Some discussions and questions, please see [issues/228](https://github.com/go-vg - Update Window Handle - Try support Android, maybe support IOS -## Donate - -Supporting robotgo, [buy me a coffee](https://github.com/go-vgo/buy-me-a-coffee). - -#### Paypal - -Donate money by [paypal](https://www.paypal.me/veni0/25) to my account [vzvway@gmail.com](vzvway@gmail.com) - - ## Contributors - See [contributors page](https://github.com/go-vgo/robotgo/graphs/contributors) for full list of contributors. diff --git a/README_zh.md b/README_zh.md index b1db37c2..42378a1a 100644 --- a/README_zh.md +++ b/README_zh.md @@ -345,14 +345,6 @@ GOOS=windows GOARCH=amd64 CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64 - 更新 Window Handle - 尝试支持 Android, 也许支持 IOS -## Donate - - - -#### Paypal - -Donate money by [paypal](https://www.paypal.me/veni0/25) to my account [vzvway@gmail.com](vzvway@gmail.com) - ## Contributors - See [contributors page](https://github.com/go-vgo/robotgo/graphs/contributors) for full list of contributors. From b537cf4a3e5df229ccbb1e5c7aff8bf205cd8242 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 18 Oct 2020 10:37:03 -0400 Subject: [PATCH 029/327] update dockerfile and appveyor.yml --- .circleci/images/primary/Dockerfile | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index af5839e9..04591f9f 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.15.2-stretch AS build +FROM golang:1.15.3-stretch AS build # FROM govgo/go:1.11.1 RUN apt update && apt install -y --no-install-recommends \ diff --git a/appveyor.yml b/appveyor.yml index f8b33c5a..862511c6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,7 +34,7 @@ environment: PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% # - COMPILER: MINGW_W64 # ARCHITECTURE: x64 - GOVERSION: 1.15.2 + GOVERSION: 1.15.3 # GOPATH: c:\gopath # scripts that run after cloning repository From fb2d6f2720100d1d0f56c5deb9b368c9fe5909e7 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 27 Oct 2020 10:46:17 -0400 Subject: [PATCH 030/327] update error return and print --- robotgo_unix.go | 16 +++++++--------- window/window.h | 2 +- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/robotgo_unix.go b/robotgo_unix.go index 524f96b3..1463e75f 100644 --- a/robotgo_unix.go +++ b/robotgo_unix.go @@ -28,13 +28,12 @@ func GetBounds(pid int32, args ...int) (int, int, int, int) { var hwnd int if len(args) > 0 { hwnd = args[0] - return internalGetBounds(pid, hwnd) } xid, err := GetXId(xu, pid) if err != nil { - log.Println("GetXid from Pid errors is: ", err) + log.Println("Get Xid from Pid errors is: ", err) return 0, 0, 0, 0 } @@ -46,13 +45,12 @@ func internalGetTitle(pid int32, args ...int32) string { var hwnd int32 if len(args) > 0 { hwnd = args[0] - return cgetTitle(pid, hwnd) } xid, err := GetXId(xu, pid) if err != nil { - log.Println("GetXid from Pid errors is: ", err) + log.Println("Get Xid from Pid errors is: ", err) return "" } @@ -61,22 +59,22 @@ func internalGetTitle(pid int32, args ...int32) string { // ActivePIDC active the window by PID, // If args[0] > 0 on the unix platform via a xid to active -func ActivePIDC(pid int32, args ...int) { +func ActivePIDC(pid int32, args ...int) error { var hwnd int if len(args) > 0 { hwnd = args[0] - internalActive(pid, hwnd) - return + return nil } xid, err := GetXId(xu, pid) if err != nil { - log.Println("GetXid from Pid errors is: ", err) - return + log.Println("Get Xid from Pid errors is: ", err) + return err } internalActive(int32(xid), hwnd) + return nil } // ActivePID active the window by PID, diff --git a/window/window.h b/window/window.h index 8eda37be..6293ca92 100644 --- a/window/window.h +++ b/window/window.h @@ -85,7 +85,7 @@ void set_handle_pid_mData(uintptr pid, uintptr isHwnd){ bool IsValid(){ initWindow(initHandle); if (!IsAxEnabled(true)) { - printf("%s\n", "Window:Accessibility API is disabled!\n" + printf("%s\n", "Window: Accessibility API is disabled!\n" "Failed to enable access for assistive devices."); } MData actdata = GetActive(); From fe3b4b3331a11edf9a471253869d822c419fd40e Mon Sep 17 00:00:00 2001 From: rocket049 Date: Thu, 29 Oct 2020 13:05:40 +0800 Subject: [PATCH 031/327] add func ToImage: convert C.MMBitmapRef to standard image.Image --- robotgo.go | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/robotgo.go b/robotgo.go index ee291ef1..c06b51e5 100644 --- a/robotgo.go +++ b/robotgo.go @@ -1542,3 +1542,29 @@ func ActiveName(name string) error { return err } + +// ToImage convert C.MMBitmapRef to standard image.Image +func ToImage(bit C.MMBitmapRef) image.Image { + bmp1 := ToBitmap(bit) + img1 := image.NewRGBA(image.Rect(0, 0, bmp1.Width, bmp1.Height)) + img1.Pix = make([]uint8, bmp1.Bytewidth*bmp1.Height) + copyToVUint8A(img1.Pix, bmp1.ImgBuf) + img1.Stride = bmp1.Bytewidth + return img1 +} + +func val(p *uint8, n int) uint8 { + addr := uintptr(unsafe.Pointer(p)) + addr += uintptr(n) + p1 := (*uint8)(unsafe.Pointer(addr)) + return *p1 +} + +func copyToVUint8A(dst []uint8, src *uint8) { + for i := 0; i < len(dst)-4; i += 4 { + dst[i] = val(src, i+2) + dst[i+1] = val(src, i+1) + dst[i+2] = val(src, i) + dst[i+3] = val(src, i+3) + } +} From 5528eee0315babc89954fd5a90032cd96531ad4c Mon Sep 17 00:00:00 2001 From: vcaesar Date: Fri, 30 Oct 2020 15:25:28 -0400 Subject: [PATCH 032/327] add ToImage examples code --- .gitignore | 1 + examples/bitmap/main.go | 3 +++ robotgo.go | 53 +++++++++++++++++++++-------------------- 3 files changed, 31 insertions(+), 26 deletions(-) diff --git a/.gitignore b/.gitignore index cbf0a0a7..d561f40f 100644 --- a/.gitignore +++ b/.gitignore @@ -78,3 +78,4 @@ vendor # Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 .glide/ +examples/bitmap/test_IMG.png diff --git a/examples/bitmap/main.go b/examples/bitmap/main.go index ae858011..345bc4e1 100644 --- a/examples/bitmap/main.go +++ b/examples/bitmap/main.go @@ -21,6 +21,9 @@ import ( func toBitmap(bmp robotgo.CBitmap) { bitmap := robotgo.ToMMBitmapRef(bmp) + img := robotgo.ToImage(bitmap) + fmt.Println("img: ", img) + imgo.SaveToPNG("test_IMG.png", img) gbit := robotgo.ToBitmap(bitmap) fmt.Println("go bitmap", gbit, gbit.Width) diff --git a/robotgo.go b/robotgo.go index c06b51e5..35777956 100644 --- a/robotgo.go +++ b/robotgo.go @@ -1107,6 +1107,33 @@ func DecodeImg(path string) (image.Image, string, error) { return imgo.DecodeFile(path) } +// ToImage convert C.MMBitmapRef to standard image.Image +func ToImage(bit C.MMBitmapRef) image.Image { + bmp1 := ToBitmap(bit) + img1 := image.NewRGBA(image.Rect(0, 0, bmp1.Width, bmp1.Height)) + img1.Pix = make([]uint8, bmp1.Bytewidth*bmp1.Height) + + copyToVUint8A(img1.Pix, bmp1.ImgBuf) + img1.Stride = bmp1.Bytewidth + return img1 +} + +func val(p *uint8, n int) uint8 { + addr := uintptr(unsafe.Pointer(p)) + addr += uintptr(n) + p1 := (*uint8)(unsafe.Pointer(addr)) + return *p1 +} + +func copyToVUint8A(dst []uint8, src *uint8) { + for i := 0; i < len(dst)-4; i += 4 { + dst[i] = val(src, i+2) + dst[i+1] = val(src, i+1) + dst[i+2] = val(src, i) + dst[i+3] = val(src, i+3) + } +} + // OpenImg open the image return []byte func OpenImg(path string) []byte { return imgo.ImgToBytes(path) @@ -1542,29 +1569,3 @@ func ActiveName(name string) error { return err } - -// ToImage convert C.MMBitmapRef to standard image.Image -func ToImage(bit C.MMBitmapRef) image.Image { - bmp1 := ToBitmap(bit) - img1 := image.NewRGBA(image.Rect(0, 0, bmp1.Width, bmp1.Height)) - img1.Pix = make([]uint8, bmp1.Bytewidth*bmp1.Height) - copyToVUint8A(img1.Pix, bmp1.ImgBuf) - img1.Stride = bmp1.Bytewidth - return img1 -} - -func val(p *uint8, n int) uint8 { - addr := uintptr(unsafe.Pointer(p)) - addr += uintptr(n) - p1 := (*uint8)(unsafe.Pointer(addr)) - return *p1 -} - -func copyToVUint8A(dst []uint8, src *uint8) { - for i := 0; i < len(dst)-4; i += 4 { - dst[i] = val(src, i+2) - dst[i+1] = val(src, i+1) - dst[i+2] = val(src, i) - dst[i+3] = val(src, i+3) - } -} From f50de436420e0e1c03b5bd51a6ccdd7ce5d7feac Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 4 Nov 2020 09:55:15 -0400 Subject: [PATCH 033/327] add more image function and update go mod --- examples/bitmap/main.go | 4 ++-- go.mod | 7 +++---- go.sum | 23 ++++++++++------------- robotgo.go | 11 ++++++++--- 4 files changed, 23 insertions(+), 22 deletions(-) diff --git a/examples/bitmap/main.go b/examples/bitmap/main.go index 345bc4e1..a9318d2f 100644 --- a/examples/bitmap/main.go +++ b/examples/bitmap/main.go @@ -98,12 +98,12 @@ func decode() { } fmt.Println("decode test.png", img, name) - byt := robotgo.OpenImg("test.png") + byt, _ := robotgo.OpenImg("test.png") imgo.Save("test2.png", byt) w, h := robotgo.GetImgSize("test.png") fmt.Println("image width and hight ", w, h) - w, h = imgo.GetSize("test.png") + w, h, _ = imgo.GetSize("test.png") fmt.Println("image width and hight ", w, h) // convert image diff --git a/go.mod b/go.mod index 785d7c99..d6559a8b 100644 --- a/go.mod +++ b/go.mod @@ -2,18 +2,17 @@ module github.com/go-vgo/robotgo require ( github.com/davecgh/go-spew v1.1.1 // indirect - github.com/lxn/win v0.0.0-20191128105842-2da648fda5b4 + github.com/lxn/win v0.0.0-20201021184640-9c48443b1f44 github.com/otiai10/curr v1.0.0 // indirect github.com/otiai10/gosseract v2.2.1+incompatible github.com/robotn/gohook v0.30.4 github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 - github.com/vcaesar/gops v0.10.0 - github.com/vcaesar/imgo v0.10.0 + github.com/vcaesar/gops v0.10.1 + github.com/vcaesar/imgo v0.12.0 github.com/vcaesar/tt v0.11.0 golang.org/x/image v0.0.0-20200927104501-e162460cd6b5 golang.org/x/net v0.0.0-20201002202402-0a1ea396d57c // indirect - golang.org/x/sys v0.0.0-20201005172224-997123666555 // indirect ) // replace golang.org/x/sys => github.com/golang/sys v0.0.0-20190109145017-48ac38b7c8cb diff --git a/go.sum b/go.sum index e3768b7e..68aaa432 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI= github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= -github.com/lxn/win v0.0.0-20191128105842-2da648fda5b4 h1:5BmtGkQbch91lglMHQ9JIDGiYCL3kBRBA0ItZTvOcEI= -github.com/lxn/win v0.0.0-20191128105842-2da648fda5b4/go.mod h1:ouWl4wViUNh8tPSIwxTVMuS014WakR1hqvBc2I0bMoA= +github.com/lxn/win v0.0.0-20201021184640-9c48443b1f44 h1:5EnI2+vhRty/RE7v983dfdv0wKrDapW5xNHBMdDT4uY= +github.com/lxn/win v0.0.0-20201021184640-9c48443b1f44/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95 h1:+OLn68pqasWca0z5ryit9KGfp3sUsW4Lqg32iRMJyzs= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= github.com/otiai10/curr v1.0.0 h1:TJIWdbX0B+kpNagQrjgq8bCMrbhiuX73M2XwgtDMoOI= @@ -33,17 +33,15 @@ github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/vcaesar/gops v0.10.0 h1:pVIwPfHNKdkHBFyMQu5x5patIPGE+R8kd3+4BIEU7sU= -github.com/vcaesar/gops v0.10.0/go.mod h1:HDKiKqHeRYwEhBUTjgBHWT/PkwvLusticopFNbGO/eY= -github.com/vcaesar/imgo v0.10.0 h1:6TOWsQFHdxIq7UVijeKBnhOymO+lDuRJwuP7VhSeR9U= -github.com/vcaesar/imgo v0.10.0/go.mod h1:52+3yYrTNjWKh+CkQozNRCLWCE/X666yAWPGbYC3DZI= +github.com/vcaesar/gops v0.10.1 h1:RFNFMuiuoLzZpibAhGuOJ7BDbOUWPL19S8gWhODaJfU= +github.com/vcaesar/gops v0.10.1/go.mod h1:301l7s41oGSmfI7F9ojpRHeF9MzZZ6Mv5vC038riB50= +github.com/vcaesar/imgo v0.12.0 h1:y2anuhS9i1KZBntYmN2je/rXn/oe26YNDZ57AsLJfN0= +github.com/vcaesar/imgo v0.12.0/go.mod h1:ZSmAFXF91Ch6xe9iz1LinzALa6w9T6c57fH+WqNhMBE= github.com/vcaesar/tt v0.10.1/go.mod h1:GHPxQYhn+7OgKakRusH7KJ0M5MhywoeLb8Fcffs/Gtg= github.com/vcaesar/tt v0.11.0 h1:obQecjgbnAxxC6OYGY6yDvhGRW2PR5wD8Ma2uJH3WGA= github.com/vcaesar/tt v0.11.0/go.mod h1:GHPxQYhn+7OgKakRusH7KJ0M5MhywoeLb8Fcffs/Gtg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a h1:gHevYm0pO4QUbwy8Dmdr01R5r1BuKtfYqRqF0h/Cbh0= -golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20200927104501-e162460cd6b5 h1:QelT11PB4FXiDEXucrfNckHoFxwt8USGY1ajP1ZF5lM= golang.org/x/image v0.0.0-20200927104501-e162460cd6b5/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -51,12 +49,11 @@ golang.org/x/net v0.0.0-20201002202402-0a1ea396d57c h1:dk0ukUIHmGHqASjP0iue2261i golang.org/x/net v0.0.0-20201002202402-0a1ea396d57c/go.mod h1:iQL9McJNjoIa5mjH6nYTCTZXUN6RP+XW3eib7Ya3XcI= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1 h1:gZpLHxUX5BdYLA08Lj4YCJNN/jk7KtquiArPoeX0WvA= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201005172224-997123666555 h1:fihtqzYxy4E31W1yUlyRGveTZT1JIP0bmKaDZ2ceKAw= -golang.org/x/sys v0.0.0-20201005172224-997123666555/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13 h1:5jaG59Zhd+8ZXe8C+lgiAGqkOaZBruqrWclLkgAww34= +golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201101102859-da207088b7d1 h1:a/mKvvZr9Jcc8oKfcmgzyp7OwF73JPWsQLvH1z2Kxck= +golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/robotgo.go b/robotgo.go index 35777956..99128cc8 100644 --- a/robotgo.go +++ b/robotgo.go @@ -1135,13 +1135,18 @@ func copyToVUint8A(dst []uint8, src *uint8) { } // OpenImg open the image return []byte -func OpenImg(path string) []byte { +func OpenImg(path string) ([]byte, error) { return imgo.ImgToBytes(path) } // SaveImg save the image by []byte -func SaveImg(b []byte, path string) { - imgo.Save(path, b) +func SaveImg(b []byte, path string) error { + return imgo.Save(path, b) +} + +// SavePng save the image by image.Image +func SavePng(img image.Image, path string) error { + return imgo.SaveToPNG(path, img) } // BitmapStr bitmap from string From 06ad6eb8a1fda64feffe10e7b248c0b4f74ffce7 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 5 Nov 2020 10:57:51 -0400 Subject: [PATCH 034/327] update ShowAlert optimize return code --- README.md | 2 +- README_zh.md | 2 +- examples/window/main.go | 2 +- robotgo.go | 4 ++-- test/main.go | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 28b8ddaf..9d5ef100 100644 --- a/README.md +++ b/README.md @@ -311,7 +311,7 @@ func main() { } abool := robotgo.ShowAlert("test", "robotgo") - if abool == 0 { + if abool { fmt.Println("ok@@@ ", "ok") } diff --git a/README_zh.md b/README_zh.md index 42378a1a..760990b4 100644 --- a/README_zh.md +++ b/README_zh.md @@ -308,7 +308,7 @@ func main() { } abool := robotgo.ShowAlert("test", "robotgo") - if abool == 0 { + if abool { fmt.Println("ok@@@ ", "ok") } diff --git a/examples/window/main.go b/examples/window/main.go index b9536292..fb8bbb16 100644 --- a/examples/window/main.go +++ b/examples/window/main.go @@ -20,7 +20,7 @@ import ( func alert() { // show Alert Window abool := robotgo.ShowAlert("hello", "robotgo") - if abool == 0 { + if abool { fmt.Println("ok@@@", "ok") } robotgo.ShowAlert("hello", "robotgo", "Ok", "Cancel") diff --git a/robotgo.go b/robotgo.go index 99128cc8..7adf936e 100644 --- a/robotgo.go +++ b/robotgo.go @@ -1361,7 +1361,7 @@ ____ __ ____ __ .__ __. _______ ______ ____ __ ____ */ // ShowAlert show a alert window -func ShowAlert(title, msg string, args ...string) int { +func ShowAlert(title, msg string, args ...string) bool { var ( // title string // msg string @@ -1392,7 +1392,7 @@ func ShowAlert(title, msg string, args ...string) int { C.free(unsafe.Pointer(adefaultButton)) C.free(unsafe.Pointer(acancelButton)) - return ibool + return ibool == 0 } // IsValid valid the window diff --git a/test/main.go b/test/main.go index 26664119..30e84064 100644 --- a/test/main.go +++ b/test/main.go @@ -19,7 +19,7 @@ import ( func aRobotgo() { abool := robotgo.ShowAlert("test", "robotgo") - if abool == 0 { + if abool { fmt.Println("ok@@@", "ok") } From 83852edd8b00393b1692ba4f6afeac3702ab6684 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 11 Nov 2020 13:14:22 -0400 Subject: [PATCH 035/327] update dockerfile and appveyor.yml --- .circleci/images/primary/Dockerfile | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index 04591f9f..5176314e 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.15.3-stretch AS build +FROM golang:1.15.4-stretch AS build # FROM govgo/go:1.11.1 RUN apt update && apt install -y --no-install-recommends \ diff --git a/appveyor.yml b/appveyor.yml index 862511c6..bd60b642 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,7 +34,7 @@ environment: PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% # - COMPILER: MINGW_W64 # ARCHITECTURE: x64 - GOVERSION: 1.15.3 + GOVERSION: 1.15.4 # GOPATH: c:\gopath # scripts that run after cloning repository From 7bdc236c3ff0cf6e9c99ee7efbbe28a7b46cc54b Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sat, 14 Nov 2020 14:21:25 -0400 Subject: [PATCH 036/327] update dockerfile --- .circleci/images/primary/Dockerfile | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index 5176314e..cc9d0798 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.15.4-stretch AS build +FROM golang:1.15.5-stretch AS build # FROM govgo/go:1.11.1 RUN apt update && apt install -y --no-install-recommends \ diff --git a/appveyor.yml b/appveyor.yml index bd60b642..3dcb9619 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,7 +34,7 @@ environment: PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% # - COMPILER: MINGW_W64 # ARCHITECTURE: x64 - GOVERSION: 1.15.4 + GOVERSION: 1.15.5 # GOPATH: c:\gopath # scripts that run after cloning repository From 8a93b17118ea38928ad6b20f0c7ba7c3197f5637 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 26 Nov 2020 12:12:03 -0400 Subject: [PATCH 037/327] add more test and update go mod --- go.mod | 4 ++-- go.sum | 10 ++++++---- robotgo_test.go | 4 ++++ 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index d6559a8b..48b7a98b 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,7 @@ module github.com/go-vgo/robotgo require ( github.com/davecgh/go-spew v1.1.1 // indirect - github.com/lxn/win v0.0.0-20201021184640-9c48443b1f44 + github.com/lxn/win v0.0.0-20201111105847-2a20daff6a55 github.com/otiai10/curr v1.0.0 // indirect github.com/otiai10/gosseract v2.2.1+incompatible github.com/robotn/gohook v0.30.4 @@ -12,7 +12,7 @@ require ( github.com/vcaesar/imgo v0.12.0 github.com/vcaesar/tt v0.11.0 golang.org/x/image v0.0.0-20200927104501-e162460cd6b5 - golang.org/x/net v0.0.0-20201002202402-0a1ea396d57c // indirect + golang.org/x/net v0.0.0-20201110031124-69a78807bb2b // indirect ) // replace golang.org/x/sys => github.com/golang/sys v0.0.0-20190109145017-48ac38b7c8cb diff --git a/go.sum b/go.sum index 68aaa432..22b67ed2 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI= github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= -github.com/lxn/win v0.0.0-20201021184640-9c48443b1f44 h1:5EnI2+vhRty/RE7v983dfdv0wKrDapW5xNHBMdDT4uY= -github.com/lxn/win v0.0.0-20201021184640-9c48443b1f44/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk= +github.com/lxn/win v0.0.0-20201111105847-2a20daff6a55 h1:4BxFx5XCtXc+nFtXDGDW+Uu5sPtsAbvPh6RObj3fG9o= +github.com/lxn/win v0.0.0-20201111105847-2a20daff6a55/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95 h1:+OLn68pqasWca0z5ryit9KGfp3sUsW4Lqg32iRMJyzs= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= github.com/otiai10/curr v1.0.0 h1:TJIWdbX0B+kpNagQrjgq8bCMrbhiuX73M2XwgtDMoOI= @@ -45,8 +45,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/image v0.0.0-20200927104501-e162460cd6b5 h1:QelT11PB4FXiDEXucrfNckHoFxwt8USGY1ajP1ZF5lM= golang.org/x/image v0.0.0-20200927104501-e162460cd6b5/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20201002202402-0a1ea396d57c h1:dk0ukUIHmGHqASjP0iue2261isepFCC6XRCSd1nHgDw= -golang.org/x/net v0.0.0-20201002202402-0a1ea396d57c/go.mod h1:iQL9McJNjoIa5mjH6nYTCTZXUN6RP+XW3eib7Ya3XcI= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -55,6 +55,8 @@ golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201101102859-da207088b7d1 h1:a/mKvvZr9Jcc8oKfcmgzyp7OwF73JPWsQLvH1z2Kxck= golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= diff --git a/robotgo_test.go b/robotgo_test.go index e1ef7858..34f0500e 100644 --- a/robotgo_test.go +++ b/robotgo_test.go @@ -144,6 +144,10 @@ func TestBitmap(t *testing.T) { e := SaveBitmap(bit, "robot_test.png") tt.Empty(t, e) + img := ToImage(bit) + err := SavePng(img, "robot_img.png") + tt.Nil(t, err) + bit1 := OpenBitmap("robot_test.png") b := tt.TypeOf(bit, bit1) tt.True(t, b) From 3baa63dc7f43d61db69810afb44719c8d5bae5ec Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 6 Dec 2020 12:32:58 -0400 Subject: [PATCH 038/327] update dockerfile --- .circleci/images/primary/Dockerfile | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index cc9d0798..497a451a 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.15.5-stretch AS build +FROM golang:1.15.6-stretch AS build # FROM govgo/go:1.11.1 RUN apt update && apt install -y --no-install-recommends \ diff --git a/appveyor.yml b/appveyor.yml index 3dcb9619..501e6721 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,7 +34,7 @@ environment: PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% # - COMPILER: MINGW_W64 # ARCHITECTURE: x64 - GOVERSION: 1.15.5 + GOVERSION: 1.15.6 # GOPATH: c:\gopath # scripts that run after cloning repository From d0efccf91abdac394a3c7657605dab3b7cfcb72b Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 6 Jan 2021 14:13:23 -0400 Subject: [PATCH 039/327] update go mod --- go.mod | 8 ++++---- go.sum | 21 ++++++++++----------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 48b7a98b..ef021ba8 100644 --- a/go.mod +++ b/go.mod @@ -5,13 +5,13 @@ require ( github.com/lxn/win v0.0.0-20201111105847-2a20daff6a55 github.com/otiai10/curr v1.0.0 // indirect github.com/otiai10/gosseract v2.2.1+incompatible - github.com/robotn/gohook v0.30.4 + github.com/robotn/gohook v0.30.5 github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 - github.com/vcaesar/gops v0.10.1 - github.com/vcaesar/imgo v0.12.0 + github.com/vcaesar/gops v0.10.2 + github.com/vcaesar/imgo v0.12.1 github.com/vcaesar/tt v0.11.0 - golang.org/x/image v0.0.0-20200927104501-e162460cd6b5 + golang.org/x/image v0.0.0-20201208152932-35266b937fa6 golang.org/x/net v0.0.0-20201110031124-69a78807bb2b // indirect ) diff --git a/go.sum b/go.sum index 22b67ed2..35f4d72a 100644 --- a/go.sum +++ b/go.sum @@ -20,8 +20,8 @@ github.com/otiai10/mint v1.3.0 h1:Ady6MKVezQwHBkGzLFbrsywyp09Ah7rkmfjV3Bcr5uc= github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/robotn/gohook v0.30.4 h1:MSGU6SGhvT//nERZBqZVlutb20ezIDhKrdYrFVQAAH0= -github.com/robotn/gohook v0.30.4/go.mod h1:WTp0iFJqlggobr3vz9HIpRMDPWAf5/JMnLU/M34VKQo= +github.com/robotn/gohook v0.30.5 h1:yECDQXcKUcMxYLzPWBEKaHNiNss6lLq15RrgouDCKw4= +github.com/robotn/gohook v0.30.5/go.mod h1:FXryR68cDIho8rjE7MKxt4n4aK2FBqp+d/0HK4oiGP8= github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 h1:2lhSR8N3T6I30q096DT7/5AKEIcf1vvnnWAmS0wfnNY= github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934/go.mod h1:SxQhJskUJ4rleVU44YvnrdvxQr0tKy5SRSigBrCgyyQ= github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 h1:2uX8QRLkkxn2EpAQ6I3KhA79BkdRZfvugJUzJadiJwk= @@ -33,17 +33,16 @@ github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/vcaesar/gops v0.10.1 h1:RFNFMuiuoLzZpibAhGuOJ7BDbOUWPL19S8gWhODaJfU= -github.com/vcaesar/gops v0.10.1/go.mod h1:301l7s41oGSmfI7F9ojpRHeF9MzZZ6Mv5vC038riB50= -github.com/vcaesar/imgo v0.12.0 h1:y2anuhS9i1KZBntYmN2je/rXn/oe26YNDZ57AsLJfN0= -github.com/vcaesar/imgo v0.12.0/go.mod h1:ZSmAFXF91Ch6xe9iz1LinzALa6w9T6c57fH+WqNhMBE= -github.com/vcaesar/tt v0.10.1/go.mod h1:GHPxQYhn+7OgKakRusH7KJ0M5MhywoeLb8Fcffs/Gtg= +github.com/vcaesar/gops v0.10.2 h1:agDWYawurQVqyV0bcGf/6xgM5VFq0/pmlLTgAhC2yD0= +github.com/vcaesar/gops v0.10.2/go.mod h1:C5OfFWnxVszWFHpqE63qRc9mqmEPcFtQKKOpw0h22G0= +github.com/vcaesar/imgo v0.12.1 h1:/mmZPL0CQwXtdr73ouoCu8Z9gmfmdgaFYoG0YSZ1gdU= +github.com/vcaesar/imgo v0.12.1/go.mod h1:MwS4X0FXkLxshu8jMrHCLEM0S6JOQ6lU3drq5nO9AdE= github.com/vcaesar/tt v0.11.0 h1:obQecjgbnAxxC6OYGY6yDvhGRW2PR5wD8Ma2uJH3WGA= github.com/vcaesar/tt v0.11.0/go.mod h1:GHPxQYhn+7OgKakRusH7KJ0M5MhywoeLb8Fcffs/Gtg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/image v0.0.0-20200927104501-e162460cd6b5 h1:QelT11PB4FXiDEXucrfNckHoFxwt8USGY1ajP1ZF5lM= -golang.org/x/image v0.0.0-20200927104501-e162460cd6b5/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20201208152932-35266b937fa6 h1:nfeHNc1nAqecKCy2FCy4HY+soOOe5sDLJ/gZLbx6GYI= +golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -52,8 +51,8 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13 h1:5jaG59Zhd+8ZXe8C+lgiAGqkOaZBruqrWclLkgAww34= golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201101102859-da207088b7d1 h1:a/mKvvZr9Jcc8oKfcmgzyp7OwF73JPWsQLvH1z2Kxck= -golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad h1:MCsdmFSdEd4UEa5TKS5JztCRHK/WtvNei1edOj5RSRo= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From b1dd8732ff9d57707f8ab09fa512a4f644fccc3a Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 20 Jan 2021 11:26:48 -0400 Subject: [PATCH 040/327] update dockerfile and appveyor.yml --- .circleci/images/primary/Dockerfile | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index 497a451a..8683f833 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.15.6-stretch AS build +FROM golang:1.15.7-stretch AS build # FROM govgo/go:1.11.1 RUN apt update && apt install -y --no-install-recommends \ diff --git a/appveyor.yml b/appveyor.yml index 501e6721..d20d893c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,7 +34,7 @@ environment: PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% # - COMPILER: MINGW_W64 # ARCHITECTURE: x64 - GOVERSION: 1.15.6 + GOVERSION: 1.15.7 # GOPATH: c:\gopath # scripts that run after cloning repository From 5bf71e637e6fc943fdc5ddde1eb3431f40e4bc8e Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 26 Jan 2021 12:59:47 -0400 Subject: [PATCH 041/327] add find every color code --- bitmap/goBitmap.h | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/bitmap/goBitmap.h b/bitmap/goBitmap.h index 2a17bbdb..424ad096 100644 --- a/bitmap/goBitmap.h +++ b/bitmap/goBitmap.h @@ -60,8 +60,7 @@ MMPoint find_bitmap(MMBitmapRef bitmap, MMBitmapRef sbit, float tolerance){ // printf("x=%d, y=%d, width=%d, height=%d\n", rect.origin.x, // rect.origin.y, rect.size.width, rect.size.height); - if (findBitmapInRect(bitmap, sbit, &point, - rect, tolerance) == 0) { + if (findBitmapInRect(bitmap, sbit, &point, rect, tolerance) == 0) { return point; } @@ -69,19 +68,18 @@ MMPoint find_bitmap(MMBitmapRef bitmap, MMBitmapRef sbit, float tolerance){ } MMPoint *find_every_bitmap(MMBitmapRef bitmap, MMBitmapRef sbit, float tolerance, MMPoint *list){ - if (!bitmap_ready(bitmap) || !bitmap_ready(sbit)) return NULL; + if (!bitmap_ready(bitmap) || !bitmap_ready(sbit)) { return NULL; } MMPoint point; MMPointArrayRef pointArray; MMRect rect = MMBitmapGetBounds(bitmap); - if (findBitmapInRect(bitmap, sbit, &point, - rect, tolerance) == 0) { + if (findBitmapInRect(bitmap, sbit, &point, rect, tolerance) == 0) { return NULL; } pointArray = findAllBitmapInRect(bitmap, sbit, rect, tolerance); - if (pointArray == NULL) return NULL; + if (pointArray == NULL) { return NULL; } memcpy(list, pointArray->array, sizeof(MMPoint) * pointArray->count); destroyMMPointArray(pointArray); @@ -93,7 +91,6 @@ int count_of_bitmap(MMBitmapRef bitmap, MMBitmapRef sbit, float tolerance){ if (!bitmap_ready(bitmap) || !bitmap_ready(sbit)) return 0; MMRect rect = MMBitmapGetBounds(bitmap); - return countOfBitmapInRect(bitmap, sbit, rect, tolerance); } @@ -126,9 +123,8 @@ MMBitmapRef bitmap_from_string(const char *str){ MMBitmapRef bitmap; MMBMPStringError err; - if ((bitmap = createMMBitmapFromString( - (unsigned char*)str, len, &err ) - ) == NULL) { + if ((bitmap = createMMBitmapFromString((unsigned char*)str, len, &err )) + == NULL) { return NULL; } @@ -148,7 +144,6 @@ char *tostring_bitmap(MMBitmapRef bitmap){ MMBMPStringError err; buf = (char *)createStringFromMMBitmap(bitmap, &err); - return buf; } @@ -174,7 +169,7 @@ MMBitmapRef get_portion(MMBitmapRef bit_map, MMRect rect){ } MMRGBHex bitmap_get_color(MMBitmapRef bitmap, size_t x, size_t y){ - if (!bitmap_ready(bitmap)) return 0; + if (!bitmap_ready(bitmap)) { return 0; } MMPoint point; point = MMPointMake(x, y); @@ -197,6 +192,21 @@ MMPoint bitmap_find_color(MMBitmapRef bitmap, MMRGBHex color, float tolerance){ return point; } +MMPoint *bitmap_find_every_color(MMBitmapRef bitmap, MMRGBHex color, float tolerance, MMPoint *list){ + if (!bitmap_ready(bitmap)) { return NULL; } + MMRect rect = MMBitmapGetBounds(bitmap); + MMPointArrayRef pointArray; + + pointArray = findAllColorInRect(bitmap, color, rect, tolerance); + if (pointArray == NULL) { return NULL; } + + memcpy(list, pointArray->array, sizeof(MMPoint) * pointArray->count); + destroyMMPointArray(pointArray); + if (list == NULL) { return NULL; } + + return list; +} + int bitmap_count_of_color(MMBitmapRef bitmap, MMRGBHex color, float tolerance){ if (!bitmap_ready(bitmap)) return 0; MMRect rect = MMBitmapGetBounds(bitmap); From 5c45871af70efe3a26fa474b7189e2fa56f4afc2 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 28 Jan 2021 13:46:08 -0400 Subject: [PATCH 042/327] add find every color function --- robotgo.go | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/robotgo.go b/robotgo.go index 7adf936e..8034eb0b 100644 --- a/robotgo.go +++ b/robotgo.go @@ -1298,6 +1298,45 @@ func FindColorCS(color CHex, x, y, w, h int, args ...float64) (int, int) { return rx, ry } +// FindEveryColor find every color +func FindEveryColor(color CHex, args ...interface{}) (int, int) { + var ( + bitmap C.MMBitmapRef + tolerance C.float = 0.01 + lpos C.MMPoint + ) + + if len(args) > 0 && args[0] != nil { + bitmap = args[0].(C.MMBitmapRef) + } else { + bitmap = CaptureScreen() + } + + if len(args) > 1 { + tolerance = C.float(args[1].(float64)) + } + + if len(args) > 2 { + lpos.x = C.size_t(args[2].(int)) + lpos.y = 0 + } else { + lpos.x = 0 + lpos.y = 0 + } + + if len(args) > 3 { + lpos.x = C.size_t(args[2].(int)) + lpos.y = C.size_t(args[3].(int)) + } + + pos := C.bitmap_find_every_color(bitmap, C.MMRGBHex(color), tolerance, &lpos) + if len(args) <= 0 { + FreeBitmap(bitmap) + } + + return int(pos.x), int(pos.y) +} + // CountColor count bitmap color func CountColor(color CHex, args ...interface{}) int { var ( From 488a81253f5c4aa5fe037fd7c9f5f3da43f6cbff Mon Sep 17 00:00:00 2001 From: vcaesar Date: Fri, 29 Jan 2021 13:56:58 -0400 Subject: [PATCH 043/327] add free and find all point function --- bitmap/goBitmap.h | 21 +++++---------------- robotgo.go | 35 +++++++++++++++++++++++++++++++---- 2 files changed, 36 insertions(+), 20 deletions(-) diff --git a/bitmap/goBitmap.h b/bitmap/goBitmap.h index 424ad096..359d9f23 100644 --- a/bitmap/goBitmap.h +++ b/bitmap/goBitmap.h @@ -67,24 +67,19 @@ MMPoint find_bitmap(MMBitmapRef bitmap, MMBitmapRef sbit, float tolerance){ return point; } -MMPoint *find_every_bitmap(MMBitmapRef bitmap, MMBitmapRef sbit, float tolerance, MMPoint *list){ +MMPointArrayRef find_every_bitmap(MMBitmapRef bitmap, MMBitmapRef sbit, float tolerance, MMPoint *list){ if (!bitmap_ready(bitmap) || !bitmap_ready(sbit)) { return NULL; } MMPoint point; MMPointArrayRef pointArray; - MMRect rect = MMBitmapGetBounds(bitmap); + MMRect rect = MMBitmapGetBounds(sbit); if (findBitmapInRect(bitmap, sbit, &point, rect, tolerance) == 0) { return NULL; } pointArray = findAllBitmapInRect(bitmap, sbit, rect, tolerance); - if (pointArray == NULL) { return NULL; } - - memcpy(list, pointArray->array, sizeof(MMPoint) * pointArray->count); - destroyMMPointArray(pointArray); - - return list; + return pointArray; } int count_of_bitmap(MMBitmapRef bitmap, MMBitmapRef sbit, float tolerance){ @@ -192,19 +187,13 @@ MMPoint bitmap_find_color(MMBitmapRef bitmap, MMRGBHex color, float tolerance){ return point; } -MMPoint *bitmap_find_every_color(MMBitmapRef bitmap, MMRGBHex color, float tolerance, MMPoint *list){ +MMPointArrayRef bitmap_find_every_color(MMBitmapRef bitmap, MMRGBHex color, float tolerance, MMPoint *list){ if (!bitmap_ready(bitmap)) { return NULL; } MMRect rect = MMBitmapGetBounds(bitmap); MMPointArrayRef pointArray; pointArray = findAllColorInRect(bitmap, color, rect, tolerance); - if (pointArray == NULL) { return NULL; } - - memcpy(list, pointArray->array, sizeof(MMPoint) * pointArray->count); - destroyMMPointArray(pointArray); - if (list == NULL) { return NULL; } - - return list; + return pointArray; } int bitmap_count_of_color(MMBitmapRef bitmap, MMRGBHex color, float tolerance){ diff --git a/robotgo.go b/robotgo.go index 8034eb0b..655e599a 100644 --- a/robotgo.go +++ b/robotgo.go @@ -1017,8 +1017,13 @@ func FindPic(path string, args ...interface{}) (int, int) { return fx, fy } +// FreeMMPointArr free MMPoint array +func FreeMMPointArr(pointArray C.MMPointArrayRef) { + C.destroyMMPointArray(pointArray) +} + // FindEveryBitmap find the every bitmap -func FindEveryBitmap(bit C.MMBitmapRef, args ...interface{}) (int, int) { +func FindEveryBitmap(bit C.MMBitmapRef, args ...interface{}) (posArr []MPoint) { var ( sbit C.MMBitmapRef tolerance C.float = 0.01 @@ -1050,12 +1055,23 @@ func FindEveryBitmap(bit C.MMBitmapRef, args ...interface{}) (int, int) { pos := C.find_every_bitmap(bit, sbit, tolerance, &lpos) // FreeBitmap(bit) + defer FreeMMPointArr(pos) if len(args) <= 0 { FreeBitmap(sbit) } + cSize := pos.count + cArray := pos.array + gSlice := (*[1 << 30]C.MMPoint)(unsafe.Pointer(cArray))[:cSize:cSize] + for i := 0; i < len(gSlice); i++ { + posArr = append(posArr, MPoint{ + x: int(gSlice[i].x), + y: int(gSlice[i].y), + }) + } + // fmt.Println("pos----", pos) - return int(pos.x), int(pos.y) + return } // CountBitmap count of the bitmap @@ -1299,7 +1315,7 @@ func FindColorCS(color CHex, x, y, w, h int, args ...float64) (int, int) { } // FindEveryColor find every color -func FindEveryColor(color CHex, args ...interface{}) (int, int) { +func FindEveryColor(color CHex, args ...interface{}) (posArr []MPoint) { var ( bitmap C.MMBitmapRef tolerance C.float = 0.01 @@ -1330,11 +1346,22 @@ func FindEveryColor(color CHex, args ...interface{}) (int, int) { } pos := C.bitmap_find_every_color(bitmap, C.MMRGBHex(color), tolerance, &lpos) + defer FreeMMPointArr(pos) if len(args) <= 0 { FreeBitmap(bitmap) } - return int(pos.x), int(pos.y) + cSize := pos.count + cArray := pos.array + gSlice := (*[1 << 30]C.MMPoint)(unsafe.Pointer(cArray))[:cSize:cSize] + for i := 0; i < len(gSlice); i++ { + posArr = append(posArr, MPoint{ + x: int(gSlice[i].x), + y: int(gSlice[i].y), + }) + } + + return } // CountColor count bitmap color From 25a40029243664e424f11015c3df78a1637d39f8 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 31 Jan 2021 12:44:15 -0400 Subject: [PATCH 044/327] update find bitmap and color --- bitmap/goBitmap.h | 2 +- robotgo.go | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/bitmap/goBitmap.h b/bitmap/goBitmap.h index 359d9f23..0ac6557a 100644 --- a/bitmap/goBitmap.h +++ b/bitmap/goBitmap.h @@ -75,7 +75,7 @@ MMPointArrayRef find_every_bitmap(MMBitmapRef bitmap, MMBitmapRef sbit, float to MMRect rect = MMBitmapGetBounds(sbit); if (findBitmapInRect(bitmap, sbit, &point, rect, tolerance) == 0) { - return NULL; + // return NULL; } pointArray = findAllBitmapInRect(bitmap, sbit, rect, tolerance); diff --git a/robotgo.go b/robotgo.go index 655e599a..5eaa3441 100644 --- a/robotgo.go +++ b/robotgo.go @@ -1055,10 +1055,13 @@ func FindEveryBitmap(bit C.MMBitmapRef, args ...interface{}) (posArr []MPoint) { pos := C.find_every_bitmap(bit, sbit, tolerance, &lpos) // FreeBitmap(bit) - defer FreeMMPointArr(pos) if len(args) <= 0 { FreeBitmap(sbit) } + if pos == nil { + return + } + defer FreeMMPointArr(pos) cSize := pos.count cArray := pos.array @@ -1346,11 +1349,15 @@ func FindEveryColor(color CHex, args ...interface{}) (posArr []MPoint) { } pos := C.bitmap_find_every_color(bitmap, C.MMRGBHex(color), tolerance, &lpos) - defer FreeMMPointArr(pos) if len(args) <= 0 { FreeBitmap(bitmap) } + if pos == nil { + return + } + defer FreeMMPointArr(pos) + cSize := pos.count cArray := pos.array gSlice := (*[1 << 30]C.MMPoint)(unsafe.Pointer(cArray))[:cSize:cSize] From bfaba0b1d2bb8760d071e6556c2822fd7349eefc Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 31 Jan 2021 13:29:42 -0400 Subject: [PATCH 045/327] compatible with 32-bit platforms --- robotgo.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/robotgo.go b/robotgo.go index 5eaa3441..3cdc1ffe 100644 --- a/robotgo.go +++ b/robotgo.go @@ -1065,7 +1065,7 @@ func FindEveryBitmap(bit C.MMBitmapRef, args ...interface{}) (posArr []MPoint) { cSize := pos.count cArray := pos.array - gSlice := (*[1 << 30]C.MMPoint)(unsafe.Pointer(cArray))[:cSize:cSize] + gSlice := (*[(1 << 28) - 1]C.MMPoint)(unsafe.Pointer(cArray))[:cSize:cSize] for i := 0; i < len(gSlice); i++ { posArr = append(posArr, MPoint{ x: int(gSlice[i].x), @@ -1360,7 +1360,7 @@ func FindEveryColor(color CHex, args ...interface{}) (posArr []MPoint) { cSize := pos.count cArray := pos.array - gSlice := (*[1 << 30]C.MMPoint)(unsafe.Pointer(cArray))[:cSize:cSize] + gSlice := (*[(1 << 28) - 1]C.MMPoint)(unsafe.Pointer(cArray))[:cSize:cSize] for i := 0; i < len(gSlice); i++ { posArr = append(posArr, MPoint{ x: int(gSlice[i].x), From 3c1663dd9d7201515a487cdd4a932d354ccaf6be Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 1 Feb 2021 11:17:51 -0400 Subject: [PATCH 046/327] add more bitmap examples --- bitmap/goBitmap.h | 7 +++---- examples/bitmap/main.go | 6 ++++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/bitmap/goBitmap.h b/bitmap/goBitmap.h index 0ac6557a..68f16b6d 100644 --- a/bitmap/goBitmap.h +++ b/bitmap/goBitmap.h @@ -83,7 +83,7 @@ MMPointArrayRef find_every_bitmap(MMBitmapRef bitmap, MMBitmapRef sbit, float to } int count_of_bitmap(MMBitmapRef bitmap, MMBitmapRef sbit, float tolerance){ - if (!bitmap_ready(bitmap) || !bitmap_ready(sbit)) return 0; + if (!bitmap_ready(bitmap) || !bitmap_ready(sbit)) { return 0; } MMRect rect = MMBitmapGetBounds(bitmap); return countOfBitmapInRect(bitmap, sbit, rect, tolerance); @@ -109,7 +109,6 @@ MMBitmapRef bitmap_open(char *path, uint16_t ttype){ bitmap = newMMBitmapFromFile(path, ttype, &err); // printf("....%zd\n", bitmap->width); return bitmap; - } MMBitmapRef bitmap_from_string(const char *str){ @@ -118,7 +117,7 @@ MMBitmapRef bitmap_from_string(const char *str){ MMBitmapRef bitmap; MMBMPStringError err; - if ((bitmap = createMMBitmapFromString((unsigned char*)str, len, &err )) + if ((bitmap = createMMBitmapFromString((unsigned char*)str, len, &err)) == NULL) { return NULL; } @@ -144,7 +143,7 @@ char *tostring_bitmap(MMBitmapRef bitmap){ // out with size 200 is enough bool bitmap_str(MMBitmapRef bitmap, char *out){ - if (!bitmap_ready(bitmap)) return false; + if (!bitmap_ready(bitmap)) { return false; } sprintf(out, "", (unsigned long)bitmap->width, diff --git a/examples/bitmap/main.go b/examples/bitmap/main.go index a9318d2f..dea7b848 100644 --- a/examples/bitmap/main.go +++ b/examples/bitmap/main.go @@ -57,6 +57,9 @@ func findColor(bmp robotgo.CBitmap) { fmt.Println("count...", cnt) cnt1 := robotgo.CountColorCS(0xAADCDC, 10, 20, 30, 40) fmt.Println("count...", cnt1) + + arr := robotgo.FindEveryColor(0xAADCDC) + fmt.Println("find all color: ", arr) } func bitmapString(bmp robotgo.CBitmap) { @@ -146,6 +149,9 @@ func findBitmap(bmp robotgo.CBitmap) { fx, fy = robotgo.FindPic("test.tif") fmt.Println("FindPic------", fx, fy) + + arr := robotgo.FindEveryBitmap(openbit) + fmt.Println("find all bitmap: ", arr) } func bitmap() { From 708278a48dac6c6f68cf0d4304acaca25a311331 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 2 Feb 2021 10:17:38 -0400 Subject: [PATCH 047/327] update point to public --- robotgo.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/robotgo.go b/robotgo.go index 3cdc1ffe..9a4089ef 100644 --- a/robotgo.go +++ b/robotgo.go @@ -99,8 +99,8 @@ type Bitmap struct { // MPoint is MPoint struct type MPoint struct { - x int - y int + X int + Y int } // Try handler(err) @@ -1068,8 +1068,8 @@ func FindEveryBitmap(bit C.MMBitmapRef, args ...interface{}) (posArr []MPoint) { gSlice := (*[(1 << 28) - 1]C.MMPoint)(unsafe.Pointer(cArray))[:cSize:cSize] for i := 0; i < len(gSlice); i++ { posArr = append(posArr, MPoint{ - x: int(gSlice[i].x), - y: int(gSlice[i].y), + X: int(gSlice[i].x), + Y: int(gSlice[i].y), }) } @@ -1363,8 +1363,8 @@ func FindEveryColor(color CHex, args ...interface{}) (posArr []MPoint) { gSlice := (*[(1 << 28) - 1]C.MMPoint)(unsafe.Pointer(cArray))[:cSize:cSize] for i := 0; i < len(gSlice); i++ { posArr = append(posArr, MPoint{ - x: int(gSlice[i].x), - y: int(gSlice[i].y), + X: int(gSlice[i].x), + Y: int(gSlice[i].y), }) } From 32f91a5150aaabd42ff9146ad7a2302d6ff11a29 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 7 Feb 2021 14:28:04 -0400 Subject: [PATCH 048/327] update dockerfile and appveyor.yml --- .circleci/images/primary/Dockerfile | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index 8683f833..fa9b5360 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.15.7-stretch AS build +FROM golang:1.15.8-stretch AS build # FROM govgo/go:1.11.1 RUN apt update && apt install -y --no-install-recommends \ diff --git a/appveyor.yml b/appveyor.yml index d20d893c..8296d215 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,7 +34,7 @@ environment: PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% # - COMPILER: MINGW_W64 # ARCHITECTURE: x64 - GOVERSION: 1.15.7 + GOVERSION: 1.15.8 # GOPATH: c:\gopath # scripts that run after cloning repository From d8605a21917c22ee18eebb9556980d0d169e840b Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 10 Feb 2021 12:09:06 -0400 Subject: [PATCH 049/327] add more examples --- examples/bitmap/main.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/examples/bitmap/main.go b/examples/bitmap/main.go index dea7b848..adaf3293 100644 --- a/examples/bitmap/main.go +++ b/examples/bitmap/main.go @@ -60,6 +60,9 @@ func findColor(bmp robotgo.CBitmap) { arr := robotgo.FindEveryColor(0xAADCDC) fmt.Println("find all color: ", arr) + for i := 0; i < len(arr); i++ { + fmt.Println("pos is: ", arr[i].X, arr[i].Y) + } } func bitmapString(bmp robotgo.CBitmap) { @@ -152,6 +155,9 @@ func findBitmap(bmp robotgo.CBitmap) { arr := robotgo.FindEveryBitmap(openbit) fmt.Println("find all bitmap: ", arr) + for i := 0; i < len(arr); i++ { + fmt.Println("pos is: ", arr[i].X, arr[i].Y) + } } func bitmap() { From bde093a1c7e4d8a3959649f415ec7c8c91af7d29 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 23 Feb 2021 13:53:16 -0400 Subject: [PATCH 050/327] update dockerfile and CI yml --- .circleci/images/primary/Dockerfile | 2 +- .github/workflows/go.yml | 4 ++-- .travis.yml | 3 ++- appveyor.yml | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index fa9b5360..b45a592e 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.15.8-stretch AS build +FROM golang:1.16-stretch AS build # FROM govgo/go:1.11.1 RUN apt update && apt install -y --no-install-recommends \ diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 176b0e38..b3fc8af0 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -10,10 +10,10 @@ jobs: runs-on: ${{ matrix.os }} steps: - - name: Set up Go 1.15 + - name: Set up Go 1.16 uses: actions/setup-go@v1 with: - go-version: 1.15 + go-version: 1.16 id: go - name: Check out code into the Go module directory diff --git a/.travis.yml b/.travis.yml index 1ba8d5c1..a251a09d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,8 @@ go: # - 1.12.x # - 1.13.x # - 1.14.x - - 1.15.x + # - 1.15.x + - 1.16.x # - tip addons: diff --git a/appveyor.yml b/appveyor.yml index 8296d215..04cac2bc 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,7 +34,7 @@ environment: PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% # - COMPILER: MINGW_W64 # ARCHITECTURE: x64 - GOVERSION: 1.15.8 + GOVERSION: 1.16 # GOPATH: c:\gopath # scripts that run after cloning repository From 031b46cb881d4bdbed56c5fada5deb408b5f14c0 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Fri, 5 Mar 2021 14:58:53 -0400 Subject: [PATCH 051/327] update examples and version --- examples/color-picker/main.go | 5 ++++- examples/key/main.go | 2 +- robotgo.go | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/examples/color-picker/main.go b/examples/color-picker/main.go index 48f188ac..751b26d1 100644 --- a/examples/color-picker/main.go +++ b/examples/color-picker/main.go @@ -16,7 +16,10 @@ func colorPicker() { fmt.Println("color: #", clo) // clipboard - robotgo.WriteAll("#" + clo) + err := robotgo.WriteAll("#" + clo) + if err != nil { + fmt.Println("err: ", err) + } } } diff --git a/examples/key/main.go b/examples/key/main.go index d4de1936..1fe27fa4 100644 --- a/examples/key/main.go +++ b/examples/key/main.go @@ -99,7 +99,7 @@ func cilp() { if err != nil { fmt.Println("robotgo.ReadAll err is: ", err) } - fmt.Println(text) + fmt.Println("text: ", text) } func key() { diff --git a/robotgo.go b/robotgo.go index 9a4089ef..16485744 100644 --- a/robotgo.go +++ b/robotgo.go @@ -70,7 +70,7 @@ import ( const ( // Version get the robotgo version - Version = "v0.91.0.1089, MT. Rainier!" + Version = "v0.93.1.1189, MT. Rainier!" ) // GetVersion get the robotgo version From 6eeacf0a7e761a45db60c946e04048aad1ea6089 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 14 Mar 2021 11:23:13 -0400 Subject: [PATCH 052/327] update appveyor.yml and dockerfile --- .circleci/images/primary/Dockerfile | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index b45a592e..88b5c99a 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.16-stretch AS build +FROM golang:1.16.2-stretch AS build # FROM govgo/go:1.11.1 RUN apt update && apt install -y --no-install-recommends \ diff --git a/appveyor.yml b/appveyor.yml index 04cac2bc..a4da0cdc 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,7 +34,7 @@ environment: PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% # - COMPILER: MINGW_W64 # ARCHITECTURE: x64 - GOVERSION: 1.16 + GOVERSION: 1.16.2 # GOPATH: c:\gopath # scripts that run after cloning repository From 26cd76492a6675388dc5c5a2fbc46312e1019922 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 4 Apr 2021 13:51:12 -0400 Subject: [PATCH 053/327] update dockerfile and appveyor.yml --- .circleci/images/primary/Dockerfile | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index 88b5c99a..12c11467 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.16.2-stretch AS build +FROM golang:1.16.3-stretch AS build # FROM govgo/go:1.11.1 RUN apt update && apt install -y --no-install-recommends \ diff --git a/appveyor.yml b/appveyor.yml index a4da0cdc..0f092674 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,7 +34,7 @@ environment: PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% # - COMPILER: MINGW_W64 # ARCHITECTURE: x64 - GOVERSION: 1.16.2 + GOVERSION: 1.16.3 # GOPATH: c:\gopath # scripts that run after cloning repository From fec092bfd76853cf60532a5c628d428459244b0c Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 9 May 2021 10:50:40 -0400 Subject: [PATCH 054/327] update dockerfile and appveyor.yml --- .circleci/images/primary/Dockerfile | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index 12c11467..36809f39 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.16.3-stretch AS build +FROM golang:1.16.4-stretch AS build # FROM govgo/go:1.11.1 RUN apt update && apt install -y --no-install-recommends \ diff --git a/appveyor.yml b/appveyor.yml index 0f092674..acf4b46c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,7 +34,7 @@ environment: PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% # - COMPILER: MINGW_W64 # ARCHITECTURE: x64 - GOVERSION: 1.16.3 + GOVERSION: 1.16.4 # GOPATH: c:\gopath # scripts that run after cloning repository From 0d7798c6c373ce405b53e257e560448da6f431b9 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Fri, 28 May 2021 14:31:05 -0400 Subject: [PATCH 055/327] add byte to image function --- robotgo.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/robotgo.go b/robotgo.go index 16485744..661c4a4a 100644 --- a/robotgo.go +++ b/robotgo.go @@ -49,6 +49,7 @@ package robotgo import "C" import ( + "bytes" "fmt" "image" @@ -1126,6 +1127,12 @@ func DecodeImg(path string) (image.Image, string, error) { return imgo.DecodeFile(path) } +// ByteToImg convert []byte to image.Image +func ByteToImg(b []byte) (image.Image, error) { + img, _, err := image.Decode(bytes.NewReader(b)) + return img, err +} + // ToImage convert C.MMBitmapRef to standard image.Image func ToImage(bit C.MMBitmapRef) image.Image { bmp1 := ToBitmap(bit) From cad782738cf14ec7ba125ce0aa6313f9d5fcc21c Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sat, 29 May 2021 09:58:26 -0400 Subject: [PATCH 056/327] update free bitmap fixed #333 --- robotgo.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/robotgo.go b/robotgo.go index 661c4a4a..e0e2f408 100644 --- a/robotgo.go +++ b/robotgo.go @@ -978,7 +978,7 @@ func FindBitmap(bit C.MMBitmapRef, args ...interface{}) (int, int) { fx, fy := internalFindBitmap(bit, sbit, tolerance) // FreeBitmap(bit) - if len(args) <= 0 { + if len(args) <= 0 || (len(args) > 0 && args[0] == nil) { FreeBitmap(sbit) } @@ -1011,7 +1011,7 @@ func FindPic(path string, args ...interface{}) (int, int) { fx, fy := internalFindBitmap(openbit, sbit, tolerance) FreeBitmap(openbit) - if len(args) <= 0 { + if len(args) <= 0 || (len(args) > 0 && args[0] == nil) { FreeBitmap(sbit) } @@ -1056,7 +1056,7 @@ func FindEveryBitmap(bit C.MMBitmapRef, args ...interface{}) (posArr []MPoint) { pos := C.find_every_bitmap(bit, sbit, tolerance, &lpos) // FreeBitmap(bit) - if len(args) <= 0 { + if len(args) <= 0 || (len(args) > 0 && args[0] == nil) { FreeBitmap(sbit) } if pos == nil { @@ -1299,7 +1299,7 @@ func FindColor(color CHex, args ...interface{}) (int, int) { } pos := C.bitmap_find_color(bitmap, C.MMRGBHex(color), tolerance) - if len(args) <= 0 { + if len(args) <= 0 || (len(args) > 0 && args[0] == nil) { FreeBitmap(bitmap) } @@ -1356,7 +1356,7 @@ func FindEveryColor(color CHex, args ...interface{}) (posArr []MPoint) { } pos := C.bitmap_find_every_color(bitmap, C.MMRGBHex(color), tolerance, &lpos) - if len(args) <= 0 { + if len(args) <= 0 || (len(args) > 0 && args[0] == nil) { FreeBitmap(bitmap) } @@ -1396,7 +1396,7 @@ func CountColor(color CHex, args ...interface{}) int { } count := C.bitmap_count_of_color(bitmap, C.MMRGBHex(color), tolerance) - if len(args) <= 0 { + if len(args) <= 0 || (len(args) > 0 && args[0] == nil) { FreeBitmap(bitmap) } From bdec2bf058d897f9c7f0acf535fa60743db42904 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sat, 29 May 2021 10:37:37 -0400 Subject: [PATCH 057/327] update go mod --- go.mod | 7 +++++-- go.sum | 20 +++++++++++--------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/go.mod b/go.mod index ef021ba8..bc509974 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,10 @@ module github.com/go-vgo/robotgo require ( + github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/lxn/win v0.0.0-20201111105847-2a20daff6a55 + github.com/go-ole/go-ole v1.2.5 // indirect + github.com/lxn/win v0.0.0-20210218163916-a377121e959e github.com/otiai10/curr v1.0.0 // indirect github.com/otiai10/gosseract v2.2.1+incompatible github.com/robotn/gohook v0.30.5 @@ -11,8 +13,9 @@ require ( github.com/vcaesar/gops v0.10.2 github.com/vcaesar/imgo v0.12.1 github.com/vcaesar/tt v0.11.0 - golang.org/x/image v0.0.0-20201208152932-35266b937fa6 + golang.org/x/image v0.0.0-20210504121937-7319ad40d33e golang.org/x/net v0.0.0-20201110031124-69a78807bb2b // indirect + golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea // indirect ) // replace golang.org/x/sys => github.com/golang/sys v0.0.0-20190109145017-48ac38b7c8cb diff --git a/go.sum b/go.sum index 35f4d72a..b80b383a 100644 --- a/go.sum +++ b/go.sum @@ -1,16 +1,16 @@ github.com/BurntSushi/freetype-go v0.0.0-20160129220410-b763ddbfe298/go.mod h1:D+QujdIlUNfa0igpNMk6UIvlb6C252URs4yupRUV4lQ= github.com/BurntSushi/graphics-go v0.0.0-20160129215708-b43f31a4a966/go.mod h1:Mid70uvE93zn9wgF92A/r5ixgnvX8Lh68fxp9KQBaI0= -github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk= github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 h1:5sXbqlSomvdjlRbWyNqkPsJ3Fg+tQZCbgeX1VGljbQY= +github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI= github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= -github.com/lxn/win v0.0.0-20201111105847-2a20daff6a55 h1:4BxFx5XCtXc+nFtXDGDW+Uu5sPtsAbvPh6RObj3fG9o= -github.com/lxn/win v0.0.0-20201111105847-2a20daff6a55/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk= -github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95 h1:+OLn68pqasWca0z5ryit9KGfp3sUsW4Lqg32iRMJyzs= +github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY= +github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/lxn/win v0.0.0-20210218163916-a377121e959e h1:H+t6A/QJMbhCSEH5rAuRxh+CtW96g0Or0Fxa9IKr4uc= +github.com/lxn/win v0.0.0-20210218163916-a377121e959e/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= github.com/otiai10/curr v1.0.0 h1:TJIWdbX0B+kpNagQrjgq8bCMrbhiuX73M2XwgtDMoOI= github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= @@ -41,18 +41,20 @@ github.com/vcaesar/tt v0.11.0 h1:obQecjgbnAxxC6OYGY6yDvhGRW2PR5wD8Ma2uJH3WGA= github.com/vcaesar/tt v0.11.0/go.mod h1:GHPxQYhn+7OgKakRusH7KJ0M5MhywoeLb8Fcffs/Gtg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/image v0.0.0-20201208152932-35266b937fa6 h1:nfeHNc1nAqecKCy2FCy4HY+soOOe5sDLJ/gZLbx6GYI= golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20210504121937-7319ad40d33e h1:PzJMNfFQx+QO9hrC1GwZ4BoPGeNGhfeQEgcQFArEjPk= +golang.org/x/image v0.0.0-20210504121937-7319ad40d33e/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13 h1:5jaG59Zhd+8ZXe8C+lgiAGqkOaZBruqrWclLkgAww34= golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad h1:MCsdmFSdEd4UEa5TKS5JztCRHK/WtvNei1edOj5RSRo= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea h1:+WiDlPBBaO+h9vPNZi8uJ3k4BkKQB7Iow3aqwHVA5hI= +golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From c22af9f286f165f6c0a9c8a06d4a742610a47500 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 30 May 2021 13:17:32 -0400 Subject: [PATCH 058/327] add more image convert function --- robotgo.go | 92 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 59 insertions(+), 33 deletions(-) diff --git a/robotgo.go b/robotgo.go index e0e2f408..554f64bd 100644 --- a/robotgo.go +++ b/robotgo.go @@ -62,6 +62,8 @@ import ( "unsafe" // "syscall" + "encoding/base64" + "image/jpeg" "os/exec" "github.com/go-vgo/robotgo/clipboard" @@ -940,6 +942,63 @@ func TocharBitmap(bit C.MMBitmapRef) *C.char { return strBit } +// ToByteImg convert image.Image to []byte +func ToByteImg(img image.Image) []byte { + buff := bytes.NewBuffer(nil) + jpeg.Encode(buff, img, nil) + + var dist []byte + base64.StdEncoding.Encode(dist, buff.Bytes()) + + return dist +} + +// ToStringImg convert image.Image to string +func ToStringImg(img image.Image) string { + return string(ToByteImg(img)) +} + +// StrToImg convert base64 string to image.Image +func StrToImg(data string) (image.Image, error) { + reader := base64.NewDecoder(base64.StdEncoding, strings.NewReader(data)) + m, _, err := image.Decode(reader) + + return m, err +} + +// ByteToImg convert []byte to image.Image +func ByteToImg(b []byte) (image.Image, error) { + img, _, err := image.Decode(bytes.NewReader(b)) + return img, err +} + +// ToImage convert C.MMBitmapRef to standard image.Image +func ToImage(bit C.MMBitmapRef) image.Image { + bmp1 := ToBitmap(bit) + img1 := image.NewRGBA(image.Rect(0, 0, bmp1.Width, bmp1.Height)) + img1.Pix = make([]uint8, bmp1.Bytewidth*bmp1.Height) + + copyToVUint8A(img1.Pix, bmp1.ImgBuf) + img1.Stride = bmp1.Bytewidth + return img1 +} + +func val(p *uint8, n int) uint8 { + addr := uintptr(unsafe.Pointer(p)) + addr += uintptr(n) + p1 := (*uint8)(unsafe.Pointer(addr)) + return *p1 +} + +func copyToVUint8A(dst []uint8, src *uint8) { + for i := 0; i < len(dst)-4; i += 4 { + dst[i] = val(src, i+2) + dst[i+1] = val(src, i+1) + dst[i+2] = val(src, i) + dst[i+3] = val(src, i+3) + } +} + func internalFindBitmap(bit, sbit C.MMBitmapRef, tolerance float64) (int, int) { pos := C.find_bitmap(bit, sbit, C.float(tolerance)) // fmt.Println("pos----", pos) @@ -1127,39 +1186,6 @@ func DecodeImg(path string) (image.Image, string, error) { return imgo.DecodeFile(path) } -// ByteToImg convert []byte to image.Image -func ByteToImg(b []byte) (image.Image, error) { - img, _, err := image.Decode(bytes.NewReader(b)) - return img, err -} - -// ToImage convert C.MMBitmapRef to standard image.Image -func ToImage(bit C.MMBitmapRef) image.Image { - bmp1 := ToBitmap(bit) - img1 := image.NewRGBA(image.Rect(0, 0, bmp1.Width, bmp1.Height)) - img1.Pix = make([]uint8, bmp1.Bytewidth*bmp1.Height) - - copyToVUint8A(img1.Pix, bmp1.ImgBuf) - img1.Stride = bmp1.Bytewidth - return img1 -} - -func val(p *uint8, n int) uint8 { - addr := uintptr(unsafe.Pointer(p)) - addr += uintptr(n) - p1 := (*uint8)(unsafe.Pointer(addr)) - return *p1 -} - -func copyToVUint8A(dst []uint8, src *uint8) { - for i := 0; i < len(dst)-4; i += 4 { - dst[i] = val(src, i+2) - dst[i+1] = val(src, i+1) - dst[i+2] = val(src, i) - dst[i+3] = val(src, i+3) - } -} - // OpenImg open the image return []byte func OpenImg(path string) ([]byte, error) { return imgo.ImgToBytes(path) From 0ad9a5bbb9fdd85d6c7a60db8177408aa7213e3f Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sat, 5 Jun 2021 12:34:51 -0400 Subject: [PATCH 059/327] update dockerfile and appveyor.yml --- .circleci/images/primary/Dockerfile | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index 36809f39..f193510c 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.16.4-stretch AS build +FROM golang:1.16.5-stretch AS build # FROM govgo/go:1.11.1 RUN apt update && apt install -y --no-install-recommends \ diff --git a/appveyor.yml b/appveyor.yml index acf4b46c..746d371f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,7 +34,7 @@ environment: PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% # - COMPILER: MINGW_W64 # ARCHITECTURE: x64 - GOVERSION: 1.16.4 + GOVERSION: 1.16.5 # GOPATH: c:\gopath # scripts that run after cloning repository From 1a59ed4cc17d8d02133cad69b0071d60b1baf120 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 9 Jun 2021 12:18:45 -0400 Subject: [PATCH 060/327] update gops to v0.20.0 and other mod pkg --- go.mod | 7 ++----- go.sum | 27 ++++++++++++++------------- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/go.mod b/go.mod index bc509974..0e7fd613 100644 --- a/go.mod +++ b/go.mod @@ -1,21 +1,18 @@ module github.com/go-vgo/robotgo require ( - github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/go-ole/go-ole v1.2.5 // indirect github.com/lxn/win v0.0.0-20210218163916-a377121e959e github.com/otiai10/curr v1.0.0 // indirect github.com/otiai10/gosseract v2.2.1+incompatible github.com/robotn/gohook v0.30.5 github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 - github.com/vcaesar/gops v0.10.2 + github.com/vcaesar/gops v0.20.0 github.com/vcaesar/imgo v0.12.1 github.com/vcaesar/tt v0.11.0 - golang.org/x/image v0.0.0-20210504121937-7319ad40d33e + golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9 golang.org/x/net v0.0.0-20201110031124-69a78807bb2b // indirect - golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea // indirect ) // replace golang.org/x/sys => github.com/golang/sys v0.0.0-20190109145017-48ac38b7c8cb diff --git a/go.sum b/go.sum index b80b383a..f6b941f6 100644 --- a/go.sum +++ b/go.sum @@ -1,12 +1,10 @@ github.com/BurntSushi/freetype-go v0.0.0-20160129220410-b763ddbfe298/go.mod h1:D+QujdIlUNfa0igpNMk6UIvlb6C252URs4yupRUV4lQ= github.com/BurntSushi/graphics-go v0.0.0-20160129215708-b43f31a4a966/go.mod h1:Mid70uvE93zn9wgF92A/r5ixgnvX8Lh68fxp9KQBaI0= -github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 h1:5sXbqlSomvdjlRbWyNqkPsJ3Fg+tQZCbgeX1VGljbQY= github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY= github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/lxn/win v0.0.0-20210218163916-a377121e959e h1:H+t6A/QJMbhCSEH5rAuRxh+CtW96g0Or0Fxa9IKr4uc= @@ -26,15 +24,17 @@ github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 h1:2lhSR8N3T6I30q096DT7 github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934/go.mod h1:SxQhJskUJ4rleVU44YvnrdvxQr0tKy5SRSigBrCgyyQ= github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 h1:2uX8QRLkkxn2EpAQ6I3KhA79BkdRZfvugJUzJadiJwk= github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770/go.mod h1:svkDXUDQjUiWzLrA0OZgHc4lbOts3C+uRfP6/yjwYnU= -github.com/shirou/gopsutil v2.19.11+incompatible h1:lJHR0foqAjI4exXqWsU3DbH7bX1xvdhGdnXTIARA9W4= -github.com/shirou/gopsutil v2.19.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 h1:udFKJ0aHUL60LboW/A+DfgoHVedieIzIXE8uylPue0U= -github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc= +github.com/shirou/gopsutil v3.21.5+incompatible h1:OloQyEerMi7JUrXiNzy8wQ5XN+baemxSl12QgIzt0jc= +github.com/shirou/gopsutil v3.21.5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/vcaesar/gops v0.10.2 h1:agDWYawurQVqyV0bcGf/6xgM5VFq0/pmlLTgAhC2yD0= -github.com/vcaesar/gops v0.10.2/go.mod h1:C5OfFWnxVszWFHpqE63qRc9mqmEPcFtQKKOpw0h22G0= +github.com/tklauser/go-sysconf v0.3.6 h1:oc1sJWvKkmvIxhDHeKWvZS4f6AW+YcoguSfRF2/Hmo4= +github.com/tklauser/go-sysconf v0.3.6/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= +github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= +github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= +github.com/vcaesar/gops v0.20.0 h1:SqP/rzDJh7Dy4/Obrjqv+ZftUig+b46BECj9cQ1mCTw= +github.com/vcaesar/gops v0.20.0/go.mod h1:EvpOHW7re4rBSzI1B/Rly0CxfT7C9lLo7Rpgs6IVpF0= github.com/vcaesar/imgo v0.12.1 h1:/mmZPL0CQwXtdr73ouoCu8Z9gmfmdgaFYoG0YSZ1gdU= github.com/vcaesar/imgo v0.12.1/go.mod h1:MwS4X0FXkLxshu8jMrHCLEM0S6JOQ6lU3drq5nO9AdE= github.com/vcaesar/tt v0.11.0 h1:obQecjgbnAxxC6OYGY6yDvhGRW2PR5wD8Ma2uJH3WGA= @@ -42,8 +42,8 @@ github.com/vcaesar/tt v0.11.0/go.mod h1:GHPxQYhn+7OgKakRusH7KJ0M5MhywoeLb8Fcffs/ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20210504121937-7319ad40d33e h1:PzJMNfFQx+QO9hrC1GwZ4BoPGeNGhfeQEgcQFArEjPk= -golang.org/x/image v0.0.0-20210504121937-7319ad40d33e/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9 h1:D0iM1dTCbD5Dg1CbuvLC/v/agLc79efSj/L35Q3Vqhs= +golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -52,11 +52,12 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea h1:+WiDlPBBaO+h9vPNZi8uJ3k4BkKQB7Iow3aqwHVA5hI= -golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210608053332-aa57babbf139 h1:C+AwYEtBp/VQwoLntUmQ/yx3MS9vmZaKNdw5eOpoQe8= +golang.org/x/sys v0.0.0-20210608053332-aa57babbf139/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 8d3cb6a6e00da32c90f1deccdc5f6fbb053c8bca Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 10 Jun 2021 13:22:16 -0400 Subject: [PATCH 061/327] update gohook fixed warning --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 0e7fd613..0748ca52 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ require ( github.com/lxn/win v0.0.0-20210218163916-a377121e959e github.com/otiai10/curr v1.0.0 // indirect github.com/otiai10/gosseract v2.2.1+incompatible - github.com/robotn/gohook v0.30.5 + github.com/robotn/gohook v0.30.6 github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 github.com/vcaesar/gops v0.20.0 diff --git a/go.sum b/go.sum index f6b941f6..0c8e38fe 100644 --- a/go.sum +++ b/go.sum @@ -18,8 +18,8 @@ github.com/otiai10/mint v1.3.0 h1:Ady6MKVezQwHBkGzLFbrsywyp09Ah7rkmfjV3Bcr5uc= github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/robotn/gohook v0.30.5 h1:yECDQXcKUcMxYLzPWBEKaHNiNss6lLq15RrgouDCKw4= -github.com/robotn/gohook v0.30.5/go.mod h1:FXryR68cDIho8rjE7MKxt4n4aK2FBqp+d/0HK4oiGP8= +github.com/robotn/gohook v0.30.6 h1:hH2KzyRsThtOqQ4M2ZPiOaib4vx70pz1DqgrBm26vPk= +github.com/robotn/gohook v0.30.6/go.mod h1:FXryR68cDIho8rjE7MKxt4n4aK2FBqp+d/0HK4oiGP8= github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 h1:2lhSR8N3T6I30q096DT7/5AKEIcf1vvnnWAmS0wfnNY= github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934/go.mod h1:SxQhJskUJ4rleVU44YvnrdvxQr0tKy5SRSigBrCgyyQ= github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 h1:2uX8QRLkkxn2EpAQ6I3KhA79BkdRZfvugJUzJadiJwk= From 2a8a0e9d92cb5160b9a897bf4db5f047410034ce Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 13 Jul 2021 13:06:00 -0400 Subject: [PATCH 062/327] update dockerfile and appveyor.yml --- .circleci/images/primary/Dockerfile | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index f193510c..25cebaed 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.16.5-stretch AS build +FROM golang:1.16.6-stretch AS build # FROM govgo/go:1.11.1 RUN apt update && apt install -y --no-install-recommends \ diff --git a/appveyor.yml b/appveyor.yml index 746d371f..e7c71e3b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,7 +34,7 @@ environment: PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% # - COMPILER: MINGW_W64 # ARCHITECTURE: x64 - GOVERSION: 1.16.5 + GOVERSION: 1.16.6 # GOPATH: c:\gopath # scripts that run after cloning repository From 7bbc39e9758945d2d216a33439ed1a2d8382c746 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 20 Jul 2021 11:45:50 -0400 Subject: [PATCH 063/327] add more bitmap examples --- examples/bitmap/main.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/examples/bitmap/main.go b/examples/bitmap/main.go index adaf3293..be1dee62 100644 --- a/examples/bitmap/main.go +++ b/examples/bitmap/main.go @@ -132,6 +132,12 @@ func bitmapTest(bmp robotgo.CBitmap) { fx, fy = robotgo.FindBitmap(bit) fmt.Println("FindBitmap------", fx, fy) + + fx, fy = robotgo.FindBitmap(bit, nil, 0.2) + fmt.Println("find bitmap: ", fx, fy) + + fx, fy = robotgo.FindBitmap(bit, bitmap, 0.3) + fmt.Println("find bitmap: ", fx, fy) } func findBitmap(bmp robotgo.CBitmap) { From d008e6aa253cf2361d8149e93b3f5ac016e73485 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 26 Jul 2021 13:38:55 -0400 Subject: [PATCH 064/327] Update clipboard example code --- clipboard/example/example.go | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/clipboard/example/example.go b/clipboard/example/example.go index f29304e0..3b6cb377 100644 --- a/clipboard/example/example.go +++ b/clipboard/example/example.go @@ -7,14 +7,19 @@ import ( ) func main() { - clipboard.WriteAll("日本語") + err := clipboard.WriteAll("日本語") + if err != nil { + log.Println("clipboard write all error: ", err) + } + text, err := clipboard.ReadAll() if err != nil { log.Println("clipboard read all error: ", err) - } else { - if text != "" { - log.Println("text is: ", text) - // Output: 日本語 - } + return + } + + if text != "" { + log.Println("text is: ", text) + // Output: 日本語 } } From 3dba431fcd8c97d4658a61c7198c33587818536c Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 29 Jul 2021 11:54:29 -0400 Subject: [PATCH 065/327] add mac os M1 support --- .gitignore | 2 ++ cdeps/mac/{ => amd}/libpng.a | Bin cdeps/mac/m1/libpng.a | Bin 0 -> 258360 bytes robotgo.go | 3 ++- 4 files changed, 4 insertions(+), 1 deletion(-) rename cdeps/mac/{ => amd}/libpng.a (100%) create mode 100644 cdeps/mac/m1/libpng.a diff --git a/.gitignore b/.gitignore index d561f40f..e301e5c1 100644 --- a/.gitignore +++ b/.gitignore @@ -56,6 +56,8 @@ vendor # ## *.a !cdeps/mac/libpng.a +!cdeps/mac/amd/libpng.a +!cdeps/mac/m1/libpng.a !cdeps/win32/libpng.a !cdeps/win64/libpng.a # diff --git a/cdeps/mac/libpng.a b/cdeps/mac/amd/libpng.a similarity index 100% rename from cdeps/mac/libpng.a rename to cdeps/mac/amd/libpng.a diff --git a/cdeps/mac/m1/libpng.a b/cdeps/mac/m1/libpng.a new file mode 100644 index 0000000000000000000000000000000000000000..ce2fd03eb76a47c4b39a4a3f512b84c3df49b81a GIT binary patch literal 258360 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

$%_QGS`Wd8QKd&W7> z>5NyS`=gd8GrH$m)<>Uuw(fSdSUp*bU2VHK`?`y>ud-h+BOG4z`-$w2W8Yo}W5+t? zslD#87rJKrD8U|2|>b#Ru)5B z)uY4pYOkKG8M$dA5?Q`)Ms1c@0XYQ zl(^2j$VuD5=y`~Gk2K4k;B+--Lk{mC&vzugDjVl-JFN6M>}hGsVcopydKdC!{hU3f zp&9ILq`tRP-!jh@z9RcpSxc&*{F0|LA0W+C=U#Y>=EIjvJ<(tIlHF|y-G$U~LiHPr z(G-7-!Mo7$zIm9tt$di+n=R~dG2Ry*Ll4cDF`IgB5<$i?JD95|yPAB{Z)${=bcbRO z>{aXn@a?2@?SB=v4dXoN6zp}}&EJRgzn47IazAvXBwb4Qc}7j5yRGIY#RZ4iYqRc? z!nPX1Jj35~cS_Q4JyUb1x`!qGD&a)Ny3br~y{@6v9{QViT`ARX@JE+O1=SBvDb_D@wx=`03-vEQ~5`wwN*_53Z{Gpcqc z6m0%Mg6bE2>&B1ddu#3j`fBWo?eRT+V2||MbD8IqY^mR!W8{ zG2djoQ}M?_`as=>RNO56p}r3x;}X^xg?9EmNFO9+TZK)Sxm&DtLn+5F_HF-S%hMTi zud~(-XTSOf)1S`ROc`@VJe{$R^1q3k&i6b#yPC3#yV&Hcp1vUQCDc_sWo?`z>509B z3hcMey%pJzUJ~hwd>3^8)f`!WjOL;Ik1oZd!&CXq%-Jb}Z;Q3#9OIar4<7po^TdYG zNEdxpjN33*PhBqIc_tX={g}NCrSgn8&xfp!KF^#pdY`bgH_3ks&+ZnUU7_3gW~29y zXQ*d8x(!P?Cv#?DHRplv;5=~S<1aH8ulOe=6UHEQlxOY)-G*|uG-O1}C5O2+wmZ|r z?rG9s#+JyUfqAx?iz1Ul#Fw~LTN*P~e)v~&HWSwAw`6@m`a`GwuC}i{zPP zV~lqeT>4{KE7$Le`1{kP?tR!QNnqZzf>-sW zzY_lmjJu={m$+TXM&`~7_@)c5Nja&O%=tc&`JM_x+KHq+U&dX8PaL}7?F8O|7dVqN znRs^)uW`^FNt20(T@MxSDg4iQ65eL+_jWE}77}JM{7B!nV9>&(T%E@b;l<_TL)r@n zE4*MoBxy2pW#&L1CDG?+Ti7&$|AqWD@-A3CI)H7J#OiOm5*MDh@0t61d5%B2@7wot zrt`*MK+kojR3G|rW5!KCY07xlHN1KO_hRo1+t5jqvF&u;GxVV3{UUw8Q%1&fI})Y8 zg7=){l7=qEd`S`q-i7ZZ;z^qk+s)Fp#XkX_Wu77KZumU!Nql=@Xk~sfHl;)^KVn|+ zZCBFg@;F8DIJCMN9+Szh8Xl8aTS(#^$r=HCCS9m7e2RU84Qtk8egZ2BRcq=hS70zKOZO2d$u0)9#)^x567s&!zic2 z1jKr=+mNlTP~?a;4>90TvkE17j^zexb=CUyVhUq^N%10U`37w>1aC2sp}16bFO+&M z;mZH9^Y1NM&N{tu{hIKC3F%tf&h` z`_xvh+fW5_*ae{&8_)1Bj`^aeWe*H%SVRX&8l4JUw7We8>T z8&c(Ul~X7Xjb%NySE?SYLg-H5nu^+r)s

V;MF)>Z}cG&_%X(#TsSp11^<*L%%W| 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 nS#Z@@5%Sf~LiAQy+R@O!z9;R73Yp57eq Date: Sat, 7 Aug 2021 14:00:23 -0400 Subject: [PATCH 066/327] update dockerfile and appveyor.yml --- .circleci/images/primary/Dockerfile | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index 25cebaed..157b439f 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.16.6-stretch AS build +FROM golang:1.16.7-stretch AS build # FROM govgo/go:1.11.1 RUN apt update && apt install -y --no-install-recommends \ diff --git a/appveyor.yml b/appveyor.yml index e7c71e3b..fabe54a8 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,7 +34,7 @@ environment: PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% # - COMPILER: MINGW_W64 # ARCHITECTURE: x64 - GOVERSION: 1.16.6 + GOVERSION: 1.16.7 # GOPATH: c:\gopath # scripts that run after cloning repository From 7b5dd14927d9020045c48d63d9a5ae4832919711 Mon Sep 17 00:00:00 2001 From: hi20160616 <74967912+hi20160616@users.noreply.github.com> Date: Tue, 17 Aug 2021 23:56:38 +0800 Subject: [PATCH 067/327] Update README.md Section ####Other to windows (#348) * Update README.md section Ubuntu I'd try and pass test for cross-compile on ubuntu to windows i386 and x86_64, my case: https://github.com/hi20160616/robotclick/blob/main/.github/workflows/goreleaser.yml I dig and read many issues here, and collect the right way to cross-compile for windows binary. I think it will help someone like me to fix bugs while cross compile. like error `zlib.h cannot find out` usually because of we installed it via source, that not useful on **mingw-w64**. I also suggest this update to let newbee easy to use this grand code. * Update README.md section #### Other to windows I'd try and pass test for cross-compile on ubuntu to windows i386 and x86_64, my case: https://github.com/hi20160616/robotclick/blob/main/.github/workflows/goreleaser.yml. I dig and read many issues here, and collect the right way to cross-compile for windows binary. I think it will help someone like me to fix bugs while cross compile. like error `zlib.h cannot find out` usually because of we installed it via source, that not useful on **mingw-w64**. I also suggest this update to let newbee easy to use this grand code. --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 9d5ef100..fa9aed52 100644 --- a/README.md +++ b/README.md @@ -330,6 +330,14 @@ go build main.go ``` #### Other to windows +Install Requirements: +```bash +sudo apt-get install gcc-multilib +sudo apt-get install gcc-mingw-w64 +# fix err: zlib.h: No such file or directory +sudo apt-get install libz-mingw-w64-dev +``` +Build the binary: ```Go GOOS=windows GOARCH=amd64 CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ go build -x ./ ``` From 2daa5b775eeeb6da5c750911c19d115aa46aa406 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 17 Aug 2021 12:29:01 -0400 Subject: [PATCH 068/327] Update README.md --- README.md | 13 ++++++++----- README_zh.md | 13 ++++++++++++- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index fa9aed52..d3eaad25 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ sudo apt install libxkbcommon-dev sudo apt install xsel xclip ``` -#### Fedora: +##### Fedora: ```yml sudo dnf install libxkbcommon-devel libXtst-devel libxkbcommon-x11-devel xorg-x11-xkb-utils-devel @@ -330,17 +330,20 @@ go build main.go ``` #### Other to windows -Install Requirements: + +##### Install Requirements (Ubuntu): ```bash -sudo apt-get install gcc-multilib -sudo apt-get install gcc-mingw-w64 +sudo apt install gcc-multilib +sudo apt install gcc-mingw-w64 # fix err: zlib.h: No such file or directory -sudo apt-get install libz-mingw-w64-dev +sudo apt install libz-mingw-w64-dev ``` + Build the binary: ```Go GOOS=windows GOARCH=amd64 CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ go build -x ./ ``` + ``` // CC=mingw-w64\x86_64-7.2.0-win32-seh-rt_v5-rev1\mingw64\bin\gcc.exe // CXX=mingw-w64\x86_64-7.2.0-win32-seh-rt_v5-rev1\mingw64\bin\g++.exe diff --git a/README_zh.md b/README_zh.md index 760990b4..8bba16b7 100644 --- a/README_zh.md +++ b/README_zh.md @@ -88,7 +88,7 @@ sudo apt install xsel xclip ``` -#### Fedora: +##### Fedora: ```yml sudo dnf install libxkbcommon-devel libXtst-devel libxkbcommon-x11-devel xorg-x11-xkb-utils-devel @@ -327,9 +327,20 @@ go build main.go ``` #### Other to windows + +##### Install Requirements (Ubuntu): +```bash +sudo apt install gcc-multilib +sudo apt install gcc-mingw-w64 +sudo apt install libz-mingw-w64-dev +``` + +##### Build the binary: + ```Go GOOS=windows GOARCH=amd64 CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ go build -x ./ ``` + ``` // CC=mingw-w64\x86_64-7.2.0-win32-seh-rt_v5-rev1\mingw64\bin\gcc.exe // CXX=mingw-w64\x86_64-7.2.0-win32-seh-rt_v5-rev1\mingw64\bin\g++.exe From 4fcd79c2084b289b6e74d6f96c168fca4a6be322 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 17 Aug 2021 12:32:26 -0400 Subject: [PATCH 069/327] Update Dockerfile and go.yml --- .circleci/images/primary/Dockerfile | 2 +- .github/workflows/go.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index 157b439f..353ff278 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.16.7-stretch AS build +FROM golang:1.7-stretch AS build # FROM govgo/go:1.11.1 RUN apt update && apt install -y --no-install-recommends \ diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index b3fc8af0..0f509b14 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -10,10 +10,10 @@ jobs: runs-on: ${{ matrix.os }} steps: - - name: Set up Go 1.16 + - name: Set up Go 1.17 uses: actions/setup-go@v1 with: - go-version: 1.16 + go-version: 1.17 id: go - name: Check out code into the Go module directory From 9b1346d066fa3a3beabb1a04beaabeb2b47ddc83 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 17 Aug 2021 13:01:21 -0400 Subject: [PATCH 070/327] add windows arm support --- .gitignore | 4 ++++ base/png_io_c.h | 4 ++-- cdeps/{ => win/amd}/win32/libpng.a | Bin cdeps/{ => win/amd}/win32/png.h | 0 cdeps/{ => win/amd}/win32/pngconf.h | 0 cdeps/{ => win/amd}/win32/pnglibconf.h | 0 cdeps/{ => win/amd}/win32/zconf.h | 0 cdeps/{ => win/amd}/win32/zlib.h | 0 cdeps/{ => win/amd}/win64/libpng.a | Bin cdeps/{ => win/amd}/win64/png.h | 0 cdeps/{ => win/amd}/win64/pngconf.h | 0 cdeps/{ => win/amd}/win64/pnglibconf.h | 0 cdeps/{ => win/amd}/win64/zconf.h | 0 cdeps/{ => win/amd}/win64/zlib.h | 0 robotgo.go | 5 +++-- 15 files changed, 9 insertions(+), 4 deletions(-) rename cdeps/{ => win/amd}/win32/libpng.a (100%) rename cdeps/{ => win/amd}/win32/png.h (100%) rename cdeps/{ => win/amd}/win32/pngconf.h (100%) rename cdeps/{ => win/amd}/win32/pnglibconf.h (100%) rename cdeps/{ => win/amd}/win32/zconf.h (100%) rename cdeps/{ => win/amd}/win32/zlib.h (100%) rename cdeps/{ => win/amd}/win64/libpng.a (100%) rename cdeps/{ => win/amd}/win64/png.h (100%) rename cdeps/{ => win/amd}/win64/pngconf.h (100%) rename cdeps/{ => win/amd}/win64/pnglibconf.h (100%) rename cdeps/{ => win/amd}/win64/zconf.h (100%) rename cdeps/{ => win/amd}/win64/zlib.h (100%) diff --git a/.gitignore b/.gitignore index e301e5c1..9c73dc21 100644 --- a/.gitignore +++ b/.gitignore @@ -58,8 +58,12 @@ vendor !cdeps/mac/libpng.a !cdeps/mac/amd/libpng.a !cdeps/mac/m1/libpng.a +# !cdeps/win32/libpng.a !cdeps/win64/libpng.a +!cdeps/win/amd/win32/libpng.a +!cdeps/win/amd/win64/libpng.a +!cdeps/win/arm/libpng.a # *.la *.lo diff --git a/base/png_io_c.h b/base/png_io_c.h index 5aab25f2..0ce05410 100644 --- a/base/png_io_c.h +++ b/base/png_io_c.h @@ -7,9 +7,9 @@ #include #elif defined(IS_WINDOWS) #if defined (__x86_64__) - #include "../cdeps/win64/png.h" + #include "../cdeps/amd/win64/png.h" #else - #include "../cdeps/win32/png.h" + #include "../cdeps/amd/win32/png.h" #endif #endif diff --git a/cdeps/win32/libpng.a b/cdeps/win/amd/win32/libpng.a similarity index 100% rename from cdeps/win32/libpng.a rename to cdeps/win/amd/win32/libpng.a diff --git a/cdeps/win32/png.h b/cdeps/win/amd/win32/png.h similarity index 100% rename from cdeps/win32/png.h rename to cdeps/win/amd/win32/png.h diff --git a/cdeps/win32/pngconf.h b/cdeps/win/amd/win32/pngconf.h similarity index 100% rename from cdeps/win32/pngconf.h rename to cdeps/win/amd/win32/pngconf.h diff --git a/cdeps/win32/pnglibconf.h b/cdeps/win/amd/win32/pnglibconf.h similarity index 100% rename from cdeps/win32/pnglibconf.h rename to cdeps/win/amd/win32/pnglibconf.h diff --git a/cdeps/win32/zconf.h b/cdeps/win/amd/win32/zconf.h similarity index 100% rename from cdeps/win32/zconf.h rename to cdeps/win/amd/win32/zconf.h diff --git a/cdeps/win32/zlib.h b/cdeps/win/amd/win32/zlib.h similarity index 100% rename from cdeps/win32/zlib.h rename to cdeps/win/amd/win32/zlib.h diff --git a/cdeps/win64/libpng.a b/cdeps/win/amd/win64/libpng.a similarity index 100% rename from cdeps/win64/libpng.a rename to cdeps/win/amd/win64/libpng.a diff --git a/cdeps/win64/png.h b/cdeps/win/amd/win64/png.h similarity index 100% rename from cdeps/win64/png.h rename to cdeps/win/amd/win64/png.h diff --git a/cdeps/win64/pngconf.h b/cdeps/win/amd/win64/pngconf.h similarity index 100% rename from cdeps/win64/pngconf.h rename to cdeps/win/amd/win64/pngconf.h diff --git a/cdeps/win64/pnglibconf.h b/cdeps/win/amd/win64/pnglibconf.h similarity index 100% rename from cdeps/win64/pnglibconf.h rename to cdeps/win/amd/win64/pnglibconf.h diff --git a/cdeps/win64/zconf.h b/cdeps/win/amd/win64/zconf.h similarity index 100% rename from cdeps/win64/zconf.h rename to cdeps/win/amd/win64/zconf.h diff --git a/cdeps/win64/zlib.h b/cdeps/win/amd/win64/zlib.h similarity index 100% rename from cdeps/win64/zlib.h rename to cdeps/win/amd/win64/zlib.h diff --git a/robotgo.go b/robotgo.go index 873ff69c..861119bc 100644 --- a/robotgo.go +++ b/robotgo.go @@ -37,8 +37,9 @@ package robotgo //#endif // #cgo windows LDFLAGS: -lgdi32 -luser32 -lpng -lz #cgo windows LDFLAGS: -lgdi32 -luser32 - #cgo windows,amd64 LDFLAGS: -L${SRCDIR}/cdeps/win64 -lpng -lz - #cgo windows,386 LDFLAGS: -L${SRCDIR}/cdeps/win32 -lpng -lz + #cgo windows,amd64 LDFLAGS: -L${SRCDIR}/cdeps/win/amd/win64 -lpng -lz + #cgo windows,386 LDFLAGS: -L${SRCDIR}/cdeps/win/amd/win32 -lpng -lz + #cgo windows,arm64 LDFLAGS:-L${SRCDIR}/cdeps/win/arm -lpng -lz // #include #include "screen/goScreen.h" #include "mouse/goMouse.h" From b99994998deb20cf06a93d8aec633ff15c97e42b Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 17 Aug 2021 13:09:25 -0400 Subject: [PATCH 071/327] Update png.h path --- base/png_io_c.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/png_io_c.h b/base/png_io_c.h index 0ce05410..9609e283 100644 --- a/base/png_io_c.h +++ b/base/png_io_c.h @@ -7,9 +7,9 @@ #include #elif defined(IS_WINDOWS) #if defined (__x86_64__) - #include "../cdeps/amd/win64/png.h" + #include "../cdeps/win/amd/win64/png.h" #else - #include "../cdeps/amd/win32/png.h" + #include "../cdeps/win/amd/win32/png.h" #endif #endif From 450feedc11d583521e20e0abca61200baac22eee Mon Sep 17 00:00:00 2001 From: "Sean E. Russell" Date: Wed, 18 Aug 2021 16:11:05 -0500 Subject: [PATCH 072/327] This fixes #351 --- robotgo.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/robotgo.go b/robotgo.go index 861119bc..95e35dd1 100644 --- a/robotgo.go +++ b/robotgo.go @@ -738,6 +738,9 @@ func toUC(text string) []string { textUnQ := textQ[1 : len(textQ)-1] st := strings.Replace(textUnQ, "\\u", "U", -1) + if st == "\\\\" { + st = "\\" + } uc = append(uc, st) } From 45251144e506c053a312127b031943ee99649365 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 19 Aug 2021 14:03:11 -0400 Subject: [PATCH 073/327] Export ToUC function and update test code --- robotgo.go | 7 ++++--- robotgo_test.go | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/robotgo.go b/robotgo.go index 95e35dd1..f6bf0dde 100644 --- a/robotgo.go +++ b/robotgo.go @@ -75,7 +75,7 @@ import ( const ( // Version get the robotgo version - Version = "v0.93.1.1189, MT. Rainier!" + Version = "v0.99.1.1189, MT. Rainier!" ) // GetVersion get the robotgo version @@ -730,7 +730,8 @@ func UnicodeType(str uint32) { C.unicodeType(cstr) } -func toUC(text string) []string { +// ToUC trans string to unicode []string +func ToUC(text string) []string { var uc []string for _, r := range text { @@ -768,7 +769,7 @@ func TypeStr(str string, args ...float64) { } if runtime.GOOS == "linux" { - strUc := toUC(str) + strUc := ToUC(str) for i := 0; i < len(strUc); i++ { ru := []rune(strUc[i]) if len(ru) <= 1 { diff --git a/robotgo_test.go b/robotgo_test.go index 34f0500e..cce772aa 100644 --- a/robotgo_test.go +++ b/robotgo_test.go @@ -126,8 +126,9 @@ func TestTypeStr(t *testing.T) { e := PasteStr("s") tt.Empty(t, e) - uc := toUC("s") - tt.Equal(t, "[s]", uc) + s1 := "abc\\\\cd/s@世界" + uc := ToUC(s1) + tt.Equal(t, "[a b c \\ \\ c d / s @ U4e16 U754c]", uc) } func TestKeyCode(t *testing.T) { From a38bb946c16428113ae25e9d7c0985517135e133 Mon Sep 17 00:00:00 2001 From: "Sean E. Russell" Date: Thu, 19 Aug 2021 13:28:02 -0500 Subject: [PATCH 074/327] Fixes #258: char* arrays in C not being copied correctly --- window/window.h | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/window/window.h b/window/window.h index 6293ca92..fcf1a6e8 100644 --- a/window/window.h +++ b/window/window.h @@ -646,7 +646,15 @@ char* get_title_by_hand(MData m_data){ // Check result value if (result != NULL) { // Convert result to a string - char *name = (char*)result; + char *name = (char*)calloc(strlen(result)+1, sizeof(char*)); + char *rptr = (char*)result; + char *nptr = name; + while (*rptr) { + *nptr = *rptr; + nptr++; + rptr++; + } + *nptr = '\0'; XFree(result); if (name != NULL) { return name; } @@ -658,8 +666,17 @@ char* get_title_by_hand(MData m_data){ // Check result value if (result != NULL) { // Convert result to a string - char *name = (char*)result; + char *name = (char*)calloc(strlen(result)+1, sizeof(char*)); + char *rptr = (char*)result; + char *nptr = name; + while (*rptr) { + *nptr = *rptr; + nptr++; + rptr++; + } + *nptr = '\0'; XFree(result); + return name; } From 422f8fdc88320db3d5223ccf7264f7b39abb6641 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sat, 21 Aug 2021 10:58:08 -0400 Subject: [PATCH 075/327] Fixed Linux TypeStr() function double quote --- robotgo.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/robotgo.go b/robotgo.go index f6bf0dde..c88163ca 100644 --- a/robotgo.go +++ b/robotgo.go @@ -742,6 +742,9 @@ func ToUC(text string) []string { if st == "\\\\" { st = "\\" } + if st == `\"` { + st = `"` + } uc = append(uc, st) } From a76997757bd7220366055bc20a0234aad849062a Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 22 Aug 2021 10:47:21 -0400 Subject: [PATCH 076/327] Update go mod --- go.mod | 8 ++++---- go.sum | 49 +++++++++++++++++++++++++------------------------ 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/go.mod b/go.mod index 0748ca52..a2717c63 100644 --- a/go.mod +++ b/go.mod @@ -5,13 +5,13 @@ require ( github.com/lxn/win v0.0.0-20210218163916-a377121e959e github.com/otiai10/curr v1.0.0 // indirect github.com/otiai10/gosseract v2.2.1+incompatible - github.com/robotn/gohook v0.30.6 + github.com/robotn/gohook v0.31.0 github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 - github.com/vcaesar/gops v0.20.0 - github.com/vcaesar/imgo v0.12.1 + github.com/vcaesar/gops v0.21.1 + github.com/vcaesar/imgo v0.12.2 github.com/vcaesar/tt v0.11.0 - golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9 + golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d golang.org/x/net v0.0.0-20201110031124-69a78807bb2b // indirect ) diff --git a/go.sum b/go.sum index 0c8e38fe..5972875e 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ github.com/BurntSushi/freetype-go v0.0.0-20160129220410-b763ddbfe298/go.mod h1:D+QujdIlUNfa0igpNMk6UIvlb6C252URs4yupRUV4lQ= github.com/BurntSushi/graphics-go v0.0.0-20160129215708-b43f31a4a966/go.mod h1:Mid70uvE93zn9wgF92A/r5ixgnvX8Lh68fxp9KQBaI0= -github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 h1:5sXbqlSomvdjlRbWyNqkPsJ3Fg+tQZCbgeX1VGljbQY= -github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= +github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -18,32 +18,32 @@ github.com/otiai10/mint v1.3.0 h1:Ady6MKVezQwHBkGzLFbrsywyp09Ah7rkmfjV3Bcr5uc= github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/robotn/gohook v0.30.6 h1:hH2KzyRsThtOqQ4M2ZPiOaib4vx70pz1DqgrBm26vPk= -github.com/robotn/gohook v0.30.6/go.mod h1:FXryR68cDIho8rjE7MKxt4n4aK2FBqp+d/0HK4oiGP8= +github.com/robotn/gohook v0.31.0 h1:gduiVso8bmSWO+k8Af/ehskIeKvd25PwuKt/nHK4+bk= +github.com/robotn/gohook v0.31.0/go.mod h1:FXryR68cDIho8rjE7MKxt4n4aK2FBqp+d/0HK4oiGP8= github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 h1:2lhSR8N3T6I30q096DT7/5AKEIcf1vvnnWAmS0wfnNY= github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934/go.mod h1:SxQhJskUJ4rleVU44YvnrdvxQr0tKy5SRSigBrCgyyQ= github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 h1:2uX8QRLkkxn2EpAQ6I3KhA79BkdRZfvugJUzJadiJwk= github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770/go.mod h1:svkDXUDQjUiWzLrA0OZgHc4lbOts3C+uRfP6/yjwYnU= -github.com/shirou/gopsutil v3.21.5+incompatible h1:OloQyEerMi7JUrXiNzy8wQ5XN+baemxSl12QgIzt0jc= -github.com/shirou/gopsutil v3.21.5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil v3.21.7+incompatible h1:g/wcPHcuCQvHSePVofjQljd2vX4ty0+J6VoMB+NPcdk= +github.com/shirou/gopsutil v3.21.7+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/tklauser/go-sysconf v0.3.6 h1:oc1sJWvKkmvIxhDHeKWvZS4f6AW+YcoguSfRF2/Hmo4= -github.com/tklauser/go-sysconf v0.3.6/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= -github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= -github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= -github.com/vcaesar/gops v0.20.0 h1:SqP/rzDJh7Dy4/Obrjqv+ZftUig+b46BECj9cQ1mCTw= -github.com/vcaesar/gops v0.20.0/go.mod h1:EvpOHW7re4rBSzI1B/Rly0CxfT7C9lLo7Rpgs6IVpF0= -github.com/vcaesar/imgo v0.12.1 h1:/mmZPL0CQwXtdr73ouoCu8Z9gmfmdgaFYoG0YSZ1gdU= -github.com/vcaesar/imgo v0.12.1/go.mod h1:MwS4X0FXkLxshu8jMrHCLEM0S6JOQ6lU3drq5nO9AdE= +github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/tklauser/go-sysconf v0.3.8 h1:41Nq9J+pxKud4IQ830J5LlS5nl67dVQC7AuisUooaOU= +github.com/tklauser/go-sysconf v0.3.8/go.mod h1:z4zYWRS+X53WUKtBcmDg1comV3fPhdQnzasnIHUoLDU= +github.com/tklauser/numcpus v0.2.3/go.mod h1:vpEPS/JC+oZGGQ/My/vJnNsvMDQL6PwOqt8dsCw5j+E= +github.com/tklauser/numcpus v0.3.0 h1:ILuRUQBtssgnxw0XXIjKUC56fgnOrFoQQ/4+DeU2biQ= +github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8= +github.com/vcaesar/gops v0.21.1 h1:a8ZCbho+K3RP1+hlkGCSWih84Iu3hjXYKwZW3970hkg= +github.com/vcaesar/gops v0.21.1/go.mod h1:upqQTBNSvazU+AvHwXY7VPdJscLoOqOxw+vkmJKnjEk= +github.com/vcaesar/imgo v0.12.2 h1:PvIcE/832kDyxou+sE8ClSqXoPVU9xEMY47ieICkWhg= +github.com/vcaesar/imgo v0.12.2/go.mod h1:eJscuTEdc6sVn/hZruy8kWi61xqKHLtbAYyPeYcn+t4= github.com/vcaesar/tt v0.11.0 h1:obQecjgbnAxxC6OYGY6yDvhGRW2PR5wD8Ma2uJH3WGA= github.com/vcaesar/tt v0.11.0/go.mod h1:GHPxQYhn+7OgKakRusH7KJ0M5MhywoeLb8Fcffs/Gtg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9 h1:D0iM1dTCbD5Dg1CbuvLC/v/agLc79efSj/L35Q3Vqhs= -golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d h1:RNPAfi2nHY7C2srAV8A49jpsYr0ADedCk1wq6fTMTvs= +golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -52,14 +52,15 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210608053332-aa57babbf139 h1:C+AwYEtBp/VQwoLntUmQ/yx3MS9vmZaKNdw5eOpoQe8= -golang.org/x/sys v0.0.0-20210608053332-aa57babbf139/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55 h1:rw6UNGRMfarCepjI8qOepea/SXwIBVfTKjztZ5gBbq4= +golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From 6724c74c7a166619a8b58ec5d51bd1ed7a6db345 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 22 Aug 2021 10:56:13 -0400 Subject: [PATCH 077/327] Update circle.yml and travis.yml --- .circleci/config.yml | 8 +++++++- .travis.yml | 3 ++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 963b3e33..54858e17 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -4,12 +4,18 @@ jobs: build: docker: # using custom image, see .circleci/images/primary/Dockerfile - - image: govgo/robotgoci:1.10.3 + # - image: govgo/robotgoci:1.10.3 + - image: golang:1.16.7 working_directory: /gopath/src/github.com/go-vgo/robotgo steps: - checkout # specify any bash command here prefixed with `run: ` - run: apt update + - run: apt -y install gcc libc6-dev + - run: apt -y install libx11-dev xorg-dev libxtst-dev libpng++-dev + - run: apt -y install xcb libxcb-xkb-dev x11-xkb-utils libx11-xcb-dev libxkbcommon-x11-dev + - run: apt -y install libxkbcommon-dev + - run: apt -y install xsel xclip - run: apt -y install xvfb # # override: diff --git a/.travis.yml b/.travis.yml index a251a09d..ca8107c7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,8 @@ go: # - 1.13.x # - 1.14.x # - 1.15.x - - 1.16.x + # - 1.16.x + - 1.17.x # - tip addons: From 9969a331a67bcd9469d8ce179116776bfacd068d Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 24 Aug 2021 12:17:03 -0400 Subject: [PATCH 078/327] Remove unless example code and update circle.yml --- .circleci/config.yml | 8 ++++---- examples/window/main.go | 4 ---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 54858e17..d1edb3e2 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -12,10 +12,10 @@ jobs: # specify any bash command here prefixed with `run: ` - run: apt update - run: apt -y install gcc libc6-dev - - run: apt -y install libx11-dev xorg-dev libxtst-dev libpng++-dev - - run: apt -y install xcb libxcb-xkb-dev x11-xkb-utils libx11-xcb-dev libxkbcommon-x11-dev - - run: apt -y install libxkbcommon-dev - - run: apt -y install xsel xclip + libx11-dev xorg-dev libxtst-dev libpng++-dev + xcb libxcb-xkb-dev x11-xkb-utils libx11-xcb-dev libxkbcommon-x11-dev + libxkbcommon-dev + xsel xclip - run: apt -y install xvfb # # override: diff --git a/examples/window/main.go b/examples/window/main.go index fb8bbb16..292ee35b 100644 --- a/examples/window/main.go +++ b/examples/window/main.go @@ -39,10 +39,6 @@ func get() { hwnd := robotgo.GetHandle() fmt.Println("hwnd---", hwnd) - // get current Window Handle - bhwnd := robotgo.GetBHandle() - fmt.Println("bhwnd---", bhwnd) - // get current Window title title := robotgo.GetTitle() fmt.Println("title-----", title) From f04e5bf6a3c79db4f043b654042b2931fed3b662 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Fri, 27 Aug 2021 12:51:57 -0400 Subject: [PATCH 079/327] Removed drop api example code and Update README.md --- README.md | 8 ++++---- README_zh.md | 10 +++++----- examples/README.md | 4 ++-- examples/key/main.go | 4 ++-- test/main.go | 4 ++-- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index d3eaad25..3de7f360 100644 --- a/README.md +++ b/README.md @@ -149,7 +149,7 @@ import ( func main() { robotgo.TypeStr("Hello World") robotgo.TypeStr("だんしゃり", 1.0) - // robotgo.TypeString("テストする") + // robotgo.TypeStr("テストする") robotgo.TypeStr("Hi galaxy. こんにちは世界.") robotgo.Sleep(1) @@ -158,7 +158,7 @@ func main() { // robotgo.UnicodeType(ustr) robotgo.KeyTap("enter") - // robotgo.TypeString("en") + // robotgo.TypeStr("en") robotgo.KeyTap("i", "alt", "command") arr := []string{"alt", "command"} @@ -322,7 +322,7 @@ func main() { ## CrossCompiling -##### Windows64 to win32 +##### Windows64 to windows32 ```Go SET CGO_ENABLED=1 SET GOARCH=386 @@ -331,7 +331,7 @@ go build main.go #### Other to windows -##### Install Requirements (Ubuntu): +Install Requirements (Ubuntu): ```bash sudo apt install gcc-multilib sudo apt install gcc-mingw-w64 diff --git a/README_zh.md b/README_zh.md index 8bba16b7..5938b4c2 100644 --- a/README_zh.md +++ b/README_zh.md @@ -147,7 +147,7 @@ import ( func main() { robotgo.TypeStr("Hello World. Winter is coming!") robotgo.TypeStr("だんしゃり", 1.0) - // robotgo.TypeString("テストする") + // robotgo.TypeStr("テストする") robotgo.TypeStr("Hi galaxy. こんにちは世界.") robotgo.Sleep(1) @@ -156,7 +156,7 @@ func main() { // robotgo.UnicodeType(ustr) robotgo.KeyTap("enter") - // robotgo.TypeString("en") + // robotgo.TypeStr("en") robotgo.KeyTap("i", "alt", "command") arr := []string{"alt", "command"} @@ -319,7 +319,7 @@ func main() { ## CrossCompiling -##### Windows64 to win32 +##### Windows64 to windows32 ```Go SET CGO_ENABLED=1 SET GOARCH=386 @@ -328,14 +328,14 @@ go build main.go #### Other to windows -##### Install Requirements (Ubuntu): +Install Requirements (Ubuntu): ```bash sudo apt install gcc-multilib sudo apt install gcc-mingw-w64 sudo apt install libz-mingw-w64-dev ``` -##### Build the binary: +Build the binary: ```Go GOOS=windows GOARCH=amd64 CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ go build -x ./ diff --git a/examples/README.md b/examples/README.md index 4692a6cb..e7ef0690 100644 --- a/examples/README.md +++ b/examples/README.md @@ -36,13 +36,13 @@ import ( func main() { robotgo.TypeStr("Hello World") - // robotgo.TypeString("だんしゃり") + // robotgo.TypeStr("だんしゃり") robotgo.TypeStr("だんしゃり") // ustr := uint32(robotgo.CharCodeAt("だんしゃり", 0)) // robotgo.UnicodeType(ustr) robotgo.KeyTap("enter") - robotgo.TypeString("en") + robotgo.TypeStr("en") robotgo.KeyTap("i", "alt", "command") arr := []string{"alt", "command"} robotgo.KeyTap("i", arr) diff --git a/examples/key/main.go b/examples/key/main.go index 1fe27fa4..1caec80f 100644 --- a/examples/key/main.go +++ b/examples/key/main.go @@ -26,7 +26,7 @@ func typeStr() { robotgo.TypeStr("Hi galaxy. こんにちは世界.") robotgo.Sleep(2) - // robotgo.TypeString("So, hi, bye!") + // robotgo.TypeStr("So, hi, bye!") robotgo.MilliSleep(100) ustr := uint32(robotgo.CharCodeAt("So, hi, bye!", 0)) @@ -86,7 +86,7 @@ func keyToggle() { } func cilp() { - // robotgo.TypeString("en") + // robotgo.TypeStr("en") // write string to clipboard e := robotgo.WriteAll("テストする") diff --git a/test/main.go b/test/main.go index 30e84064..4640216e 100644 --- a/test/main.go +++ b/test/main.go @@ -41,12 +41,12 @@ func aRobotgo() { color := robotgo.GetPixelColor(100, 200) fmt.Println("color@@@", color) - robotgo.TypeString("Hello World") + robotgo.TypeStr("Hello World") // robotgo.KeyTap("a", "control") robotgo.KeyTap("f1", "control") // robotgo.KeyTap("enter") // robotgo.KeyToggle("enter", "down") - robotgo.TypeString("en") + robotgo.TypeStr("en") abitmap := robotgo.CaptureScreen() fmt.Println("all...", abitmap) From c562426b5ebf3431766e46e618c7a6c7218db2e6 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 7 Sep 2021 12:44:31 -0400 Subject: [PATCH 080/327] add ToRGBA() function support --- robotgo.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/robotgo.go b/robotgo.go index c88163ca..0a80d3e9 100644 --- a/robotgo.go +++ b/robotgo.go @@ -983,6 +983,11 @@ func ByteToImg(b []byte) (image.Image, error) { // ToImage convert C.MMBitmapRef to standard image.Image func ToImage(bit C.MMBitmapRef) image.Image { + return ToRGBA(bit) +} + +// ToRGBA convert C.MMBitmapRef to standard image.RGBA +func ToRGBA(bit C.MMBitmapRef) *image.RGBA { bmp1 := ToBitmap(bit) img1 := image.NewRGBA(image.Rect(0, 0, bmp1.Width, bmp1.Height)) img1.Pix = make([]uint8, bmp1.Bytewidth*bmp1.Height) From debdcc31d8c720465e50b2fef39654f783a19db0 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 8 Sep 2021 13:13:23 -0400 Subject: [PATCH 081/327] add ImgToBitmap and RGBAToBitmap support --- go.mod | 2 +- go.sum | 4 ++-- img.go | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 img.go diff --git a/go.mod b/go.mod index a2717c63..73ae9f9f 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 github.com/vcaesar/gops v0.21.1 - github.com/vcaesar/imgo v0.12.2 + github.com/vcaesar/imgo v0.20.0 github.com/vcaesar/tt v0.11.0 golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d golang.org/x/net v0.0.0-20201110031124-69a78807bb2b // indirect diff --git a/go.sum b/go.sum index 5972875e..d0a7a739 100644 --- a/go.sum +++ b/go.sum @@ -36,8 +36,8 @@ github.com/tklauser/numcpus v0.3.0 h1:ILuRUQBtssgnxw0XXIjKUC56fgnOrFoQQ/4+DeU2bi github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8= github.com/vcaesar/gops v0.21.1 h1:a8ZCbho+K3RP1+hlkGCSWih84Iu3hjXYKwZW3970hkg= github.com/vcaesar/gops v0.21.1/go.mod h1:upqQTBNSvazU+AvHwXY7VPdJscLoOqOxw+vkmJKnjEk= -github.com/vcaesar/imgo v0.12.2 h1:PvIcE/832kDyxou+sE8ClSqXoPVU9xEMY47ieICkWhg= -github.com/vcaesar/imgo v0.12.2/go.mod h1:eJscuTEdc6sVn/hZruy8kWi61xqKHLtbAYyPeYcn+t4= +github.com/vcaesar/imgo v0.20.0 h1:lX7a2vygTri0Z3VYpwoQA2LPvbphFyT5ON4NTqdC4wQ= +github.com/vcaesar/imgo v0.20.0/go.mod h1:eJscuTEdc6sVn/hZruy8kWi61xqKHLtbAYyPeYcn+t4= github.com/vcaesar/tt v0.11.0 h1:obQecjgbnAxxC6OYGY6yDvhGRW2PR5wD8Ma2uJH3WGA= github.com/vcaesar/tt v0.11.0/go.mod h1:GHPxQYhn+7OgKakRusH7KJ0M5MhywoeLb8Fcffs/Gtg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= diff --git a/img.go b/img.go new file mode 100644 index 00000000..c526ae3a --- /dev/null +++ b/img.go @@ -0,0 +1,63 @@ +// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// https://github.com/go-vgo/robotgo/blob/master/LICENSE +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +package robotgo + +import ( + "image" + "unsafe" + + "github.com/vcaesar/imgo" +) + +// RGBAToBitmap convert the standard image.RGBA to Bitmap +func RGBAToBitmap(r1 *image.RGBA) (bit Bitmap) { + bit.Width = r1.Bounds().Size().X + bit.Height = r1.Bounds().Size().Y + bit.Bytewidth = r1.Stride + + src := ToUint8p(r1.Pix) + bit.ImgBuf = src + + bit.BitsPixel = 32 + bit.BytesPerPixel = 32 / 8 + + return +} + +// ImgToBitmap convert the standard image.Image to Bitmap +func ImgToBitmap(m image.Image) (bit Bitmap) { + bit.Width = m.Bounds().Size().X + bit.Height = m.Bounds().Size().Y + + pix, stride, _ := imgo.EncodeImg(m) + bit.Bytewidth = stride + + src := ToUint8p(pix) + bit.ImgBuf = src + // + bit.BitsPixel = 32 + bit.BytesPerPixel = 32 / 8 + return +} + +// ToUint8p convert the []uint8 to uint8 pointer +func ToUint8p(dst []uint8) *uint8 { + src := make([]uint8, len(dst)+10) + for i := 0; i < len(dst)-4; i += 4 { + src[i+3] = dst[i+3] + src[i] = dst[i+2] + src[i+1] = dst[i+1] + src[i+2] = dst[i] + } + + ptr := unsafe.Pointer(&src[0]) + return (*uint8)(ptr) +} From 3e402696be944d18582239ceb4fdafb592be585b Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 8 Sep 2021 13:28:42 -0400 Subject: [PATCH 082/327] Update and move image function to img.go --- README.md | 2 +- img.go | 66 ++++++++++++++++++++++++++++++++++++++++++++++ robotgo.go | 77 +----------------------------------------------------- 3 files changed, 68 insertions(+), 77 deletions(-) diff --git a/README.md b/README.md index 3de7f360..6e1e30e3 100644 --- a/README.md +++ b/README.md @@ -368,6 +368,6 @@ Some discussions and questions, please see [issues/228](https://github.com/go-vg ## License -Robotgo is primarily distributed under the terms of both the MIT license and the Apache License (Version 2.0), with portions covered by various BSD-like licenses. +Robotgo is primarily distributed under the terms of "both the MIT license and the Apache License (Version 2.0)", with portions covered by various BSD-like licenses. See [LICENSE-APACHE](http://www.apache.org/licenses/LICENSE-2.0), [LICENSE-MIT](https://github.com/go-vgo/robotgo/blob/master/LICENSE). diff --git a/img.go b/img.go index c526ae3a..79d5b0f5 100644 --- a/img.go +++ b/img.go @@ -17,6 +17,46 @@ import ( "github.com/vcaesar/imgo" ) +// DecodeImg decode the image to image.Image and return +func DecodeImg(path string) (image.Image, string, error) { + return imgo.DecodeFile(path) +} + +// OpenImg open the image return []byte +func OpenImg(path string) ([]byte, error) { + return imgo.ImgToBytes(path) +} + +// SaveImg save the image by []byte +func SaveImg(b []byte, path string) error { + return imgo.Save(path, b) +} + +// SavePng save the image by image.Image +func SavePng(img image.Image, path string) error { + return imgo.SaveToPNG(path, img) +} + +// ToByteImg convert image.Image to []byte +func ToByteImg(img image.Image) []byte { + return imgo.ToByteImg(img) +} + +// ToStringImg convert image.Image to string +func ToStringImg(img image.Image) string { + return string(ToByteImg(img)) +} + +// StrToImg convert base64 string to image.Image +func StrToImg(data string) (image.Image, error) { + return imgo.StrToImg(data) +} + +// ByteToImg convert []byte to image.Image +func ByteToImg(b []byte) (image.Image, error) { + return imgo.ByteToImg(b) +} + // RGBAToBitmap convert the standard image.RGBA to Bitmap func RGBAToBitmap(r1 *image.RGBA) (bit Bitmap) { bit.Width = r1.Bounds().Size().X @@ -61,3 +101,29 @@ func ToUint8p(dst []uint8) *uint8 { ptr := unsafe.Pointer(&src[0]) return (*uint8)(ptr) } + +// ToRGBAGo convert Bitmap to standard image.RGBA +func ToRGBAGo(bmp1 Bitmap) *image.RGBA { + img1 := image.NewRGBA(image.Rect(0, 0, bmp1.Width, bmp1.Height)) + img1.Pix = make([]uint8, bmp1.Bytewidth*bmp1.Height) + + copyToVUint8A(img1.Pix, bmp1.ImgBuf) + img1.Stride = bmp1.Bytewidth + return img1 +} + +func val(p *uint8, n int) uint8 { + addr := uintptr(unsafe.Pointer(p)) + addr += uintptr(n) + p1 := (*uint8)(unsafe.Pointer(addr)) + return *p1 +} + +func copyToVUint8A(dst []uint8, src *uint8) { + for i := 0; i < len(dst)-4; i += 4 { + dst[i] = val(src, i+2) + dst[i+1] = val(src, i+1) + dst[i+2] = val(src, i) + dst[i+3] = val(src, i+3) + } +} diff --git a/robotgo.go b/robotgo.go index 0a80d3e9..08ab0024 100644 --- a/robotgo.go +++ b/robotgo.go @@ -51,7 +51,6 @@ package robotgo import "C" import ( - "bytes" "fmt" "image" @@ -64,12 +63,9 @@ import ( "unsafe" // "syscall" - "encoding/base64" - "image/jpeg" "os/exec" "github.com/go-vgo/robotgo/clipboard" - "github.com/vcaesar/imgo" "github.com/vcaesar/tt" ) @@ -951,36 +947,6 @@ func TocharBitmap(bit C.MMBitmapRef) *C.char { return strBit } -// ToByteImg convert image.Image to []byte -func ToByteImg(img image.Image) []byte { - buff := bytes.NewBuffer(nil) - jpeg.Encode(buff, img, nil) - - var dist []byte - base64.StdEncoding.Encode(dist, buff.Bytes()) - - return dist -} - -// ToStringImg convert image.Image to string -func ToStringImg(img image.Image) string { - return string(ToByteImg(img)) -} - -// StrToImg convert base64 string to image.Image -func StrToImg(data string) (image.Image, error) { - reader := base64.NewDecoder(base64.StdEncoding, strings.NewReader(data)) - m, _, err := image.Decode(reader) - - return m, err -} - -// ByteToImg convert []byte to image.Image -func ByteToImg(b []byte) (image.Image, error) { - img, _, err := image.Decode(bytes.NewReader(b)) - return img, err -} - // ToImage convert C.MMBitmapRef to standard image.Image func ToImage(bit C.MMBitmapRef) image.Image { return ToRGBA(bit) @@ -989,28 +955,7 @@ func ToImage(bit C.MMBitmapRef) image.Image { // ToRGBA convert C.MMBitmapRef to standard image.RGBA func ToRGBA(bit C.MMBitmapRef) *image.RGBA { bmp1 := ToBitmap(bit) - img1 := image.NewRGBA(image.Rect(0, 0, bmp1.Width, bmp1.Height)) - img1.Pix = make([]uint8, bmp1.Bytewidth*bmp1.Height) - - copyToVUint8A(img1.Pix, bmp1.ImgBuf) - img1.Stride = bmp1.Bytewidth - return img1 -} - -func val(p *uint8, n int) uint8 { - addr := uintptr(unsafe.Pointer(p)) - addr += uintptr(n) - p1 := (*uint8)(unsafe.Pointer(addr)) - return *p1 -} - -func copyToVUint8A(dst []uint8, src *uint8) { - for i := 0; i < len(dst)-4; i += 4 { - dst[i] = val(src, i+2) - dst[i+1] = val(src, i+1) - dst[i+2] = val(src, i) - dst[i+3] = val(src, i+3) - } + return ToRGBAGo(bmp1) } func internalFindBitmap(bit, sbit C.MMBitmapRef, tolerance float64) (int, int) { @@ -1195,26 +1140,6 @@ func OpenBitmap(gpath string, args ...int) C.MMBitmapRef { return bit } -// DecodeImg decode the image to image.Image and return -func DecodeImg(path string) (image.Image, string, error) { - return imgo.DecodeFile(path) -} - -// OpenImg open the image return []byte -func OpenImg(path string) ([]byte, error) { - return imgo.ImgToBytes(path) -} - -// SaveImg save the image by []byte -func SaveImg(b []byte, path string) error { - return imgo.Save(path, b) -} - -// SavePng save the image by image.Image -func SavePng(img image.Image, path string) error { - return imgo.SaveToPNG(path, img) -} - // BitmapStr bitmap from string func BitmapStr(str string) C.MMBitmapRef { return BitmapFromStr(str) From 621e6b45856a4274e37a3d0eb21be02ac8035b51 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 8 Sep 2021 13:46:11 -0400 Subject: [PATCH 083/327] add more img to bitmap examples code --- .gitignore | 5 +++++ examples/bitmap/imgToBitmap/main.go | 23 +++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 examples/bitmap/imgToBitmap/main.go diff --git a/.gitignore b/.gitignore index 9c73dc21..3e2dcc87 100644 --- a/.gitignore +++ b/.gitignore @@ -84,4 +84,9 @@ vendor # Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 .glide/ + +# examples/bitmap/test_IMG.png +examples/bitmap/imgToBitmap/test_01.png +examples/bitmap/imgToBitmap/test_002.jpeg +examples/bitmap/imgToBitmap/test_003.jpeg diff --git a/examples/bitmap/imgToBitmap/main.go b/examples/bitmap/imgToBitmap/main.go new file mode 100644 index 00000000..f6179ea6 --- /dev/null +++ b/examples/bitmap/imgToBitmap/main.go @@ -0,0 +1,23 @@ +package main + +import ( + "fmt" + + "github.com/go-vgo/robotgo" + "github.com/vcaesar/imgo" +) + +func main() { + bit1 := robotgo.CaptureScreen(300, 300, 100, 100) + robotgo.SaveBitmap(bit1, "test_003.jpeg") + + m1 := robotgo.ToImage(bit1) + fmt.Println("m1: ", m1.Bounds()) + imgo.SaveToPNG("test_01.png", m1) + + r1 := robotgo.ToRGBA(bit1) + fmt.Println("r1: ", r1.Pix) + + bit2 := robotgo.ToCBitmap(robotgo.ImgToBitmap(m1)) + robotgo.SaveBitmap(bit2, "test_002.jpeg") +} From 05e35e1d1e8d541ec35369073843bf76667eea91 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 8 Sep 2021 13:49:50 -0400 Subject: [PATCH 084/327] Update file name --- examples/bitmap/{bitmap-bytes => bitmapTobytes}/main.go | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename examples/bitmap/{bitmap-bytes => bitmapTobytes}/main.go (100%) diff --git a/examples/bitmap/bitmap-bytes/main.go b/examples/bitmap/bitmapTobytes/main.go similarity index 100% rename from examples/bitmap/bitmap-bytes/main.go rename to examples/bitmap/bitmapTobytes/main.go From 871ec1a2c4b7c81ddf067e9fa239faaf5e490695 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Fri, 10 Sep 2021 14:30:37 -0400 Subject: [PATCH 085/327] Update go mod and xx.yml --- .circleci/config.yml | 2 +- .circleci/images/primary/Dockerfile | 2 +- appveyor.yml | 2 +- go.mod | 2 +- go.sum | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d1edb3e2..bd1b612b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,7 +5,7 @@ jobs: docker: # using custom image, see .circleci/images/primary/Dockerfile # - image: govgo/robotgoci:1.10.3 - - image: golang:1.16.7 + - image: golang:1.17.1 working_directory: /gopath/src/github.com/go-vgo/robotgo steps: - checkout diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index 353ff278..2700dbea 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.7-stretch AS build +FROM golang:1.7.1-stretch AS build # FROM govgo/go:1.11.1 RUN apt update && apt install -y --no-install-recommends \ diff --git a/appveyor.yml b/appveyor.yml index fabe54a8..fe8550f7 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,7 +34,7 @@ environment: PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% # - COMPILER: MINGW_W64 # ARCHITECTURE: x64 - GOVERSION: 1.16.7 + GOVERSION: 1.17.1 # GOPATH: c:\gopath # scripts that run after cloning repository diff --git a/go.mod b/go.mod index 73ae9f9f..56fa8ac2 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ require ( github.com/lxn/win v0.0.0-20210218163916-a377121e959e github.com/otiai10/curr v1.0.0 // indirect github.com/otiai10/gosseract v2.2.1+incompatible - github.com/robotn/gohook v0.31.0 + github.com/robotn/gohook v0.31.1 github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 github.com/vcaesar/gops v0.21.1 diff --git a/go.sum b/go.sum index d0a7a739..7f4a1fa7 100644 --- a/go.sum +++ b/go.sum @@ -18,8 +18,8 @@ github.com/otiai10/mint v1.3.0 h1:Ady6MKVezQwHBkGzLFbrsywyp09Ah7rkmfjV3Bcr5uc= github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/robotn/gohook v0.31.0 h1:gduiVso8bmSWO+k8Af/ehskIeKvd25PwuKt/nHK4+bk= -github.com/robotn/gohook v0.31.0/go.mod h1:FXryR68cDIho8rjE7MKxt4n4aK2FBqp+d/0HK4oiGP8= +github.com/robotn/gohook v0.31.1 h1:jfXrEYQe6cptRxKJn6BkC/U4PBLq5yWxD4Nq6coCiPE= +github.com/robotn/gohook v0.31.1/go.mod h1:FXryR68cDIho8rjE7MKxt4n4aK2FBqp+d/0HK4oiGP8= github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 h1:2lhSR8N3T6I30q096DT7/5AKEIcf1vvnnWAmS0wfnNY= github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934/go.mod h1:SxQhJskUJ4rleVU44YvnrdvxQr0tKy5SRSigBrCgyyQ= github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 h1:2uX8QRLkkxn2EpAQ6I3KhA79BkdRZfvugJUzJadiJwk= From aae0a14e7f0ddc43c052eef721719fe342b23d34 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 13 Sep 2021 12:07:32 -0400 Subject: [PATCH 086/327] add SaveJpeg() function support --- img.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/img.go b/img.go index 79d5b0f5..f40da775 100644 --- a/img.go +++ b/img.go @@ -37,6 +37,11 @@ func SavePng(img image.Image, path string) error { return imgo.SaveToPNG(path, img) } +// SaveJpeg save the image by image.Image +func SaveJpeg(img image.Image, path string) error { + return imgo.SaveToJpeg(path, img) +} + // ToByteImg convert image.Image to []byte func ToByteImg(img image.Image) []byte { return imgo.ToByteImg(img) From 9468b8fdde856293fc6f868caec6ce2a8d9fcd5d Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 13 Sep 2021 12:28:23 -0400 Subject: [PATCH 087/327] Update README.md and example --- README.md | 22 ++++++++++++++++++++-- README_zh.md | 23 +++++++++++++++++++++-- examples/screen/main.go | 2 +- 3 files changed, 42 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 6e1e30e3..9b824009 100644 --- a/README.md +++ b/README.md @@ -130,6 +130,11 @@ import ( func main() { robotgo.ScrollMouse(10, "up") + robotgo.Scroll(100, 200) + + robotgo.MoveMouse(10, 10) + robotgo.Drag(10, 10) + robotgo.MouseClick("left", true) robotgo.MoveMouseSmooth(100, 200, 1.0, 100.0) } @@ -189,6 +194,9 @@ func main() { color := robotgo.GetPixelColor(100, 200) fmt.Println("color---- ", color) + + sx, sy := robotgo.GetScreenSize() + fmt.Println("get screen size: ", sx, sy) } ``` @@ -208,9 +216,19 @@ func main() { // use `defer robotgo.FreeBitmap(bit)` to free the bitmap defer robotgo.FreeBitmap(bitmap) - fmt.Println("...", bitmap) + fmt.Println("bitmap...", bitmap) + img := robotgo.ToImage(bitmap) + robotgo.SavePng(img, "test_1.png") + + bit2 := robotgo.ToCBitmap(robotgo.ImgToBitmap(img)) + fx, fy := robotgo.FindBitmap(bit2) + fmt.Println("FindBitmap------ ", fx, fy) + + arr := robotgo.FindEveryBitmap(bit2) + fmt.Println("Find every bitmap: ", arr) + robotgo.SaveBitmap(bitmap, "test.png") - fx, fy := robotgo.FindBitmap(bitmap) + fx, fy = robotgo.FindBitmap(bitmap) fmt.Println("FindBitmap------ ", fx, fy) robotgo.SaveBitmap(bitmap, "test.png") diff --git a/README_zh.md b/README_zh.md index 5938b4c2..ce808292 100644 --- a/README_zh.md +++ b/README_zh.md @@ -128,6 +128,11 @@ import ( func main() { robotgo.ScrollMouse(10, "up") + robotgo.Scroll(100, 200) + + robotgo.MoveMouse(10, 10) + robotgo.Drag(10, 10) + robotgo.MouseClick("left", true) robotgo.MoveMouseSmooth(100, 200, 1.0, 100.0) } @@ -187,6 +192,9 @@ func main() { color := robotgo.GetPixelColor(100, 200) fmt.Println("color----", color) + + sx, sy := robotgo.GetScreenSize() + fmt.Println("get screen size: ", sx, sy) } ``` @@ -205,9 +213,20 @@ func main() { bitmap := robotgo.CaptureScreen(10, 20, 30, 40) // use `defer robotgo.FreeBitmap(bit)` to free the bitmap defer robotgo.FreeBitmap(bitmap) - fmt.Println("...", bitmap) + + fmt.Println("bitmap...", bitmap) + img := robotgo.ToImage(bitmap) + robotgo.SavePng(img, "test_1.png") + + bit2 := robotgo.ToCBitmap(robotgo.ImgToBitmap(img)) + fx, fy := robotgo.FindBitmap(bit2) + fmt.Println("FindBitmap------ ", fx, fy) + + arr := robotgo.FindEveryBitmap(bit2) + fmt.Println("Find every bitmap: ", arr) + robotgo.SaveBitmap(bitmap, "test.png") - fx, fy := robotgo.FindBitmap(bitmap) + fx, fy = robotgo.FindBitmap(bitmap) fmt.Println("FindBitmap------", fx, fy) robotgo.SaveBitmap(bitmap, "test.png") diff --git a/examples/screen/main.go b/examples/screen/main.go index 123c4282..53fdb009 100644 --- a/examples/screen/main.go +++ b/examples/screen/main.go @@ -63,7 +63,7 @@ func screen() { // gets the screen width and height sx, sy := robotgo.GetScreenSize() - fmt.Println("...", sx, sy) + fmt.Println("get screen size: ", sx, sy) color() } From cd0b69b3a10ddc8b3c848ae94df8928a243e1a07 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 15 Sep 2021 11:23:24 -0400 Subject: [PATCH 088/327] add more bitmap examples code --- .gitignore | 4 ++++ examples/bitmap/imgToBitmap/main.go | 29 +++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/.gitignore b/.gitignore index 3e2dcc87..5ec28c09 100644 --- a/.gitignore +++ b/.gitignore @@ -90,3 +90,7 @@ examples/bitmap/test_IMG.png examples/bitmap/imgToBitmap/test_01.png examples/bitmap/imgToBitmap/test_002.jpeg examples/bitmap/imgToBitmap/test_003.jpeg +examples/bitmap/imgToBitmap/test_1.png +examples/bitmap/imgToBitmap/test_2.jpeg +examples/bitmap/imgToBitmap/test.png +robot_img.png diff --git a/examples/bitmap/imgToBitmap/main.go b/examples/bitmap/imgToBitmap/main.go index f6179ea6..e97a2af5 100644 --- a/examples/bitmap/imgToBitmap/main.go +++ b/examples/bitmap/imgToBitmap/main.go @@ -1,14 +1,22 @@ +//go:build go1.16 +// +build go1.16 + package main import ( + _ "embed" "fmt" "github.com/go-vgo/robotgo" "github.com/vcaesar/imgo" ) +//go:embed test_01.png +var testPng []byte + func main() { bit1 := robotgo.CaptureScreen(300, 300, 100, 100) + defer robotgo.FreeBitmap(bit1) robotgo.SaveBitmap(bit1, "test_003.jpeg") m1 := robotgo.ToImage(bit1) @@ -20,4 +28,25 @@ func main() { bit2 := robotgo.ToCBitmap(robotgo.ImgToBitmap(m1)) robotgo.SaveBitmap(bit2, "test_002.jpeg") + + test() +} + +func test() { + bitmap := robotgo.CaptureScreen(10, 10, 10, 10) + defer robotgo.FreeBitmap(bitmap) + + img := robotgo.ToImage(bitmap) + robotgo.SavePng(img, "test_1.png") + + img1, _ := robotgo.ByteToImg(testPng) + robotgo.SaveJpeg(img1, "test_2.jpeg") + + bit2 := robotgo.ToCBitmap(robotgo.ImgToBitmap(img)) + fx, fy := robotgo.FindBitmap(bit2) + fmt.Println("FindBitmap------ ", fx, fy) + + arr := robotgo.FindEveryBitmap(bit2) + fmt.Println("Find every bitmap: ", arr) + robotgo.SaveBitmap(bitmap, "test.png") } From 51661803b13a63963ee0eae15298fa3c9f91c22c Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 15 Sep 2021 11:38:26 -0400 Subject: [PATCH 089/327] Update go mod and Update README.md --- README.md | 16 ++++++++-------- README_zh.md | 2 +- go.mod | 21 +++++++++++++++++---- go.sum | 24 ++++++++++-------------- 4 files changed, 36 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 9b824009..d8a0c448 100644 --- a/README.md +++ b/README.md @@ -125,7 +125,7 @@ Note go1.10.x C file compilation cache problem, [golang #24355](https://github.c package main import ( - "github.com/go-vgo/robotgo" + "github.com/go-vgo/robotgo" ) func main() { @@ -183,9 +183,9 @@ func main() { package main import ( - "fmt" + "fmt" - "github.com/go-vgo/robotgo" + "github.com/go-vgo/robotgo" ) func main() { @@ -196,7 +196,7 @@ func main() { fmt.Println("color---- ", color) sx, sy := robotgo.GetScreenSize() - fmt.Println("get screen size: ", sx, sy) + fmt.Println("get screen size: ", sx, sy) } ``` @@ -206,9 +206,9 @@ func main() { package main import ( - "fmt" + "fmt" - "github.com/go-vgo/robotgo" + "github.com/go-vgo/robotgo" ) func main() { @@ -302,9 +302,9 @@ func event() { package main import ( - "fmt" + "fmt" - "github.com/go-vgo/robotgo" + "github.com/go-vgo/robotgo" ) func main() { diff --git a/README_zh.md b/README_zh.md index ce808292..cf85f8aa 100644 --- a/README_zh.md +++ b/README_zh.md @@ -194,7 +194,7 @@ func main() { fmt.Println("color----", color) sx, sy := robotgo.GetScreenSize() - fmt.Println("get screen size: ", sx, sy) + fmt.Println("get screen size: ", sx, sy) } ``` diff --git a/go.mod b/go.mod index 56fa8ac2..7cf0e864 100644 --- a/go.mod +++ b/go.mod @@ -1,20 +1,33 @@ module github.com/go-vgo/robotgo +go 1.17 + require ( - github.com/davecgh/go-spew v1.1.1 // indirect github.com/lxn/win v0.0.0-20210218163916-a377121e959e - github.com/otiai10/curr v1.0.0 // indirect github.com/otiai10/gosseract v2.2.1+incompatible github.com/robotn/gohook v0.31.1 github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 - github.com/vcaesar/gops v0.21.1 + github.com/vcaesar/gops v0.21.2 github.com/vcaesar/imgo v0.20.0 github.com/vcaesar/tt v0.11.0 golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d golang.org/x/net v0.0.0-20201110031124-69a78807bb2b // indirect ) +require ( + github.com/StackExchange/wmi v1.2.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-ole/go-ole v1.2.5 // indirect + github.com/otiai10/mint v1.3.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/shirou/gopsutil v3.21.8+incompatible // indirect + github.com/tklauser/go-sysconf v0.3.9 // indirect + github.com/tklauser/numcpus v0.3.0 // indirect + golang.org/x/sys v0.0.0-20210915083310-ed5796bab164 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect +) + // replace golang.org/x/sys => github.com/golang/sys v0.0.0-20190109145017-48ac38b7c8cb -go 1.13 +// go 1.13 diff --git a/go.sum b/go.sum index 7f4a1fa7..402ddcaa 100644 --- a/go.sum +++ b/go.sum @@ -10,8 +10,6 @@ github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiU github.com/lxn/win v0.0.0-20210218163916-a377121e959e h1:H+t6A/QJMbhCSEH5rAuRxh+CtW96g0Or0Fxa9IKr4uc= github.com/lxn/win v0.0.0-20210218163916-a377121e959e/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= -github.com/otiai10/curr v1.0.0 h1:TJIWdbX0B+kpNagQrjgq8bCMrbhiuX73M2XwgtDMoOI= -github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= github.com/otiai10/gosseract v2.2.1+incompatible h1:Ry5ltVdpdp4LAa2bMjsSJH34XHVOV7XMi41HtzL8X2I= github.com/otiai10/gosseract v2.2.1+incompatible/go.mod h1:XrzWItCzCpFRZ35n3YtVTgq5bLAhFIkascoRo8G32QE= github.com/otiai10/mint v1.3.0 h1:Ady6MKVezQwHBkGzLFbrsywyp09Ah7rkmfjV3Bcr5uc= @@ -24,18 +22,17 @@ github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 h1:2lhSR8N3T6I30q096DT7 github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934/go.mod h1:SxQhJskUJ4rleVU44YvnrdvxQr0tKy5SRSigBrCgyyQ= github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 h1:2uX8QRLkkxn2EpAQ6I3KhA79BkdRZfvugJUzJadiJwk= github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770/go.mod h1:svkDXUDQjUiWzLrA0OZgHc4lbOts3C+uRfP6/yjwYnU= -github.com/shirou/gopsutil v3.21.7+incompatible h1:g/wcPHcuCQvHSePVofjQljd2vX4ty0+J6VoMB+NPcdk= -github.com/shirou/gopsutil v3.21.7+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil v3.21.8+incompatible h1:sh0foI8tMRlCidUJR+KzqWYWxrkuuPIGiO6Vp+KXdCU= +github.com/shirou/gopsutil v3.21.8+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/tklauser/go-sysconf v0.3.8 h1:41Nq9J+pxKud4IQ830J5LlS5nl67dVQC7AuisUooaOU= -github.com/tklauser/go-sysconf v0.3.8/go.mod h1:z4zYWRS+X53WUKtBcmDg1comV3fPhdQnzasnIHUoLDU= -github.com/tklauser/numcpus v0.2.3/go.mod h1:vpEPS/JC+oZGGQ/My/vJnNsvMDQL6PwOqt8dsCw5j+E= +github.com/tklauser/go-sysconf v0.3.9 h1:JeUVdAOWhhxVcU6Eqr/ATFHgXk/mmiItdKeJPev3vTo= +github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs= github.com/tklauser/numcpus v0.3.0 h1:ILuRUQBtssgnxw0XXIjKUC56fgnOrFoQQ/4+DeU2biQ= github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8= -github.com/vcaesar/gops v0.21.1 h1:a8ZCbho+K3RP1+hlkGCSWih84Iu3hjXYKwZW3970hkg= -github.com/vcaesar/gops v0.21.1/go.mod h1:upqQTBNSvazU+AvHwXY7VPdJscLoOqOxw+vkmJKnjEk= +github.com/vcaesar/gops v0.21.2 h1:OwWoJR0zb+AK41TN2adhZUP9lAmaRMzkWwf7Ux5Mx00= +github.com/vcaesar/gops v0.21.2/go.mod h1:BEJGigAc9GORbEegWX9rRon/qwibjDs8p50WYm2KlXw= github.com/vcaesar/imgo v0.20.0 h1:lX7a2vygTri0Z3VYpwoQA2LPvbphFyT5ON4NTqdC4wQ= github.com/vcaesar/imgo v0.20.0/go.mod h1:eJscuTEdc6sVn/hZruy8kWi61xqKHLtbAYyPeYcn+t4= github.com/vcaesar/tt v0.11.0 h1:obQecjgbnAxxC6OYGY6yDvhGRW2PR5wD8Ma2uJH3WGA= @@ -52,15 +49,14 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55 h1:rw6UNGRMfarCepjI8qOepea/SXwIBVfTKjztZ5gBbq4= -golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210915083310-ed5796bab164 h1:7ZDGnxgHAMw7thfC5bEos0RDAccZKxioiWBhfIe+tvw= +golang.org/x/sys v0.0.0-20210915083310-ed5796bab164/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From 657cbe47015e8d4b4f6e78377b01f7c9ab10d890 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 15 Sep 2021 11:43:34 -0400 Subject: [PATCH 090/327] add more key toggle function --- robotgo.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/robotgo.go b/robotgo.go index 08ab0024..5ac3eddd 100644 --- a/robotgo.go +++ b/robotgo.go @@ -63,6 +63,7 @@ import ( "unsafe" // "syscall" + "math/rand" "os/exec" "github.com/go-vgo/robotgo/clipboard" @@ -697,6 +698,23 @@ func KeyToggle(key string, args ...string) string { return C.GoString(str) } +// KeyPress press key string +func KeyPress(key string) { + KeyDown(key) + Sleep(15 + rand.Intn(10)) + KeyUp(key) +} + +// KeyDown press down a key +func KeyDown(key string) { + KeyToggle(key, "down") +} + +// KeyUp press up a key +func KeyUp(key string) { + KeyToggle(key, "up") +} + // ReadAll read string from clipboard func ReadAll() (string, error) { return clipboard.ReadAll() From cc451789226414a7c4fe96225a085f62c2825a10 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 15 Sep 2021 11:57:59 -0400 Subject: [PATCH 091/327] gofmt to 1.17 build tag --- clipboard/clipboard_darwin.go | 1 + clipboard/clipboard_unix.go | 1 + clipboard/clipboard_windows.go | 1 + robotgo_mac_win.go | 1 + robotgo_ocr.go | 1 + robotgo_test.go | 1 + robotgo_unix.go | 1 + robotgo_win.go | 1 + 8 files changed, 8 insertions(+) diff --git a/clipboard/clipboard_darwin.go b/clipboard/clipboard_darwin.go index 58d4a2da..eedd4c3a 100644 --- a/clipboard/clipboard_darwin.go +++ b/clipboard/clipboard_darwin.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin // +build darwin package clipboard diff --git a/clipboard/clipboard_unix.go b/clipboard/clipboard_unix.go index dcae8085..fde35cbd 100644 --- a/clipboard/clipboard_unix.go +++ b/clipboard/clipboard_unix.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build freebsd || linux || netbsd || openbsd || solaris || dragonfly // +build freebsd linux netbsd openbsd solaris dragonfly package clipboard diff --git a/clipboard/clipboard_windows.go b/clipboard/clipboard_windows.go index 406bb658..2b9202ed 100644 --- a/clipboard/clipboard_windows.go +++ b/clipboard/clipboard_windows.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build windows // +build windows package clipboard diff --git a/robotgo_mac_win.go b/robotgo_mac_win.go index 53d75413..de6d21ac 100644 --- a/robotgo_mac_win.go +++ b/robotgo_mac_win.go @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//go:build darwin || windows // +build darwin windows package robotgo diff --git a/robotgo_ocr.go b/robotgo_ocr.go index 6e1939fb..b931a853 100644 --- a/robotgo_ocr.go +++ b/robotgo_ocr.go @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//go:build ocr // +build ocr package robotgo diff --git a/robotgo_test.go b/robotgo_test.go index cce772aa..9eb2de8d 100644 --- a/robotgo_test.go +++ b/robotgo_test.go @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//go:build darwin || windows // +build darwin windows package robotgo diff --git a/robotgo_unix.go b/robotgo_unix.go index 1463e75f..009c9d4a 100644 --- a/robotgo_unix.go +++ b/robotgo_unix.go @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//go:build !darwin && !windows // +build !darwin,!windows package robotgo diff --git a/robotgo_win.go b/robotgo_win.go index eac9a9d4..46a3808a 100644 --- a/robotgo_win.go +++ b/robotgo_win.go @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +//go:build windows // +build windows package robotgo From 458d389e097e2985e7373800e0a9777e134aba2f Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 15 Sep 2021 12:37:42 -0400 Subject: [PATCH 092/327] Update bitmap examples code --- .gitignore | 1 + examples/bitmap/imgToBitmap/main.go | 4 ++-- examples/bitmap/imgToBitmap/test_007.jpeg | Bin 0 -> 3261 bytes 3 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 examples/bitmap/imgToBitmap/test_007.jpeg diff --git a/.gitignore b/.gitignore index 5ec28c09..c97edc9f 100644 --- a/.gitignore +++ b/.gitignore @@ -93,4 +93,5 @@ examples/bitmap/imgToBitmap/test_003.jpeg examples/bitmap/imgToBitmap/test_1.png examples/bitmap/imgToBitmap/test_2.jpeg examples/bitmap/imgToBitmap/test.png +examples/bitmap/imgToBitmap/test_7.jpeg robot_img.png diff --git a/examples/bitmap/imgToBitmap/main.go b/examples/bitmap/imgToBitmap/main.go index e97a2af5..0d6d8a4c 100644 --- a/examples/bitmap/imgToBitmap/main.go +++ b/examples/bitmap/imgToBitmap/main.go @@ -11,7 +11,7 @@ import ( "github.com/vcaesar/imgo" ) -//go:embed test_01.png +//go:embed test_007.jpeg var testPng []byte func main() { @@ -40,7 +40,7 @@ func test() { robotgo.SavePng(img, "test_1.png") img1, _ := robotgo.ByteToImg(testPng) - robotgo.SaveJpeg(img1, "test_2.jpeg") + robotgo.SaveJpeg(img1, "test_7.jpeg") bit2 := robotgo.ToCBitmap(robotgo.ImgToBitmap(img)) fx, fy := robotgo.FindBitmap(bit2) diff --git a/examples/bitmap/imgToBitmap/test_007.jpeg b/examples/bitmap/imgToBitmap/test_007.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..0823de1f5b7facd6c0729da2614871a3b9112d93 GIT binary patch literal 3261 zcmbW&c{tQ-8wc>;m|={qtXW2u;mDFA!`RC~RT!_LOa$|k_YeS$|=P~^0*ARI0#AulB=E{A}_&!|YtomWs&QWB9;)kG<3$X`%W z1i@f1HdZ!%c6NS6F}RrG{~Y>zfRh=p0c^k^ae#pn1m*0K^FTE5N@4VgN%J znV`%t7S@vh0|*RefPfhpA&}#j5yy7`gp-j=OyLp}_q7{PabF%qd~!ZBLZ`BY7xQ^T z;=)b8doUKhQ~UyglD|ovk(N}XbdvKcTVRL_m<`^WexF(RB$VbPH~%F4CHn6`_x>-@ zKcIg+^l^X<3_2bdm=n+j)=$~jHP$D;Pe)`k_Cw5l#(ht_+^^#D?|fzJfziFeJG9wZ zUVmtKC9iFlpdjHrz&wC@-w#zqc9U-A#1Omkdf;n)VL`kgahwg_(xt;@HZtI`l4P1A zUSd!4#6I%l@@cW7j}3vjP=%;o5*oz@^7id(Q(-JXrCue?3mYi>^k`}u7VX2&` zx=OYGd|gj?!C|pw(lYc{5uxb$hCN4hTELx&)C3OIquk-SOXJp+-=+$pjL+;GDy++M znJU}zg!n0}x4fsl@71Gu1l_*@TLYGI(OV*Ex@DS2`Qe`=v)i53`S>46a45F1%`S{Y zG$@a^eVA2K@+M&>7eW)aN8W}AIgAdi6rom0cB}KXvF&B6Z%R+RZM=g<9AKP0{2f~h z3$wjf+FK+RqIe@+28EY>uJ#SgU~X5lz5ix8&ze#;Y!exAxJ*eUpkGZoQ1>|c);U{q zi`$%|)LE#Ht1z)$c0q64SAGefo2U^3!n<54V_j=#(IY*piShH2kGZcS=gRqF{5w+m*TAO~ zBaW-*gEe-EM)HuV25CrK8<5Z#`LHo)cfc-_u@o|HE40H zmE4=NvcKLf;qz#D`9->=ts0rO;%55nh*LkTZRGI4YkE{}}OR<4$e<+@ZN;{j-&nwcXPe1=h7AWE_LbPgt)<9Ess1vb=@y;rzo{4Hjf(}nC!^7mD% zRkyknCQ@CEL?=4KR?F!ML+DnRrGLlS?lTVY-}>NVz22QwY%s00(8SBBD}HzTb@#2N zN#0cx96so--TY^+g>%%eSBpMFyFs~t5WoejAMOU@T{z1ex z)d3ePo)*Yr$j zX*JRa=QOS47Gvt)?rUCz;WAnFQ6;Ch3#%9m6>j|cR7M*&34N*ho>xK zDE8@w^9J!3P4?9*(B22bwzcZ)ego6mbya$ouAOE`pNC+{aLdv}E~=f2#&XLVA2L2> z%LYH8DQ!W(SYKAFNE9ETc&qu)MDr{f9-(;(_JnkO^9Ff(dctyU-rljud6)Foi~vm? z`h9=cCfq(>qaUH`3*UBr7as!;fG@=@2l(7npL}j#YuJQ^b2P{6O&Nx5=~AM@37OpP zCWT)nJ+oqOZ5gbey=ud~94bNw99`Y5wE{-nKI})OFeE2pYsY#^COkdlxE;`Et6bGw zL1e7jDDv){JF$PfY$5%#E(CDHo1wG{whLKeiv+WjJxrAM{~#tjH1qOjuaqgr*M2%} zX}TGqWmj4-(TaOvOD-ra3iW8WP&+y6>RR%qNncTrPk>PH?Y@>CPz*u@ZC z>Q_=04I(arQN?E2X@8UxFe%Xv2kbQ)TdgdI`CZb_xMmq4yP{duyZqWqUqycTksikk z5u;(RK3*Lgzfj}uT`%@wIJMN#9DsnYC7u?}l4N9{=iMZ|{=#1y{)_m z!>lWcenrjG0YB|SzBIC@_74iKB?%yr%o2YC%&^)UsfBlvCkbUFp<=m1QUVA2-H z14V!K*i)F%qShPn7{$m fwK^I-_4DptSMkiDMe{n#y#%j1EWyC&0)6aXG&3FM literal 0 HcmV?d00001 From a23859625e9e21d94cbfa225eace9cec6cc062a5 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 16 Sep 2021 15:18:56 -0400 Subject: [PATCH 093/327] Update version and keycode --- .gitignore | 1 + key/keycode_c.h | 4 ++-- robotgo.go | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index c97edc9f..c00b3573 100644 --- a/.gitignore +++ b/.gitignore @@ -95,3 +95,4 @@ examples/bitmap/imgToBitmap/test_2.jpeg examples/bitmap/imgToBitmap/test.png examples/bitmap/imgToBitmap/test_7.jpeg robot_img.png +examples/bitmap/bitmapTobytes/out.jpg diff --git a/key/keycode_c.h b/key/keycode_c.h index 9fd0d369..8e54dcba 100644 --- a/key/keycode_c.h +++ b/key/keycode_c.h @@ -46,7 +46,6 @@ struct XSpecialCharacterMapping XSpecialCharacterTable[] = { {'@', XK_at}, {':', XK_colon}, {';', XK_semicolon}, - {'`', XK_grave}, {'{', XK_braceleft}, {'}', XK_braceright}, {'|', XK_bar}, @@ -55,10 +54,11 @@ struct XSpecialCharacterMapping XSpecialCharacterTable[] = { {')', XK_parenright}, {' ', XK_space}, {'/', XK_slash}, + {'\\', XK_backslash}, + {'`', XK_grave}, {'"', XK_quoteright}, {'\'', XK_quotedbl}, // {'\'', XK_quoteright}, - {'\\', XK_backslash}, {'\t', XK_Tab}, {'\n', XK_Return} }; diff --git a/robotgo.go b/robotgo.go index 5ac3eddd..59d5bc66 100644 --- a/robotgo.go +++ b/robotgo.go @@ -72,7 +72,7 @@ import ( const ( // Version get the robotgo version - Version = "v0.99.1.1189, MT. Rainier!" + Version = "v0.100.0.1189, MT. Baker!" ) // GetVersion get the robotgo version From c070578b42c3d07e7a7bea3b44f1ea47661b862a Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 16 Sep 2021 15:46:15 -0400 Subject: [PATCH 094/327] Update docs remove drop API --- docs/doc.md | 24 ++++++++++++------------ docs/doc_zh.md | 25 +++++++++++++------------ 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/docs/doc.md b/docs/doc.md index b5fe095f..cca93699 100644 --- a/docs/doc.md +++ b/docs/doc.md @@ -5,14 +5,14 @@ ## [Keyboard](#Keyboard) ##### [Keys](https://github.com/go-vgo/robotgo/blob/master/docs/keys.md) -##### [SetKeyboardDelay](#SetKeyDelay) (Equivalent to SetKeyDelay, Wno-deprecated) + ##### [SetKeyDelay](#SetKeyDelay) ##### [KeyTap](#KeyTap) ##### [KeyToggle](#KeyToggle) -##### [TypeString](#TypeString) -##### [TypeStringDelayed](#TypeStrDelay) (Equivalent to TypeStrDelay, Wno-deprecated) -##### [TypeStrDelay](#TypeStrDelay) + ##### [TypeStr](#TypeStr) +##### [TypeStrDelay](#TypeStrDelay) ##### [WriteAll](#WriteAll) ##### [ReadAll](#ReadAll) @@ -57,7 +57,7 @@ ## [Event](#Event) -##### [LEvent](#LEvent) (Equivalent to AddEvent, Wno-deprecated) + ##### [AddEvent](#AddEvent) ##### [StopEvent](#StopEvent) @@ -71,7 +71,7 @@ ##### [GetActive](#GetActive) ##### [SetHandle](#SetHandle) ##### [GetHandle](#GetHandle) -##### [GetBHandle](#GetHandle) + ##### [GetTitle](#GetTitle) ##### [GetPID](#GetPID) ##### [Pids](#Pids) @@ -126,24 +126,24 @@ modifier (optional, string or array) - Accepts alt, command (mac), control, and #### Return: return KeyToggle status -###

.TypeString(string)

+ -###

.TypeStrDelay(string, cpm)

+###

.TypeStr(string)

#### Arguments: string - The string to send. - cpm - Characters per minute. -###

.TypeStr(string)

+###

.TypeStrDelay(string, cpm)

#### Arguments: string - The string to send. + cpm - Characters per minute. ###

.WriteAll(text string)

@@ -331,7 +331,7 @@ robotgo.ScrollMouse(50, "down") Gets part or all of the screen. GoCaptureScreen Returns a go struct - Capture_Screen (Drop support) + #### Arguments: diff --git a/docs/doc_zh.md b/docs/doc_zh.md index 774df827..1f7e4390 100644 --- a/docs/doc_zh.md +++ b/docs/doc_zh.md @@ -5,14 +5,14 @@ ## [键盘](#Keyboard) ##### [Keys](https://github.com/go-vgo/robotgo/blob/master/docs/keys.md) -##### [SetKeyboardDelay](#SetKeyDelay) (相当于 SetKeyDelay, 废弃 API) + ##### [SetKeyDelay](#SetKeyDelay) ##### [KeyTap](#KeyTap) ##### [KeyToggle](#KeyToggle) -##### [TypeString](#TypeString) -##### [TypeStringDelayed](#TypeStrDelay) (相当于 TypeStrDelay, 废弃 API) -##### [TypeStrDelay](#TypeStrDelay) + ##### [TypeStr](#TypeStr) +##### [TypeStrDelay](#TypeStrDelay) ##### [WriteAll](#WriteAll) ##### [ReadAll](#ReadAll) @@ -59,7 +59,7 @@ ## [事件](#Event) -##### [LEvent](#AddEvent) (相当于 AddEvent, 废弃 API) + ##### [AddEvent](#AddEvent) ##### [StopEvent](#StopEvent) @@ -73,7 +73,7 @@ ##### [GetActive](#GetActive) ##### [SetHandle](#SetHandle) ##### [GetHandle](#GetHandle) -##### [GetBHandle](#GetHandle) + ##### [GetTitle](#GetTitle) ##### [GetPID](#GetPID) ##### [Pids](#Pids) @@ -131,24 +131,25 @@ modifier (optional, string or array) - Accepts alt, command (mac), control, and 返回 KeyToggle 状态 -###

.TypeString(string)

+ -###

.TypeStrDelay(string, cpm)

+###

.TypeStr(string)

#### 参数: string - The string to send. - cpm - Characters per minute. -###

.TypeStr(string)

+ +###

.TypeStrDelay(string, cpm)

#### 参数: string - The string to send. + cpm - Characters per minute. ###

.WriteAll(text string)

@@ -345,7 +346,7 @@ robotgo.ScrollMouse(50, "down") Gets part or all of the screen. GoCaptureScreen Returns a go struct - Capture_Screen (废弃) + #### 参数: From 4dcdfe7f423cb9a0b417f7c24258233b60569dba Mon Sep 17 00:00:00 2001 From: vcaesar Date: Fri, 17 Sep 2021 11:10:11 -0400 Subject: [PATCH 095/327] Update README.md --- README.md | 4 ++-- README_zh.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d8a0c448..9c3b4c8a 100644 --- a/README.md +++ b/README.md @@ -15,9 +15,9 @@ - >Golang Desktop Automation. Control the mouse, keyboard, bitmap, read the screen, Window Handle and global event listener. + >Golang Desktop Automation. Control the mouse, keyboard, bitmap and image, read the screen, process, Window Handle and global event listener. -RobotGo supports Mac, Windows, and Linux(X11). +RobotGo supports Mac, Windows, and Linux(X11); and robotgo supports arm64 and x86-amd64. [Chinese Simplified](https://github.com/go-vgo/robotgo/blob/master/README_zh.md) diff --git a/README_zh.md b/README_zh.md index cf85f8aa..b2a84710 100644 --- a/README_zh.md +++ b/README_zh.md @@ -9,7 +9,7 @@ [![GitHub release](https://img.shields.io/github/release/go-vgo/robotgo.svg)](https://github.com/go-vgo/robotgo/releases/latest) [![Join the chat at https://gitter.im/go-vgo/robotgo](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/go-vgo/robotgo?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) - >Golang 跨平台自动化系统,控制键盘鼠标位图和读取屏幕,窗口句柄以及全局事件监听 + >Golang 跨平台自动化系统,控制键盘、鼠标、位图、图像、读取屏幕,进程、窗口句柄以及全局事件监听 RobotGo 支持 Mac, Windows, and Linux(X11). From 2768d0877a715d2e48972c7b51d380d6c64e19d4 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Fri, 24 Sep 2021 12:32:20 -0400 Subject: [PATCH 096/327] add more image function support --- README.md | 2 +- README_zh.md | 2 +- examples/bitmap/main.go | 3 ++- go.mod | 4 ++-- go.sum | 7 ++++--- img.go | 20 +++++++++++++++----- 6 files changed, 25 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 9c3b4c8a..72977c45 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ - >Golang Desktop Automation. Control the mouse, keyboard, bitmap and image, read the screen, process, Window Handle and global event listener. +> Golang Desktop Automation. Control the mouse, keyboard, bitmap and image, read the screen, process, Window Handle and global event listener. RobotGo supports Mac, Windows, and Linux(X11); and robotgo supports arm64 and x86-amd64. diff --git a/README_zh.md b/README_zh.md index b2a84710..38163dd8 100644 --- a/README_zh.md +++ b/README_zh.md @@ -9,7 +9,7 @@ [![GitHub release](https://img.shields.io/github/release/go-vgo/robotgo.svg)](https://github.com/go-vgo/robotgo/releases/latest) [![Join the chat at https://gitter.im/go-vgo/robotgo](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/go-vgo/robotgo?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) - >Golang 跨平台自动化系统,控制键盘、鼠标、位图、图像、读取屏幕,进程、窗口句柄以及全局事件监听 +> Golang 跨平台自动化系统,控制键盘、鼠标、位图、图像、读取屏幕,进程、窗口句柄以及全局事件监听 RobotGo 支持 Mac, Windows, and Linux(X11). diff --git a/examples/bitmap/main.go b/examples/bitmap/main.go index be1dee62..9c3662db 100644 --- a/examples/bitmap/main.go +++ b/examples/bitmap/main.go @@ -34,6 +34,7 @@ func toBitmap(bmp robotgo.CBitmap) { robotgo.SaveBitmap(cbit, "tocbitmap.png") } +// find color func findColor(bmp robotgo.CBitmap) { bitmap := robotgo.ToMMBitmapRef(bmp) @@ -105,7 +106,7 @@ func decode() { fmt.Println("decode test.png", img, name) byt, _ := robotgo.OpenImg("test.png") - imgo.Save("test2.png", byt) + imgo.SaveByte("test2.png", byt) w, h := robotgo.GetImgSize("test.png") fmt.Println("image width and hight ", w, h) diff --git a/go.mod b/go.mod index 7cf0e864..c4147aa2 100644 --- a/go.mod +++ b/go.mod @@ -9,8 +9,8 @@ require ( github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 github.com/vcaesar/gops v0.21.2 - github.com/vcaesar/imgo v0.20.0 - github.com/vcaesar/tt v0.11.0 + github.com/vcaesar/imgo v0.30.0 + github.com/vcaesar/tt v0.20.0 golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d golang.org/x/net v0.0.0-20201110031124-69a78807bb2b // indirect ) diff --git a/go.sum b/go.sum index 402ddcaa..2a4a91ec 100644 --- a/go.sum +++ b/go.sum @@ -33,10 +33,11 @@ github.com/tklauser/numcpus v0.3.0 h1:ILuRUQBtssgnxw0XXIjKUC56fgnOrFoQQ/4+DeU2bi github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8= github.com/vcaesar/gops v0.21.2 h1:OwWoJR0zb+AK41TN2adhZUP9lAmaRMzkWwf7Ux5Mx00= github.com/vcaesar/gops v0.21.2/go.mod h1:BEJGigAc9GORbEegWX9rRon/qwibjDs8p50WYm2KlXw= -github.com/vcaesar/imgo v0.20.0 h1:lX7a2vygTri0Z3VYpwoQA2LPvbphFyT5ON4NTqdC4wQ= -github.com/vcaesar/imgo v0.20.0/go.mod h1:eJscuTEdc6sVn/hZruy8kWi61xqKHLtbAYyPeYcn+t4= -github.com/vcaesar/tt v0.11.0 h1:obQecjgbnAxxC6OYGY6yDvhGRW2PR5wD8Ma2uJH3WGA= +github.com/vcaesar/imgo v0.30.0 h1:ODQVX0EFJEh+WkKahCBtE0SqcDCIjl/kjiOplR0Ouh8= +github.com/vcaesar/imgo v0.30.0/go.mod h1:8TGnt5hjaMgwDByvMFIzUDSh5uSea4n1tAbSvnhvA6U= github.com/vcaesar/tt v0.11.0/go.mod h1:GHPxQYhn+7OgKakRusH7KJ0M5MhywoeLb8Fcffs/Gtg= +github.com/vcaesar/tt v0.20.0 h1:9t2Ycb9RNHcP0WgQgIaRKJBB+FrRdejuaL6uWIHuoBA= +github.com/vcaesar/tt v0.20.0/go.mod h1:GHPxQYhn+7OgKakRusH7KJ0M5MhywoeLb8Fcffs/Gtg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d h1:RNPAfi2nHY7C2srAV8A49jpsYr0ADedCk1wq6fTMTvs= diff --git a/img.go b/img.go index f40da775..69d2d302 100644 --- a/img.go +++ b/img.go @@ -27,9 +27,19 @@ func OpenImg(path string) ([]byte, error) { return imgo.ImgToBytes(path) } +// Read read the file return image.Image +func Read(path string) (image.Image, error) { + return imgo.Read(path) +} + +// Save create a image file with the image.Image +func Save(img image.Image, path string) error { + return imgo.Save(path, img) +} + // SaveImg save the image by []byte func SaveImg(b []byte, path string) error { - return imgo.Save(path, b) + return imgo.SaveByte(path, b) } // SavePng save the image by image.Image @@ -43,13 +53,13 @@ func SaveJpeg(img image.Image, path string) error { } // ToByteImg convert image.Image to []byte -func ToByteImg(img image.Image) []byte { - return imgo.ToByteImg(img) +func ToByteImg(img image.Image, fm ...string) []byte { + return imgo.ToByteImg(img, fm...) } // ToStringImg convert image.Image to string -func ToStringImg(img image.Image) string { - return string(ToByteImg(img)) +func ToStringImg(img image.Image, fm ...string) string { + return string(ToByteImg(img, fm...)) } // StrToImg convert base64 string to image.Image From aabde2eca6e8a4f060a55a8ec01d32886a08bb77 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 27 Sep 2021 13:54:11 -0400 Subject: [PATCH 097/327] update go mod and test code --- go.mod | 4 ++-- go.sum | 8 ++++---- robotgo_test.go | 3 +++ 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index c4147aa2..5de515bb 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.17 require ( github.com/lxn/win v0.0.0-20210218163916-a377121e959e github.com/otiai10/gosseract v2.2.1+incompatible - github.com/robotn/gohook v0.31.1 + github.com/robotn/gohook v0.31.2 github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 github.com/vcaesar/gops v0.21.2 @@ -24,7 +24,7 @@ require ( github.com/shirou/gopsutil v3.21.8+incompatible // indirect github.com/tklauser/go-sysconf v0.3.9 // indirect github.com/tklauser/numcpus v0.3.0 // indirect - golang.org/x/sys v0.0.0-20210915083310-ed5796bab164 // indirect + golang.org/x/sys v0.0.0-20210925032602-92d5a993a665 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) diff --git a/go.sum b/go.sum index 2a4a91ec..1ca03bc6 100644 --- a/go.sum +++ b/go.sum @@ -16,8 +16,8 @@ github.com/otiai10/mint v1.3.0 h1:Ady6MKVezQwHBkGzLFbrsywyp09Ah7rkmfjV3Bcr5uc= github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/robotn/gohook v0.31.1 h1:jfXrEYQe6cptRxKJn6BkC/U4PBLq5yWxD4Nq6coCiPE= -github.com/robotn/gohook v0.31.1/go.mod h1:FXryR68cDIho8rjE7MKxt4n4aK2FBqp+d/0HK4oiGP8= +github.com/robotn/gohook v0.31.2 h1:ADIppQ3T0Sd+kaDMb4Vnv6UeSmhNfK0H0HpPWCd8G5I= +github.com/robotn/gohook v0.31.2/go.mod h1:0BQit8783ey63WXFau8TvoaTYfNtsAhqZ0RJaqlYi6E= github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 h1:2lhSR8N3T6I30q096DT7/5AKEIcf1vvnnWAmS0wfnNY= github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934/go.mod h1:SxQhJskUJ4rleVU44YvnrdvxQr0tKy5SRSigBrCgyyQ= github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 h1:2uX8QRLkkxn2EpAQ6I3KhA79BkdRZfvugJUzJadiJwk= @@ -35,7 +35,6 @@ github.com/vcaesar/gops v0.21.2 h1:OwWoJR0zb+AK41TN2adhZUP9lAmaRMzkWwf7Ux5Mx00= github.com/vcaesar/gops v0.21.2/go.mod h1:BEJGigAc9GORbEegWX9rRon/qwibjDs8p50WYm2KlXw= github.com/vcaesar/imgo v0.30.0 h1:ODQVX0EFJEh+WkKahCBtE0SqcDCIjl/kjiOplR0Ouh8= github.com/vcaesar/imgo v0.30.0/go.mod h1:8TGnt5hjaMgwDByvMFIzUDSh5uSea4n1tAbSvnhvA6U= -github.com/vcaesar/tt v0.11.0/go.mod h1:GHPxQYhn+7OgKakRusH7KJ0M5MhywoeLb8Fcffs/Gtg= github.com/vcaesar/tt v0.20.0 h1:9t2Ycb9RNHcP0WgQgIaRKJBB+FrRdejuaL6uWIHuoBA= github.com/vcaesar/tt v0.20.0/go.mod h1:GHPxQYhn+7OgKakRusH7KJ0M5MhywoeLb8Fcffs/Gtg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -51,8 +50,9 @@ golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210915083310-ed5796bab164 h1:7ZDGnxgHAMw7thfC5bEos0RDAccZKxioiWBhfIe+tvw= golang.org/x/sys v0.0.0-20210915083310-ed5796bab164/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210925032602-92d5a993a665 h1:QOQNt6vCjMpXE7JSK5VvAzJC1byuN3FgTNSBwf+CJgI= +golang.org/x/sys v0.0.0-20210925032602-92d5a993a665/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= diff --git a/robotgo_test.go b/robotgo_test.go index 9eb2de8d..e7c09286 100644 --- a/robotgo_test.go +++ b/robotgo_test.go @@ -107,6 +107,9 @@ func TestKey(t *testing.T) { e := KeyTap("v", "cmd") tt.Empty(t, e) + e = KeyTap("enter") + tt.Empty(t, e) + e = KeyToggle("v", "up") tt.Empty(t, e) } From b92ccdeff11d898821a61cff6e4ed610ca3c9e92 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 27 Sep 2021 14:38:30 -0400 Subject: [PATCH 098/327] Update CHANGELOG.md --- docs/CHANGELOG.md | 110 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index d7f4d4c3..84d474b3 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,6 +1,116 @@ # CHANGELOG +## RobotGo v0.100.0, MT. Baker; Enhancement bitmap and image, add arm support... + +### Add + +- [NEW] add more image function support +- [NEW] add ImgToBitmap(), ToImg(), FindEveryBitmap(), FindEveryColor(), Svae(), Read(), SaveJpeg() and other function support + +- [NEW] add func ToImage: convert C.MMBitmapRef to standard image.Image +- [NEW] add ToImage examples code +- [NEW] add more image function and update go mod + +- [NEW] add find every color function +- [NEW] add free and find all point function +- [NEW] update find bitmap and color + +- [NEW] add byte to image function +- [NEW] add more image convert function + +- [NEW] add mac os M1 support +- [NEW] add windows arm support + +- [NEW] add more key toggle and press function + +- [NEW] add ToRGBA() function support +- [NEW] add ImgToBitmap and RGBAToBitmap support +- [NEW] Update and move image function to img.go + +- [NEW] add more img to bitmap examples code and Update file name + +### Update + +- [NEW] Update README.md and CHANGELOG.md +- [NEW] add macOS to .travis.yml +- [NEW] update go mod pkg + +- [NEW] Update hook examples link to newest +- [NEW] update dockerfile and appveyor to go1.14.4 + +- [NEW] Update README.md, add more examples +- [NEW] move hook and event to gohook +- [NEW] move cbitmap and bitmap-bytes to bitmap dir + +- [NEW] update some name +- [NEW] update dockerfile and appveyor.yml + +- [NEW] update clipboard code +- [NEW] update hook code and more API + +- [NEW] optimize code and update version +- [NEW] add paste string err return and optimize code +- [NEW] update go.yml and travis.yml to go1.15 +- [NEW] Update Ubuntu apt-get to apt + +- [NEW] update go version and key code +- [NEW] update test code and go mod +- [NEW] Update README.md and test code + +- [NEW] update parameter name and version +- [NEW] update dockerfile and appveyor.yml +- [NEW] update error return and print + +- [NEW] update ShowAlert optimize return code +- [NEW] add more test and update go mod + +- [NEW] compatible with 32-bit platforms +- [NEW] add more bitmap examples + +- [NEW] update point structure to public + +- [NEW] add more examples +- [NEW] update examples and version +- [NEW] Update clipboard example code + +- [NEW] Update README.md Section ####Other to windows (#348) … +- [NEW] Update png.h path +- [NEW] Update go mod +- [NEW] Update circle.yml and travis.yml + +- [NEW] Remove unless example code and update circle.yml +- [NEW] Removed drop api example code and Update README.md + +- [NEW] Update go mod and xx.yml +- [NEW] Update README.md and example + +- [NEW] add more bitmap examples code +- [NEW] Update go mod and Update README.md +- [NEW] gofmt to 1.17 build tag +- [NEW] Update bitmap examples code + +- [NEW] Update version and keycode +- [NEW] Update docs remove drop API + + +### Fixed + +- [FIX] Update go mod and fixed #290 +- [FIX] Update gohook to v0.30.2 fixed bug +- [FIX] Fixed Mouse buttons reversed type +- [FIX] Fixed returns "Invalid key code specified." if specified character is not v… … add keyCodeForCharFallBack + +- [FIX] This fixes the disappearing backslash issue #351 +- [FIX] Export ToUC function and update test code +- [FIX] Fixes #258: char* arrays in C not being copied correctly +- [FIX] Fixed Linux TypeStr() function double quote + +- [FIX] update free bitmap fixed #333 +- [FIX] update gops to v0.20.0 fixed bug and other mod pkg +- [FIX] update gohook fixed warning + + ## RobotGo v0.90.0, MT. Rainier From 41564cbe2d17dba2cd8d673968fea234965ad516 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Fri, 8 Oct 2021 15:24:47 -0400 Subject: [PATCH 099/327] Update dockerfile and appveyor.yml --- .circleci/images/primary/Dockerfile | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index 2700dbea..a08ffa75 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.7.1-stretch AS build +FROM golang:1.7.2-stretch AS build # FROM govgo/go:1.11.1 RUN apt update && apt install -y --no-install-recommends \ diff --git a/appveyor.yml b/appveyor.yml index fe8550f7..05601ec6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,7 +34,7 @@ environment: PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% # - COMPILER: MINGW_W64 # ARCHITECTURE: x64 - GOVERSION: 1.17.1 + GOVERSION: 1.17.2 # GOPATH: c:\gopath # scripts that run after cloning repository From 0feac878f9d3f06bd279c9d93707e80d1233da58 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sat, 9 Oct 2021 09:33:41 -0400 Subject: [PATCH 100/327] Update godoc --- robotgo.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/robotgo.go b/robotgo.go index 59d5bc66..0a192ed5 100644 --- a/robotgo.go +++ b/robotgo.go @@ -827,7 +827,7 @@ func PasteStr(str string) string { return KeyTap("v", "control") } -// TypeString send a string, support unicode +// Deprecated: TypeString send a string, support unicode // TypeStr(string: The string to send), Wno-deprecated func TypeString(str string, delay ...int) { tt.Drop("TypeString", "TypeStr") @@ -848,7 +848,7 @@ func TypeStrDelay(str string, delay int) { Sleep(delay) } -// TypeStringDelayed type string delayed, Wno-deprecated +// Deprecated: TypeStringDelayed type string delayed, Wno-deprecated func TypeStringDelayed(str string, delay int) { tt.Drop("TypeStringDelayed", "TypeStrDelay") TypeStrDelay(str, delay) @@ -859,7 +859,7 @@ func SetKeyDelay(delay int) { C.set_keyboard_delay(C.size_t(delay)) } -// SetKeyboardDelay set keyboard delay, Wno-deprecated, +// Deprecated: SetKeyboardDelay set keyboard delay, Wno-deprecated, // this function will be removed in version v1.0.0 func SetKeyboardDelay(delay int) { tt.Drop("SetKeyboardDelay", "SetKeyDelay") @@ -1236,7 +1236,7 @@ func CopyBitPB(bitmap C.MMBitmapRef) bool { return gbool } -// CopyBitpb copy bitmap to pasteboard, Wno-deprecated +// Deprecated: CopyBitpb copy bitmap to pasteboard, Wno-deprecated func CopyBitpb(bitmap C.MMBitmapRef) bool { tt.Drop("CopyBitpb", "CopyBitPB") return CopyBitPB(bitmap) @@ -1564,7 +1564,7 @@ func GetHandle() int { return ghwnd } -// GetBHandle get the window handle, Wno-deprecated +// Deprecated: GetBHandle get the window handle, Wno-deprecated func GetBHandle() int { tt.Drop("GetBHandle", "GetHandle") hwnd := C.bget_handle() From 185c253a821986f3a376d649c1cc4578a91ba45e Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 12 Oct 2021 10:18:15 -0400 Subject: [PATCH 101/327] Update README.md --- README.md | 16 ++++++++++++++++ README_zh.md | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/README.md b/README.md index 72977c45..8d71643b 100644 --- a/README.md +++ b/README.md @@ -209,6 +209,7 @@ import ( "fmt" "github.com/go-vgo/robotgo" + "github.com/vcaesar/gcv" ) func main() { @@ -233,6 +234,21 @@ func main() { robotgo.SaveBitmap(bitmap, "test.png") } + +func opencv() { + name := "test.png" + name1 := "test_001.png" + robotgo.SaveCapture(name, 10, 10, 30, 30) + robotgo.SaveCapture(name1) + + fmt.Print("gcv find image: ") + fmt.Println(gcv.FindImgFile(name, name1)) + + bit := robotgo.OpenBitmap(name) + defer robotgo.FindBitmap(bit) + fmt.Print("find bitmap: ") + fmt.Println(robotgo.FindBitmap(bit)) +} ``` #### [Event](https://github.com/go-vgo/robotgo/blob/master/examples/gohook/main.go) diff --git a/README_zh.md b/README_zh.md index 38163dd8..253a2b33 100644 --- a/README_zh.md +++ b/README_zh.md @@ -207,6 +207,7 @@ import ( "fmt" "github.com/go-vgo/robotgo" + "github.com/vcaesar/gcv" ) func main() { @@ -231,6 +232,21 @@ func main() { robotgo.SaveBitmap(bitmap, "test.png") } + +func opencv() { + name := "test.png" + name1 := "test_001.png" + robotgo.SaveCapture(name, 10, 10, 30, 30) + robotgo.SaveCapture(name1) + + fmt.Print("gcv find image: ") + fmt.Println(gcv.FindImgFile(name, name1)) + + bit := robotgo.OpenBitmap(name) + defer robotgo.FindBitmap(bit) + fmt.Print("find bitmap: ") + fmt.Println(robotgo.FindBitmap(bit)) +} ``` #### [事件](https://github.com/go-vgo/robotgo/blob/master/examples/gohook/main.go) From 1498a7d32eab27384721bee1013777f21bf64b46 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 12 Oct 2021 11:11:38 -0400 Subject: [PATCH 102/327] add more hook keycode and Update README.md --- README.md | 22 +++++++++++----------- README_zh.md | 22 +++++++++++----------- keycode.go | 18 ++++++++++++++---- 3 files changed, 36 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 8d71643b..8a5274d6 100644 --- a/README.md +++ b/README.md @@ -236,18 +236,18 @@ func main() { } func opencv() { - name := "test.png" - name1 := "test_001.png" - robotgo.SaveCapture(name, 10, 10, 30, 30) - robotgo.SaveCapture(name1) + name := "test.png" + name1 := "test_001.png" + robotgo.SaveCapture(name, 10, 10, 30, 30) + robotgo.SaveCapture(name1) - fmt.Print("gcv find image: ") - fmt.Println(gcv.FindImgFile(name, name1)) + fmt.Print("gcv find image: ") + fmt.Println(gcv.FindImgFile(name, name1)) - bit := robotgo.OpenBitmap(name) + bit := robotgo.OpenBitmap(name) defer robotgo.FindBitmap(bit) - fmt.Print("find bitmap: ") - fmt.Println(robotgo.FindBitmap(bit)) + fmt.Print("find bitmap: ") + fmt.Println(robotgo.FindBitmap(bit)) } ``` @@ -286,10 +286,10 @@ func add() { } func low() { - EvChan := hook.Start() + evChan := hook.Start() defer hook.End() - for ev := range EvChan { + for ev := range evChan { fmt.Println("hook: ", ev) } } diff --git a/README_zh.md b/README_zh.md index 253a2b33..502a0f45 100644 --- a/README_zh.md +++ b/README_zh.md @@ -234,18 +234,18 @@ func main() { } func opencv() { - name := "test.png" - name1 := "test_001.png" - robotgo.SaveCapture(name, 10, 10, 30, 30) - robotgo.SaveCapture(name1) + name := "test.png" + name1 := "test_001.png" + robotgo.SaveCapture(name, 10, 10, 30, 30) + robotgo.SaveCapture(name1) - fmt.Print("gcv find image: ") - fmt.Println(gcv.FindImgFile(name, name1)) + fmt.Print("gcv find image: ") + fmt.Println(gcv.FindImgFile(name, name1)) - bit := robotgo.OpenBitmap(name) + bit := robotgo.OpenBitmap(name) defer robotgo.FindBitmap(bit) - fmt.Print("find bitmap: ") - fmt.Println(robotgo.FindBitmap(bit)) + fmt.Print("find bitmap: ") + fmt.Println(robotgo.FindBitmap(bit)) } ``` @@ -284,10 +284,10 @@ func add() { } func low() { - EvChan := hook.Start() + evChan := hook.Start() defer hook.End() - for ev := range EvChan { + for ev := range evChan { fmt.Println("hook: ", ev) } } diff --git a/keycode.go b/keycode.go index 82db599f..4ec2d3b3 100644 --- a/keycode.go +++ b/keycode.go @@ -37,6 +37,8 @@ var Keycode = uMap{ "9": 10, "0": 11, "-": 12, + "=": 13, + "_": 12, "+": 13, // "q": 16, @@ -51,7 +53,10 @@ var Keycode = uMap{ "p": 25, "[": 26, "]": 27, + "{": 26, + "}": 27, "\\": 43, + "|": 43, // "a": 30, "s": 31, @@ -64,6 +69,8 @@ var Keycode = uMap{ "l": 38, ";": 39, "'": 40, + ":": 39, + `"`: 40, // "z": 44, "x": 45, @@ -75,6 +82,9 @@ var Keycode = uMap{ ",": 51, ".": 52, "/": 53, + "<": 51, + ">": 52, + "?": 53, // "f1": 59, "f2": 60, @@ -92,18 +102,18 @@ var Keycode = uMap{ "esc": 1, "delete": 14, "tab": 15, + "enter": 28, "ctrl": 29, "control": 29, - "alt": 56, - "space": 57, "shift": 42, "rshift": 54, - "enter": 28, + "space": 57, // + "alt": 56, + "ralt": 3640, "cmd": 3675, "command": 3675, "rcmd": 3676, - "ralt": 3640, // "up": 57416, "down": 57424, From 336b7cea9fb8c7315ee4590b67ccb09603b4e7e4 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 12 Oct 2021 12:03:50 -0400 Subject: [PATCH 103/327] add free bitmap array support and Update README.md --- README.md | 17 +++++++++++++++++ README_zh.md | 17 +++++++++++++++++ robotgo.go | 9 ++++++++- 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8a5274d6..1ff7b90f 100644 --- a/README.md +++ b/README.md @@ -186,6 +186,7 @@ import ( "fmt" "github.com/go-vgo/robotgo" + "github.com/vcaesar/imgo" ) func main() { @@ -197,6 +198,13 @@ func main() { sx, sy := robotgo.GetScreenSize() fmt.Println("get screen size: ", sx, sy) + + bit := robotgo.CaptureScreen(10, 10, 30, 30) + defer robotgo.FreeBitmap(bit) + robotgo.SaveBimap(bit, "test_1.png") + + img := robotgo.ToImage(bit) + imgo.Save("test.png", img) } ``` @@ -248,6 +256,15 @@ func opencv() { defer robotgo.FindBitmap(bit) fmt.Print("find bitmap: ") fmt.Println(robotgo.FindBitmap(bit)) + + bit0 := robotgo.CaptureScreen() + img := robotgo.ToImage(bit0) + bit1 := robotgo.CaptureScreen(10, 10, 30, 30) + img1 := robotgo.ToImage(bit1) + defer robotgo.FreeBitmapArr(bit0, bit1) + + fmt.Print("gcv find image: ") + fmt.Println(gcv.FindImg(img1, img)) } ``` diff --git a/README_zh.md b/README_zh.md index 502a0f45..1660c6c2 100644 --- a/README_zh.md +++ b/README_zh.md @@ -184,6 +184,7 @@ import ( "fmt" "github.com/go-vgo/robotgo" + "github.com/vcaesar/imgo" ) func main() { @@ -195,6 +196,13 @@ func main() { sx, sy := robotgo.GetScreenSize() fmt.Println("get screen size: ", sx, sy) + + bit := robotgo.CaptureScreen(10, 10, 30, 30) + defer robotgo.FreeBitmap(bit) + robotgo.SaveBimap(bit, "test_1.png") + + img := robotgo.ToImage(bit) + imgo.Save("test.png", img) } ``` @@ -246,6 +254,15 @@ func opencv() { defer robotgo.FindBitmap(bit) fmt.Print("find bitmap: ") fmt.Println(robotgo.FindBitmap(bit)) + + bit0 := robotgo.CaptureScreen() + img := robotgo.ToImage(bit0) + bit1 := robotgo.CaptureScreen(10, 10, 30, 30) + img1 := robotgo.ToImage(bit1) + defer robotgo.FreeBitmapArr(bit0, bit1) + + fmt.Print("gcv find image: ") + fmt.Println(gcv.FindImg(img1, img)) } ``` diff --git a/robotgo.go b/robotgo.go index 0a192ed5..2b232d25 100644 --- a/robotgo.go +++ b/robotgo.go @@ -1215,12 +1215,19 @@ func Convert(opath, spath string, args ...int) { SaveBitmap(bitmap, spath, mtype) } -// FreeBitmap free and dealloc bitmap +// FreeBitmap free and dealloc the C bitmap func FreeBitmap(bitmap C.MMBitmapRef) { // C.destroyMMBitmap(bitmap) C.bitmap_dealloc(bitmap) } +// FreeBitmapArr free and dealloc the C bitmap array +func FreeBitmapArr(bit ...C.MMBitmapRef) { + for i := 0; i < len(bit); i++ { + FreeBitmap(bit[i]) + } +} + // ReadBitmap returns false and sets error if |bitmap| is NULL func ReadBitmap(bitmap C.MMBitmapRef) bool { abool := C.bitmap_ready(bitmap) From 088d6744539a42fcba43812c6da8d27c523f2736 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 12 Oct 2021 12:07:16 -0400 Subject: [PATCH 104/327] Fixed a typo --- README.md | 2 +- README_zh.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1ff7b90f..e12e3ac4 100644 --- a/README.md +++ b/README.md @@ -201,7 +201,7 @@ func main() { bit := robotgo.CaptureScreen(10, 10, 30, 30) defer robotgo.FreeBitmap(bit) - robotgo.SaveBimap(bit, "test_1.png") + robotgo.SaveBitmap(bit, "test_1.png") img := robotgo.ToImage(bit) imgo.Save("test.png", img) diff --git a/README_zh.md b/README_zh.md index 1660c6c2..86f0420b 100644 --- a/README_zh.md +++ b/README_zh.md @@ -199,7 +199,7 @@ func main() { bit := robotgo.CaptureScreen(10, 10, 30, 30) defer robotgo.FreeBitmap(bit) - robotgo.SaveBimap(bit, "test_1.png") + robotgo.SaveBitmap(bit, "test_1.png") img := robotgo.ToImage(bit) imgo.Save("test.png", img) From dc5f64ef65235a2fe98306375be12076b279c1d3 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 12 Oct 2021 12:13:06 -0400 Subject: [PATCH 105/327] Update README.md --- README.md | 9 ++++++--- README_zh.md | 9 ++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index e12e3ac4..cae9d07d 100644 --- a/README.md +++ b/README.md @@ -132,11 +132,12 @@ func main() { robotgo.ScrollMouse(10, "up") robotgo.Scroll(100, 200) - robotgo.MoveMouse(10, 10) + robotgo.Move(10, 10) robotgo.Drag(10, 10) - robotgo.MouseClick("left", true) - robotgo.MoveMouseSmooth(100, 200, 1.0, 100.0) + robotgo.Click("left", true) + robotgo.MoveSmooth(100, 200, 1.0, 100.0) + robotgo.MouseToggle("up") } ``` @@ -169,6 +170,8 @@ func main() { arr := []string{"alt", "command"} robotgo.KeyTap("i", arr) + robotgo.KeyToggle("a", "down") + robotgo.WriteAll("Test") text, err := robotgo.ReadAll() if err == nil { diff --git a/README_zh.md b/README_zh.md index 86f0420b..c6c17420 100644 --- a/README_zh.md +++ b/README_zh.md @@ -130,11 +130,12 @@ func main() { robotgo.ScrollMouse(10, "up") robotgo.Scroll(100, 200) - robotgo.MoveMouse(10, 10) + robotgo.Move(10, 10) robotgo.Drag(10, 10) - robotgo.MouseClick("left", true) - robotgo.MoveMouseSmooth(100, 200, 1.0, 100.0) + robotgo.Click("left", true) + robotgo.MoveSmooth(100, 200, 1.0, 100.0) + robotgo.MouseToggle("up") } ``` @@ -167,6 +168,8 @@ func main() { arr := []string{"alt", "command"} robotgo.KeyTap("i", arr) + robotgo.KeyToggle("a", "down") + robotgo.WriteAll("テストする") text, err := robotgo.ReadAll() if err == nil { From 0c262d4d4298a8fd536fb29d61cd4c693f891a12 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 13 Oct 2021 15:07:40 -0400 Subject: [PATCH 106/327] add all mouse and key sleep option and CaptureImg(), Scale0(), ScrollRelative() function; Update godoc and name --- robotgo.go | 82 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 59 insertions(+), 23 deletions(-) diff --git a/robotgo.go b/robotgo.go index 2b232d25..e68a3b14 100644 --- a/robotgo.go +++ b/robotgo.go @@ -80,6 +80,13 @@ func GetVersion() string { return Version } +var ( + // MouseSleep set the mouse default millisecond sleep time + MouseSleep = 0 + // KeySleep set the key default millisecond sleep time + KeySleep = 0 +) + type ( // Map a map[string]interface{} Map map[string]interface{} @@ -222,7 +229,7 @@ func SysScale() float64 { return float64(s) } -// Scaled x * sys-scale +// Scaled return x * sys_scale func Scaled(x int) int { return int(float64(x) * SysScale()) } @@ -261,6 +268,11 @@ func Scale() int { return dpi[x] } +// Scale0 return ScaleX() / 0.96 +func Scale0() int { + return int(float64(ScaleX()) / 0.96) +} + // Mul mul the scale func Mul(x int) int { s := Scale() @@ -328,6 +340,14 @@ func GoCaptureScreen(args ...int) Bitmap { return ToBitmap(bit) } +// CaptureImg capture the screen and return image.Image +func CaptureImg(args ...int) image.Image { + bit := CaptureScreen(args...) + defer FreeBitmap(bit) + + return ToImage(bit) +} + // SaveCapture capture screen and save func SaveCapture(spath string, args ...int) { bit := CaptureScreen(args...) @@ -370,22 +390,23 @@ func MoveMouse(x, y int) { Move(x, y) } -// Move move the mouse +// Move move the mouse to (x, y) func Move(x, y int) { cx := C.int32_t(x) cy := C.int32_t(y) C.move_mouse(cx, cy) + + MilliSleep(MouseSleep) } -// DragMouse drag the mouse +// DragMouse drag the mouse to (x, y) func DragMouse(x, y int, args ...string) { Drag(x, y, args...) } -// Drag drag the mouse +// Drag drag the mouse to (x, y) func Drag(x, y int, args ...string) { var button C.MMMouseButton = C.LEFT_BUTTON - cx := C.int32_t(x) cy := C.int32_t(y) @@ -394,6 +415,7 @@ func Drag(x, y int, args ...string) { } C.drag_mouse(cx, cy, button) + MilliSleep(MouseSleep) } // DragSmooth drag the mouse smooth @@ -436,6 +458,7 @@ func MoveSmooth(x, y int, args ...interface{}) bool { } cbool := C.move_mouse_smooth(cx, cy, low, high, C.int(mouseDelay)) + MilliSleep(MouseSleep) return bool(cbool) } @@ -449,12 +472,12 @@ func MoveArgs(x, y int) (int, int) { return mx, my } -// MoveRelative move mose relative +// MoveRelative move mouse with relative func MoveRelative(x, y int) { Move(MoveArgs(x, y)) } -// MoveSmoothRelative move mose smooth relative +// MoveSmoothRelative move mouse smooth with relative func MoveSmoothRelative(x, y int, args ...interface{}) { mx, my := MoveArgs(x, y) MoveSmooth(mx, my, args...) @@ -495,6 +518,7 @@ func Click(args ...interface{}) { } C.mouse_click(button, double) + MilliSleep(MouseSleep) } // MoveClick move and click the mouse @@ -523,6 +547,7 @@ func MouseToggle(togKey string, args ...interface{}) int { i := C.mouse_toggle(down, button) C.free(unsafe.Pointer(down)) + MilliSleep(MouseSleep) return int(i) } @@ -533,9 +558,10 @@ func ScrollMouse(x int, direction string) { C.scroll_mouse(cx, cy) C.free(unsafe.Pointer(cy)) + MilliSleep(MouseSleep) } -// Scroll scroll the mouse with x, y +// Scroll scroll the mouse to (x, y) // // robotgo.Scroll(x, y, msDelay int) func Scroll(x, y int, args ...int) { @@ -549,6 +575,13 @@ func Scroll(x, y int, args ...int) { cz := C.int(msDelay) C.scroll(cx, cy, cz) + MilliSleep(MouseSleep) +} + +// ScrollRelative scroll mouse with relative +func ScrollRelative(x, y int, args ...int) { + mx, my := MoveArgs(x, y) + Scroll(mx, my, args...) } // SetMouseDelay set mouse delay @@ -645,6 +678,7 @@ func KeyTap(tapKey string, args ...interface{}) string { C.free(unsafe.Pointer(amod)) C.free(unsafe.Pointer(amodt)) + MilliSleep(KeySleep) return C.GoString(str) } @@ -695,6 +729,7 @@ func KeyToggle(key string, args ...string) string { C.free(unsafe.Pointer(cmKey)) C.free(unsafe.Pointer(cmKeyT)) + MilliSleep(KeySleep) return C.GoString(str) } @@ -811,6 +846,7 @@ func TypeStr(str string, args ...float64) { MicroSleep(tm) // } } + MilliSleep(KeySleep) } // PasteStr paste a string, support UTF-8 @@ -989,7 +1025,7 @@ func FindCBitmap(bmp CBitmap, args ...interface{}) (int, int) { // FindBitmap find the bitmap's pos // -// robotgo.FindBitmap(bitmap, subbitamp C.MMBitmapRef, tolerance float64) +// robotgo.FindBitmap(bitmap, source_bitamp C.MMBitmapRef, tolerance float64) // // |tolerance| should be in the range 0.0f - 1.0f, denoting how closely the // colors in the bitmaps need to match, with 0 being exact and 1 being any. @@ -1023,7 +1059,7 @@ func FindBitmap(bit C.MMBitmapRef, args ...interface{}) (int, int) { // FindPic finding the image by path // -// robotgo.FindPic(path string, subbitamp C.MMBitmapRef, tolerance float64) +// robotgo.FindPic(path string, source_bitamp C.MMBitmapRef, tolerance float64) // // This method only automatically free the internal bitmap, // use `defer robotgo.FreeBitmap(bit)` to free the bitmap @@ -1435,32 +1471,32 @@ func ShowAlert(title, msg string, args ...string) bool { var ( // title string // msg string - defaultButton = "Ok" - cancelButton = "Cancel" + defaultBtn = "Ok" + cancelBtn = "Cancel" ) if len(args) > 0 { // title = args[0] // msg = args[1] - defaultButton = args[0] + defaultBtn = args[0] } if len(args) > 1 { - cancelButton = args[1] + cancelBtn = args[1] } - atitle := C.CString(title) - amsg := C.CString(msg) - adefaultButton := C.CString(defaultButton) - acancelButton := C.CString(cancelButton) + cTitle := C.CString(title) + cMsg := C.CString(msg) + defaultButton := C.CString(defaultBtn) + cancelButton := C.CString(cancelBtn) - cbool := C.show_alert(atitle, amsg, adefaultButton, acancelButton) + cbool := C.show_alert(cTitle, cMsg, defaultButton, cancelButton) ibool := int(cbool) - C.free(unsafe.Pointer(atitle)) - C.free(unsafe.Pointer(amsg)) - C.free(unsafe.Pointer(adefaultButton)) - C.free(unsafe.Pointer(acancelButton)) + C.free(unsafe.Pointer(cTitle)) + C.free(unsafe.Pointer(cMsg)) + C.free(unsafe.Pointer(defaultButton)) + C.free(unsafe.Pointer(cancelButton)) return ibool == 0 } From ad5a1aa7ca7d1a1c4165639caa1ea7d54b35f268 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 13 Oct 2021 15:15:09 -0400 Subject: [PATCH 107/327] update screen code --- screen/screengrab_c.h | 62 ++++++++++++++----------------------------- 1 file changed, 20 insertions(+), 42 deletions(-) diff --git a/screen/screengrab_c.h b/screen/screengrab_c.h index 358f6a3e..e3318c46 100644 --- a/screen/screengrab_c.h +++ b/screen/screengrab_c.h @@ -27,10 +27,7 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect){ CGDirectDisplayID displayID = CGMainDisplayID(); CGImageRef image = CGDisplayCreateImageForRect(displayID, - CGRectMake(rect.origin.x, - rect.origin.y, - rect.size.w, - rect.size.h)); + CGRectMake(rect.origin.x, rect.origin.y, rect.size.w, rect.size.h)); if (!image) { return NULL; } @@ -43,15 +40,12 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect){ CFDataGetBytes(imageData, CFRangeMake(0, bufferSize), buffer); - bitmap = createMMBitmap(buffer, - CGImageGetWidth(image), - CGImageGetHeight(image), - CGImageGetBytesPerRow(image), - CGImageGetBitsPerPixel(image), + bitmap = createMMBitmap(buffer, + CGImageGetWidth(image),CGImageGetHeight(image), + CGImageGetBytesPerRow(image), CGImageGetBitsPerPixel(image), CGImageGetBitsPerPixel(image) / 8); CFRelease(imageData); - CGImageRelease(image); return bitmap; @@ -59,22 +53,16 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect){ MMBitmapRef bitmap; Display *display = XOpenDisplay(NULL); - XImage *image = XGetImage(display, - XDefaultRootWindow(display), - (int)rect.origin.x, - (int)rect.origin.y, - (unsigned int)rect.size.w, - (unsigned int)rect.size.h, - AllPlanes, ZPixmap); + XImage *image = XGetImage(display, XDefaultRootWindow(display), + (int)rect.origin.x, (int)rect.origin.y, + (unsigned int)rect.size.w,(unsigned int)rect.size.h, + AllPlanes, ZPixmap); XCloseDisplay(display); - if (image == NULL) return NULL; - - bitmap = createMMBitmap((uint8_t *)image->data, - rect.size.w, - rect.size.h, - (size_t)image->bytes_per_line, - (uint8_t)image->bits_per_pixel, - (uint8_t)image->bits_per_pixel / 8); + if (image == NULL) { return NULL; } + + bitmap = createMMBitmap((uint8_t *)image->data, + rect.size.w, rect.size.h, (size_t)image->bytes_per_line, + (uint8_t)image->bits_per_pixel, (uint8_t)image->bits_per_pixel / 8); image->data = NULL; /* Steal ownership of bitmap data so we don't have to * copy it. */ XDestroyImage(image); @@ -101,7 +89,7 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect){ bi.bmiHeader.biClrImportant = 0; screen = GetDC(NULL); /* Get entire screen */ - if (screen == NULL) return NULL; + if (screen == NULL) { return NULL; } /* Get screen data in display device context. */ dib = CreateDIBSection(screen, &bi, DIB_RGB_COLORS, &data, NULL, 0); @@ -109,30 +97,20 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect){ /* Copy the data into a bitmap struct. */ if ((screenMem = CreateCompatibleDC(screen)) == NULL || SelectObject(screenMem, dib) == NULL || - !BitBlt(screenMem, - (int)0, - (int)0, - (int)rect.size.w, - (int)rect.size.h, - screen, - rect.origin.x, - rect.origin.y, - SRCCOPY)) { + !BitBlt(screenMem, (int)0, (int)0, (int)rect.size.w, (int)rect.size.h, + screen, rect.origin.x, rect.origin.y, SRCCOPY) + ) { /* Error copying data. */ ReleaseDC(NULL, screen); DeleteObject(dib); - if (screenMem != NULL) DeleteDC(screenMem); + if (screenMem != NULL) { DeleteDC(screenMem); } return NULL; } - bitmap = createMMBitmap(NULL, - rect.size.w, - rect.size.h, - 4 * rect.size.w, - (uint8_t)bi.bmiHeader.biBitCount, - 4); + bitmap = createMMBitmap(NULL, rect.size.w, rect.size.h, 4 * rect.size.w, + (uint8_t)bi.bmiHeader.biBitCount, 4); /* Copy the data to our pixel buffer. */ if (bitmap != NULL) { From 7643a714b8d481b5d3067117c1fbb15353158070 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 13 Oct 2021 15:23:36 -0400 Subject: [PATCH 108/327] Update README.md --- README.md | 30 ++++++++++++++++++++---------- README_zh.md | 30 ++++++++++++++++++++---------- 2 files changed, 40 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index cae9d07d..edc3e502 100644 --- a/README.md +++ b/README.md @@ -131,8 +131,12 @@ import ( func main() { robotgo.ScrollMouse(10, "up") robotgo.Scroll(100, 200) + robotgo.MilliSleep(100) + robotgo.ScrollRelative(10, -100) - robotgo.Move(10, 10) + robotgo.MouseSleep = 100 + robotgo.Move(10, 20) + robotgo.MoveRelative(0, -10) robotgo.Drag(10, 10) robotgo.Click("left", true) @@ -163,6 +167,7 @@ func main() { // ustr := uint32(robotgo.CharCodeAt("Test", 0)) // robotgo.UnicodeType(ustr) + robotgo.KeySleep = 100 robotgo.KeyTap("enter") // robotgo.TypeStr("en") robotgo.KeyTap("i", "alt", "command") @@ -170,6 +175,7 @@ func main() { arr := []string{"alt", "command"} robotgo.KeyTap("i", arr) + robotgo.MilliSleep(100) robotgo.KeyToggle("a", "down") robotgo.WriteAll("Test") @@ -249,25 +255,29 @@ func main() { func opencv() { name := "test.png" name1 := "test_001.png" - robotgo.SaveCapture(name, 10, 10, 30, 30) - robotgo.SaveCapture(name1) + robotgo.SaveCapture(name1, 10, 10, 30, 30) + robotgo.SaveCapture(name) fmt.Print("gcv find image: ") - fmt.Println(gcv.FindImgFile(name, name1)) + fmt.Println(gcv.FindImgFile(name1, name)) + fmt.Println(gcv.FindAllImgFile(name1, name)) - bit := robotgo.OpenBitmap(name) + bit := robotgo.OpenBitmap(name1) defer robotgo.FindBitmap(bit) fmt.Print("find bitmap: ") fmt.Println(robotgo.FindBitmap(bit)) - bit0 := robotgo.CaptureScreen() - img := robotgo.ToImage(bit0) - bit1 := robotgo.CaptureScreen(10, 10, 30, 30) - img1 := robotgo.ToImage(bit1) - defer robotgo.FreeBitmapArr(bit0, bit1) + // bit0 := robotgo.CaptureScreen() + // img := robotgo.ToImage(bit0) + // bit1 := robotgo.CaptureScreen(10, 10, 30, 30) + // img1 := robotgo.ToImage(bit1) + // defer robotgo.FreeBitmapArr(bit0, bit1) + img := robotgo.CaptureImg() + img1 := robotgo.CaptureImg(10, 10, 30, 30) fmt.Print("gcv find image: ") fmt.Println(gcv.FindImg(img1, img)) + fmt.Println(gcv.FindAllImg(img1, img)) } ``` diff --git a/README_zh.md b/README_zh.md index c6c17420..71eba4e6 100644 --- a/README_zh.md +++ b/README_zh.md @@ -129,8 +129,12 @@ import ( func main() { robotgo.ScrollMouse(10, "up") robotgo.Scroll(100, 200) + robotgo.MilliSleep(100) + robotgo.ScrollRelative(10, -100) - robotgo.Move(10, 10) + robotgo.MouseSleep = 100 + robotgo.Move(10, 20) + robotgo.MoveRelative(0, -10) robotgo.Drag(10, 10) robotgo.Click("left", true) @@ -161,6 +165,7 @@ func main() { // ustr := uint32(robotgo.CharCodeAt("テストする", 0)) // robotgo.UnicodeType(ustr) + robotgo.KeySleep = 100 robotgo.KeyTap("enter") // robotgo.TypeStr("en") robotgo.KeyTap("i", "alt", "command") @@ -168,6 +173,7 @@ func main() { arr := []string{"alt", "command"} robotgo.KeyTap("i", arr) + robotgo.MilliSleep(100) robotgo.KeyToggle("a", "down") robotgo.WriteAll("テストする") @@ -247,25 +253,29 @@ func main() { func opencv() { name := "test.png" name1 := "test_001.png" - robotgo.SaveCapture(name, 10, 10, 30, 30) - robotgo.SaveCapture(name1) + robotgo.SaveCapture(name1, 10, 10, 30, 30) + robotgo.SaveCapture(name) fmt.Print("gcv find image: ") - fmt.Println(gcv.FindImgFile(name, name1)) + fmt.Println(gcv.FindImgFile(name1, name)) + fmt.Println(gcv.FindAllImgFile(name1, name)) - bit := robotgo.OpenBitmap(name) + bit := robotgo.OpenBitmap(name1) defer robotgo.FindBitmap(bit) fmt.Print("find bitmap: ") fmt.Println(robotgo.FindBitmap(bit)) - bit0 := robotgo.CaptureScreen() - img := robotgo.ToImage(bit0) - bit1 := robotgo.CaptureScreen(10, 10, 30, 30) - img1 := robotgo.ToImage(bit1) - defer robotgo.FreeBitmapArr(bit0, bit1) + // bit0 := robotgo.CaptureScreen() + // img := robotgo.ToImage(bit0) + // bit1 := robotgo.CaptureScreen(10, 10, 30, 30) + // img1 := robotgo.ToImage(bit1) + // defer robotgo.FreeBitmapArr(bit0, bit1) + img := robotgo.CaptureImg() + img1 := robotgo.CaptureImg(10, 10, 30, 30) fmt.Print("gcv find image: ") fmt.Println(gcv.FindImg(img1, img)) + fmt.Println(gcv.FindAllImg(img1, img)) } ``` From db6723eb00020f845a05e389c10bfdcca7762bbf Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 18 Oct 2021 10:52:35 -0400 Subject: [PATCH 109/327] Update README.md --- README.md | 18 +++++++++++++++++- README_zh.md | 18 +++++++++++++++++- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index edc3e502..80c9e107 100644 --- a/README.md +++ b/README.md @@ -226,7 +226,6 @@ import ( "fmt" "github.com/go-vgo/robotgo" - "github.com/vcaesar/gcv" ) func main() { @@ -251,6 +250,23 @@ func main() { robotgo.SaveBitmap(bitmap, "test.png") } +``` + +#### [OpenCV](https://github.com/vcaesar/gcv) + +```Go +package main + +import ( + "fmt" + + "github.com/go-vgo/robotgo" + "github.com/vcaesar/gcv" +) + +func main() { + opencv() +} func opencv() { name := "test.png" diff --git a/README_zh.md b/README_zh.md index 71eba4e6..b971b07e 100644 --- a/README_zh.md +++ b/README_zh.md @@ -224,7 +224,6 @@ import ( "fmt" "github.com/go-vgo/robotgo" - "github.com/vcaesar/gcv" ) func main() { @@ -249,6 +248,23 @@ func main() { robotgo.SaveBitmap(bitmap, "test.png") } +``` + +#### [OpenCV](https://github.com/vcaesar/gcv) + +```Go +package main + +import ( + "fmt" + + "github.com/go-vgo/robotgo" + "github.com/vcaesar/gcv" +) + +func main() { + opencv() +} func opencv() { name := "test.png" From 3b92bb6207ea6987f85be9971744c5af9445746d Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 18 Oct 2021 10:55:14 -0400 Subject: [PATCH 110/327] add more image function --- img.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/img.go b/img.go index 69d2d302..6409cf82 100644 --- a/img.go +++ b/img.go @@ -72,6 +72,21 @@ func ByteToImg(b []byte) (image.Image, error) { return imgo.ByteToImg(b) } +// ImgSize get the file image size +func ImgSize(path string) (int, int, error) { + return imgo.GetSize(path) +} + +// Width return the image.Image width +func Width(img image.Image) int { + return img.Bounds().Max.X +} + +// Height return the image.Image height +func Height(img image.Image) int { + return img.Bounds().Max.Y +} + // RGBAToBitmap convert the standard image.RGBA to Bitmap func RGBAToBitmap(r1 *image.RGBA) (bit Bitmap) { bit.Width = r1.Bounds().Size().X From 9393d57c208d0b586cbe80651d08e2031eb04514 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 18 Oct 2021 11:36:24 -0400 Subject: [PATCH 111/327] Update key sleep and fix typo --- robotgo.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/robotgo.go b/robotgo.go index e68a3b14..fc4ff135 100644 --- a/robotgo.go +++ b/robotgo.go @@ -137,7 +137,7 @@ func MicroSleep(tm float64) { C.microsleep(C.double(tm)) } -// GoString teans C.char to string +// GoString trans C.char to string func GoString(char *C.char) string { return C.GoString(char) } @@ -386,7 +386,6 @@ func CheckMouse(btn string) C.MMMouseButton { // MoveMouse move the mouse func MoveMouse(x, y int) { - // C.size_t int Move(x, y) } @@ -463,7 +462,7 @@ func MoveSmooth(x, y int, args ...interface{}) bool { return bool(cbool) } -// MoveArgs move mose relative args +// MoveArgs move mouse relative args func MoveArgs(x, y int) (int, int) { mx, my := GetMousePos() mx = mx + x @@ -629,6 +628,7 @@ func KeyTap(tapKey string, args ...interface{}) string { str := C.key_Taps(zkey, (**C.char)(unsafe.Pointer(&ckeyArr[0])), C.int(num), 0) + MilliSleep(KeySleep) return C.GoString(str) } @@ -668,6 +668,7 @@ func KeyTap(tapKey string, args ...interface{}) string { str := C.key_Taps(zkey, (**C.char)(unsafe.Pointer(&ckeyArr[0])), C.int(num), C.int(keyDelay)) + MilliSleep(KeySleep) return C.GoString(str) } @@ -699,6 +700,7 @@ func KeyToggle(key string, args ...string) string { } str := C.key_Toggles(ckey, (**C.char)(unsafe.Pointer(&ckeyArr[0])), C.int(num)) + MilliSleep(KeySleep) return C.GoString(str) } @@ -736,7 +738,7 @@ func KeyToggle(key string, args ...string) string { // KeyPress press key string func KeyPress(key string) { KeyDown(key) - Sleep(15 + rand.Intn(10)) + Sleep(1 + rand.Intn(3)) KeyUp(key) } From 86da52b96dce755d291f8456ca045e03b37e4eaf Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 18 Oct 2021 12:43:34 -0400 Subject: [PATCH 112/327] Update examples and godoc --- examples/key/main.go | 12 +++++++----- examples/mouse/main.go | 10 ++++++---- robotgo.go | 2 +- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/examples/key/main.go b/examples/key/main.go index 1caec80f..d4aa8b3f 100644 --- a/examples/key/main.go +++ b/examples/key/main.go @@ -20,13 +20,13 @@ import ( func typeStr() { // importing "Hello World" robotgo.TypeStr("Hello World!", 1.0) - + robotgo.KeySleep = 100 robotgo.TypeStr("だんしゃり") - robotgo.MicroSleep(10.2) - robotgo.TypeStr("Hi galaxy. こんにちは世界.") - robotgo.Sleep(2) - // robotgo.TypeStr("So, hi, bye!") + robotgo.TypeStr("Hi galaxy. こんにちは世界. 你好, 再见!") + + robotgo.Sleep(1) + robotgo.TypeStr("So, hi, bye!") robotgo.MilliSleep(100) ustr := uint32(robotgo.CharCodeAt("So, hi, bye!", 0)) @@ -38,6 +38,7 @@ func typeStr() { func keyTap() { // press "enter" robotgo.KeyTap("enter") + robotgo.KeySleep = 200 robotgo.KeyTap("a") robotgo.MilliSleep(100) robotgo.KeyTap("a", "ctrl") @@ -71,6 +72,7 @@ func keyTap() { } func keyToggle() { + // robotgo.KeySleep = 150 robotgo.KeyToggle("a", "down") robotgo.KeyToggle("a", "down", "alt") robotgo.Sleep(1) diff --git a/examples/mouse/main.go b/examples/mouse/main.go index e4ecfb12..9380fb6f 100644 --- a/examples/mouse/main.go +++ b/examples/mouse/main.go @@ -18,11 +18,12 @@ import ( ) func move() { + robotgo.MouseSleep = 100 robotgo.Move(100, 200) robotgo.MoveRelative(10, -200) // move the mouse to 100, 200 - robotgo.MoveMouse(100, 200) + robotgo.Move(100, 200) robotgo.Drag(10, 10) robotgo.Drag(20, 20, "right") @@ -37,7 +38,8 @@ func move() { for i := 0; i < 1080; i += 1000 { fmt.Println(i) - robotgo.MoveMouse(800, i) + // MoveMouse(800, i) + robotgo.Move(800, i) } } @@ -50,7 +52,7 @@ func click() { robotgo.Click("right", false) // double click the left mouse button - robotgo.MouseClick("left", true) + robotgo.Click("left", true) } func get() { @@ -61,7 +63,7 @@ func get() { fmt.Println("mouse...", "586") } - robotgo.MoveMouse(x, y) + robotgo.Move(x, y) } func toggleAndScroll() { diff --git a/robotgo.go b/robotgo.go index fc4ff135..8e8ba7c9 100644 --- a/robotgo.go +++ b/robotgo.go @@ -167,7 +167,7 @@ func U32ToHex(hex C.uint32_t) C.MMRGBHex { return C.MMRGBHex(hex) } -// U8ToHex teans *C.uint8_t to C.MMRGBHex +// U8ToHex trans *C.uint8_t to C.MMRGBHex func U8ToHex(hex *C.uint8_t) C.MMRGBHex { return C.MMRGBHex(*hex) } From 10ae65cc6c3867c23687aae92f9d407566356259 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 28 Oct 2021 13:21:25 -0400 Subject: [PATCH 113/327] Update README.md --- README.md | 11 ++++++++++- README_zh.md | 11 ++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 80c9e107..3d7f5da8 100644 --- a/README.md +++ b/README.md @@ -240,6 +240,7 @@ func main() { bit2 := robotgo.ToCBitmap(robotgo.ImgToBitmap(img)) fx, fy := robotgo.FindBitmap(bit2) fmt.Println("FindBitmap------ ", fx, fy) + robotgo.Move(fx, fy) arr := robotgo.FindEveryBitmap(bit2) fmt.Println("Find every bitmap: ", arr) @@ -259,6 +260,7 @@ package main import ( "fmt" + "math/rand" "github.com/go-vgo/robotgo" "github.com/vcaesar/gcv" @@ -293,7 +295,14 @@ func opencv() { fmt.Print("gcv find image: ") fmt.Println(gcv.FindImg(img1, img)) - fmt.Println(gcv.FindAllImg(img1, img)) + fmt.Println() + + res := gcv.FindAllImg(img1, img) + fmt.Println(res[0].TopLeft.Y, res[0].Rects.TopLeft.X, res) + x, y := res[0].TopLeft.X, res[0].TopLeft.Y + robotgo.Move(x, y-rand.Intn(5)) + robotgo.MilliSleep(100) + robotgo.Click() } ``` diff --git a/README_zh.md b/README_zh.md index b971b07e..5a2d8e61 100644 --- a/README_zh.md +++ b/README_zh.md @@ -238,6 +238,7 @@ func main() { bit2 := robotgo.ToCBitmap(robotgo.ImgToBitmap(img)) fx, fy := robotgo.FindBitmap(bit2) fmt.Println("FindBitmap------ ", fx, fy) + robotgo.Move(fx, fy) arr := robotgo.FindEveryBitmap(bit2) fmt.Println("Find every bitmap: ", arr) @@ -257,6 +258,7 @@ package main import ( "fmt" + "math/rand" "github.com/go-vgo/robotgo" "github.com/vcaesar/gcv" @@ -291,7 +293,14 @@ func opencv() { fmt.Print("gcv find image: ") fmt.Println(gcv.FindImg(img1, img)) - fmt.Println(gcv.FindAllImg(img1, img)) + fmt.Println() + + res := gcv.FindAllImg(img1, img) + fmt.Println(res[0].TopLeft.Y, res[0].Rects.TopLeft.X, res) + x, y := res[0].TopLeft.X, res[0].TopLeft.Y + robotgo.Move(x, y-rand.Intn(5)) + robotgo.MilliSleep(100) + robotgo.Click() } ``` From 341f2281d6e753f06fb83a34d31637a340d8796f Mon Sep 17 00:00:00 2001 From: vcaesar Date: Fri, 29 Oct 2021 11:51:43 -0400 Subject: [PATCH 114/327] Add get the screen rect support --- README.md | 1 + bitmap/goBitmap.h | 2 +- robotgo.go | 51 +++++++++++++++++++++++++++++++++--------- screen/goScreen.h | 2 +- screen/screen_c.h | 56 +++++++++++++++++++++++++++++++++++++++++------ 5 files changed, 93 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 3d7f5da8..d9b71718 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ RobotGo supports Mac, Windows, and Linux(X11); and robotgo supports arm64 and x8 - [Chinese Docs](https://github.com/go-vgo/robotgo/blob/master/docs/doc_zh.md) ## Binding: +[ADB](https://github.com/vcaesar/adb), packaging android adb API. [Robotn](https://github.com/vcaesar/robotn), binding JavaScript and other, support more language. diff --git a/bitmap/goBitmap.h b/bitmap/goBitmap.h index 68f16b6d..429fa397 100644 --- a/bitmap/goBitmap.h +++ b/bitmap/goBitmap.h @@ -141,7 +141,7 @@ char *tostring_bitmap(MMBitmapRef bitmap){ return buf; } -// out with size 200 is enough +// char out size 200 is enough bool bitmap_str(MMBitmapRef bitmap, char *out){ if (!bitmap_ready(bitmap)) { return false; } sprintf(out, " 0 { + display = displayId[0] + } + + rect := C.getScreenRect(C.int32_t(display)) + return Rect{ + Point{ + X: int(rect.origin.x), + Y: int(rect.origin.y), + }, + Size{ + W: int(rect.size.w), + H: int(rect.size.h), + }, + } +} + // Scale get the screen scale func Scale() int { dpi := map[int]int{ @@ -322,7 +353,7 @@ func CaptureScreen(args ...int) C.MMBitmapRef { x = 0 y = 0 - // Get screen size. + // Get the main screen size. displaySize := C.getMainDisplaySize() w = displaySize.w h = displaySize.h @@ -1098,7 +1129,7 @@ func FreeMMPointArr(pointArray C.MMPointArrayRef) { } // FindEveryBitmap find the every bitmap -func FindEveryBitmap(bit C.MMBitmapRef, args ...interface{}) (posArr []MPoint) { +func FindEveryBitmap(bit C.MMBitmapRef, args ...interface{}) (posArr []Point) { var ( sbit C.MMBitmapRef tolerance C.float = 0.01 @@ -1142,7 +1173,7 @@ func FindEveryBitmap(bit C.MMBitmapRef, args ...interface{}) (posArr []MPoint) { cArray := pos.array gSlice := (*[(1 << 28) - 1]C.MMPoint)(unsafe.Pointer(cArray))[:cSize:cSize] for i := 0; i < len(gSlice); i++ { - posArr = append(posArr, MPoint{ + posArr = append(posArr, Point{ X: int(gSlice[i].x), Y: int(gSlice[i].y), }) @@ -1353,7 +1384,7 @@ func FindColorCS(color CHex, x, y, w, h int, args ...float64) (int, int) { } // FindEveryColor find every color -func FindEveryColor(color CHex, args ...interface{}) (posArr []MPoint) { +func FindEveryColor(color CHex, args ...interface{}) (posArr []Point) { var ( bitmap C.MMBitmapRef tolerance C.float = 0.01 @@ -1397,7 +1428,7 @@ func FindEveryColor(color CHex, args ...interface{}) (posArr []MPoint) { cArray := pos.array gSlice := (*[(1 << 28) - 1]C.MMPoint)(unsafe.Pointer(cArray))[:cSize:cSize] for i := 0; i < len(gSlice); i++ { - posArr = append(posArr, MPoint{ + posArr = append(posArr, Point{ X: int(gSlice[i].x), Y: int(gSlice[i].y), }) diff --git a/screen/goScreen.h b/screen/goScreen.h index 648f73f0..b2d64714 100644 --- a/screen/goScreen.h +++ b/screen/goScreen.h @@ -97,7 +97,7 @@ char* get_XDisplay_name(){ // capture_screen capture screen MMBitmapRef capture_screen(int32_t x, int32_t y, int32_t w, int32_t h){ - // if (){ + // if () { // x = 0; // y = 0; // // Get screen size. diff --git a/screen/screen_c.h b/screen/screen_c.h index 9f9f2cd9..ec4fb412 100644 --- a/screen/screen_c.h +++ b/screen/screen_c.h @@ -19,15 +19,57 @@ MMSizeInt32 getMainDisplaySize(void){ Display *display = XGetMainDisplay(); const int screen = DefaultScreen(display); - return MMSizeInt32Make((int32_t)DisplayWidth(display, screen), - (int32_t)DisplayHeight(display, screen)); + return MMSizeInt32Make( + (int32_t)DisplayWidth(display, screen), + (int32_t)DisplayHeight(display, screen)); #elif defined(IS_WINDOWS) if (GetSystemMetrics(SM_CMONITORS) == 1) { - return MMSizeInt32Make((int32_t)GetSystemMetrics(SM_CXSCREEN), - (int32_t)GetSystemMetrics(SM_CYSCREEN)); - } else { - return MMSizeInt32Make((int32_t)GetSystemMetrics(SM_CXVIRTUALSCREEN), - (int32_t)GetSystemMetrics(SM_CYVIRTUALSCREEN)); + return MMSizeInt32Make( + (int32_t)GetSystemMetrics(SM_CXSCREEN), + (int32_t)GetSystemMetrics(SM_CYSCREEN)); + } else { + return MMSizeInt32Make( + (int32_t)GetSystemMetrics(SM_CXVIRTUALSCREEN), + (int32_t)GetSystemMetrics(SM_CYVIRTUALSCREEN)); + } +#endif +} + +MMRectInt32 getScreenRect(int32_t display_id) { +#if defined(IS_MACOSX) + CGDirectDisplayID displayID = (CGDirectDisplayID) display_id; + if (display_id == 0) { + displayID = CGMainDisplayID(); + } + CGRect displayRect = CGDisplayBounds(displayID); + + CGPoint point = displayRect.origin; + CGSize size = displayRect.size; + return MMRectInt32Make( + (int32_t)point.x, (int32_t)point.y, + (int32_t)size.width, (int32_t)size.height); +#elif defined(USE_X11) + Display *display = XGetMainDisplay(); + const int screen = DefaultScreen(display); + + return MMRectInt32Make( + (int32_t)0, + (int32_t)0, + (int32_t)DisplayWidth(display, screen), + (int32_t)DisplayHeight(display, screen)); +#elif defined(IS_WINDOWS) + if (GetSystemMetrics(SM_CMONITORS) == 1) { + return MMRectInt32Make( + (int32_t)GetSystemMetrics(SM_XSCREEN), + (int32_t)GetSystemMetrics(SM_YSCREEN), + (int32_t)GetSystemMetrics(SM_CXSCREEN), + (int32_t)GetSystemMetrics(SM_CYSCREEN)); + } else { + return MMRectInt32Make( + (int32_t)GetSystemMetrics(SM_XVIRTUALSCREEN), + (int32_t)GetSystemMetrics(SM_YVIRTUALSCREEN), + (int32_t)GetSystemMetrics(SM_CXVIRTUALSCREEN), + (int32_t)GetSystemMetrics(SM_CYVIRTUALSCREEN)); } #endif } From 105487021351cacbab20ddc4f8209ff24a9c6060 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Fri, 29 Oct 2021 11:57:09 -0400 Subject: [PATCH 115/327] Update windows code fixed build --- screen/screen_c.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/screen/screen_c.h b/screen/screen_c.h index ec4fb412..bc33e977 100644 --- a/screen/screen_c.h +++ b/screen/screen_c.h @@ -60,8 +60,8 @@ MMRectInt32 getScreenRect(int32_t display_id) { #elif defined(IS_WINDOWS) if (GetSystemMetrics(SM_CMONITORS) == 1) { return MMRectInt32Make( - (int32_t)GetSystemMetrics(SM_XSCREEN), - (int32_t)GetSystemMetrics(SM_YSCREEN), + (int32_t)0, + (int32_t)0, (int32_t)GetSystemMetrics(SM_CXSCREEN), (int32_t)GetSystemMetrics(SM_CYSCREEN)); } else { From 19502c79cea89d97b8b94e3b190e690de95f574c Mon Sep 17 00:00:00 2001 From: vcaesar Date: Fri, 5 Nov 2021 14:07:15 -0400 Subject: [PATCH 116/327] Update OpenCV README.md and CI --- .circleci/config.yml | 2 +- .circleci/images/primary/Dockerfile | 2 +- README.md | 8 ++++++++ README_zh.md | 8 ++++++++ appveyor.yml | 2 +- 5 files changed, 19 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index bd1b612b..ae0745b5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,7 +5,7 @@ jobs: docker: # using custom image, see .circleci/images/primary/Dockerfile # - image: govgo/robotgoci:1.10.3 - - image: golang:1.17.1 + - image: golang:1.17.3 working_directory: /gopath/src/github.com/go-vgo/robotgo steps: - checkout diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index a08ffa75..3d2036ba 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.7.2-stretch AS build +FROM golang:1.7.3-stretch AS build # FROM govgo/go:1.11.1 RUN apt update && apt install -y --no-install-recommends \ diff --git a/README.md b/README.md index d9b71718..9eb02dc9 100644 --- a/README.md +++ b/README.md @@ -304,6 +304,14 @@ func opencv() { robotgo.Move(x, y-rand.Intn(5)) robotgo.MilliSleep(100) robotgo.Click() + + res = gcv.FindAll(img1, img) // use find template and sift + fmt.Println("find all: ", res) + res1 := gcv.Find(img1, img) + fmt.Println("find: ", res1) + + x, y = gcv.FindX(img1, img) + fmt.Println(x, y) } ``` diff --git a/README_zh.md b/README_zh.md index 5a2d8e61..e178ac25 100644 --- a/README_zh.md +++ b/README_zh.md @@ -301,6 +301,14 @@ func opencv() { robotgo.Move(x, y-rand.Intn(5)) robotgo.MilliSleep(100) robotgo.Click() + + res = gcv.FindAll(img1, img) // use find template and sift + fmt.Println("find all: ", res) + res1 := gcv.Find(img1, img) + fmt.Println("find: ", res1) + + x, y = gcv.FindX(img1, img) + fmt.Println(x, y) } ``` diff --git a/appveyor.yml b/appveyor.yml index 05601ec6..1ca1af88 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,7 +34,7 @@ environment: PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% # - COMPILER: MINGW_W64 # ARCHITECTURE: x64 - GOVERSION: 1.17.2 + GOVERSION: 1.17.3 # GOPATH: c:\gopath # scripts that run after cloning repository From 27bc0e2d97a836e9038eb6786ddb44716f37324f Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sat, 6 Nov 2021 14:45:06 -0400 Subject: [PATCH 117/327] add color and mouse pos picker cmd support --- {examples/color-picker => cmd/color-pos}/main.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) rename {examples/color-picker => cmd/color-pos}/main.go (69%) diff --git a/examples/color-picker/main.go b/cmd/color-pos/main.go similarity index 69% rename from examples/color-picker/main.go rename to cmd/color-pos/main.go index 751b26d1..4383a45b 100644 --- a/examples/color-picker/main.go +++ b/cmd/color-pos/main.go @@ -16,15 +16,16 @@ func colorPicker() { fmt.Println("color: #", clo) // clipboard - err := robotgo.WriteAll("#" + clo) + s1 := fmt.Sprint(x, ", ", y) + ": " + "#" + clo + err := robotgo.WriteAll(s1) if err != nil { - fmt.Println("err: ", err) + fmt.Println("clipboard err: ", err) } } } func main() { - fmt.Println("color picker...") + fmt.Println("color picker: ") for { colorPicker() From 4782da7e770d40f94e6b1044b575def6bc41b93e Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sat, 6 Nov 2021 15:15:34 -0400 Subject: [PATCH 118/327] remove unless files and move windows cdeps to win --- base/png_io_c.h | 6 +- cdeps/win/amd/win64/png.h | 2309 ------------------------ cdeps/win/amd/win64/pngconf.h | 649 ------- cdeps/win/amd/win64/pnglibconf.h | 181 -- cdeps/win/amd/win64/zconf.h | 428 ----- cdeps/win/amd/win64/zlib.h | 1613 ----------------- cdeps/win/{amd/win32 => }/png.h | 0 cdeps/win/{amd/win32 => }/pngconf.h | 0 cdeps/win/{amd/win32 => }/pnglibconf.h | 0 cdeps/win/{amd/win32 => }/zconf.h | 0 cdeps/win/{amd/win32 => }/zlib.h | 0 11 files changed, 1 insertion(+), 5185 deletions(-) delete mode 100755 cdeps/win/amd/win64/png.h delete mode 100755 cdeps/win/amd/win64/pngconf.h delete mode 100755 cdeps/win/amd/win64/pnglibconf.h delete mode 100755 cdeps/win/amd/win64/zconf.h delete mode 100755 cdeps/win/amd/win64/zlib.h rename cdeps/win/{amd/win32 => }/png.h (100%) rename cdeps/win/{amd/win32 => }/pngconf.h (100%) rename cdeps/win/{amd/win32 => }/pnglibconf.h (100%) rename cdeps/win/{amd/win32 => }/zconf.h (100%) rename cdeps/win/{amd/win32 => }/zlib.h (100%) diff --git a/base/png_io_c.h b/base/png_io_c.h index 9609e283..4968de69 100644 --- a/base/png_io_c.h +++ b/base/png_io_c.h @@ -6,11 +6,7 @@ #elif defined(USE_X11) #include #elif defined(IS_WINDOWS) - #if defined (__x86_64__) - #include "../cdeps/win/amd/win64/png.h" - #else - #include "../cdeps/win/amd/win32/png.h" - #endif + #include "../cdeps/win/png.h" #endif #include /* fopen() */ diff --git a/cdeps/win/amd/win64/png.h b/cdeps/win/amd/win64/png.h deleted file mode 100755 index 9e9b46c0..00000000 --- a/cdeps/win/amd/win64/png.h +++ /dev/null @@ -1,2309 +0,0 @@ - -/* png.h - header file for PNG reference library - * - * libpng version 1.5.2 - March 31, 2011 - * Copyright (c) 1998-2011 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This code is released under the libpng license (See LICENSE, below) - * - * Authors and maintainers: - * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat - * libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger - * libpng versions 0.97, January 1998, through 1.5.2 - March 31, 2011: Glenn - * See also "Contributing Authors", below. - * - * Note about libpng version numbers: - * - * Due to various miscommunications, unforeseen code incompatibilities - * and occasional factors outside the authors' control, version numbering - * on the library has not always been consistent and straightforward. - * The following table summarizes matters since version 0.89c, which was - * the first widely used release: - * - * source png.h png.h shared-lib - * version string int version - * ------- ------ ----- ---------- - * 0.89c "1.0 beta 3" 0.89 89 1.0.89 - * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90] - * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95] - * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96] - * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97] - * 0.97c 0.97 97 2.0.97 - * 0.98 0.98 98 2.0.98 - * 0.99 0.99 98 2.0.99 - * 0.99a-m 0.99 99 2.0.99 - * 1.00 1.00 100 2.1.0 [100 should be 10000] - * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000] - * 1.0.1 png.h string is 10001 2.1.0 - * 1.0.1a-e identical to the 10002 from here on, the shared library - * 1.0.2 source version) 10002 is 2.V where V is the source code - * 1.0.2a-b 10003 version, except as noted. - * 1.0.3 10003 - * 1.0.3a-d 10004 - * 1.0.4 10004 - * 1.0.4a-f 10005 - * 1.0.5 (+ 2 patches) 10005 - * 1.0.5a-d 10006 - * 1.0.5e-r 10100 (not source compatible) - * 1.0.5s-v 10006 (not binary compatible) - * 1.0.6 (+ 3 patches) 10006 (still binary incompatible) - * 1.0.6d-f 10007 (still binary incompatible) - * 1.0.6g 10007 - * 1.0.6h 10007 10.6h (testing xy.z so-numbering) - * 1.0.6i 10007 10.6i - * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0) - * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible) - * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible) - * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) - * 1.0.7 1 10007 (still compatible) - * 1.0.8beta1-4 1 10008 2.1.0.8beta1-4 - * 1.0.8rc1 1 10008 2.1.0.8rc1 - * 1.0.8 1 10008 2.1.0.8 - * 1.0.9beta1-6 1 10009 2.1.0.9beta1-6 - * 1.0.9rc1 1 10009 2.1.0.9rc1 - * 1.0.9beta7-10 1 10009 2.1.0.9beta7-10 - * 1.0.9rc2 1 10009 2.1.0.9rc2 - * 1.0.9 1 10009 2.1.0.9 - * 1.0.10beta1 1 10010 2.1.0.10beta1 - * 1.0.10rc1 1 10010 2.1.0.10rc1 - * 1.0.10 1 10010 2.1.0.10 - * 1.0.11beta1-3 1 10011 2.1.0.11beta1-3 - * 1.0.11rc1 1 10011 2.1.0.11rc1 - * 1.0.11 1 10011 2.1.0.11 - * 1.0.12beta1-2 2 10012 2.1.0.12beta1-2 - * 1.0.12rc1 2 10012 2.1.0.12rc1 - * 1.0.12 2 10012 2.1.0.12 - * 1.1.0a-f - 10100 2.1.1.0a-f (branch abandoned) - * 1.2.0beta1-2 2 10200 2.1.2.0beta1-2 - * 1.2.0beta3-5 3 10200 3.1.2.0beta3-5 - * 1.2.0rc1 3 10200 3.1.2.0rc1 - * 1.2.0 3 10200 3.1.2.0 - * 1.2.1beta1-4 3 10201 3.1.2.1beta1-4 - * 1.2.1rc1-2 3 10201 3.1.2.1rc1-2 - * 1.2.1 3 10201 3.1.2.1 - * 1.2.2beta1-6 12 10202 12.so.0.1.2.2beta1-6 - * 1.0.13beta1 10 10013 10.so.0.1.0.13beta1 - * 1.0.13rc1 10 10013 10.so.0.1.0.13rc1 - * 1.2.2rc1 12 10202 12.so.0.1.2.2rc1 - * 1.0.13 10 10013 10.so.0.1.0.13 - * 1.2.2 12 10202 12.so.0.1.2.2 - * 1.2.3rc1-6 12 10203 12.so.0.1.2.3rc1-6 - * 1.2.3 12 10203 12.so.0.1.2.3 - * 1.2.4beta1-3 13 10204 12.so.0.1.2.4beta1-3 - * 1.0.14rc1 13 10014 10.so.0.1.0.14rc1 - * 1.2.4rc1 13 10204 12.so.0.1.2.4rc1 - * 1.0.14 10 10014 10.so.0.1.0.14 - * 1.2.4 13 10204 12.so.0.1.2.4 - * 1.2.5beta1-2 13 10205 12.so.0.1.2.5beta1-2 - * 1.0.15rc1-3 10 10015 10.so.0.1.0.15rc1-3 - * 1.2.5rc1-3 13 10205 12.so.0.1.2.5rc1-3 - * 1.0.15 10 10015 10.so.0.1.0.15 - * 1.2.5 13 10205 12.so.0.1.2.5 - * 1.2.6beta1-4 13 10206 12.so.0.1.2.6beta1-4 - * 1.0.16 10 10016 10.so.0.1.0.16 - * 1.2.6 13 10206 12.so.0.1.2.6 - * 1.2.7beta1-2 13 10207 12.so.0.1.2.7beta1-2 - * 1.0.17rc1 10 10017 12.so.0.1.0.17rc1 - * 1.2.7rc1 13 10207 12.so.0.1.2.7rc1 - * 1.0.17 10 10017 12.so.0.1.0.17 - * 1.2.7 13 10207 12.so.0.1.2.7 - * 1.2.8beta1-5 13 10208 12.so.0.1.2.8beta1-5 - * 1.0.18rc1-5 10 10018 12.so.0.1.0.18rc1-5 - * 1.2.8rc1-5 13 10208 12.so.0.1.2.8rc1-5 - * 1.0.18 10 10018 12.so.0.1.0.18 - * 1.2.8 13 10208 12.so.0.1.2.8 - * 1.2.9beta1-3 13 10209 12.so.0.1.2.9beta1-3 - * 1.2.9beta4-11 13 10209 12.so.0.9[.0] - * 1.2.9rc1 13 10209 12.so.0.9[.0] - * 1.2.9 13 10209 12.so.0.9[.0] - * 1.2.10beta1-7 13 10210 12.so.0.10[.0] - * 1.2.10rc1-2 13 10210 12.so.0.10[.0] - * 1.2.10 13 10210 12.so.0.10[.0] - * 1.4.0beta1-5 14 10400 14.so.0.0[.0] - * 1.2.11beta1-4 13 10211 12.so.0.11[.0] - * 1.4.0beta7-8 14 10400 14.so.0.0[.0] - * 1.2.11 13 10211 12.so.0.11[.0] - * 1.2.12 13 10212 12.so.0.12[.0] - * 1.4.0beta9-14 14 10400 14.so.0.0[.0] - * 1.2.13 13 10213 12.so.0.13[.0] - * 1.4.0beta15-36 14 10400 14.so.0.0[.0] - * 1.4.0beta37-87 14 10400 14.so.14.0[.0] - * 1.4.0rc01 14 10400 14.so.14.0[.0] - * 1.4.0beta88-109 14 10400 14.so.14.0[.0] - * 1.4.0rc02-08 14 10400 14.so.14.0[.0] - * 1.4.0 14 10400 14.so.14.0[.0] - * 1.4.1beta01-03 14 10401 14.so.14.1[.0] - * 1.4.1rc01 14 10401 14.so.14.1[.0] - * 1.4.1beta04-12 14 10401 14.so.14.1[.0] - * 1.4.1 14 10401 14.so.14.1[.0] - * 1.4.2 14 10402 14.so.14.2[.0] - * 1.4.3 14 10403 14.so.14.3[.0] - * 1.4.4 14 10404 14.so.14.4[.0] - * 1.5.0beta01-58 15 10500 15.so.15.0[.0] - * 1.5.0rc01-07 15 10500 15.so.15.0[.0] - * 1.5.0 15 10500 15.so.15.0[.0] - * 1.5.1beta01-11 15 10501 15.so.15.1[.0] - * 1.5.1rc01-02 15 10501 15.so.15.1[.0] - * 1.5.1 15 10501 15.so.15.1[.0] - * 1.5.2beta01-03 15 10502 15.so.15.2[.0] - * 1.5.2rc01-03 15 10502 15.so.15.2[.0] - * 1.5.2 15 10502 15.so.15.2[.0] - * - * Henceforth the source version will match the shared-library major - * and minor numbers; the shared-library major version number will be - * used for changes in backward compatibility, as it is intended. The - * PNG_LIBPNG_VER macro, which is not used within libpng but is available - * for applications, is an unsigned integer of the form xyyzz corresponding - * to the source version x.y.z (leading zeros in y and z). Beta versions - * were given the previous public release number plus a letter, until - * version 1.0.6j; from then on they were given the upcoming public - * release number plus "betaNN" or "rcN". - * - * Binary incompatibility exists only when applications make direct access - * to the info_ptr or png_ptr members through png.h, and the compiled - * application is loaded with a different version of the library. - * - * DLLNUM will change each time there are forward or backward changes - * in binary compatibility (e.g., when a new feature is added). - * - * See libpng-manual.txt or libpng.3 for more information. The PNG - * specification is available as a W3C Recommendation and as an ISO - * Specification, -# endif - - /* Need the time information for converting tIME chunks, it - * defines struct tm: - */ -# ifdef PNG_CONVERT_tIME_SUPPORTED - /* "time.h" functions are not supported on all operating systems */ -# include -# endif -# endif - -/* Machine specific configuration. */ -# include "pngconf.h" -#endif - -/* - * Added at libpng-1.2.8 - * - * Ref MSDN: Private as priority over Special - * VS_FF_PRIVATEBUILD File *was not* built using standard release - * procedures. If this value is given, the StringFileInfo block must - * contain a PrivateBuild string. - * - * VS_FF_SPECIALBUILD File *was* built by the original company using - * standard release procedures but is a variation of the standard - * file of the same version number. If this value is given, the - * StringFileInfo block must contain a SpecialBuild string. - */ - -#ifdef PNG_USER_PRIVATEBUILD /* From pnglibconf.h */ -# define PNG_LIBPNG_BUILD_TYPE \ - (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_PRIVATE) -#else -# ifdef PNG_LIBPNG_SPECIALBUILD -# define PNG_LIBPNG_BUILD_TYPE \ - (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_SPECIAL) -# else -# define PNG_LIBPNG_BUILD_TYPE (PNG_LIBPNG_BUILD_BASE_TYPE) -# endif -#endif - -#ifndef PNG_VERSION_INFO_ONLY - -/* Inhibit C++ name-mangling for libpng functions but not for system calls. */ -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/* Version information for C files, stored in png.c. This had better match - * the version above. - */ -#define png_libpng_ver png_get_header_ver(NULL) - -/* This file is arranged in several sections: - * - * 1. Any configuration options that can be specified by for the application - * code when it is built. (Build time configuration is in pnglibconf.h) - * 2. Type definitions (base types are defined in pngconf.h), structure - * definitions. - * 3. Exported library functions. - * - * The library source code has additional files (principally pngpriv.h) that - * allow configuration of the library. - */ -/* Section 1: run time configuration - * See pnglibconf.h for build time configuration - * - * Run time configuration allows the application to choose between - * implementations of certain arithmetic APIs. The default is set - * at build time and recorded in pnglibconf.h, but it is safe to - * override these (and only these) settings. Note that this won't - * change what the library does, only application code, and the - * settings can (and probably should) be made on a per-file basis - * by setting the #defines before including png.h - * - * Use macros to read integers from PNG data or use the exported - * functions? - * PNG_USE_READ_MACROS: use the macros (see below) Note that - * the macros evaluate their argument multiple times. - * PNG_NO_USE_READ_MACROS: call the relevant library function. - * - * Use the alternative algorithm for compositing alpha samples that - * does not use division? - * PNG_READ_COMPOSITE_NODIV_SUPPORTED: use the 'no division' - * algorithm. - * PNG_NO_READ_COMPOSITE_NODIV: use the 'division' algorithm. - * - * How to handle benign errors if PNG_ALLOW_BENIGN_ERRORS is - * false? - * PNG_ALLOW_BENIGN_ERRORS: map calls to the benign error - * APIs to png_warning. - * Otherwise the calls are mapped to png_error. - */ - -/* Section 2: type definitions, including structures and compile time - * constants. - * See pngconf.h for base types that vary by machine/system - */ - -/* This triggers a compiler error in png.c, if png.c and png.h - * do not agree upon the version number. - */ -typedef char* png_libpng_version_1_5_2; - -/* Three color definitions. The order of the red, green, and blue, (and the - * exact size) is not important, although the size of the fields need to - * be png_byte or png_uint_16 (as defined below). - */ -typedef struct png_color_struct -{ - png_byte red; - png_byte green; - png_byte blue; -} png_color; -typedef png_color FAR * png_colorp; -typedef PNG_CONST png_color FAR * png_const_colorp; -typedef png_color FAR * FAR * png_colorpp; - -typedef struct png_color_16_struct -{ - png_byte index; /* used for palette files */ - png_uint_16 red; /* for use in red green blue files */ - png_uint_16 green; - png_uint_16 blue; - png_uint_16 gray; /* for use in grayscale files */ -} png_color_16; -typedef png_color_16 FAR * png_color_16p; -typedef PNG_CONST png_color_16 FAR * png_const_color_16p; -typedef png_color_16 FAR * FAR * png_color_16pp; - -typedef struct png_color_8_struct -{ - png_byte red; /* for use in red green blue files */ - png_byte green; - png_byte blue; - png_byte gray; /* for use in grayscale files */ - png_byte alpha; /* for alpha channel files */ -} png_color_8; -typedef png_color_8 FAR * png_color_8p; -typedef PNG_CONST png_color_8 FAR * png_const_color_8p; -typedef png_color_8 FAR * FAR * png_color_8pp; - -/* - * The following two structures are used for the in-core representation - * of sPLT chunks. - */ -typedef struct png_sPLT_entry_struct -{ - png_uint_16 red; - png_uint_16 green; - png_uint_16 blue; - png_uint_16 alpha; - png_uint_16 frequency; -} png_sPLT_entry; -typedef png_sPLT_entry FAR * png_sPLT_entryp; -typedef PNG_CONST png_sPLT_entry FAR * png_const_sPLT_entryp; -typedef png_sPLT_entry FAR * FAR * png_sPLT_entrypp; - -/* When the depth of the sPLT palette is 8 bits, the color and alpha samples - * occupy the LSB of their respective members, and the MSB of each member - * is zero-filled. The frequency member always occupies the full 16 bits. - */ - -typedef struct png_sPLT_struct -{ - png_charp name; /* palette name */ - png_byte depth; /* depth of palette samples */ - png_sPLT_entryp entries; /* palette entries */ - png_int_32 nentries; /* number of palette entries */ -} png_sPLT_t; -typedef png_sPLT_t FAR * png_sPLT_tp; -typedef PNG_CONST png_sPLT_t FAR * png_const_sPLT_tp; -typedef png_sPLT_t FAR * FAR * png_sPLT_tpp; - -#ifdef PNG_TEXT_SUPPORTED -/* png_text holds the contents of a text/ztxt/itxt chunk in a PNG file, - * and whether that contents is compressed or not. The "key" field - * points to a regular zero-terminated C string. The "text", "lang", and - * "lang_key" fields can be regular C strings, empty strings, or NULL pointers. - * However, the * structure returned by png_get_text() will always contain - * regular zero-terminated C strings (possibly empty), never NULL pointers, - * so they can be safely used in printf() and other string-handling functions. - */ -typedef struct png_text_struct -{ - int compression; /* compression value: - -1: tEXt, none - 0: zTXt, deflate - 1: iTXt, none - 2: iTXt, deflate */ - png_charp key; /* keyword, 1-79 character description of "text" */ - png_charp text; /* comment, may be an empty string (ie "") - or a NULL pointer */ - png_size_t text_length; /* length of the text string */ - png_size_t itxt_length; /* length of the itxt string */ - png_charp lang; /* language code, 0-79 characters - or a NULL pointer */ - png_charp lang_key; /* keyword translated UTF-8 string, 0 or more - chars or a NULL pointer */ -} png_text; -typedef png_text FAR * png_textp; -typedef PNG_CONST png_text FAR * png_const_textp; -typedef png_text FAR * FAR * png_textpp; -#endif - -/* Supported compression types for text in PNG files (tEXt, and zTXt). - * The values of the PNG_TEXT_COMPRESSION_ defines should NOT be changed. */ -#define PNG_TEXT_COMPRESSION_NONE_WR -3 -#define PNG_TEXT_COMPRESSION_zTXt_WR -2 -#define PNG_TEXT_COMPRESSION_NONE -1 -#define PNG_TEXT_COMPRESSION_zTXt 0 -#define PNG_ITXT_COMPRESSION_NONE 1 -#define PNG_ITXT_COMPRESSION_zTXt 2 -#define PNG_TEXT_COMPRESSION_LAST 3 /* Not a valid value */ - -/* png_time is a way to hold the time in an machine independent way. - * Two conversions are provided, both from time_t and struct tm. There - * is no portable way to convert to either of these structures, as far - * as I know. If you know of a portable way, send it to me. As a side - * note - PNG has always been Year 2000 compliant! - */ -typedef struct png_time_struct -{ - png_uint_16 year; /* full year, as in, 1995 */ - png_byte month; /* month of year, 1 - 12 */ - png_byte day; /* day of month, 1 - 31 */ - png_byte hour; /* hour of day, 0 - 23 */ - png_byte minute; /* minute of hour, 0 - 59 */ - png_byte second; /* second of minute, 0 - 60 (for leap seconds) */ -} png_time; -typedef png_time FAR * png_timep; -typedef PNG_CONST png_time FAR * png_const_timep; -typedef png_time FAR * FAR * png_timepp; - -#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) || \ - defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED) -/* png_unknown_chunk is a structure to hold queued chunks for which there is - * no specific support. The idea is that we can use this to queue - * up private chunks for output even though the library doesn't actually - * know about their semantics. - */ -typedef struct png_unknown_chunk_t -{ - png_byte name[5]; - png_byte *data; - png_size_t size; - - /* libpng-using applications should NOT directly modify this byte. */ - png_byte location; /* mode of operation at read time */ -} -png_unknown_chunk; -typedef png_unknown_chunk FAR * png_unknown_chunkp; -typedef PNG_CONST png_unknown_chunk FAR * png_const_unknown_chunkp; -typedef png_unknown_chunk FAR * FAR * png_unknown_chunkpp; -#endif - -typedef struct png_info_def png_info; -typedef png_info FAR * png_infop; -typedef PNG_CONST png_info FAR * png_const_infop; -typedef png_info FAR * FAR * png_infopp; - -/* Maximum positive integer used in PNG is (2^31)-1 */ -#define PNG_UINT_31_MAX ((png_uint_32)0x7fffffffL) -#define PNG_UINT_32_MAX ((png_uint_32)(-1)) -#define PNG_SIZE_MAX ((png_size_t)(-1)) - -/* These are constants for fixed point values encoded in the - * PNG specification manner (x100000) - */ -#define PNG_FP_1 100000 -#define PNG_FP_HALF 50000 - -/* These describe the color_type field in png_info. */ -/* color type masks */ -#define PNG_COLOR_MASK_PALETTE 1 -#define PNG_COLOR_MASK_COLOR 2 -#define PNG_COLOR_MASK_ALPHA 4 - -/* color types. Note that not all combinations are legal */ -#define PNG_COLOR_TYPE_GRAY 0 -#define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE) -#define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR) -#define PNG_COLOR_TYPE_RGB_ALPHA (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA) -#define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA) -/* aliases */ -#define PNG_COLOR_TYPE_RGBA PNG_COLOR_TYPE_RGB_ALPHA -#define PNG_COLOR_TYPE_GA PNG_COLOR_TYPE_GRAY_ALPHA - -/* This is for compression type. PNG 1.0-1.2 only define the single type. */ -#define PNG_COMPRESSION_TYPE_BASE 0 /* Deflate method 8, 32K window */ -#define PNG_COMPRESSION_TYPE_DEFAULT PNG_COMPRESSION_TYPE_BASE - -/* This is for filter type. PNG 1.0-1.2 only define the single type. */ -#define PNG_FILTER_TYPE_BASE 0 /* Single row per-byte filtering */ -#define PNG_INTRAPIXEL_DIFFERENCING 64 /* Used only in MNG datastreams */ -#define PNG_FILTER_TYPE_DEFAULT PNG_FILTER_TYPE_BASE - -/* These are for the interlacing type. These values should NOT be changed. */ -#define PNG_INTERLACE_NONE 0 /* Non-interlaced image */ -#define PNG_INTERLACE_ADAM7 1 /* Adam7 interlacing */ -#define PNG_INTERLACE_LAST 2 /* Not a valid value */ - -/* These are for the oFFs chunk. These values should NOT be changed. */ -#define PNG_OFFSET_PIXEL 0 /* Offset in pixels */ -#define PNG_OFFSET_MICROMETER 1 /* Offset in micrometers (1/10^6 meter) */ -#define PNG_OFFSET_LAST 2 /* Not a valid value */ - -/* These are for the pCAL chunk. These values should NOT be changed. */ -#define PNG_EQUATION_LINEAR 0 /* Linear transformation */ -#define PNG_EQUATION_BASE_E 1 /* Exponential base e transform */ -#define PNG_EQUATION_ARBITRARY 2 /* Arbitrary base exponential transform */ -#define PNG_EQUATION_HYPERBOLIC 3 /* Hyperbolic sine transformation */ -#define PNG_EQUATION_LAST 4 /* Not a valid value */ - -/* These are for the sCAL chunk. These values should NOT be changed. */ -#define PNG_SCALE_UNKNOWN 0 /* unknown unit (image scale) */ -#define PNG_SCALE_METER 1 /* meters per pixel */ -#define PNG_SCALE_RADIAN 2 /* radians per pixel */ -#define PNG_SCALE_LAST 3 /* Not a valid value */ - -/* These are for the pHYs chunk. These values should NOT be changed. */ -#define PNG_RESOLUTION_UNKNOWN 0 /* pixels/unknown unit (aspect ratio) */ -#define PNG_RESOLUTION_METER 1 /* pixels/meter */ -#define PNG_RESOLUTION_LAST 2 /* Not a valid value */ - -/* These are for the sRGB chunk. These values should NOT be changed. */ -#define PNG_sRGB_INTENT_PERCEPTUAL 0 -#define PNG_sRGB_INTENT_RELATIVE 1 -#define PNG_sRGB_INTENT_SATURATION 2 -#define PNG_sRGB_INTENT_ABSOLUTE 3 -#define PNG_sRGB_INTENT_LAST 4 /* Not a valid value */ - -/* This is for text chunks */ -#define PNG_KEYWORD_MAX_LENGTH 79 - -/* Maximum number of entries in PLTE/sPLT/tRNS arrays */ -#define PNG_MAX_PALETTE_LENGTH 256 - -/* These determine if an ancillary chunk's data has been successfully read - * from the PNG header, or if the application has filled in the corresponding - * data in the info_struct to be written into the output file. The values - * of the PNG_INFO_ defines should NOT be changed. - */ -#define PNG_INFO_gAMA 0x0001 -#define PNG_INFO_sBIT 0x0002 -#define PNG_INFO_cHRM 0x0004 -#define PNG_INFO_PLTE 0x0008 -#define PNG_INFO_tRNS 0x0010 -#define PNG_INFO_bKGD 0x0020 -#define PNG_INFO_hIST 0x0040 -#define PNG_INFO_pHYs 0x0080 -#define PNG_INFO_oFFs 0x0100 -#define PNG_INFO_tIME 0x0200 -#define PNG_INFO_pCAL 0x0400 -#define PNG_INFO_sRGB 0x0800 /* GR-P, 0.96a */ -#define PNG_INFO_iCCP 0x1000 /* ESR, 1.0.6 */ -#define PNG_INFO_sPLT 0x2000 /* ESR, 1.0.6 */ -#define PNG_INFO_sCAL 0x4000 /* ESR, 1.0.6 */ -#define PNG_INFO_IDAT 0x8000L /* ESR, 1.0.6 */ - -/* This is used for the transformation routines, as some of them - * change these values for the row. It also should enable using - * the routines for other purposes. - */ -typedef struct png_row_info_struct -{ - png_uint_32 width; /* width of row */ - png_size_t rowbytes; /* number of bytes in row */ - png_byte color_type; /* color type of row */ - png_byte bit_depth; /* bit depth of row */ - png_byte channels; /* number of channels (1, 2, 3, or 4) */ - png_byte pixel_depth; /* bits per pixel (depth * channels) */ -} png_row_info; - -typedef png_row_info FAR * png_row_infop; -typedef png_row_info FAR * FAR * png_row_infopp; - -/* These are the function types for the I/O functions and for the functions - * that allow the user to override the default I/O functions with his or her - * own. The png_error_ptr type should match that of user-supplied warning - * and error functions, while the png_rw_ptr type should match that of the - * user read/write data functions. Note that the 'write' function must not - * modify the buffer it is passed. The 'read' function, on the other hand, is - * expected to return the read data in the buffer. - */ -typedef struct png_struct_def png_struct; -typedef PNG_CONST png_struct FAR * png_const_structp; -typedef png_struct FAR * png_structp; - -typedef PNG_CALLBACK(void, *png_error_ptr, (png_structp, png_const_charp)); -typedef PNG_CALLBACK(void, *png_rw_ptr, (png_structp, png_bytep, png_size_t)); -typedef PNG_CALLBACK(void, *png_flush_ptr, (png_structp)); -typedef PNG_CALLBACK(void, *png_read_status_ptr, (png_structp, png_uint_32, - int)); -typedef PNG_CALLBACK(void, *png_write_status_ptr, (png_structp, png_uint_32, - int)); - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop)); -typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop)); - -/* The following callback receives png_uint_32 row_number, int pass for the - * png_bytep data of the row. When transforming an interlaced image the - * row number is the row number within the sub-image of the interlace pass, so - * the value will increase to the height of the sub-image (not the full image) - * then reset to 0 for the next pass. - * - * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to - * find the output pixel (x,y) given an interlaced sub-image pixel - * (row,col,pass). (See below for these macros.) - */ -typedef PNG_CALLBACK(void, *png_progressive_row_ptr, (png_structp, png_bytep, - png_uint_32, int)); -#endif - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) -typedef PNG_CALLBACK(void, *png_user_transform_ptr, (png_structp, png_row_infop, - png_bytep)); -#endif - -#ifdef PNG_USER_CHUNKS_SUPPORTED -typedef PNG_CALLBACK(int, *png_user_chunk_ptr, (png_structp, - png_unknown_chunkp)); -#endif -#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED -typedef PNG_CALLBACK(void, *png_unknown_chunk_ptr, (png_structp)); -#endif - -#ifdef PNG_SETJMP_SUPPORTED -/* This must match the function definition in , and the - * application must include this before png.h to obtain the definition - * of jmp_buf. The function is required to be PNG_NORETURN. (Note that - * PNG_PTR_NORETURN is used here because current versions of the Microsoft - * C compiler do not support the PNG_NORETURN attribute on a pointer.) - * - * If you get a type warning from the compiler when linking against this line - * then your compiler has 'longjmp' that does not match the requirements of the - * compiler that built libpng. You will have to write a wrapper function for - * your compiler's longjmp and call png_set_longjmp_fn directly (not via the - * png_jmpbuf macro.) - * - * If you get a warning here while building the library you will need to make - * changes to ensure that pnglibconf.h records the calling convention used by - * your compiler. This may be very difficult - try using a different compiler - * to build the library! - */ -typedef PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), - PNG_PTR_NORETURN); -#endif - -/* Transform masks for the high-level interface */ -#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */ -#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */ -#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */ -#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */ -#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */ -#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */ -#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */ -#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */ -#define PNG_TRANSFORM_BGR 0x0080 /* read and write */ -#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */ -#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */ -#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */ -#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* write only */ -/* Added to libpng-1.2.34 */ -#define PNG_TRANSFORM_STRIP_FILLER_BEFORE PNG_TRANSFORM_STRIP_FILLER -#define PNG_TRANSFORM_STRIP_FILLER_AFTER 0x1000 /* write only */ -/* Added to libpng-1.4.0 */ -#define PNG_TRANSFORM_GRAY_TO_RGB 0x2000 /* read only */ - -/* Flags for MNG supported features */ -#define PNG_FLAG_MNG_EMPTY_PLTE 0x01 -#define PNG_FLAG_MNG_FILTER_64 0x04 -#define PNG_ALL_MNG_FEATURES 0x05 - -/* NOTE: prior to 1.5 these functions had no 'API' style declaration, - * this allowed the zlib default functions to be used on Windows - * platforms. In 1.5 the zlib default malloc (which just calls malloc and - * ignores the first argument) should be completely compatible with the - * following. - */ -typedef PNG_CALLBACK(png_voidp, *png_malloc_ptr, (png_structp, - png_alloc_size_t)); -typedef PNG_CALLBACK(void, *png_free_ptr, (png_structp, png_voidp)); - -typedef png_struct FAR * FAR * png_structpp; - -/* Section 3: exported functions - * Here are the function definitions most commonly used. This is not - * the place to find out how to use libpng. See libpng-manual.txt for the - * full explanation, see example.c for the summary. This just provides - * a simple one line description of the use of each function. - * - * The PNG_EXPORT() and PNG_EXPORTA() macros used below are defined in - * pngconf.h and in the *.dfn files in the scripts directory. - * - * PNG_EXPORT(ordinal, type, name, (args)); - * - * ordinal: ordinal that is used while building - * *.def files. The ordinal value is only - * relevant when preprocessing png.h with - * the *.dfn files for building symbol table - * entries, and are removed by pngconf.h. - * type: return type of the function - * name: function name - * args: function arguments, with types - * - * When we wish to append attributes to a function prototype we use - * the PNG_EXPORTA() macro instead. - * - * PNG_EXPORTA(ordinal, type, name, (args), attributes); - * - * ordinal, type, name, and args: same as in PNG_EXPORT(). - * attributes: function attributes - */ - -/* Returns the version number of the library */ -PNG_EXPORT(1, png_uint_32, png_access_version_number, (void)); - -/* Tell lib we have already handled the first magic bytes. - * Handling more than 8 bytes from the beginning of the file is an error. - */ -PNG_EXPORT(2, void, png_set_sig_bytes, (png_structp png_ptr, int num_bytes)); - -/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a - * PNG file. Returns zero if the supplied bytes match the 8-byte PNG - * signature, and non-zero otherwise. Having num_to_check == 0 or - * start > 7 will always fail (ie return non-zero). - */ -PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, png_size_t start, - png_size_t num_to_check)); - -/* Simple signature checking function. This is the same as calling - * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). - */ -#define png_check_sig(sig, n) !png_sig_cmp((sig), 0, (n)) - -/* Allocate and initialize png_ptr struct for reading, and any other memory. */ -PNG_EXPORTA(4, png_structp, png_create_read_struct, - (png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn), - PNG_ALLOCATED); - -/* Allocate and initialize png_ptr struct for writing, and any other memory */ -PNG_EXPORTA(5, png_structp, png_create_write_struct, - (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, - png_error_ptr warn_fn), - PNG_ALLOCATED); - -PNG_EXPORT(6, png_size_t, png_get_compression_buffer_size, - (png_const_structp png_ptr)); - -PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structp png_ptr, - png_size_t size)); - -/* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp - * match up. - */ -#ifdef PNG_SETJMP_SUPPORTED -/* This function returns the jmp_buf built in to *png_ptr. It must be - * supplied with an appropriate 'longjmp' function to use on that jmp_buf - * unless the default error function is overridden in which case NULL is - * acceptable. The size of the jmp_buf is checked against the actual size - * allocated by the library - the call will return NULL on a mismatch - * indicating an ABI mismatch. - */ -PNG_EXPORT(8, jmp_buf*, png_set_longjmp_fn, (png_structp png_ptr, - png_longjmp_ptr longjmp_fn, size_t jmp_buf_size)); -# define png_jmpbuf(png_ptr) \ - (*png_set_longjmp_fn((png_ptr), longjmp, sizeof (jmp_buf))) -#else -# define png_jmpbuf(png_ptr) \ - (LIBPNG_WAS_COMPILED_WITH__PNG_NO_SETJMP) -#endif -/* This function should be used by libpng applications in place of - * longjmp(png_ptr->jmpbuf, val). If longjmp_fn() has been set, it - * will use it; otherwise it will call PNG_ABORT(). This function was - * added in libpng-1.5.0. - */ -PNG_EXPORTA(9, void, png_longjmp, (png_structp png_ptr, int val), - PNG_NORETURN); - -#ifdef PNG_READ_SUPPORTED -/* Reset the compression stream */ -PNG_EXPORT(10, int, png_reset_zstream, (png_structp png_ptr)); -#endif - -/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ -#ifdef PNG_USER_MEM_SUPPORTED -PNG_EXPORTA(11, png_structp, png_create_read_struct_2, - (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, - png_error_ptr warn_fn, - png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), - PNG_ALLOCATED); -PNG_EXPORTA(12, png_structp, png_create_write_struct_2, - (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, - png_error_ptr warn_fn, - png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), - PNG_ALLOCATED); -#endif - -/* Write the PNG file signature. */ -PNG_EXPORT(13, void, png_write_sig, (png_structp png_ptr)); - -/* Write a PNG chunk - size, type, (optional) data, CRC. */ -PNG_EXPORT(14, void, png_write_chunk, (png_structp png_ptr, png_const_bytep - chunk_name, png_const_bytep data, png_size_t length)); - -/* Write the start of a PNG chunk - length and chunk name. */ -PNG_EXPORT(15, void, png_write_chunk_start, (png_structp png_ptr, - png_const_bytep chunk_name, png_uint_32 length)); - -/* Write the data of a PNG chunk started with png_write_chunk_start(). */ -PNG_EXPORT(16, void, png_write_chunk_data, (png_structp png_ptr, - png_const_bytep data, png_size_t length)); - -/* Finish a chunk started with png_write_chunk_start() (includes CRC). */ -PNG_EXPORT(17, void, png_write_chunk_end, (png_structp png_ptr)); - -/* Allocate and initialize the info structure */ -PNG_EXPORTA(18, png_infop, png_create_info_struct, (png_structp png_ptr), - PNG_ALLOCATED); - -PNG_EXPORT(19, void, png_info_init_3, (png_infopp info_ptr, - png_size_t png_info_struct_size)); - -/* Writes all the PNG information before the image. */ -PNG_EXPORT(20, void, png_write_info_before_PLTE, - (png_structp png_ptr, png_infop info_ptr)); -PNG_EXPORT(21, void, png_write_info, - (png_structp png_ptr, png_infop info_ptr)); - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read the information before the actual image data. */ -PNG_EXPORT(22, void, png_read_info, - (png_structp png_ptr, png_infop info_ptr)); -#endif - -#ifdef PNG_TIME_RFC1123_SUPPORTED -PNG_EXPORT(23, png_const_charp, png_convert_to_rfc1123, - (png_structp png_ptr, - png_const_timep ptime)); -#endif - -#ifdef PNG_CONVERT_tIME_SUPPORTED -/* Convert from a struct tm to png_time */ -PNG_EXPORT(24, void, png_convert_from_struct_tm, (png_timep ptime, - PNG_CONST struct tm FAR * ttime)); - -/* Convert from time_t to png_time. Uses gmtime() */ -PNG_EXPORT(25, void, png_convert_from_time_t, - (png_timep ptime, time_t ttime)); -#endif /* PNG_CONVERT_tIME_SUPPORTED */ - -#ifdef PNG_READ_EXPAND_SUPPORTED -/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */ -PNG_EXPORT(26, void, png_set_expand, (png_structp png_ptr)); -PNG_EXPORT(27, void, png_set_expand_gray_1_2_4_to_8, (png_structp png_ptr)); -PNG_EXPORT(28, void, png_set_palette_to_rgb, (png_structp png_ptr)); -PNG_EXPORT(29, void, png_set_tRNS_to_alpha, (png_structp png_ptr)); -#endif - -#ifdef PNG_READ_EXPAND_16_SUPPORTED -/* Expand to 16 bit channels, forces conversion of palette to RGB and expansion - * of a tRNS chunk if present. - */ -PNG_EXPORT(221, void, png_set_expand_16, (png_structp png_ptr)); -#endif - -#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) -/* Use blue, green, red order for pixels. */ -PNG_EXPORT(30, void, png_set_bgr, (png_structp png_ptr)); -#endif - -#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED -/* Expand the grayscale to 24-bit RGB if necessary. */ -PNG_EXPORT(31, void, png_set_gray_to_rgb, (png_structp png_ptr)); -#endif - -#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED -/* Reduce RGB to grayscale. */ -PNG_FP_EXPORT(32, void, png_set_rgb_to_gray, (png_structp png_ptr, - int error_action, double red, double green)); -PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed, (png_structp png_ptr, - int error_action, png_fixed_point red, png_fixed_point green)); - -PNG_EXPORT(34, png_byte, png_get_rgb_to_gray_status, (png_const_structp - png_ptr)); -#endif - -PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth, - png_colorp palette)); - -#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED -PNG_EXPORT(36, void, png_set_strip_alpha, (png_structp png_ptr)); -#endif - -#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ - defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) -PNG_EXPORT(37, void, png_set_swap_alpha, (png_structp png_ptr)); -#endif - -#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ - defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) -PNG_EXPORT(38, void, png_set_invert_alpha, (png_structp png_ptr)); -#endif - -#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) -/* Add a filler byte to 8-bit Gray or 24-bit RGB images. */ -PNG_EXPORT(39, void, png_set_filler, (png_structp png_ptr, png_uint_32 filler, - int flags)); -/* The values of the PNG_FILLER_ defines should NOT be changed */ -# define PNG_FILLER_BEFORE 0 -# define PNG_FILLER_AFTER 1 -/* Add an alpha byte to 8-bit Gray or 24-bit RGB images. */ -PNG_EXPORT(40, void, png_set_add_alpha, - (png_structp png_ptr, png_uint_32 filler, - int flags)); -#endif /* PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED */ - -#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) -/* Swap bytes in 16-bit depth files. */ -PNG_EXPORT(41, void, png_set_swap, (png_structp png_ptr)); -#endif - -#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) -/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */ -PNG_EXPORT(42, void, png_set_packing, (png_structp png_ptr)); -#endif - -#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ - defined(PNG_WRITE_PACKSWAP_SUPPORTED) -/* Swap packing order of pixels in bytes. */ -PNG_EXPORT(43, void, png_set_packswap, (png_structp png_ptr)); -#endif - -#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) -/* Converts files to legal bit depths. */ -PNG_EXPORT(44, void, png_set_shift, (png_structp png_ptr, png_const_color_8p - true_bits)); -#endif - -#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ - defined(PNG_WRITE_INTERLACING_SUPPORTED) -/* Have the code handle the interlacing. Returns the number of passes. - * MUST be called before png_read_update_info or png_start_read_image, - * otherwise it will not have the desired effect. Note that it is still - * necessary to call png_read_row or png_read_rows png_get_image_height - * times for each pass. -*/ -PNG_EXPORT(45, int, png_set_interlace_handling, (png_structp png_ptr)); -#endif - -#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) -/* Invert monochrome files */ -PNG_EXPORT(46, void, png_set_invert_mono, (png_structp png_ptr)); -#endif - -#ifdef PNG_READ_BACKGROUND_SUPPORTED -/* Handle alpha and tRNS by replacing with a background color. */ -PNG_FP_EXPORT(47, void, png_set_background, (png_structp png_ptr, - png_const_color_16p background_color, int background_gamma_code, - int need_expand, double background_gamma)); -PNG_FIXED_EXPORT(215, void, png_set_background_fixed, (png_structp png_ptr, - png_const_color_16p background_color, int background_gamma_code, - int need_expand, png_fixed_point background_gamma)); -#endif -#ifdef PNG_READ_BACKGROUND_SUPPORTED -# define PNG_BACKGROUND_GAMMA_UNKNOWN 0 -# define PNG_BACKGROUND_GAMMA_SCREEN 1 -# define PNG_BACKGROUND_GAMMA_FILE 2 -# define PNG_BACKGROUND_GAMMA_UNIQUE 3 -#endif - -#ifdef PNG_READ_16_TO_8_SUPPORTED -/* Strip the second byte of information from a 16-bit depth file. */ -PNG_EXPORT(48, void, png_set_strip_16, (png_structp png_ptr)); -#endif - -#ifdef PNG_READ_QUANTIZE_SUPPORTED -/* Turn on quantizing, and reduce the palette to the number of colors - * available. - */ -PNG_EXPORT(49, void, png_set_quantize, - (png_structp png_ptr, png_colorp palette, - int num_palette, int maximum_colors, png_const_uint_16p histogram, - int full_quantize)); -#endif - -#ifdef PNG_READ_GAMMA_SUPPORTED -/* The threshold on gamma processing is configurable but hard-wired into the - * library. The following is the floating point variant. - */ -#define PNG_GAMMA_THRESHOLD (PNG_GAMMA_THRESHOLD_FIXED*.00001) - -/* Handle gamma correction. Screen_gamma=(display_exponent) */ -PNG_FP_EXPORT(50, void, png_set_gamma, - (png_structp png_ptr, double screen_gamma, - double default_file_gamma)); -PNG_FIXED_EXPORT(208, void, png_set_gamma_fixed, (png_structp png_ptr, - png_fixed_point screen_gamma, png_fixed_point default_file_gamma)); -#endif - -#ifdef PNG_WRITE_FLUSH_SUPPORTED -/* Set how many lines between output flushes - 0 for no flushing */ -PNG_EXPORT(51, void, png_set_flush, (png_structp png_ptr, int nrows)); -/* Flush the current PNG output buffer */ -PNG_EXPORT(52, void, png_write_flush, (png_structp png_ptr)); -#endif - -/* Optional update palette with requested transformations */ -PNG_EXPORT(53, void, png_start_read_image, (png_structp png_ptr)); - -/* Optional call to update the users info structure */ -PNG_EXPORT(54, void, png_read_update_info, - (png_structp png_ptr, png_infop info_ptr)); - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read one or more rows of image data. */ -PNG_EXPORT(55, void, png_read_rows, (png_structp png_ptr, png_bytepp row, - png_bytepp display_row, png_uint_32 num_rows)); -#endif - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read a row of data. */ -PNG_EXPORT(56, void, png_read_row, (png_structp png_ptr, png_bytep row, - png_bytep display_row)); -#endif - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read the whole image into memory at once. */ -PNG_EXPORT(57, void, png_read_image, (png_structp png_ptr, png_bytepp image)); -#endif - -/* Write a row of image data */ -PNG_EXPORT(58, void, png_write_row, - (png_structp png_ptr, png_const_bytep row)); - -/* Write a few rows of image data: (*row) is not written; however, the type - * is declared as writeable to maintain compatibility with previous versions - * of libpng and to allow the 'display_row' array from read_rows to be passed - * unchanged to write_rows. - */ -PNG_EXPORT(59, void, png_write_rows, (png_structp png_ptr, png_bytepp row, - png_uint_32 num_rows)); - -/* Write the image data */ -PNG_EXPORT(60, void, png_write_image, - (png_structp png_ptr, png_bytepp image)); - -/* Write the end of the PNG file. */ -PNG_EXPORT(61, void, png_write_end, - (png_structp png_ptr, png_infop info_ptr)); - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read the end of the PNG file. */ -PNG_EXPORT(62, void, png_read_end, (png_structp png_ptr, png_infop info_ptr)); -#endif - -/* Free any memory associated with the png_info_struct */ -PNG_EXPORT(63, void, png_destroy_info_struct, (png_structp png_ptr, - png_infopp info_ptr_ptr)); - -/* Free any memory associated with the png_struct and the png_info_structs */ -PNG_EXPORT(64, void, png_destroy_read_struct, (png_structpp png_ptr_ptr, - png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); - -/* Free any memory associated with the png_struct and the png_info_structs */ -PNG_EXPORT(65, void, png_destroy_write_struct, (png_structpp png_ptr_ptr, - png_infopp info_ptr_ptr)); - -/* Set the libpng method of handling chunk CRC errors */ -PNG_EXPORT(66, void, png_set_crc_action, - (png_structp png_ptr, int crit_action, int ancil_action)); - -/* Values for png_set_crc_action() say how to handle CRC errors in - * ancillary and critical chunks, and whether to use the data contained - * therein. Note that it is impossible to "discard" data in a critical - * chunk. For versions prior to 0.90, the action was always error/quit, - * whereas in version 0.90 and later, the action for CRC errors in ancillary - * chunks is warn/discard. These values should NOT be changed. - * - * value action:critical action:ancillary - */ -#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */ -#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */ -#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */ -#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */ -#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */ -#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */ - -/* These functions give the user control over the scan-line filtering in - * libpng and the compression methods used by zlib. These functions are - * mainly useful for testing, as the defaults should work with most users. - * Those users who are tight on memory or want faster performance at the - * expense of compression can modify them. See the compression library - * header file (zlib.h) for an explination of the compression functions. - */ - -/* Set the filtering method(s) used by libpng. Currently, the only valid - * value for "method" is 0. - */ -PNG_EXPORT(67, void, png_set_filter, - (png_structp png_ptr, int method, int filters)); - -/* Flags for png_set_filter() to say which filters to use. The flags - * are chosen so that they don't conflict with real filter types - * below, in case they are supplied instead of the #defined constants. - * These values should NOT be changed. - */ -#define PNG_NO_FILTERS 0x00 -#define PNG_FILTER_NONE 0x08 -#define PNG_FILTER_SUB 0x10 -#define PNG_FILTER_UP 0x20 -#define PNG_FILTER_AVG 0x40 -#define PNG_FILTER_PAETH 0x80 -#define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \ - PNG_FILTER_AVG | PNG_FILTER_PAETH) - -/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now. - * These defines should NOT be changed. - */ -#define PNG_FILTER_VALUE_NONE 0 -#define PNG_FILTER_VALUE_SUB 1 -#define PNG_FILTER_VALUE_UP 2 -#define PNG_FILTER_VALUE_AVG 3 -#define PNG_FILTER_VALUE_PAETH 4 -#define PNG_FILTER_VALUE_LAST 5 - -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* EXPERIMENTAL */ -/* The "heuristic_method" is given by one of the PNG_FILTER_HEURISTIC_ - * defines, either the default (minimum-sum-of-absolute-differences), or - * the experimental method (weighted-minimum-sum-of-absolute-differences). - * - * Weights are factors >= 1.0, indicating how important it is to keep the - * filter type consistent between rows. Larger numbers mean the current - * filter is that many times as likely to be the same as the "num_weights" - * previous filters. This is cumulative for each previous row with a weight. - * There needs to be "num_weights" values in "filter_weights", or it can be - * NULL if the weights aren't being specified. Weights have no influence on - * the selection of the first row filter. Well chosen weights can (in theory) - * improve the compression for a given image. - * - * Costs are factors >= 1.0 indicating the relative decoding costs of a - * filter type. Higher costs indicate more decoding expense, and are - * therefore less likely to be selected over a filter with lower computational - * costs. There needs to be a value in "filter_costs" for each valid filter - * type (given by PNG_FILTER_VALUE_LAST), or it can be NULL if you aren't - * setting the costs. Costs try to improve the speed of decompression without - * unduly increasing the compressed image size. - * - * A negative weight or cost indicates the default value is to be used, and - * values in the range [0.0, 1.0) indicate the value is to remain unchanged. - * The default values for both weights and costs are currently 1.0, but may - * change if good general weighting/cost heuristics can be found. If both - * the weights and costs are set to 1.0, this degenerates the WEIGHTED method - * to the UNWEIGHTED method, but with added encoding time/computation. - */ -PNG_FP_EXPORT(68, void, png_set_filter_heuristics, (png_structp png_ptr, - int heuristic_method, int num_weights, png_const_doublep filter_weights, - png_const_doublep filter_costs)); -PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed, - (png_structp png_ptr, - int heuristic_method, int num_weights, png_const_fixed_point_p - filter_weights, png_const_fixed_point_p filter_costs)); -#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ - -/* Heuristic used for row filter selection. These defines should NOT be - * changed. - */ -#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */ -#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */ -#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ -#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ - -/* Set the library compression level. Currently, valid values range from - * 0 - 9, corresponding directly to the zlib compression levels 0 - 9 - * (0 - no compression, 9 - "maximal" compression). Note that tests have - * shown that zlib compression levels 3-6 usually perform as well as level 9 - * for PNG images, and do considerably fewer caclulations. In the future, - * these values may not correspond directly to the zlib compression levels. - */ -PNG_EXPORT(69, void, png_set_compression_level, - (png_structp png_ptr, int level)); - -PNG_EXPORT(70, void, png_set_compression_mem_level, (png_structp png_ptr, - int mem_level)); - -PNG_EXPORT(71, void, png_set_compression_strategy, (png_structp png_ptr, - int strategy)); - -PNG_EXPORT(72, void, png_set_compression_window_bits, (png_structp png_ptr, - int window_bits)); - -PNG_EXPORT(73, void, png_set_compression_method, (png_structp png_ptr, - int method)); - -/* These next functions are called for input/output, memory, and error - * handling. They are in the file pngrio.c, pngwio.c, and pngerror.c, - * and call standard C I/O routines such as fread(), fwrite(), and - * fprintf(). These functions can be made to use other I/O routines - * at run time for those applications that need to handle I/O in a - * different manner by calling png_set_???_fn(). See libpng-manual.txt for - * more information. - */ - -#ifdef PNG_STDIO_SUPPORTED -/* Initialize the input/output for the PNG file to the default functions. */ -PNG_EXPORT(74, void, png_init_io, (png_structp png_ptr, png_FILE_p fp)); -#endif - -/* Replace the (error and abort), and warning functions with user - * supplied functions. If no messages are to be printed you must still - * write and use replacement functions. The replacement error_fn should - * still do a longjmp to the last setjmp location if you are using this - * method of error handling. If error_fn or warning_fn is NULL, the - * default function will be used. - */ - -PNG_EXPORT(75, void, png_set_error_fn, - (png_structp png_ptr, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warning_fn)); - -/* Return the user pointer associated with the error functions */ -PNG_EXPORT(76, png_voidp, png_get_error_ptr, (png_const_structp png_ptr)); - -/* Replace the default data output functions with a user supplied one(s). - * If buffered output is not used, then output_flush_fn can be set to NULL. - * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time - * output_flush_fn will be ignored (and thus can be NULL). - * It is probably a mistake to use NULL for output_flush_fn if - * write_data_fn is not also NULL unless you have built libpng with - * PNG_WRITE_FLUSH_SUPPORTED undefined, because in this case libpng's - * default flush function, which uses the standard *FILE structure, will - * be used. - */ -PNG_EXPORT(77, void, png_set_write_fn, (png_structp png_ptr, png_voidp io_ptr, - png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)); - -/* Replace the default data input function with a user supplied one. */ -PNG_EXPORT(78, void, png_set_read_fn, (png_structp png_ptr, png_voidp io_ptr, - png_rw_ptr read_data_fn)); - -/* Return the user pointer associated with the I/O functions */ -PNG_EXPORT(79, png_voidp, png_get_io_ptr, (png_structp png_ptr)); - -PNG_EXPORT(80, void, png_set_read_status_fn, (png_structp png_ptr, - png_read_status_ptr read_row_fn)); - -PNG_EXPORT(81, void, png_set_write_status_fn, (png_structp png_ptr, - png_write_status_ptr write_row_fn)); - -#ifdef PNG_USER_MEM_SUPPORTED -/* Replace the default memory allocation functions with user supplied one(s). */ -PNG_EXPORT(82, void, png_set_mem_fn, (png_structp png_ptr, png_voidp mem_ptr, - png_malloc_ptr malloc_fn, png_free_ptr free_fn)); -/* Return the user pointer associated with the memory functions */ -PNG_EXPORT(83, png_voidp, png_get_mem_ptr, (png_const_structp png_ptr)); -#endif - -#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED -PNG_EXPORT(84, void, png_set_read_user_transform_fn, (png_structp png_ptr, - png_user_transform_ptr read_user_transform_fn)); -#endif - -#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED -PNG_EXPORT(85, void, png_set_write_user_transform_fn, (png_structp png_ptr, - png_user_transform_ptr write_user_transform_fn)); -#endif - -#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED -PNG_EXPORT(86, void, png_set_user_transform_info, (png_structp png_ptr, - png_voidp user_transform_ptr, int user_transform_depth, - int user_transform_channels)); -/* Return the user pointer associated with the user transform functions */ -PNG_EXPORT(87, png_voidp, png_get_user_transform_ptr, - (png_const_structp png_ptr)); -#endif - -#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED -/* Return information about the row currently being processed. Note that these - * APIs do not fail but will return unexpected results if called outside a user - * transform callback. Also note that when transforming an interlaced image the - * row number is the row number within the sub-image of the interlace pass, so - * the value will increase to the height of the sub-image (not the full image) - * then reset to 0 for the next pass. - * - * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to - * find the output pixel (x,y) given an interlaced sub-image pixel - * (row,col,pass). (See below for these macros.) - */ -PNG_EXPORT(217, png_uint_32, png_get_current_row_number, (png_const_structp)); -PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structp)); -#endif - -#ifdef PNG_USER_CHUNKS_SUPPORTED -PNG_EXPORT(88, void, png_set_read_user_chunk_fn, (png_structp png_ptr, - png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); -PNG_EXPORT(89, png_voidp, png_get_user_chunk_ptr, (png_const_structp png_ptr)); -#endif - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -/* Sets the function callbacks for the push reader, and a pointer to a - * user-defined structure available to the callback functions. - */ -PNG_EXPORT(90, void, png_set_progressive_read_fn, (png_structp png_ptr, - png_voidp progressive_ptr, png_progressive_info_ptr info_fn, - png_progressive_row_ptr row_fn, png_progressive_end_ptr end_fn)); - -/* Returns the user pointer associated with the push read functions */ -PNG_EXPORT(91, png_voidp, png_get_progressive_ptr, (png_const_structp png_ptr)); - -/* Function to be called when data becomes available */ -PNG_EXPORT(92, void, png_process_data, - (png_structp png_ptr, png_infop info_ptr, - png_bytep buffer, png_size_t buffer_size)); - -/* A function which may be called *only* within png_process_data to stop the - * processing of any more data. The function returns the number of bytes - * remaining, excluding any that libpng has cached internally. A subsequent - * call to png_process_data must supply these bytes again. If the argument - * 'save' is set to true the routine will first save all the pending data and - * will always return 0. - */ -PNG_EXPORT(219, png_size_t, png_process_data_pause, (png_structp, int save)); - -/* A function which may be called *only* outside (after) a call to - * png_process_data. It returns the number of bytes of data to skip in the - * input. Normally it will return 0, but if it returns a non-zero value the - * application must skip than number of bytes of input data and pass the - * following data to the next call to png_process_data. - */ -PNG_EXPORT(220, png_uint_32, png_process_data_skip, (png_structp)); - -/* Function that combines rows. 'new_row' is a flag that should come from - * the callback and be non-NULL if anything needs to be done; the library - * stores its own version of the new data internally and ignores the passed - * in value. - */ -PNG_EXPORT(93, void, png_progressive_combine_row, (png_structp png_ptr, - png_bytep old_row, png_const_bytep new_row)); -#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ - -PNG_EXPORTA(94, png_voidp, png_malloc, - (png_structp png_ptr, png_alloc_size_t size), - PNG_ALLOCATED); -/* Added at libpng version 1.4.0 */ -PNG_EXPORTA(95, png_voidp, png_calloc, - (png_structp png_ptr, png_alloc_size_t size), - PNG_ALLOCATED); - -/* Added at libpng version 1.2.4 */ -PNG_EXPORTA(96, png_voidp, png_malloc_warn, (png_structp png_ptr, - png_alloc_size_t size), PNG_ALLOCATED); - -/* Frees a pointer allocated by png_malloc() */ -PNG_EXPORT(97, void, png_free, (png_structp png_ptr, png_voidp ptr)); - -/* Free data that was allocated internally */ -PNG_EXPORT(98, void, png_free_data, - (png_structp png_ptr, png_infop info_ptr, png_uint_32 free_me, int num)); - -/* Reassign responsibility for freeing existing data, whether allocated - * by libpng or by the application */ -PNG_EXPORT(99, void, png_data_freer, - (png_structp png_ptr, png_infop info_ptr, int freer, png_uint_32 mask)); - -/* Assignments for png_data_freer */ -#define PNG_DESTROY_WILL_FREE_DATA 1 -#define PNG_SET_WILL_FREE_DATA 1 -#define PNG_USER_WILL_FREE_DATA 2 -/* Flags for png_ptr->free_me and info_ptr->free_me */ -#define PNG_FREE_HIST 0x0008 -#define PNG_FREE_ICCP 0x0010 -#define PNG_FREE_SPLT 0x0020 -#define PNG_FREE_ROWS 0x0040 -#define PNG_FREE_PCAL 0x0080 -#define PNG_FREE_SCAL 0x0100 -#define PNG_FREE_UNKN 0x0200 -#define PNG_FREE_LIST 0x0400 -#define PNG_FREE_PLTE 0x1000 -#define PNG_FREE_TRNS 0x2000 -#define PNG_FREE_TEXT 0x4000 -#define PNG_FREE_ALL 0x7fff -#define PNG_FREE_MUL 0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ - -#ifdef PNG_USER_MEM_SUPPORTED -PNG_EXPORTA(100, png_voidp, png_malloc_default, (png_structp png_ptr, - png_alloc_size_t size), PNG_ALLOCATED); -PNG_EXPORT(101, void, png_free_default, (png_structp png_ptr, png_voidp ptr)); -#endif - -#ifdef PNG_ERROR_TEXT_SUPPORTED -/* Fatal error in PNG image of libpng - can't continue */ -PNG_EXPORTA(102, void, png_error, - (png_structp png_ptr, png_const_charp error_message), - PNG_NORETURN); - -/* The same, but the chunk name is prepended to the error string. */ -PNG_EXPORTA(103, void, png_chunk_error, (png_structp png_ptr, - png_const_charp error_message), PNG_NORETURN); - -#else -/* Fatal error in PNG image of libpng - can't continue */ -PNG_EXPORTA(104, void, png_err, (png_structp png_ptr), PNG_NORETURN); -#endif - -/* Non-fatal error in libpng. Can continue, but may have a problem. */ -PNG_EXPORT(105, void, png_warning, (png_structp png_ptr, - png_const_charp warning_message)); - -/* Non-fatal error in libpng, chunk name is prepended to message. */ -PNG_EXPORT(106, void, png_chunk_warning, (png_structp png_ptr, - png_const_charp warning_message)); - -#ifdef PNG_BENIGN_ERRORS_SUPPORTED -/* Benign error in libpng. Can continue, but may have a problem. - * User can choose whether to handle as a fatal error or as a warning. */ -# undef png_benign_error -PNG_EXPORT(107, void, png_benign_error, (png_structp png_ptr, - png_const_charp warning_message)); - -/* Same, chunk name is prepended to message. */ -# undef png_chunk_benign_error -PNG_EXPORT(108, void, png_chunk_benign_error, (png_structp png_ptr, - png_const_charp warning_message)); - -PNG_EXPORT(109, void, png_set_benign_errors, - (png_structp png_ptr, int allowed)); -#else -# ifdef PNG_ALLOW_BENIGN_ERRORS -# define png_benign_error png_warning -# define png_chunk_benign_error png_chunk_warning -# else -# define png_benign_error png_error -# define png_chunk_benign_error png_chunk_error -# endif -#endif - -/* The png_set_ functions are for storing values in the png_info_struct. - * Similarly, the png_get_ calls are used to read values from the - * png_info_struct, either storing the parameters in the passed variables, or - * setting pointers into the png_info_struct where the data is stored. The - * png_get_ functions return a non-zero value if the data was available - * in info_ptr, or return zero and do not change any of the parameters if the - * data was not available. - * - * These functions should be used instead of directly accessing png_info - * to avoid problems with future changes in the size and internal layout of - * png_info_struct. - */ -/* Returns "flag" if chunk data is valid in info_ptr. */ -PNG_EXPORT(110, png_uint_32, png_get_valid, - (png_const_structp png_ptr, png_const_infop info_ptr, - png_uint_32 flag)); - -/* Returns number of bytes needed to hold a transformed row. */ -PNG_EXPORT(111, png_size_t, png_get_rowbytes, (png_const_structp png_ptr, - png_const_infop info_ptr)); - -#ifdef PNG_INFO_IMAGE_SUPPORTED -/* Returns row_pointers, which is an array of pointers to scanlines that was - * returned from png_read_png(). - */ -PNG_EXPORT(112, png_bytepp, png_get_rows, - (png_const_structp png_ptr, png_const_infop info_ptr)); -/* Set row_pointers, which is an array of pointers to scanlines for use - * by png_write_png(). - */ -PNG_EXPORT(113, void, png_set_rows, (png_structp png_ptr, - png_infop info_ptr, png_bytepp row_pointers)); -#endif - -/* Returns number of color channels in image. */ -PNG_EXPORT(114, png_byte, png_get_channels, - (png_const_structp png_ptr, png_const_infop info_ptr)); - -#ifdef PNG_EASY_ACCESS_SUPPORTED -/* Returns image width in pixels. */ -PNG_EXPORT(115, png_uint_32, png_get_image_width, (png_const_structp png_ptr, - png_const_infop info_ptr)); - -/* Returns image height in pixels. */ -PNG_EXPORT(116, png_uint_32, png_get_image_height, (png_const_structp png_ptr, - png_const_infop info_ptr)); - -/* Returns image bit_depth. */ -PNG_EXPORT(117, png_byte, png_get_bit_depth, - (png_const_structp png_ptr, png_const_infop info_ptr)); - -/* Returns image color_type. */ -PNG_EXPORT(118, png_byte, png_get_color_type, (png_const_structp png_ptr, - png_const_infop info_ptr)); - -/* Returns image filter_type. */ -PNG_EXPORT(119, png_byte, png_get_filter_type, (png_const_structp png_ptr, - png_const_infop info_ptr)); - -/* Returns image interlace_type. */ -PNG_EXPORT(120, png_byte, png_get_interlace_type, (png_const_structp png_ptr, - png_const_infop info_ptr)); - -/* Returns image compression_type. */ -PNG_EXPORT(121, png_byte, png_get_compression_type, (png_const_structp png_ptr, - png_const_infop info_ptr)); - -/* Returns image resolution in pixels per meter, from pHYs chunk data. */ -PNG_EXPORT(122, png_uint_32, png_get_pixels_per_meter, - (png_const_structp png_ptr, png_const_infop info_ptr)); -PNG_EXPORT(123, png_uint_32, png_get_x_pixels_per_meter, - (png_const_structp png_ptr, png_const_infop info_ptr)); -PNG_EXPORT(124, png_uint_32, png_get_y_pixels_per_meter, - (png_const_structp png_ptr, png_const_infop info_ptr)); - -/* Returns pixel aspect ratio, computed from pHYs chunk data. */ -PNG_FP_EXPORT(125, float, png_get_pixel_aspect_ratio, - (png_const_structp png_ptr, png_const_infop info_ptr)); -PNG_FIXED_EXPORT(210, png_fixed_point, png_get_pixel_aspect_ratio_fixed, - (png_const_structp png_ptr, png_const_infop info_ptr)); - -/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ -PNG_EXPORT(126, png_int_32, png_get_x_offset_pixels, - (png_const_structp png_ptr, png_const_infop info_ptr)); -PNG_EXPORT(127, png_int_32, png_get_y_offset_pixels, - (png_const_structp png_ptr, png_const_infop info_ptr)); -PNG_EXPORT(128, png_int_32, png_get_x_offset_microns, - (png_const_structp png_ptr, png_const_infop info_ptr)); -PNG_EXPORT(129, png_int_32, png_get_y_offset_microns, - (png_const_structp png_ptr, png_const_infop info_ptr)); - -#endif /* PNG_EASY_ACCESS_SUPPORTED */ - -/* Returns pointer to signature string read from PNG header */ -PNG_EXPORT(130, png_const_bytep, png_get_signature, - (png_const_structp png_ptr, png_infop info_ptr)); - -#ifdef PNG_bKGD_SUPPORTED -PNG_EXPORT(131, png_uint_32, png_get_bKGD, - (png_const_structp png_ptr, png_infop info_ptr, - png_color_16p *background)); -#endif - -#ifdef PNG_bKGD_SUPPORTED -PNG_EXPORT(132, void, png_set_bKGD, (png_structp png_ptr, png_infop info_ptr, - png_const_color_16p background)); -#endif - -#ifdef PNG_cHRM_SUPPORTED -PNG_FP_EXPORT(133, png_uint_32, png_get_cHRM, (png_const_structp png_ptr, - png_const_infop info_ptr, double *white_x, double *white_y, double *red_x, - double *red_y, double *green_x, double *green_y, double *blue_x, - double *blue_y)); -#ifdef PNG_FIXED_POINT_SUPPORTED /* Otherwise not implemented */ -PNG_FIXED_EXPORT(134, png_uint_32, png_get_cHRM_fixed, - (png_const_structp png_ptr, - png_const_infop info_ptr, png_fixed_point *int_white_x, - png_fixed_point *int_white_y, png_fixed_point *int_red_x, - png_fixed_point *int_red_y, png_fixed_point *int_green_x, - png_fixed_point *int_green_y, png_fixed_point *int_blue_x, - png_fixed_point *int_blue_y)); -#endif -#endif - -#ifdef PNG_cHRM_SUPPORTED -PNG_FP_EXPORT(135, void, png_set_cHRM, - (png_structp png_ptr, png_infop info_ptr, - double white_x, double white_y, double red_x, double red_y, double green_x, - double green_y, double blue_x, double blue_y)); -PNG_FIXED_EXPORT(136, void, png_set_cHRM_fixed, (png_structp png_ptr, - png_infop info_ptr, png_fixed_point int_white_x, - png_fixed_point int_white_y, png_fixed_point int_red_x, - png_fixed_point int_red_y, png_fixed_point int_green_x, - png_fixed_point int_green_y, png_fixed_point int_blue_x, - png_fixed_point int_blue_y)); -#endif - -#ifdef PNG_gAMA_SUPPORTED -PNG_FP_EXPORT(137, png_uint_32, png_get_gAMA, - (png_const_structp png_ptr, png_const_infop info_ptr, - double *file_gamma)); -PNG_FIXED_EXPORT(138, png_uint_32, png_get_gAMA_fixed, - (png_const_structp png_ptr, png_const_infop info_ptr, - png_fixed_point *int_file_gamma)); -#endif - -#ifdef PNG_gAMA_SUPPORTED -PNG_FP_EXPORT(139, void, png_set_gAMA, (png_structp png_ptr, - png_infop info_ptr, double file_gamma)); -PNG_FIXED_EXPORT(140, void, png_set_gAMA_fixed, (png_structp png_ptr, - png_infop info_ptr, png_fixed_point int_file_gamma)); -#endif - -#ifdef PNG_hIST_SUPPORTED -PNG_EXPORT(141, png_uint_32, png_get_hIST, - (png_const_structp png_ptr, png_const_infop info_ptr, - png_uint_16p *hist)); -#endif - -#ifdef PNG_hIST_SUPPORTED -PNG_EXPORT(142, void, png_set_hIST, (png_structp png_ptr, - png_infop info_ptr, png_const_uint_16p hist)); -#endif - -PNG_EXPORT(143, png_uint_32, png_get_IHDR, - (png_structp png_ptr, png_infop info_ptr, - png_uint_32 *width, png_uint_32 *height, int *bit_depth, int *color_type, - int *interlace_method, int *compression_method, int *filter_method)); - -PNG_EXPORT(144, void, png_set_IHDR, - (png_structp png_ptr, png_infop info_ptr, - png_uint_32 width, png_uint_32 height, int bit_depth, int color_type, - int interlace_method, int compression_method, int filter_method)); - -#ifdef PNG_oFFs_SUPPORTED -PNG_EXPORT(145, png_uint_32, png_get_oFFs, - (png_const_structp png_ptr, png_const_infop info_ptr, - png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type)); -#endif - -#ifdef PNG_oFFs_SUPPORTED -PNG_EXPORT(146, void, png_set_oFFs, - (png_structp png_ptr, png_infop info_ptr, - png_int_32 offset_x, png_int_32 offset_y, int unit_type)); -#endif - -#ifdef PNG_pCAL_SUPPORTED -PNG_EXPORT(147, png_uint_32, png_get_pCAL, - (png_const_structp png_ptr, png_const_infop info_ptr, - png_charp *purpose, png_int_32 *X0, png_int_32 *X1, int *type, - int *nparams, - png_charp *units, png_charpp *params)); -#endif - -#ifdef PNG_pCAL_SUPPORTED -PNG_EXPORT(148, void, png_set_pCAL, (png_structp png_ptr, - png_infop info_ptr, - png_const_charp purpose, png_int_32 X0, png_int_32 X1, int type, - int nparams, png_const_charp units, png_charpp params)); -#endif - -#ifdef PNG_pHYs_SUPPORTED -PNG_EXPORT(149, png_uint_32, png_get_pHYs, - (png_const_structp png_ptr, png_const_infop info_ptr, - png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); -#endif - -#ifdef PNG_pHYs_SUPPORTED -PNG_EXPORT(150, void, png_set_pHYs, - (png_structp png_ptr, png_infop info_ptr, - png_uint_32 res_x, png_uint_32 res_y, int unit_type)); -#endif - -PNG_EXPORT(151, png_uint_32, png_get_PLTE, - (png_const_structp png_ptr, png_const_infop info_ptr, - png_colorp *palette, int *num_palette)); - -PNG_EXPORT(152, void, png_set_PLTE, - (png_structp png_ptr, png_infop info_ptr, - png_const_colorp palette, int num_palette)); - -#ifdef PNG_sBIT_SUPPORTED -PNG_EXPORT(153, png_uint_32, png_get_sBIT, - (png_const_structp png_ptr, png_infop info_ptr, - png_color_8p *sig_bit)); -#endif - -#ifdef PNG_sBIT_SUPPORTED -PNG_EXPORT(154, void, png_set_sBIT, - (png_structp png_ptr, png_infop info_ptr, png_const_color_8p sig_bit)); -#endif - -#ifdef PNG_sRGB_SUPPORTED -PNG_EXPORT(155, png_uint_32, png_get_sRGB, (png_const_structp png_ptr, - png_const_infop info_ptr, int *file_srgb_intent)); -#endif - -#ifdef PNG_sRGB_SUPPORTED -PNG_EXPORT(156, void, png_set_sRGB, - (png_structp png_ptr, png_infop info_ptr, int srgb_intent)); -PNG_EXPORT(157, void, png_set_sRGB_gAMA_and_cHRM, (png_structp png_ptr, - png_infop info_ptr, int srgb_intent)); -#endif - -#ifdef PNG_iCCP_SUPPORTED -PNG_EXPORT(158, png_uint_32, png_get_iCCP, - (png_const_structp png_ptr, png_const_infop info_ptr, - png_charpp name, int *compression_type, png_bytepp profile, - png_uint_32 *proflen)); -#endif - -#ifdef PNG_iCCP_SUPPORTED -PNG_EXPORT(159, void, png_set_iCCP, - (png_structp png_ptr, png_infop info_ptr, - png_const_charp name, int compression_type, png_const_bytep profile, - png_uint_32 proflen)); -#endif - -#ifdef PNG_sPLT_SUPPORTED -PNG_EXPORT(160, png_uint_32, png_get_sPLT, - (png_const_structp png_ptr, png_const_infop info_ptr, - png_sPLT_tpp entries)); -#endif - -#ifdef PNG_sPLT_SUPPORTED -PNG_EXPORT(161, void, png_set_sPLT, - (png_structp png_ptr, png_infop info_ptr, - png_const_sPLT_tp entries, int nentries)); -#endif - -#ifdef PNG_TEXT_SUPPORTED -/* png_get_text also returns the number of text chunks in *num_text */ -PNG_EXPORT(162, png_uint_32, png_get_text, - (png_const_structp png_ptr, png_const_infop info_ptr, - png_textp *text_ptr, int *num_text)); -#endif - -/* Note while png_set_text() will accept a structure whose text, - * language, and translated keywords are NULL pointers, the structure - * returned by png_get_text will always contain regular - * zero-terminated C strings. They might be empty strings but - * they will never be NULL pointers. - */ - -#ifdef PNG_TEXT_SUPPORTED -PNG_EXPORT(163, void, png_set_text, - (png_structp png_ptr, png_infop info_ptr, - png_const_textp text_ptr, int num_text)); -#endif - -#ifdef PNG_tIME_SUPPORTED -PNG_EXPORT(164, png_uint_32, png_get_tIME, - (png_const_structp png_ptr, png_infop info_ptr, png_timep *mod_time)); -#endif - -#ifdef PNG_tIME_SUPPORTED -PNG_EXPORT(165, void, png_set_tIME, - (png_structp png_ptr, png_infop info_ptr, png_const_timep mod_time)); -#endif - -#ifdef PNG_tRNS_SUPPORTED -PNG_EXPORT(166, png_uint_32, png_get_tRNS, - (png_const_structp png_ptr, png_infop info_ptr, - png_bytep *trans_alpha, int *num_trans, png_color_16p *trans_color)); -#endif - -#ifdef PNG_tRNS_SUPPORTED -PNG_EXPORT(167, void, png_set_tRNS, - (png_structp png_ptr, png_infop info_ptr, - png_const_bytep trans_alpha, int num_trans, - png_const_color_16p trans_color)); -#endif - -#ifdef PNG_sCAL_SUPPORTED -PNG_FP_EXPORT(168, png_uint_32, png_get_sCAL, - (png_const_structp png_ptr, png_const_infop info_ptr, - int *unit, double *width, double *height)); -#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED -/* NOTE: this API is currently implemented using floating point arithmetic, - * consequently it can only be used on systems with floating point support. - * In any case the range of values supported by png_fixed_point is small and it - * is highly recommended that png_get_sCAL_s be used instead. - */ -PNG_FIXED_EXPORT(214, png_uint_32, png_get_sCAL_fixed, - (png_structp png_ptr, png_const_infop info_ptr, int *unit, - png_fixed_point *width, - png_fixed_point *height)); -#endif -PNG_EXPORT(169, png_uint_32, png_get_sCAL_s, - (png_const_structp png_ptr, png_const_infop info_ptr, - int *unit, png_charpp swidth, png_charpp sheight)); - -PNG_FP_EXPORT(170, void, png_set_sCAL, - (png_structp png_ptr, png_infop info_ptr, - int unit, double width, double height)); -PNG_FIXED_EXPORT(213, void, png_set_sCAL_fixed, (png_structp png_ptr, - png_infop info_ptr, int unit, png_fixed_point width, - png_fixed_point height)); -PNG_EXPORT(171, void, png_set_sCAL_s, - (png_structp png_ptr, png_infop info_ptr, - int unit, png_const_charp swidth, png_const_charp sheight)); -#endif /* PNG_sCAL_SUPPORTED */ - -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED -/* Provide a list of chunks and how they are to be handled, if the built-in - handling or default unknown chunk handling is not desired. Any chunks not - listed will be handled in the default manner. The IHDR and IEND chunks - must not be listed. - keep = 0: follow default behaviour - = 1: do not keep - = 2: keep only if safe-to-copy - = 3: keep even if unsafe-to-copy -*/ -PNG_EXPORT(172, void, png_set_keep_unknown_chunks, - (png_structp png_ptr, int keep, - png_const_bytep chunk_list, int num_chunks)); -PNG_EXPORT(173, int, png_handle_as_unknown, (png_structp png_ptr, - png_const_bytep chunk_name)); -#endif -#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED -PNG_EXPORT(174, void, png_set_unknown_chunks, (png_structp png_ptr, - png_infop info_ptr, png_const_unknown_chunkp unknowns, - int num_unknowns)); -PNG_EXPORT(175, void, png_set_unknown_chunk_location, - (png_structp png_ptr, png_infop info_ptr, int chunk, int location)); -PNG_EXPORT(176, int, png_get_unknown_chunks, (png_const_structp png_ptr, - png_const_infop info_ptr, png_unknown_chunkpp entries)); -#endif - -/* Png_free_data() will turn off the "valid" flag for anything it frees. - * If you need to turn it off for a chunk that your application has freed, - * you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); - */ -PNG_EXPORT(177, void, png_set_invalid, - (png_structp png_ptr, png_infop info_ptr, int mask)); - -#ifdef PNG_INFO_IMAGE_SUPPORTED -/* The "params" pointer is currently not used and is for future expansion. */ -PNG_EXPORT(178, void, png_read_png, (png_structp png_ptr, png_infop info_ptr, - int transforms, png_voidp params)); -PNG_EXPORT(179, void, png_write_png, (png_structp png_ptr, png_infop info_ptr, - int transforms, png_voidp params)); -#endif - -PNG_EXPORT(180, png_const_charp, png_get_copyright, - (png_const_structp png_ptr)); -PNG_EXPORT(181, png_const_charp, png_get_header_ver, - (png_const_structp png_ptr)); -PNG_EXPORT(182, png_const_charp, png_get_header_version, - (png_const_structp png_ptr)); -PNG_EXPORT(183, png_const_charp, png_get_libpng_ver, - (png_const_structp png_ptr)); - -#ifdef PNG_MNG_FEATURES_SUPPORTED -PNG_EXPORT(184, png_uint_32, png_permit_mng_features, (png_structp png_ptr, - png_uint_32 mng_features_permitted)); -#endif - -/* For use in png_set_keep_unknown, added to version 1.2.6 */ -#define PNG_HANDLE_CHUNK_AS_DEFAULT 0 -#define PNG_HANDLE_CHUNK_NEVER 1 -#define PNG_HANDLE_CHUNK_IF_SAFE 2 -#define PNG_HANDLE_CHUNK_ALWAYS 3 - -/* Strip the prepended error numbers ("#nnn ") from error and warning - * messages before passing them to the error or warning handler. - */ -#ifdef PNG_ERROR_NUMBERS_SUPPORTED -PNG_EXPORT(185, void, png_set_strip_error_numbers, - (png_structp png_ptr, - png_uint_32 strip_mode)); -#endif - -/* Added in libpng-1.2.6 */ -#ifdef PNG_SET_USER_LIMITS_SUPPORTED -PNG_EXPORT(186, void, png_set_user_limits, (png_structp png_ptr, - png_uint_32 user_width_max, png_uint_32 user_height_max)); -PNG_EXPORT(187, png_uint_32, png_get_user_width_max, - (png_const_structp png_ptr)); -PNG_EXPORT(188, png_uint_32, png_get_user_height_max, - (png_const_structp png_ptr)); -/* Added in libpng-1.4.0 */ -PNG_EXPORT(189, void, png_set_chunk_cache_max, (png_structp png_ptr, - png_uint_32 user_chunk_cache_max)); -PNG_EXPORT(190, png_uint_32, png_get_chunk_cache_max, - (png_const_structp png_ptr)); -/* Added in libpng-1.4.1 */ -PNG_EXPORT(191, void, png_set_chunk_malloc_max, (png_structp png_ptr, - png_alloc_size_t user_chunk_cache_max)); -PNG_EXPORT(192, png_alloc_size_t, png_get_chunk_malloc_max, - (png_const_structp png_ptr)); -#endif - -#if defined(PNG_INCH_CONVERSIONS_SUPPORTED) -PNG_EXPORT(193, png_uint_32, png_get_pixels_per_inch, - (png_const_structp png_ptr, png_const_infop info_ptr)); - -PNG_EXPORT(194, png_uint_32, png_get_x_pixels_per_inch, - (png_const_structp png_ptr, png_const_infop info_ptr)); - -PNG_EXPORT(195, png_uint_32, png_get_y_pixels_per_inch, - (png_const_structp png_ptr, png_const_infop info_ptr)); - -PNG_FP_EXPORT(196, float, png_get_x_offset_inches, - (png_const_structp png_ptr, png_const_infop info_ptr)); -#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ -PNG_FIXED_EXPORT(211, png_fixed_point, png_get_x_offset_inches_fixed, - (png_structp png_ptr, png_const_infop info_ptr)); -#endif - -PNG_FP_EXPORT(197, float, png_get_y_offset_inches, (png_const_structp png_ptr, - png_const_infop info_ptr)); -#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ -PNG_FIXED_EXPORT(212, png_fixed_point, png_get_y_offset_inches_fixed, - (png_structp png_ptr, png_const_infop info_ptr)); -#endif - -# ifdef PNG_pHYs_SUPPORTED -PNG_EXPORT(198, png_uint_32, png_get_pHYs_dpi, (png_const_structp png_ptr, - png_const_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, - int *unit_type)); -# endif /* PNG_pHYs_SUPPORTED */ -#endif /* PNG_INCH_CONVERSIONS_SUPPORTED */ - -/* Added in libpng-1.4.0 */ -#ifdef PNG_IO_STATE_SUPPORTED -PNG_EXPORT(199, png_uint_32, png_get_io_state, (png_structp png_ptr)); - -PNG_EXPORTA(200, png_const_bytep, png_get_io_chunk_name, - (png_structp png_ptr), PNG_DEPRECATED); -PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type, - (png_const_structp png_ptr)); - -/* The flags returned by png_get_io_state() are the following: */ -# define PNG_IO_NONE 0x0000 /* no I/O at this moment */ -# define PNG_IO_READING 0x0001 /* currently reading */ -# define PNG_IO_WRITING 0x0002 /* currently writing */ -# define PNG_IO_SIGNATURE 0x0010 /* currently at the file signature */ -# define PNG_IO_CHUNK_HDR 0x0020 /* currently at the chunk header */ -# define PNG_IO_CHUNK_DATA 0x0040 /* currently at the chunk data */ -# define PNG_IO_CHUNK_CRC 0x0080 /* currently at the chunk crc */ -# define PNG_IO_MASK_OP 0x000f /* current operation: reading/writing */ -# define PNG_IO_MASK_LOC 0x00f0 /* current location: sig/hdr/data/crc */ -#endif /* ?PNG_IO_STATE_SUPPORTED */ - -/* Interlace support. The following macros are always defined so that if - * libpng interlace handling is turned off the macros may be used to handle - * interlaced images within the application. - */ -#define PNG_INTERLACE_ADAM7_PASSES 7 - -/* Two macros to return the first row and first column of the original, - * full, image which appears in a given pass. 'pass' is in the range 0 - * to 6 and the result is in the range 0 to 7. - */ -#define PNG_PASS_START_ROW(pass) (((1U&~(pass))<<(3-((pass)>>1)))&7) -#define PNG_PASS_START_COL(pass) (((1U& (pass))<<(3-(((pass)+1)>>1)))&7) - -/* Two macros to help evaluate the number of rows or columns in each - * pass. This is expressed as a shift - effectively log2 of the number or - * rows or columns in each 8x8 tile of the original image. - */ -#define PNG_PASS_ROW_SHIFT(pass) ((pass)>2?(8-(pass))>>1:3) -#define PNG_PASS_COL_SHIFT(pass) ((pass)>1?(7-(pass))>>1:3) - -/* Hence two macros to determine the number of rows or columns in a given - * pass of an image given its height or width. In fact these macros may - * return non-zero even though the sub-image is empty, because the other - * dimension may be empty for a small image. - */ -#define PNG_PASS_ROWS(height, pass) (((height)+(((1<>PNG_PASS_ROW_SHIFT(pass)) -#define PNG_PASS_COLS(width, pass) (((width)+(((1<>PNG_PASS_COL_SHIFT(pass)) - -/* For the reader row callbacks (both progressive and sequential) it is - * necessary to find the row in the output image given a row in an interlaced - * image, so two more macros: - */ -#define PNG_ROW_FROM_PASS_ROW(yIn, pass) \ - (((yIn)<>(((7-(off))-(pass))<<2)) & 0xFU) | \ - ((0x01145AF0U>>(((7-(off))-(pass))<<2)) & 0xF0U)) - -#define PNG_ROW_IN_INTERLACE_PASS(y, pass) \ - ((PNG_PASS_MASK(pass,0) >> ((y)&7)) & 1) -#define PNG_COL_IN_INTERLACE_PASS(x, pass) \ - ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1) - -#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED -/* With these routines we avoid an integer divide, which will be slower on - * most machines. However, it does take more operations than the corresponding - * divide method, so it may be slower on a few RISC systems. There are two - * shifts (by 8 or 16 bits) and an addition, versus a single integer divide. - * - * Note that the rounding factors are NOT supposed to be the same! 128 and - * 32768 are correct for the NODIV code; 127 and 32767 are correct for the - * standard method. - * - * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ] - */ - - /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ - -# define png_composite(composite, fg, alpha, bg) \ - { png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) \ - * (png_uint_16)(alpha) \ - + (png_uint_16)(bg)*(png_uint_16)(255 \ - - (png_uint_16)(alpha)) + (png_uint_16)128); \ - (composite) = (png_byte)((temp + (temp >> 8)) >> 8); } - -# define png_composite_16(composite, fg, alpha, bg) \ - { png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) \ - * (png_uint_32)(alpha) \ - + (png_uint_32)(bg)*(png_uint_32)(65535L \ - - (png_uint_32)(alpha)) + (png_uint_32)32768L); \ - (composite) = (png_uint_16)((temp + (temp >> 16)) >> 16); } - -#else /* Standard method using integer division */ - -# define png_composite(composite, fg, alpha, bg) \ - (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) + \ - (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ - (png_uint_16)127) / 255) - -# define png_composite_16(composite, fg, alpha, bg) \ - (composite) = (png_uint_16)(((png_uint_32)(fg) * (png_uint_32)(alpha) + \ - (png_uint_32)(bg)*(png_uint_32)(65535L - (png_uint_32)(alpha)) + \ - (png_uint_32)32767) / (png_uint_32)65535L) -#endif /* PNG_READ_COMPOSITE_NODIV_SUPPORTED */ - -#ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED -PNG_EXPORT(201, png_uint_32, png_get_uint_32, (png_const_bytep buf)); -PNG_EXPORT(202, png_uint_16, png_get_uint_16, (png_const_bytep buf)); -PNG_EXPORT(203, png_int_32, png_get_int_32, (png_const_bytep buf)); -#endif - -PNG_EXPORT(204, png_uint_32, png_get_uint_31, (png_structp png_ptr, - png_const_bytep buf)); -/* No png_get_int_16 -- may be added if there's a real need for it. */ - -/* Place a 32-bit number into a buffer in PNG byte order (big-endian). */ -#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED -PNG_EXPORT(205, void, png_save_uint_32, (png_bytep buf, png_uint_32 i)); -#endif -#ifdef PNG_SAVE_INT_32_SUPPORTED -PNG_EXPORT(206, void, png_save_int_32, (png_bytep buf, png_int_32 i)); -#endif - -/* Place a 16-bit number into a buffer in PNG byte order. - * The parameter is declared unsigned int, not png_uint_16, - * just to avoid potential problems on pre-ANSI C compilers. - */ -#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED -PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i)); -/* No png_save_int_16 -- may be added if there's a real need for it. */ -#endif - -#ifdef PNG_USE_READ_MACROS -/* Inline macros to do direct reads of bytes from the input buffer. - * The png_get_int_32() routine assumes we are using two's complement - * format for negative values, which is almost certainly true. - */ -# define png_get_uint_32(buf) \ - (((png_uint_32)(*(buf)) << 24) + \ - ((png_uint_32)(*((buf) + 1)) << 16) + \ - ((png_uint_32)(*((buf) + 2)) << 8) + \ - ((png_uint_32)(*((buf) + 3)))) - - /* From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the - * function) incorrectly returned a value of type png_uint_32. - */ -# define png_get_uint_16(buf) \ - ((png_uint_16) \ - (((unsigned int)(*(buf)) << 8) + \ - ((unsigned int)(*((buf) + 1))))) - -# define png_get_int_32(buf) \ - ((png_int_32)((*(buf) & 0x80) \ - ? -((png_int_32)((png_get_uint_32(buf) ^ 0xffffffffL) + 1)) \ - : (png_int_32)png_get_uint_32(buf))) -#endif - -/* Maintainer: Put new public prototypes here ^, in libpng.3, and project - * defs - */ - -/* The last ordinal number (this is the *last* one already used; the next - * one to use is one more than this.) Maintainer, remember to add an entry to - * scripts/symbols.def as well. - */ -#ifdef PNG_EXPORT_LAST_ORDINAL - PNG_EXPORT_LAST_ORDINAL(221); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* PNG_VERSION_INFO_ONLY */ -/* Do not put anything past this line */ -#endif /* PNG_H */ diff --git a/cdeps/win/amd/win64/pngconf.h b/cdeps/win/amd/win64/pngconf.h deleted file mode 100755 index 084de8ef..00000000 --- a/cdeps/win/amd/win64/pngconf.h +++ /dev/null @@ -1,649 +0,0 @@ - -/* pngconf.h - machine configurable file for libpng - * - * libpng version 1.5.2 - March 31, 2011 - * - * Copyright (c) 1998-2011 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This code is released under the libpng license. - * For conditions of distribution and use, see the disclaimer - * and license in png.h - * - */ - -/* Any machine specific code is near the front of this file, so if you - * are configuring libpng for a machine, you may want to read the section - * starting here down to where it starts to typedef png_color, png_text, - * and png_info. - */ - -#ifndef PNGCONF_H -#define PNGCONF_H - -#ifndef PNG_BUILDING_SYMBOL_TABLE -/* PNG_NO_LIMITS_H may be used to turn off the use of the standard C - * definition file for machine specific limits, this may impact the - * correctness of the definitons below (see uses of INT_MAX). - */ -# ifndef PNG_NO_LIMITS_H -# include -# endif - -/* For the memory copy APIs (i.e. the standard definitions of these), - * because this file defines png_memcpy and so on the base APIs must - * be defined here. - */ -# ifdef BSD -# include -# else -# include -# endif - -/* For png_FILE_p - this provides the standard definition of a - * FILE - */ -# ifdef PNG_STDIO_SUPPORTED -# include -# endif -#endif - -/* This controls optimization of the reading of 16 and 32 bit values - * from PNG files. It can be set on a per-app-file basis - it - * just changes whether a macro is used to the function is called. - * The library builder sets the default, if read functions are not - * built into the library the macro implementation is forced on. - */ -#ifndef PNG_READ_INT_FUNCTIONS_SUPPORTED -# define PNG_USE_READ_MACROS -#endif -#if !defined(PNG_NO_USE_READ_MACROS) && !defined(PNG_USE_READ_MACROS) -# if PNG_DEFAULT_READ_MACROS -# define PNG_USE_READ_MACROS -# endif -#endif - -/* COMPILER SPECIFIC OPTIONS. - * - * These options are provided so that a variety of difficult compilers - * can be used. Some are fixed at build time (e.g. PNG_API_RULE - * below) but still have compiler specific implementations, others - * may be changed on a per-file basis when compiling against libpng. - */ - -/* The PNGARG macro protects us against machines that don't have function - * prototypes (ie K&R style headers). If your compiler does not handle - * function prototypes, define this macro and use the included ansi2knr. - * I've always been able to use _NO_PROTO as the indicator, but you may - * need to drag the empty declaration out in front of here, or change the - * ifdef to suit your own needs. - */ -#ifndef PNGARG - -# ifdef OF /* zlib prototype munger */ -# define PNGARG(arglist) OF(arglist) -# else - -# ifdef _NO_PROTO -# define PNGARG(arglist) () -# else -# define PNGARG(arglist) arglist -# endif /* _NO_PROTO */ - -# endif /* OF */ - -#endif /* PNGARG */ - -/* Function calling conventions. - * ============================= - * Normally it is not necessary to specify to the compiler how to call - * a function - it just does it - however on x86 systems derived from - * Microsoft and Borland C compilers ('IBM PC', 'DOS', 'Windows' systems - * and some others) there are multiple ways to call a function and the - * default can be changed on the compiler command line. For this reason - * libpng specifies the calling convention of every exported function and - * every function called via a user supplied function pointer. This is - * done in this file by defining the following macros: - * - * PNGAPI Calling convention for exported functions. - * PNGCBAPI Calling convention for user provided (callback) functions. - * PNGCAPI Calling convention used by the ANSI-C library (required - * for longjmp callbacks and sometimes used internally to - * specify the calling convention for zlib). - * - * These macros should never be overridden. If it is necessary to - * change calling convention in a private build this can be done - * by setting PNG_API_RULE (which defaults to 0) to one of the values - * below to select the correct 'API' variants. - * - * PNG_API_RULE=0 Use PNGCAPI - the 'C' calling convention - throughout. - * This is correct in every known environment. - * PNG_API_RULE=1 Use the operating system convention for PNGAPI and - * the 'C' calling convention (from PNGCAPI) for - * callbacks (PNGCBAPI). This is no longer required - * in any known environment - if it has to be used - * please post an explanation of the problem to the - * libpng mailing list. - * - * These cases only differ if the operating system does not use the C - * calling convention, at present this just means the above cases - * (x86 DOS/Windows sytems) and, even then, this does not apply to - * Cygwin running on those systems. - * - * Note that the value must be defined in pnglibconf.h so that what - * the application uses to call the library matches the conventions - * set when building the library. - */ - -/* Symbol export - * ============= - * When building a shared library it is almost always necessary to tell - * the compiler which symbols to export. The png.h macro 'PNG_EXPORT' - * is used to mark the symbols. On some systems these symbols can be - * extracted at link time and need no special processing by the compiler, - * on other systems the symbols are flagged by the compiler and just - * the declaration requires a special tag applied (unfortunately) in a - * compiler dependent way. Some systems can do either. - * - * A small number of older systems also require a symbol from a DLL to - * be flagged to the program that calls it. This is a problem because - * we do not know in the header file included by application code that - * the symbol will come from a shared library, as opposed to a statically - * linked one. For this reason the application must tell us by setting - * the magic flag PNG_USE_DLL to turn on the special processing before - * it includes png.h. - * - * Four additional macros are used to make this happen: - * - * PNG_IMPEXP The magic (if any) to cause a symbol to be exported from - * the build or imported if PNG_USE_DLL is set - compiler - * and system specific. - * - * PNG_EXPORT_TYPE(type) A macro that pre or appends PNG_IMPEXP to - * 'type', compiler specific. - * - * PNG_DLL_EXPORT Set to the magic to use during a libpng build to - * make a symbol exported from the DLL. - * - * PNG_DLL_IMPORT Set to the magic to force the libpng symbols to come - * from a DLL - used to define PNG_IMPEXP when - * PNG_USE_DLL is set. - */ - -/* System specific discovery. - * ========================== - * This code is used at build time to find PNG_IMPEXP, the API settings - * and PNG_EXPORT_TYPE(), it may also set a macro to indicate the DLL - * import processing is possible. On Windows/x86 systems it also sets - * compiler-specific macros to the values required to change the calling - * conventions of the various functions. - */ -#if ( defined(_Windows) || defined(_WINDOWS) || defined(WIN32) ||\ - defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) ) &&\ - ( defined(_X86_) || defined(_X64_) || defined(_M_IX86) ||\ - defined(_M_X64) || defined(_M_IA64) ) - /* Windows system (DOS doesn't support DLLs) running on x86/x64. Includes - * builds under Cygwin or MinGW. Also includes Watcom builds but these need - * special treatment because they are not compatible with GCC or Visual C - * because of different calling conventions. - */ -# if PNG_API_RULE == 2 - /* If this line results in an error, either because __watcall is not - * understood or because of a redefine just below you cannot use *this* - * build of the library with the compiler you are using. *This* build was - * build using Watcom and applications must also be built using Watcom! - */ -# define PNGCAPI __watcall -# endif - -# if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800)) -# define PNGCAPI __cdecl -# if PNG_API_RULE == 1 -# define PNGAPI __stdcall -# endif -# else - /* An older compiler, or one not detected (erroneously) above, - * if necessary override on the command line to get the correct - * variants for the compiler. - */ -# ifndef PNGCAPI -# define PNGCAPI _cdecl -# endif -# if PNG_API_RULE == 1 && !defined(PNGAPI) -# define PNGAPI _stdcall -# endif -# endif /* compiler/api */ - /* NOTE: PNGCBAPI always defaults to PNGCAPI. */ - -# if defined(PNGAPI) && !defined(PNG_USER_PRIVATEBUILD) - ERROR: PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed -# endif - -# if (defined(_MSC_VER) && _MSC_VER < 800) ||\ - (defined(__BORLANDC__) && __BORLANDC__ < 0x500) - /* older Borland and MSC - * compilers used '__export' and required this to be after - * the type. - */ -# ifndef PNG_EXPORT_TYPE -# define PNG_EXPORT_TYPE(type) type PNG_IMPEXP -# endif -# define PNG_DLL_EXPORT __export -# else /* newer compiler */ -# define PNG_DLL_EXPORT __declspec(dllexport) -# ifndef PNG_DLL_IMPORT -# define PNG_DLL_IMPORT __declspec(dllimport) -# endif -# endif /* compiler */ - -#else /* !Windows/x86 */ -# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) -# define PNGAPI _System -# else /* !Windows/x86 && !OS/2 */ - /* Use the defaults, or define PNG*API on the command line (but - * this will have to be done for every compile!) - */ -# endif /* other system, !OS/2 */ -#endif /* !Windows/x86 */ - -/* Now do all the defaulting . */ -#ifndef PNGCAPI -# define PNGCAPI -#endif -#ifndef PNGCBAPI -# define PNGCBAPI PNGCAPI -#endif -#ifndef PNGAPI -# define PNGAPI PNGCAPI -#endif - -/* The default for PNG_IMPEXP depends on whether the library is - * being built or used. - */ -#ifndef PNG_IMPEXP -# ifdef PNGLIB_BUILD - /* Building the library */ -# if (defined(DLL_EXPORT)/*from libtool*/ ||\ - defined(_WINDLL) || defined(_DLL) || defined(__DLL__) ||\ - defined(_USRDLL) ||\ - defined(PNG_BUILD_DLL)) && defined(PNG_DLL_EXPORT) - /* Building a DLL. */ -# define PNG_IMPEXP PNG_DLL_EXPORT -# endif /* DLL */ -# else - /* Using the library */ -# if defined(PNG_USE_DLL) && defined(PNG_DLL_IMPORT) - /* This forces use of a DLL, disallowing static linking */ -# define PNG_IMPEXP PNG_DLL_IMPORT -# endif -# endif - -# ifndef PNG_IMPEXP -# define PNG_IMPEXP -# endif -#endif - -/* In 1.5.2 the definition of PNG_FUNCTION has been changed to always treat - * 'attributes' as a storage class - the attributes go at the start of the - * function definition, and attributes are always appended regardless of the - * compiler. This considerably simplifies these macros but may cause problems - * if any compilers both need function attributes and fail to handle them as - * a storage class (this is unlikely.) - */ -#ifndef PNG_FUNCTION -# define PNG_FUNCTION(type, name, args, attributes) attributes type name args -#endif - -#ifndef PNG_EXPORT_TYPE -# define PNG_EXPORT_TYPE(type) PNG_IMPEXP type -#endif - - /* The ordinal value is only relevant when preprocessing png.h for symbol - * table entries, so we discard it here. See the .dfn files in the - * scripts directory. - */ -#ifndef PNG_EXPORTA - -# define PNG_EXPORTA(ordinal, type, name, args, attributes)\ - PNG_FUNCTION(PNG_EXPORT_TYPE(type),(PNGAPI name),PNGARG(args), \ - extern attributes) -#endif - -/* ANSI-C (C90) does not permit a macro to be invoked with an empty argument, - * so make something non-empty to satisfy the requirement: - */ -#define PNG_EMPTY /*empty list*/ - -#define PNG_EXPORT(ordinal, type, name, args)\ - PNG_EXPORTA(ordinal, type, name, args, PNG_EMPTY) - -/* Use PNG_REMOVED to comment out a removed interface. */ -#ifndef PNG_REMOVED -# define PNG_REMOVED(ordinal, type, name, args, attributes) -#endif - -#ifndef PNG_CALLBACK -# define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) PNGARG(args) -#endif - -/* Support for compiler specific function attributes. These are used - * so that where compiler support is available incorrect use of API - * functions in png.h will generate compiler warnings. - * - * Added at libpng-1.2.41. - */ - -#ifndef PNG_NO_PEDANTIC_WARNINGS -# ifndef PNG_PEDANTIC_WARNINGS_SUPPORTED -# define PNG_PEDANTIC_WARNINGS_SUPPORTED -# endif -#endif - -#ifdef PNG_PEDANTIC_WARNINGS_SUPPORTED - /* Support for compiler specific function attributes. These are used - * so that where compiler support is available incorrect use of API - * functions in png.h will generate compiler warnings. Added at libpng - * version 1.2.41. - */ -# if defined(__GNUC__) -# ifndef PNG_USE_RESULT -# define PNG_USE_RESULT __attribute__((__warn_unused_result__)) -# endif -# ifndef PNG_NORETURN -# define PNG_NORETURN __attribute__((__noreturn__)) -# endif -# ifndef PNG_PTR_NORETURN - /* It's not enough to have the compiler be the correct compiler at - * this point - it's necessary for the library (which defines - * the type of the library longjmp) to also be the GNU library. - * This is because many systems use the GNU compiler with a - * non-GNU libc implementation. Min/GW headers are also compatible - * with GCC as well as uclibc, so it seems best to exclude known - * problem libcs here rather than just including known libcs. - * - * NOTE: this relies on the only use of PNG_PTR_NORETURN being with - * the system longjmp. If the same type is used elsewhere then this - * will need to be changed. - */ -# if !defined(__CYGWIN__) -# define PNG_PTR_NORETURN __attribute__((__noreturn__)) -# endif -# endif -# ifndef PNG_ALLOCATED -# define PNG_ALLOCATED __attribute__((__malloc__)) -# endif - - /* This specifically protects structure members that should only be - * accessed from within the library, therefore should be empty during - * a library build. - */ -# ifndef PNGLIB_BUILD -# ifndef PNG_DEPRECATED -# define PNG_DEPRECATED __attribute__((__deprecated__)) -# endif -# ifndef PNG_DEPSTRUCT -# define PNG_DEPSTRUCT __attribute__((__deprecated__)) -# endif -# ifndef PNG_PRIVATE -# if 0 /* Doesn't work so we use deprecated instead*/ -# define PNG_PRIVATE \ - __attribute__((warning("This function is not exported by libpng."))) -# else -# define PNG_PRIVATE \ - __attribute__((__deprecated__)) -# endif -# endif -# endif /* PNGLIB_BUILD */ -# endif /* __GNUC__ */ - -# if defined(_MSC_VER) && (_MSC_VER >= 1300) -# ifndef PNG_USE_RESULT -# define PNG_USE_RESULT /* not supported */ -# endif -# ifndef PNG_NORETURN -# define PNG_NORETURN __declspec(noreturn) -# endif -# ifndef PNG_PTR_NORETURN -# define PNG_PTR_NORETURN /* not supported */ -# endif -# ifndef PNG_ALLOCATED -# define PNG_ALLOCATED __declspec(restrict) -# endif - - /* This specifically protects structure members that should only be - * accessed from within the library, therefore should be empty during - * a library build. - */ -# ifndef PNGLIB_BUILD -# ifndef PNG_DEPRECATED -# define PNG_DEPRECATED __declspec(deprecated) -# endif -# ifndef PNG_DEPSTRUCT -# define PNG_DEPSTRUCT __declspec(deprecated) -# endif -# ifndef PNG_PRIVATE -# define PNG_PRIVATE __declspec(deprecated) -# endif -# endif /* PNGLIB_BUILD */ -# endif /* _MSC_VER */ -#endif /* PNG_PEDANTIC_WARNINGS */ - -#ifndef PNG_DEPRECATED -# define PNG_DEPRECATED /* Use of this function is deprecated */ -#endif -#ifndef PNG_USE_RESULT -# define PNG_USE_RESULT /* The result of this function must be checked */ -#endif -#ifndef PNG_NORETURN -# define PNG_NORETURN /* This function does not return */ -#endif -#ifndef PNG_PTR_NORETURN -# define PNG_PTR_NORETURN /* This function does not return */ -#endif -#ifndef PNG_ALLOCATED -# define PNG_ALLOCATED /* The result of the function is new memory */ -#endif -#ifndef PNG_DEPSTRUCT -# define PNG_DEPSTRUCT /* Access to this struct member is deprecated */ -#endif -#ifndef PNG_PRIVATE -# define PNG_PRIVATE /* This is a private libpng function */ -#endif -#ifndef PNG_FP_EXPORT /* A floating point API. */ -# ifdef PNG_FLOATING_POINT_SUPPORTED -# define PNG_FP_EXPORT(ordinal, type, name, args)\ - PNG_EXPORT(ordinal, type, name, args) -# else /* No floating point APIs */ -# define PNG_FP_EXPORT(ordinal, type, name, args) -# endif -#endif -#ifndef PNG_FIXED_EXPORT /* A fixed point API. */ -# ifdef PNG_FIXED_POINT_SUPPORTED -# define PNG_FIXED_EXPORT(ordinal, type, name, args)\ - PNG_EXPORT(ordinal, type, name, args) -# else /* No fixed point APIs */ -# define PNG_FIXED_EXPORT(ordinal, type, name, args) -# endif -#endif - -/* The following uses const char * instead of char * for error - * and warning message functions, so some compilers won't complain. - * If you do not want to use const, define PNG_NO_CONST here. - * - * This should not change how the APIs are called, so it can be done - * on a per-file basis in the application. - */ -#ifndef PNG_CONST -# ifndef PNG_NO_CONST -# define PNG_CONST const -# else -# define PNG_CONST -# endif -#endif - -/* Some typedefs to get us started. These should be safe on most of the - * common platforms. The typedefs should be at least as large as the - * numbers suggest (a png_uint_32 must be at least 32 bits long), but they - * don't have to be exactly that size. Some compilers dislike passing - * unsigned shorts as function parameters, so you may be better off using - * unsigned int for png_uint_16. - */ - -#if defined(INT_MAX) && (INT_MAX > 0x7ffffffeL) -typedef unsigned int png_uint_32; -typedef int png_int_32; -#else -typedef unsigned long png_uint_32; -typedef long png_int_32; -#endif -typedef unsigned short png_uint_16; -typedef short png_int_16; -typedef unsigned char png_byte; - -#ifdef PNG_NO_SIZE_T -typedef unsigned int png_size_t; -#else -typedef size_t png_size_t; -#endif -#define png_sizeof(x) (sizeof (x)) - -/* The following is needed for medium model support. It cannot be in the - * pngpriv.h header. Needs modification for other compilers besides - * MSC. Model independent support declares all arrays and pointers to be - * large using the far keyword. The zlib version used must also support - * model independent data. As of version zlib 1.0.4, the necessary changes - * have been made in zlib. The USE_FAR_KEYWORD define triggers other - * changes that are needed. (Tim Wegner) - */ - -/* Separate compiler dependencies (problem here is that zlib.h always - * defines FAR. (SJT) - */ -#ifdef __BORLANDC__ -# if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__) -# define LDATA 1 -# else -# define LDATA 0 -# endif - /* GRR: why is Cygwin in here? Cygwin is not Borland C... */ -# if !defined(__WIN32__) && !defined(__FLAT__) && !defined(__CYGWIN__) -# define PNG_MAX_MALLOC_64K /* only used in build */ -# if (LDATA != 1) -# ifndef FAR -# define FAR __far -# endif -# define USE_FAR_KEYWORD -# endif /* LDATA != 1 */ - /* Possibly useful for moving data out of default segment. - * Uncomment it if you want. Could also define FARDATA as - * const if your compiler supports it. (SJT) -# define FARDATA FAR - */ -# endif /* __WIN32__, __FLAT__, __CYGWIN__ */ -#endif /* __BORLANDC__ */ - - -/* Suggest testing for specific compiler first before testing for - * FAR. The Watcom compiler defines both __MEDIUM__ and M_I86MM, - * making reliance oncertain keywords suspect. (SJT) - */ - -/* MSC Medium model */ -#ifdef FAR -# ifdef M_I86MM -# define USE_FAR_KEYWORD -# define FARDATA FAR -# include -# endif -#endif - -/* SJT: default case */ -#ifndef FAR -# define FAR -#endif - -/* At this point FAR is always defined */ -#ifndef FARDATA -# define FARDATA -#endif - -/* Typedef for floating-point numbers that are converted - * to fixed-point with a multiple of 100,000, e.g., gamma - */ -typedef png_int_32 png_fixed_point; - -/* Add typedefs for pointers */ -typedef void FAR * png_voidp; -typedef PNG_CONST void FAR * png_const_voidp; -typedef png_byte FAR * png_bytep; -typedef PNG_CONST png_byte FAR * png_const_bytep; -typedef png_uint_32 FAR * png_uint_32p; -typedef PNG_CONST png_uint_32 FAR * png_const_uint_32p; -typedef png_int_32 FAR * png_int_32p; -typedef PNG_CONST png_int_32 FAR * png_const_int_32p; -typedef png_uint_16 FAR * png_uint_16p; -typedef PNG_CONST png_uint_16 FAR * png_const_uint_16p; -typedef png_int_16 FAR * png_int_16p; -typedef PNG_CONST png_int_16 FAR * png_const_int_16p; -typedef char FAR * png_charp; -typedef PNG_CONST char FAR * png_const_charp; -typedef png_fixed_point FAR * png_fixed_point_p; -typedef PNG_CONST png_fixed_point FAR * png_const_fixed_point_p; -typedef png_size_t FAR * png_size_tp; -typedef PNG_CONST png_size_t FAR * png_const_size_tp; - -#ifdef PNG_STDIO_SUPPORTED -typedef FILE * png_FILE_p; -#endif - -#ifdef PNG_FLOATING_POINT_SUPPORTED -typedef double FAR * png_doublep; -typedef PNG_CONST double FAR * png_const_doublep; -#endif - -/* Pointers to pointers; i.e. arrays */ -typedef png_byte FAR * FAR * png_bytepp; -typedef png_uint_32 FAR * FAR * png_uint_32pp; -typedef png_int_32 FAR * FAR * png_int_32pp; -typedef png_uint_16 FAR * FAR * png_uint_16pp; -typedef png_int_16 FAR * FAR * png_int_16pp; -typedef PNG_CONST char FAR * FAR * png_const_charpp; -typedef char FAR * FAR * png_charpp; -typedef png_fixed_point FAR * FAR * png_fixed_point_pp; -#ifdef PNG_FLOATING_POINT_SUPPORTED -typedef double FAR * FAR * png_doublepp; -#endif - -/* Pointers to pointers to pointers; i.e., pointer to array */ -typedef char FAR * FAR * FAR * png_charppp; - -/* png_alloc_size_t is guaranteed to be no smaller than png_size_t, - * and no smaller than png_uint_32. Casts from png_size_t or png_uint_32 - * to png_alloc_size_t are not necessary; in fact, it is recommended - * not to use them at all so that the compiler can complain when something - * turns out to be problematic. - * Casts in the other direction (from png_alloc_size_t to png_size_t or - * png_uint_32) should be explicitly applied; however, we do not expect - * to encounter practical situations that require such conversions. - */ -#if defined(__TURBOC__) && !defined(__FLAT__) - typedef unsigned long png_alloc_size_t; -#else -# if defined(_MSC_VER) && defined(MAXSEG_64K) - typedef unsigned long png_alloc_size_t; -# else - /* This is an attempt to detect an old Windows system where (int) is - * actually 16 bits, in that case png_malloc must have an argument with a - * bigger size to accomodate the requirements of the library. - */ -# if (defined(_Windows) || defined(_WINDOWS) || defined(_WINDOWS_)) && \ - (!defined(INT_MAX) || INT_MAX <= 0x7ffffffeL) - typedef DWORD png_alloc_size_t; -# else - typedef png_size_t png_alloc_size_t; -# endif -# endif -#endif - -#endif /* PNGCONF_H */ diff --git a/cdeps/win/amd/win64/pnglibconf.h b/cdeps/win/amd/win64/pnglibconf.h deleted file mode 100755 index e36ee348..00000000 --- a/cdeps/win/amd/win64/pnglibconf.h +++ /dev/null @@ -1,181 +0,0 @@ - -/* libpng STANDARD API DEFINITION */ - -/* pnglibconf.h - library build configuration */ - -/* libpng version 1.5.0 - last changed on February 11, 2011 */ - -/* Copyright (c) 1998-2011 Glenn Randers-Pehrson */ - -/* This code is released under the libpng license. */ -/* For conditions of distribution and use, see the disclaimer */ -/* and license in png.h */ - -/* pnglibconf.h */ -/* Derived from: scripts/pnglibconf.dfa */ -/* If you edit this file by hand you must obey the rules expressed in */ -/* pnglibconf.dfa with respect to the dependencies between the following */ -/* symbols. It is much better to generate a new file using */ -/* scripts/libpngconf.mak */ - -#ifndef PNGLCONF_H -#define PNGLCONF_H -/* settings */ -#define PNG_API_RULE 0 -#define PNG_CALLOC_SUPPORTED -#define PNG_COST_SHIFT 3 -#define PNG_DEFAULT_READ_MACROS 1 -#define PNG_GAMMA_THRESHOLD_FIXED 5000 -#define PNG_MAX_GAMMA_8 11 -#define PNG_QUANTIZE_BLUE_BITS 5 -#define PNG_QUANTIZE_GREEN_BITS 5 -#define PNG_QUANTIZE_RED_BITS 5 -#define PNG_sCAL_PRECISION 5 -#define PNG_USER_CHUNK_CACHE_MAX 0 -#define PNG_USER_CHUNK_MALLOC_MAX 0 -#define PNG_USER_HEIGHT_MAX 1000000L -#define PNG_USER_WIDTH_MAX 1000000L -#define PNG_WEIGHT_SHIFT 8 -#define PNG_ZBUF_SIZE 8192 -/* end of settings */ -/* options */ -#define PNG_16BIT_SUPPORTED -#define PNG_ALIGN_MEMORY_SUPPORTED -#define PNG_BENIGN_ERRORS_SUPPORTED -#define PNG_bKGD_SUPPORTED -#define PNG_CHECK_cHRM_SUPPORTED -#define PNG_cHRM_SUPPORTED -#define PNG_CONSOLE_IO_SUPPORTED -#define PNG_CONVERT_tIME_SUPPORTED -#define PNG_EASY_ACCESS_SUPPORTED -#define PNG_ERROR_TEXT_SUPPORTED -#define PNG_FIXED_POINT_SUPPORTED -#define PNG_FLOATING_ARITHMETIC_SUPPORTED -#define PNG_FLOATING_POINT_SUPPORTED -#define PNG_gAMA_SUPPORTED -#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED -#define PNG_hIST_SUPPORTED -#define PNG_iCCP_SUPPORTED -#define PNG_INCH_CONVERSIONS_SUPPORTED -#define PNG_INFO_IMAGE_SUPPORTED -#define PNG_IO_STATE_SUPPORTED -#define PNG_iTXt_SUPPORTED -#define PNG_MNG_FEATURES_SUPPORTED -#define PNG_oFFs_SUPPORTED -#define PNG_pCAL_SUPPORTED -#define PNG_pHYs_SUPPORTED -#define PNG_POINTER_INDEXING_SUPPORTED -#define PNG_PROGRESSIVE_READ_SUPPORTED -#define PNG_READ_16BIT_SUPPORTED -#define PNG_READ_16_TO_8_SUPPORTED -#define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED -#define PNG_READ_BACKGROUND_SUPPORTED -#define PNG_READ_BGR_SUPPORTED -#define PNG_READ_bKGD_SUPPORTED -#define PNG_READ_cHRM_SUPPORTED -#define PNG_READ_COMPOSITE_NODIV_SUPPORTED -#define PNG_READ_EXPAND_16_SUPPORTED -#define PNG_READ_EXPAND_SUPPORTED -#define PNG_READ_FILLER_SUPPORTED -#define PNG_READ_gAMA_SUPPORTED -#define PNG_READ_GAMMA_SUPPORTED -#define PNG_READ_GRAY_TO_RGB_SUPPORTED -#define PNG_READ_hIST_SUPPORTED -#define PNG_READ_iCCP_SUPPORTED -#define PNG_READ_INTERLACING_SUPPORTED -#define PNG_READ_INT_FUNCTIONS_SUPPORTED -#define PNG_READ_INVERT_ALPHA_SUPPORTED -#define PNG_READ_INVERT_SUPPORTED -#define PNG_READ_iTXt_SUPPORTED -#define PNG_READ_oFFs_SUPPORTED -#define PNG_READ_OPT_PLTE_SUPPORTED -#define PNG_READ_PACK_SUPPORTED -#define PNG_READ_PACKSWAP_SUPPORTED -#define PNG_READ_pCAL_SUPPORTED -#define PNG_READ_pHYs_SUPPORTED -#define PNG_READ_QUANTIZE_SUPPORTED -#define PNG_READ_RGB_TO_GRAY_SUPPORTED -#define PNG_READ_sBIT_SUPPORTED -#define PNG_READ_sCAL_SUPPORTED -#define PNG_READ_SHIFT_SUPPORTED -#define PNG_READ_sPLT_SUPPORTED -#define PNG_READ_sRGB_SUPPORTED -#define PNG_READ_STRIP_ALPHA_SUPPORTED -#define PNG_READ_SUPPORTED -#define PNG_READ_SWAP_ALPHA_SUPPORTED -#define PNG_READ_SWAP_SUPPORTED -#define PNG_READ_tEXt_SUPPORTED -#define PNG_READ_TEXT_SUPPORTED -#define PNG_READ_tIME_SUPPORTED -#define PNG_READ_TRANSFORMS_SUPPORTED -#define PNG_READ_tRNS_SUPPORTED -#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED -#define PNG_READ_USER_CHUNKS_SUPPORTED -#define PNG_READ_USER_TRANSFORM_SUPPORTED -#define PNG_READ_zTXt_SUPPORTED -#define PNG_SAVE_INT_32_SUPPORTED -#define PNG_sBIT_SUPPORTED -#define PNG_sCAL_SUPPORTED -#define PNG_SEQUENTIAL_READ_SUPPORTED -#define PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED -#define PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED -#define PNG_SETJMP_SUPPORTED -#define PNG_SET_USER_LIMITS_SUPPORTED -#define PNG_sPLT_SUPPORTED -#define PNG_sRGB_SUPPORTED -#define PNG_STDIO_SUPPORTED -#define PNG_tEXt_SUPPORTED -#define PNG_TEXT_SUPPORTED -#define PNG_TIME_RFC1123_SUPPORTED -#define PNG_tIME_SUPPORTED -#define PNG_tRNS_SUPPORTED -#define PNG_UNKNOWN_CHUNKS_SUPPORTED -#define PNG_USER_CHUNKS_SUPPORTED -#define PNG_USER_LIMITS_SUPPORTED -#define PNG_USER_MEM_SUPPORTED -#define PNG_USER_TRANSFORM_INFO_SUPPORTED -#define PNG_USER_TRANSFORM_PTR_SUPPORTED -#define PNG_WARNINGS_SUPPORTED -#define PNG_WRITE_16BIT_SUPPORTED -#define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED -#define PNG_WRITE_BGR_SUPPORTED -#define PNG_WRITE_bKGD_SUPPORTED -#define PNG_WRITE_cHRM_SUPPORTED -#define PNG_WRITE_FILLER_SUPPORTED -#define PNG_WRITE_FILTER_SUPPORTED -#define PNG_WRITE_FLUSH_SUPPORTED -#define PNG_WRITE_gAMA_SUPPORTED -#define PNG_WRITE_hIST_SUPPORTED -#define PNG_WRITE_iCCP_SUPPORTED -#define PNG_WRITE_INTERLACING_SUPPORTED -#define PNG_WRITE_INT_FUNCTIONS_SUPPORTED -#define PNG_WRITE_INVERT_ALPHA_SUPPORTED -#define PNG_WRITE_INVERT_SUPPORTED -#define PNG_WRITE_iTXt_SUPPORTED -#define PNG_WRITE_oFFs_SUPPORTED -#define PNG_WRITE_PACK_SUPPORTED -#define PNG_WRITE_PACKSWAP_SUPPORTED -#define PNG_WRITE_pCAL_SUPPORTED -#define PNG_WRITE_pHYs_SUPPORTED -#define PNG_WRITE_sBIT_SUPPORTED -#define PNG_WRITE_sCAL_SUPPORTED -#define PNG_WRITE_SHIFT_SUPPORTED -#define PNG_WRITE_sPLT_SUPPORTED -#define PNG_WRITE_sRGB_SUPPORTED -#define PNG_WRITE_SUPPORTED -#define PNG_WRITE_SWAP_ALPHA_SUPPORTED -#define PNG_WRITE_SWAP_SUPPORTED -#define PNG_WRITE_tEXt_SUPPORTED -#define PNG_WRITE_TEXT_SUPPORTED -#define PNG_WRITE_tIME_SUPPORTED -#define PNG_WRITE_TRANSFORMS_SUPPORTED -#define PNG_WRITE_tRNS_SUPPORTED -#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED -#define PNG_WRITE_USER_TRANSFORM_SUPPORTED -#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED -#define PNG_WRITE_zTXt_SUPPORTED -#define PNG_zTXt_SUPPORTED -/*#undef PNG_ERROR_NUMBERS_SUPPORTED*/ -/*#undef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED*/ -/* end of options */ -#endif /* PNGLCONF_H */ diff --git a/cdeps/win/amd/win64/zconf.h b/cdeps/win/amd/win64/zconf.h deleted file mode 100755 index 02ce56c4..00000000 --- a/cdeps/win/amd/win64/zconf.h +++ /dev/null @@ -1,428 +0,0 @@ -/* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2010 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#ifndef ZCONF_H -#define ZCONF_H - -/* - * If you *really* need a unique prefix for all types and library functions, - * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. - * Even better than compiling with -DZ_PREFIX would be to use configure to set - * this permanently in zconf.h using "./configure --zprefix". - */ -#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ - -/* all linked symbols */ -# define _dist_code z__dist_code -# define _length_code z__length_code -# define _tr_align z__tr_align -# define _tr_flush_block z__tr_flush_block -# define _tr_init z__tr_init -# define _tr_stored_block z__tr_stored_block -# define _tr_tally z__tr_tally -# define adler32 z_adler32 -# define adler32_combine z_adler32_combine -# define adler32_combine64 z_adler32_combine64 -# define compress z_compress -# define compress2 z_compress2 -# define compressBound z_compressBound -# define crc32 z_crc32 -# define crc32_combine z_crc32_combine -# define crc32_combine64 z_crc32_combine64 -# define deflate z_deflate -# define deflateBound z_deflateBound -# define deflateCopy z_deflateCopy -# define deflateEnd z_deflateEnd -# define deflateInit2_ z_deflateInit2_ -# define deflateInit_ z_deflateInit_ -# define deflateParams z_deflateParams -# define deflatePrime z_deflatePrime -# define deflateReset z_deflateReset -# define deflateSetDictionary z_deflateSetDictionary -# define deflateSetHeader z_deflateSetHeader -# define deflateTune z_deflateTune -# define deflate_copyright z_deflate_copyright -# define get_crc_table z_get_crc_table -# define gz_error z_gz_error -# define gz_intmax z_gz_intmax -# define gz_strwinerror z_gz_strwinerror -# define gzbuffer z_gzbuffer -# define gzclearerr z_gzclearerr -# define gzclose z_gzclose -# define gzclose_r z_gzclose_r -# define gzclose_w z_gzclose_w -# define gzdirect z_gzdirect -# define gzdopen z_gzdopen -# define gzeof z_gzeof -# define gzerror z_gzerror -# define gzflush z_gzflush -# define gzgetc z_gzgetc -# define gzgets z_gzgets -# define gzoffset z_gzoffset -# define gzoffset64 z_gzoffset64 -# define gzopen z_gzopen -# define gzopen64 z_gzopen64 -# define gzprintf z_gzprintf -# define gzputc z_gzputc -# define gzputs z_gzputs -# define gzread z_gzread -# define gzrewind z_gzrewind -# define gzseek z_gzseek -# define gzseek64 z_gzseek64 -# define gzsetparams z_gzsetparams -# define gztell z_gztell -# define gztell64 z_gztell64 -# define gzungetc z_gzungetc -# define gzwrite z_gzwrite -# define inflate z_inflate -# define inflateBack z_inflateBack -# define inflateBackEnd z_inflateBackEnd -# define inflateBackInit_ z_inflateBackInit_ -# define inflateCopy z_inflateCopy -# define inflateEnd z_inflateEnd -# define inflateGetHeader z_inflateGetHeader -# define inflateInit2_ z_inflateInit2_ -# define inflateInit_ z_inflateInit_ -# define inflateMark z_inflateMark -# define inflatePrime z_inflatePrime -# define inflateReset z_inflateReset -# define inflateReset2 z_inflateReset2 -# define inflateSetDictionary z_inflateSetDictionary -# define inflateSync z_inflateSync -# define inflateSyncPoint z_inflateSyncPoint -# define inflateUndermine z_inflateUndermine -# define inflate_copyright z_inflate_copyright -# define inflate_fast z_inflate_fast -# define inflate_table z_inflate_table -# define uncompress z_uncompress -# define zError z_zError -# define zcalloc z_zcalloc -# define zcfree z_zcfree -# define zlibCompileFlags z_zlibCompileFlags -# define zlibVersion z_zlibVersion - -/* all zlib typedefs in zlib.h and zconf.h */ -# define Byte z_Byte -# define Bytef z_Bytef -# define alloc_func z_alloc_func -# define charf z_charf -# define free_func z_free_func -# define gzFile z_gzFile -# define gz_header z_gz_header -# define gz_headerp z_gz_headerp -# define in_func z_in_func -# define intf z_intf -# define out_func z_out_func -# define uInt z_uInt -# define uIntf z_uIntf -# define uLong z_uLong -# define uLongf z_uLongf -# define voidp z_voidp -# define voidpc z_voidpc -# define voidpf z_voidpf - -/* all zlib structs in zlib.h and zconf.h */ -# define gz_header_s z_gz_header_s -# define internal_state z_internal_state - -#endif - -#if defined(__MSDOS__) && !defined(MSDOS) -# define MSDOS -#endif -#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) -# define OS2 -#endif -#if defined(_WINDOWS) && !defined(WINDOWS) -# define WINDOWS -#endif -#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) -# ifndef WIN32 -# define WIN32 -# endif -#endif -#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) -# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) -# ifndef SYS16BIT -# define SYS16BIT -# endif -# endif -#endif - -/* - * Compile with -DMAXSEG_64K if the alloc function cannot allocate more - * than 64k bytes at a time (needed on systems with 16-bit int). - */ -#ifdef SYS16BIT -# define MAXSEG_64K -#endif -#ifdef MSDOS -# define UNALIGNED_OK -#endif - -#ifdef __STDC_VERSION__ -# ifndef STDC -# define STDC -# endif -# if __STDC_VERSION__ >= 199901L -# ifndef STDC99 -# define STDC99 -# endif -# endif -#endif -#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) -# define STDC -#endif -#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) -# define STDC -#endif -#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) -# define STDC -#endif -#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) -# define STDC -#endif - -#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ -# define STDC -#endif - -#ifndef STDC -# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ -# define const /* note: need a more gentle solution here */ -# endif -#endif - -/* Some Mac compilers merge all .h files incorrectly: */ -#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) -# define NO_DUMMY_DECL -#endif - -/* Maximum value for memLevel in deflateInit2 */ -#ifndef MAX_MEM_LEVEL -# ifdef MAXSEG_64K -# define MAX_MEM_LEVEL 8 -# else -# define MAX_MEM_LEVEL 9 -# endif -#endif - -/* Maximum value for windowBits in deflateInit2 and inflateInit2. - * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files - * created by gzip. (Files created by minigzip can still be extracted by - * gzip.) - */ -#ifndef MAX_WBITS -# define MAX_WBITS 15 /* 32K LZ77 window */ -#endif - -/* The memory requirements for deflate are (in bytes): - (1 << (windowBits+2)) + (1 << (memLevel+9)) - that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) - plus a few kilobytes for small objects. For example, if you want to reduce - the default memory requirements from 256K to 128K, compile with - make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" - Of course this will generally degrade compression (there's no free lunch). - - The memory requirements for inflate are (in bytes) 1 << windowBits - that is, 32K for windowBits=15 (default value) plus a few kilobytes - for small objects. -*/ - - /* Type declarations */ - -#ifndef OF /* function prototypes */ -# ifdef STDC -# define OF(args) args -# else -# define OF(args) () -# endif -#endif - -/* The following definitions for FAR are needed only for MSDOS mixed - * model programming (small or medium model with some far allocations). - * This was tested only with MSC; for other MSDOS compilers you may have - * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, - * just define FAR to be empty. - */ -#ifdef SYS16BIT -# if defined(M_I86SM) || defined(M_I86MM) - /* MSC small or medium model */ -# define SMALL_MEDIUM -# ifdef _MSC_VER -# define FAR _far -# else -# define FAR far -# endif -# endif -# if (defined(__SMALL__) || defined(__MEDIUM__)) - /* Turbo C small or medium model */ -# define SMALL_MEDIUM -# ifdef __BORLANDC__ -# define FAR _far -# else -# define FAR far -# endif -# endif -#endif - -#if defined(WINDOWS) || defined(WIN32) - /* If building or using zlib as a DLL, define ZLIB_DLL. - * This is not mandatory, but it offers a little performance increase. - */ -# ifdef ZLIB_DLL -# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) -# ifdef ZLIB_INTERNAL -# define ZEXTERN extern __declspec(dllexport) -# else -# define ZEXTERN extern __declspec(dllimport) -# endif -# endif -# endif /* ZLIB_DLL */ - /* If building or using zlib with the WINAPI/WINAPIV calling convention, - * define ZLIB_WINAPI. - * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. - */ -# ifdef ZLIB_WINAPI -# ifdef FAR -# undef FAR -# endif -# include - /* No need for _export, use ZLIB.DEF instead. */ - /* For complete Windows compatibility, use WINAPI, not __stdcall. */ -# define ZEXPORT WINAPI -# ifdef WIN32 -# define ZEXPORTVA WINAPIV -# else -# define ZEXPORTVA FAR CDECL -# endif -# endif -#endif - -#if defined (__BEOS__) -# ifdef ZLIB_DLL -# ifdef ZLIB_INTERNAL -# define ZEXPORT __declspec(dllexport) -# define ZEXPORTVA __declspec(dllexport) -# else -# define ZEXPORT __declspec(dllimport) -# define ZEXPORTVA __declspec(dllimport) -# endif -# endif -#endif - -#ifndef ZEXTERN -# define ZEXTERN extern -#endif -#ifndef ZEXPORT -# define ZEXPORT -#endif -#ifndef ZEXPORTVA -# define ZEXPORTVA -#endif - -#ifndef FAR -# define FAR -#endif - -#if !defined(__MACTYPES__) -typedef unsigned char Byte; /* 8 bits */ -#endif -typedef unsigned int uInt; /* 16 bits or more */ -typedef unsigned long uLong; /* 32 bits or more */ - -#ifdef SMALL_MEDIUM - /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ -# define Bytef Byte FAR -#else - typedef Byte FAR Bytef; -#endif -typedef char FAR charf; -typedef int FAR intf; -typedef uInt FAR uIntf; -typedef uLong FAR uLongf; - -#ifdef STDC - typedef void const *voidpc; - typedef void FAR *voidpf; - typedef void *voidp; -#else - typedef Byte const *voidpc; - typedef Byte FAR *voidpf; - typedef Byte *voidp; -#endif - -#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ -# define Z_HAVE_UNISTD_H -#endif - -#ifdef STDC -# include /* for off_t */ -#endif - -/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and - * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even - * though the former does not conform to the LFS document), but considering - * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as - * equivalently requesting no 64-bit operations - */ -#if -_LARGEFILE64_SOURCE - -1 == 1 -# undef _LARGEFILE64_SOURCE -#endif - -#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) -# include /* for SEEK_* and off_t */ -# ifdef VMS -# include /* for off_t */ -# endif -# ifndef z_off_t -# define z_off_t off_t -# endif -#endif - -#ifndef SEEK_SET -# define SEEK_SET 0 /* Seek from beginning of file. */ -# define SEEK_CUR 1 /* Seek from current position. */ -# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ -#endif - -#ifndef z_off_t -# define z_off_t long -#endif - -#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 -# define z_off64_t off64_t -#else -# define z_off64_t z_off_t -#endif - -#if defined(__OS400__) -# define NO_vsnprintf -#endif - -#if defined(__MVS__) -# define NO_vsnprintf -#endif - -/* MVS linker does not support external names larger than 8 bytes */ -#if defined(__MVS__) - #pragma map(deflateInit_,"DEIN") - #pragma map(deflateInit2_,"DEIN2") - #pragma map(deflateEnd,"DEEND") - #pragma map(deflateBound,"DEBND") - #pragma map(inflateInit_,"ININ") - #pragma map(inflateInit2_,"ININ2") - #pragma map(inflateEnd,"INEND") - #pragma map(inflateSync,"INSY") - #pragma map(inflateSetDictionary,"INSEDI") - #pragma map(compressBound,"CMBND") - #pragma map(inflate_table,"INTABL") - #pragma map(inflate_fast,"INFA") - #pragma map(inflate_copyright,"INCOPY") -#endif - -#endif /* ZCONF_H */ diff --git a/cdeps/win/amd/win64/zlib.h b/cdeps/win/amd/win64/zlib.h deleted file mode 100755 index bfbba83e..00000000 --- a/cdeps/win/amd/win64/zlib.h +++ /dev/null @@ -1,1613 +0,0 @@ -/* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.5, April 19th, 2010 - - Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jean-loup Gailly Mark Adler - jloup@gzip.org madler@alumni.caltech.edu - - - The data format used by the zlib library is described by RFCs (Request for - Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt - (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). -*/ - -#ifndef ZLIB_H -#define ZLIB_H - -#include "zconf.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define ZLIB_VERSION "1.2.5" -#define ZLIB_VERNUM 0x1250 -#define ZLIB_VER_MAJOR 1 -#define ZLIB_VER_MINOR 2 -#define ZLIB_VER_REVISION 5 -#define ZLIB_VER_SUBREVISION 0 - -/* - The 'zlib' compression library provides in-memory compression and - decompression functions, including integrity checks of the uncompressed data. - This version of the library supports only one compression method (deflation) - but other algorithms will be added later and will have the same stream - interface. - - Compression can be done in a single step if the buffers are large enough, - or can be done by repeated calls of the compression function. In the latter - case, the application must provide more input and/or consume the output - (providing more output space) before each call. - - The compressed data format used by default by the in-memory functions is - the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped - around a deflate stream, which is itself documented in RFC 1951. - - The library also supports reading and writing files in gzip (.gz) format - with an interface similar to that of stdio using the functions that start - with "gz". The gzip format is different from the zlib format. gzip is a - gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. - - This library can optionally read and write gzip streams in memory as well. - - The zlib format was designed to be compact and fast for use in memory - and on communications channels. The gzip format was designed for single- - file compression on file systems, has a larger header than zlib to maintain - directory information, and uses a different, slower check method than zlib. - - The library does not install any signal handler. The decoder checks - the consistency of the compressed data, so the library should never crash - even in case of corrupted input. -*/ - -typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); -typedef void (*free_func) OF((voidpf opaque, voidpf address)); - -struct internal_state; - -typedef struct z_stream_s { - Bytef *next_in; /* next input byte */ - uInt avail_in; /* number of bytes available at next_in */ - uLong total_in; /* total nb of input bytes read so far */ - - Bytef *next_out; /* next output byte should be put there */ - uInt avail_out; /* remaining free space at next_out */ - uLong total_out; /* total nb of bytes output so far */ - - char *msg; /* last error message, NULL if no error */ - struct internal_state FAR *state; /* not visible by applications */ - - alloc_func zalloc; /* used to allocate the internal state */ - free_func zfree; /* used to free the internal state */ - voidpf opaque; /* private data object passed to zalloc and zfree */ - - int data_type; /* best guess about the data type: binary or text */ - uLong adler; /* adler32 value of the uncompressed data */ - uLong reserved; /* reserved for future use */ -} z_stream; - -typedef z_stream FAR *z_streamp; - -/* - gzip header information passed to and from zlib routines. See RFC 1952 - for more details on the meanings of these fields. -*/ -typedef struct gz_header_s { - int text; /* true if compressed data believed to be text */ - uLong time; /* modification time */ - int xflags; /* extra flags (not used when writing a gzip file) */ - int os; /* operating system */ - Bytef *extra; /* pointer to extra field or Z_NULL if none */ - uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ - uInt extra_max; /* space at extra (only when reading header) */ - Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ - uInt name_max; /* space at name (only when reading header) */ - Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ - uInt comm_max; /* space at comment (only when reading header) */ - int hcrc; /* true if there was or will be a header crc */ - int done; /* true when done reading gzip header (not used - when writing a gzip file) */ -} gz_header; - -typedef gz_header FAR *gz_headerp; - -/* - The application must update next_in and avail_in when avail_in has dropped - to zero. It must update next_out and avail_out when avail_out has dropped - to zero. The application must initialize zalloc, zfree and opaque before - calling the init function. All other fields are set by the compression - library and must not be updated by the application. - - The opaque value provided by the application will be passed as the first - parameter for calls of zalloc and zfree. This can be useful for custom - memory management. The compression library attaches no meaning to the - opaque value. - - zalloc must return Z_NULL if there is not enough memory for the object. - If zlib is used in a multi-threaded application, zalloc and zfree must be - thread safe. - - On 16-bit systems, the functions zalloc and zfree must be able to allocate - exactly 65536 bytes, but will not be required to allocate more than this if - the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers - returned by zalloc for objects of exactly 65536 bytes *must* have their - offset normalized to zero. The default allocation function provided by this - library ensures this (see zutil.c). To reduce memory requirements and avoid - any allocation of 64K objects, at the expense of compression ratio, compile - the library with -DMAX_WBITS=14 (see zconf.h). - - The fields total_in and total_out can be used for statistics or progress - reports. After compression, total_in holds the total size of the - uncompressed data and may be saved for use in the decompressor (particularly - if the decompressor wants to decompress everything in a single step). -*/ - - /* constants */ - -#define Z_NO_FLUSH 0 -#define Z_PARTIAL_FLUSH 1 -#define Z_SYNC_FLUSH 2 -#define Z_FULL_FLUSH 3 -#define Z_FINISH 4 -#define Z_BLOCK 5 -#define Z_TREES 6 -/* Allowed flush values; see deflate() and inflate() below for details */ - -#define Z_OK 0 -#define Z_STREAM_END 1 -#define Z_NEED_DICT 2 -#define Z_ERRNO (-1) -#define Z_STREAM_ERROR (-2) -#define Z_DATA_ERROR (-3) -#define Z_MEM_ERROR (-4) -#define Z_BUF_ERROR (-5) -#define Z_VERSION_ERROR (-6) -/* Return codes for the compression/decompression functions. Negative values - * are errors, positive values are used for special but normal events. - */ - -#define Z_NO_COMPRESSION 0 -#define Z_BEST_SPEED 1 -#define Z_BEST_COMPRESSION 9 -#define Z_DEFAULT_COMPRESSION (-1) -/* compression levels */ - -#define Z_FILTERED 1 -#define Z_HUFFMAN_ONLY 2 -#define Z_RLE 3 -#define Z_FIXED 4 -#define Z_DEFAULT_STRATEGY 0 -/* compression strategy; see deflateInit2() below for details */ - -#define Z_BINARY 0 -#define Z_TEXT 1 -#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ -#define Z_UNKNOWN 2 -/* Possible values of the data_type field (though see inflate()) */ - -#define Z_DEFLATED 8 -/* The deflate compression method (the only one supported in this version) */ - -#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ - -#define zlib_version zlibVersion() -/* for compatibility with versions < 1.0.2 */ - - - /* basic functions */ - -ZEXTERN const char * ZEXPORT zlibVersion OF((void)); -/* The application can compare zlibVersion and ZLIB_VERSION for consistency. - If the first character differs, the library code actually used is not - compatible with the zlib.h header file used by the application. This check - is automatically made by deflateInit and inflateInit. - */ - -/* -ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); - - Initializes the internal stream state for compression. The fields - zalloc, zfree and opaque must be initialized before by the caller. If - zalloc and zfree are set to Z_NULL, deflateInit updates them to use default - allocation functions. - - The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: - 1 gives best speed, 9 gives best compression, 0 gives no compression at all - (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION - requests a default compromise between speed and compression (currently - equivalent to level 6). - - deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if level is not a valid compression level, or - Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible - with the version assumed by the caller (ZLIB_VERSION). msg is set to null - if there is no error message. deflateInit does not perform any compression: - this will be done by deflate(). -*/ - - -ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); -/* - deflate compresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may introduce - some output latency (reading input without producing any output) except when - forced to flush. - - The detailed semantics are as follows. deflate performs one or both of the - following actions: - - - Compress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in and avail_in are updated and - processing will resume at this point for the next call of deflate(). - - - Provide more output starting at next_out and update next_out and avail_out - accordingly. This action is forced if the parameter flush is non zero. - Forcing flush frequently degrades the compression ratio, so this parameter - should be set only when necessary (in interactive applications). Some - output may be provided even if flush is not set. - - Before the call of deflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming more - output, and updating avail_in or avail_out accordingly; avail_out should - never be zero before the call. The application can consume the compressed - output when it wants, for example when the output buffer is full (avail_out - == 0), or after each call of deflate(). If deflate returns Z_OK and with - zero avail_out, it must be called again after making room in the output - buffer because there might be more output pending. - - Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to - decide how much data to accumulate before producing output, in order to - maximize compression. - - If the parameter flush is set to Z_SYNC_FLUSH, all pending output is - flushed to the output buffer and the output is aligned on a byte boundary, so - that the decompressor can get all input data available so far. (In - particular avail_in is zero after the call if enough output space has been - provided before the call.) Flushing may degrade compression for some - compression algorithms and so it should be used only when necessary. This - completes the current deflate block and follows it with an empty stored block - that is three bits plus filler bits to the next byte, followed by four bytes - (00 00 ff ff). - - If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the - output buffer, but the output is not aligned to a byte boundary. All of the - input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. - This completes the current deflate block and follows it with an empty fixed - codes block that is 10 bits long. This assures that enough bytes are output - in order for the decompressor to finish the block before the empty fixed code - block. - - If flush is set to Z_BLOCK, a deflate block is completed and emitted, as - for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to - seven bits of the current block are held to be written as the next byte after - the next deflate block is completed. In this case, the decompressor may not - be provided enough bits at this point in order to complete decompression of - the data provided so far to the compressor. It may need to wait for the next - block to be emitted. This is for advanced applications that need to control - the emission of deflate blocks. - - If flush is set to Z_FULL_FLUSH, all output is flushed as with - Z_SYNC_FLUSH, and the compression state is reset so that decompression can - restart from this point if previous compressed data has been damaged or if - random access is desired. Using Z_FULL_FLUSH too often can seriously degrade - compression. - - If deflate returns with avail_out == 0, this function must be called again - with the same value of the flush parameter and more output space (updated - avail_out), until the flush is complete (deflate returns with non-zero - avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that - avail_out is greater than six to avoid repeated flush markers due to - avail_out == 0 on return. - - If the parameter flush is set to Z_FINISH, pending input is processed, - pending output is flushed and deflate returns with Z_STREAM_END if there was - enough output space; if deflate returns with Z_OK, this function must be - called again with Z_FINISH and more output space (updated avail_out) but no - more input data, until it returns with Z_STREAM_END or an error. After - deflate has returned Z_STREAM_END, the only possible operations on the stream - are deflateReset or deflateEnd. - - Z_FINISH can be used immediately after deflateInit if all the compression - is to be done in a single step. In this case, avail_out must be at least the - value returned by deflateBound (see below). If deflate does not return - Z_STREAM_END, then it must be called again as described above. - - deflate() sets strm->adler to the adler32 checksum of all input read - so far (that is, total_in bytes). - - deflate() may update strm->data_type if it can make a good guess about - the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered - binary. This field is only for information purposes and does not affect the - compression algorithm in any manner. - - deflate() returns Z_OK if some progress has been made (more input - processed or more output produced), Z_STREAM_END if all input has been - consumed and all output has been produced (only when flush is set to - Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example - if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible - (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not - fatal, and deflate() can be called again with more input and more output - space to continue compressing. -*/ - - -ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any pending - output. - - deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the - stream state was inconsistent, Z_DATA_ERROR if the stream was freed - prematurely (some input or output was discarded). In the error case, msg - may be set but then points to a static string (which must not be - deallocated). -*/ - - -/* -ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); - - Initializes the internal stream state for decompression. The fields - next_in, avail_in, zalloc, zfree and opaque must be initialized before by - the caller. If next_in is not Z_NULL and avail_in is large enough (the - exact value depends on the compression method), inflateInit determines the - compression method from the zlib header and allocates all data structures - accordingly; otherwise the allocation will be deferred to the first call of - inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to - use default allocation functions. - - inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_VERSION_ERROR if the zlib library version is incompatible with the - version assumed by the caller, or Z_STREAM_ERROR if the parameters are - invalid, such as a null pointer to the structure. msg is set to null if - there is no error message. inflateInit does not perform any decompression - apart from possibly reading the zlib header if present: actual decompression - will be done by inflate(). (So next_in and avail_in may be modified, but - next_out and avail_out are unused and unchanged.) The current implementation - of inflateInit() does not process any header information -- that is deferred - until inflate() is called. -*/ - - -ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); -/* - inflate decompresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may introduce - some output latency (reading input without producing any output) except when - forced to flush. - - The detailed semantics are as follows. inflate performs one or both of the - following actions: - - - Decompress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in is updated and processing will - resume at this point for the next call of inflate(). - - - Provide more output starting at next_out and update next_out and avail_out - accordingly. inflate() provides as much output as possible, until there is - no more input data or no more space in the output buffer (see below about - the flush parameter). - - Before the call of inflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming more - output, and updating the next_* and avail_* values accordingly. The - application can consume the uncompressed output when it wants, for example - when the output buffer is full (avail_out == 0), or after each call of - inflate(). If inflate returns Z_OK and with zero avail_out, it must be - called again after making room in the output buffer because there might be - more output pending. - - The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, - Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much - output as possible to the output buffer. Z_BLOCK requests that inflate() - stop if and when it gets to the next deflate block boundary. When decoding - the zlib or gzip format, this will cause inflate() to return immediately - after the header and before the first block. When doing a raw inflate, - inflate() will go ahead and process the first block, and will return when it - gets to the end of that block, or when it runs out of data. - - The Z_BLOCK option assists in appending to or combining deflate streams. - Also to assist in this, on return inflate() will set strm->data_type to the - number of unused bits in the last byte taken from strm->next_in, plus 64 if - inflate() is currently decoding the last block in the deflate stream, plus - 128 if inflate() returned immediately after decoding an end-of-block code or - decoding the complete header up to just before the first byte of the deflate - stream. The end-of-block will not be indicated until all of the uncompressed - data from that block has been written to strm->next_out. The number of - unused bits may in general be greater than seven, except when bit 7 of - data_type is set, in which case the number of unused bits will be less than - eight. data_type is set as noted here every time inflate() returns for all - flush options, and so can be used to determine the amount of currently - consumed input in bits. - - The Z_TREES option behaves as Z_BLOCK does, but it also returns when the - end of each deflate block header is reached, before any actual data in that - block is decoded. This allows the caller to determine the length of the - deflate block header for later use in random access within a deflate block. - 256 is added to the value of strm->data_type when inflate() returns - immediately after reaching the end of the deflate block header. - - inflate() should normally be called until it returns Z_STREAM_END or an - error. However if all decompression is to be performed in a single step (a - single call of inflate), the parameter flush should be set to Z_FINISH. In - this case all pending input is processed and all pending output is flushed; - avail_out must be large enough to hold all the uncompressed data. (The size - of the uncompressed data may have been saved by the compressor for this - purpose.) The next operation on this stream must be inflateEnd to deallocate - the decompression state. The use of Z_FINISH is never required, but can be - used to inform inflate that a faster approach may be used for the single - inflate() call. - - In this implementation, inflate() always flushes as much output as - possible to the output buffer, and always uses the faster approach on the - first call. So the only effect of the flush parameter in this implementation - is on the return value of inflate(), as noted below, or when it returns early - because Z_BLOCK or Z_TREES is used. - - If a preset dictionary is needed after this call (see inflateSetDictionary - below), inflate sets strm->adler to the adler32 checksum of the dictionary - chosen by the compressor and returns Z_NEED_DICT; otherwise it sets - strm->adler to the adler32 checksum of all output produced so far (that is, - total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described - below. At the end of the stream, inflate() checks that its computed adler32 - checksum is equal to that saved by the compressor and returns Z_STREAM_END - only if the checksum is correct. - - inflate() can decompress and check either zlib-wrapped or gzip-wrapped - deflate data. The header type is detected automatically, if requested when - initializing with inflateInit2(). Any information contained in the gzip - header is not retained, so applications that need that information should - instead use raw inflate, see inflateInit2() below, or inflateBack() and - perform their own processing of the gzip header and trailer. - - inflate() returns Z_OK if some progress has been made (more input processed - or more output produced), Z_STREAM_END if the end of the compressed data has - been reached and all uncompressed output has been produced, Z_NEED_DICT if a - preset dictionary is needed at this point, Z_DATA_ERROR if the input data was - corrupted (input stream not conforming to the zlib format or incorrect check - value), Z_STREAM_ERROR if the stream structure was inconsistent (for example - next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory, - Z_BUF_ERROR if no progress is possible or if there was not enough room in the - output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and - inflate() can be called again with more input and more output space to - continue decompressing. If Z_DATA_ERROR is returned, the application may - then call inflateSync() to look for a good compression block if a partial - recovery of the data is desired. -*/ - - -ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any pending - output. - - inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state - was inconsistent. In the error case, msg may be set but then points to a - static string (which must not be deallocated). -*/ - - - /* Advanced functions */ - -/* - The following functions are needed only in some special applications. -*/ - -/* -ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, - int level, - int method, - int windowBits, - int memLevel, - int strategy)); - - This is another version of deflateInit with more compression options. The - fields next_in, zalloc, zfree and opaque must be initialized before by the - caller. - - The method parameter is the compression method. It must be Z_DEFLATED in - this version of the library. - - The windowBits parameter is the base two logarithm of the window size - (the size of the history buffer). It should be in the range 8..15 for this - version of the library. Larger values of this parameter result in better - compression at the expense of memory usage. The default value is 15 if - deflateInit is used instead. - - windowBits can also be -8..-15 for raw deflate. In this case, -windowBits - determines the window size. deflate() will then generate raw deflate data - with no zlib header or trailer, and will not compute an adler32 check value. - - windowBits can also be greater than 15 for optional gzip encoding. Add - 16 to windowBits to write a simple gzip header and trailer around the - compressed data instead of a zlib wrapper. The gzip header will have no - file name, no extra data, no comment, no modification time (set to zero), no - header crc, and the operating system will be set to 255 (unknown). If a - gzip stream is being written, strm->adler is a crc32 instead of an adler32. - - The memLevel parameter specifies how much memory should be allocated - for the internal compression state. memLevel=1 uses minimum memory but is - slow and reduces compression ratio; memLevel=9 uses maximum memory for - optimal speed. The default value is 8. See zconf.h for total memory usage - as a function of windowBits and memLevel. - - The strategy parameter is used to tune the compression algorithm. Use the - value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a - filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no - string match), or Z_RLE to limit match distances to one (run-length - encoding). Filtered data consists mostly of small values with a somewhat - random distribution. In this case, the compression algorithm is tuned to - compress them better. The effect of Z_FILTERED is to force more Huffman - coding and less string matching; it is somewhat intermediate between - Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as - fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The - strategy parameter only affects the compression ratio but not the - correctness of the compressed output even if it is not set appropriately. - Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler - decoder for special applications. - - deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid - method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is - incompatible with the version assumed by the caller (ZLIB_VERSION). msg is - set to null if there is no error message. deflateInit2 does not perform any - compression: this will be done by deflate(). -*/ - -ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); -/* - Initializes the compression dictionary from the given byte sequence - without producing any compressed output. This function must be called - immediately after deflateInit, deflateInit2 or deflateReset, before any call - of deflate. The compressor and decompressor must use exactly the same - dictionary (see inflateSetDictionary). - - The dictionary should consist of strings (byte sequences) that are likely - to be encountered later in the data to be compressed, with the most commonly - used strings preferably put towards the end of the dictionary. Using a - dictionary is most useful when the data to be compressed is short and can be - predicted with good accuracy; the data can then be compressed better than - with the default empty dictionary. - - Depending on the size of the compression data structures selected by - deflateInit or deflateInit2, a part of the dictionary may in effect be - discarded, for example if the dictionary is larger than the window size - provided in deflateInit or deflateInit2. Thus the strings most likely to be - useful should be put at the end of the dictionary, not at the front. In - addition, the current implementation of deflate will use at most the window - size minus 262 bytes of the provided dictionary. - - Upon return of this function, strm->adler is set to the adler32 value - of the dictionary; the decompressor may later use this value to determine - which dictionary has been used by the compressor. (The adler32 value - applies to the whole dictionary even if only a subset of the dictionary is - actually used by the compressor.) If a raw deflate was requested, then the - adler32 value is not computed and strm->adler is not set. - - deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a - parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is - inconsistent (for example if deflate has already been called for this stream - or if the compression method is bsort). deflateSetDictionary does not - perform any compression: this will be done by deflate(). -*/ - -ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, - z_streamp source)); -/* - Sets the destination stream as a complete copy of the source stream. - - This function can be useful when several compression strategies will be - tried, for example when there are several ways of pre-processing the input - data with a filter. The streams that will be discarded should then be freed - by calling deflateEnd. Note that deflateCopy duplicates the internal - compression state which can be quite large, so this strategy is slow and can - consume lots of memory. - - deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if the source stream state was inconsistent - (such as zalloc being Z_NULL). msg is left unchanged in both source and - destination. -*/ - -ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); -/* - This function is equivalent to deflateEnd followed by deflateInit, - but does not free and reallocate all the internal compression state. The - stream will keep the same compression level and any other attributes that - may have been set by deflateInit2. - - deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being Z_NULL). -*/ - -ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, - int level, - int strategy)); -/* - Dynamically update the compression level and compression strategy. The - interpretation of level and strategy is as in deflateInit2. This can be - used to switch between compression and straight copy of the input data, or - to switch to a different kind of input data requiring a different strategy. - If the compression level is changed, the input available so far is - compressed with the old level (and may be flushed); the new level will take - effect only at the next call of deflate(). - - Before the call of deflateParams, the stream state must be set as for - a call of deflate(), since the currently available input may have to be - compressed and flushed. In particular, strm->avail_out must be non-zero. - - deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source - stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if - strm->avail_out was zero. -*/ - -ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, - int good_length, - int max_lazy, - int nice_length, - int max_chain)); -/* - Fine tune deflate's internal compression parameters. This should only be - used by someone who understands the algorithm used by zlib's deflate for - searching for the best matching string, and even then only by the most - fanatic optimizer trying to squeeze out the last compressed bit for their - specific input data. Read the deflate.c source code for the meaning of the - max_lazy, good_length, nice_length, and max_chain parameters. - - deflateTune() can be called after deflateInit() or deflateInit2(), and - returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. - */ - -ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, - uLong sourceLen)); -/* - deflateBound() returns an upper bound on the compressed size after - deflation of sourceLen bytes. It must be called after deflateInit() or - deflateInit2(), and after deflateSetHeader(), if used. This would be used - to allocate an output buffer for deflation in a single pass, and so would be - called before deflate(). -*/ - -ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, - int bits, - int value)); -/* - deflatePrime() inserts bits in the deflate output stream. The intent - is that this function is used to start off the deflate output with the bits - leftover from a previous deflate stream when appending to it. As such, this - function can only be used for raw deflate, and must be used before the first - deflate() call after a deflateInit2() or deflateReset(). bits must be less - than or equal to 16, and that many of the least significant bits of value - will be inserted in the output. - - deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, - gz_headerp head)); -/* - deflateSetHeader() provides gzip header information for when a gzip - stream is requested by deflateInit2(). deflateSetHeader() may be called - after deflateInit2() or deflateReset() and before the first call of - deflate(). The text, time, os, extra field, name, and comment information - in the provided gz_header structure are written to the gzip header (xflag is - ignored -- the extra flags are set according to the compression level). The - caller must assure that, if not Z_NULL, name and comment are terminated with - a zero byte, and that if extra is not Z_NULL, that extra_len bytes are - available there. If hcrc is true, a gzip header crc is included. Note that - the current versions of the command-line version of gzip (up through version - 1.3.x) do not support header crc's, and will report that it is a "multi-part - gzip file" and give up. - - If deflateSetHeader is not used, the default gzip header has text false, - the time set to zero, and os set to 255, with no extra, name, or comment - fields. The gzip header is returned to the default state by deflateReset(). - - deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -/* -ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, - int windowBits)); - - This is another version of inflateInit with an extra parameter. The - fields next_in, avail_in, zalloc, zfree and opaque must be initialized - before by the caller. - - The windowBits parameter is the base two logarithm of the maximum window - size (the size of the history buffer). It should be in the range 8..15 for - this version of the library. The default value is 15 if inflateInit is used - instead. windowBits must be greater than or equal to the windowBits value - provided to deflateInit2() while compressing, or it must be equal to 15 if - deflateInit2() was not used. If a compressed stream with a larger window - size is given as input, inflate() will return with the error code - Z_DATA_ERROR instead of trying to allocate a larger window. - - windowBits can also be zero to request that inflate use the window size in - the zlib header of the compressed stream. - - windowBits can also be -8..-15 for raw inflate. In this case, -windowBits - determines the window size. inflate() will then process raw deflate data, - not looking for a zlib or gzip header, not generating a check value, and not - looking for any check values for comparison at the end of the stream. This - is for use with other formats that use the deflate compressed data format - such as zip. Those formats provide their own check values. If a custom - format is developed using the raw deflate format for compressed data, it is - recommended that a check value such as an adler32 or a crc32 be applied to - the uncompressed data as is done in the zlib, gzip, and zip formats. For - most applications, the zlib format should be used as is. Note that comments - above on the use in deflateInit2() applies to the magnitude of windowBits. - - windowBits can also be greater than 15 for optional gzip decoding. Add - 32 to windowBits to enable zlib and gzip decoding with automatic header - detection, or add 16 to decode only the gzip format (the zlib format will - return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a - crc32 instead of an adler32. - - inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_VERSION_ERROR if the zlib library version is incompatible with the - version assumed by the caller, or Z_STREAM_ERROR if the parameters are - invalid, such as a null pointer to the structure. msg is set to null if - there is no error message. inflateInit2 does not perform any decompression - apart from possibly reading the zlib header if present: actual decompression - will be done by inflate(). (So next_in and avail_in may be modified, but - next_out and avail_out are unused and unchanged.) The current implementation - of inflateInit2() does not process any header information -- that is - deferred until inflate() is called. -*/ - -ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); -/* - Initializes the decompression dictionary from the given uncompressed byte - sequence. This function must be called immediately after a call of inflate, - if that call returned Z_NEED_DICT. The dictionary chosen by the compressor - can be determined from the adler32 value returned by that call of inflate. - The compressor and decompressor must use exactly the same dictionary (see - deflateSetDictionary). For raw inflate, this function can be called - immediately after inflateInit2() or inflateReset() and before any call of - inflate() to set the dictionary. The application must insure that the - dictionary that was used for compression is provided. - - inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a - parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is - inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the - expected one (incorrect adler32 value). inflateSetDictionary does not - perform any decompression: this will be done by subsequent calls of - inflate(). -*/ - -ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); -/* - Skips invalid compressed data until a full flush point (see above the - description of deflate with Z_FULL_FLUSH) can be found, or until all - available input is skipped. No output is provided. - - inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR - if no more input was provided, Z_DATA_ERROR if no flush point has been - found, or Z_STREAM_ERROR if the stream structure was inconsistent. In the - success case, the application may save the current current value of total_in - which indicates where valid compressed data was found. In the error case, - the application may repeatedly call inflateSync, providing more input each - time, until success or end of the input data. -*/ - -ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, - z_streamp source)); -/* - Sets the destination stream as a complete copy of the source stream. - - This function can be useful when randomly accessing a large stream. The - first pass through the stream can periodically record the inflate state, - allowing restarting inflate at those points when randomly accessing the - stream. - - inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if the source stream state was inconsistent - (such as zalloc being Z_NULL). msg is left unchanged in both source and - destination. -*/ - -ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); -/* - This function is equivalent to inflateEnd followed by inflateInit, - but does not free and reallocate all the internal decompression state. The - stream will keep attributes that may have been set by inflateInit2. - - inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being Z_NULL). -*/ - -ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, - int windowBits)); -/* - This function is the same as inflateReset, but it also permits changing - the wrap and window size requests. The windowBits parameter is interpreted - the same as it is for inflateInit2. - - inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being Z_NULL), or if - the windowBits parameter is invalid. -*/ - -ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, - int bits, - int value)); -/* - This function inserts bits in the inflate input stream. The intent is - that this function is used to start inflating at a bit position in the - middle of a byte. The provided bits will be used before any bytes are used - from next_in. This function should only be used with raw inflate, and - should be used before the first inflate() call after inflateInit2() or - inflateReset(). bits must be less than or equal to 16, and that many of the - least significant bits of value will be inserted in the input. - - If bits is negative, then the input stream bit buffer is emptied. Then - inflatePrime() can be called again to put bits in the buffer. This is used - to clear out bits leftover after feeding inflate a block description prior - to feeding inflate codes. - - inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); -/* - This function returns two values, one in the lower 16 bits of the return - value, and the other in the remaining upper bits, obtained by shifting the - return value down 16 bits. If the upper value is -1 and the lower value is - zero, then inflate() is currently decoding information outside of a block. - If the upper value is -1 and the lower value is non-zero, then inflate is in - the middle of a stored block, with the lower value equaling the number of - bytes from the input remaining to copy. If the upper value is not -1, then - it is the number of bits back from the current bit position in the input of - the code (literal or length/distance pair) currently being processed. In - that case the lower value is the number of bytes already emitted for that - code. - - A code is being processed if inflate is waiting for more input to complete - decoding of the code, or if it has completed decoding but is waiting for - more output space to write the literal or match data. - - inflateMark() is used to mark locations in the input data for random - access, which may be at bit positions, and to note those cases where the - output of a code may span boundaries of random access blocks. The current - location in the input stream can be determined from avail_in and data_type - as noted in the description for the Z_BLOCK flush parameter for inflate. - - inflateMark returns the value noted above or -1 << 16 if the provided - source stream state was inconsistent. -*/ - -ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, - gz_headerp head)); -/* - inflateGetHeader() requests that gzip header information be stored in the - provided gz_header structure. inflateGetHeader() may be called after - inflateInit2() or inflateReset(), and before the first call of inflate(). - As inflate() processes the gzip stream, head->done is zero until the header - is completed, at which time head->done is set to one. If a zlib stream is - being decoded, then head->done is set to -1 to indicate that there will be - no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be - used to force inflate() to return immediately after header processing is - complete and before any actual data is decompressed. - - The text, time, xflags, and os fields are filled in with the gzip header - contents. hcrc is set to true if there is a header CRC. (The header CRC - was valid if done is set to one.) If extra is not Z_NULL, then extra_max - contains the maximum number of bytes to write to extra. Once done is true, - extra_len contains the actual extra field length, and extra contains the - extra field, or that field truncated if extra_max is less than extra_len. - If name is not Z_NULL, then up to name_max characters are written there, - terminated with a zero unless the length is greater than name_max. If - comment is not Z_NULL, then up to comm_max characters are written there, - terminated with a zero unless the length is greater than comm_max. When any - of extra, name, or comment are not Z_NULL and the respective field is not - present in the header, then that field is set to Z_NULL to signal its - absence. This allows the use of deflateSetHeader() with the returned - structure to duplicate the header. However if those fields are set to - allocated memory, then the application will need to save those pointers - elsewhere so that they can be eventually freed. - - If inflateGetHeader is not used, then the header information is simply - discarded. The header is always checked for validity, including the header - CRC if present. inflateReset() will reset the process to discard the header - information. The application would need to call inflateGetHeader() again to - retrieve the header from the next gzip stream. - - inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -/* -ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, - unsigned char FAR *window)); - - Initialize the internal stream state for decompression using inflateBack() - calls. The fields zalloc, zfree and opaque in strm must be initialized - before the call. If zalloc and zfree are Z_NULL, then the default library- - derived memory allocation routines are used. windowBits is the base two - logarithm of the window size, in the range 8..15. window is a caller - supplied buffer of that size. Except for special applications where it is - assured that deflate was used with small window sizes, windowBits must be 15 - and a 32K byte window must be supplied to be able to decompress general - deflate streams. - - See inflateBack() for the usage of these routines. - - inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of - the paramaters are invalid, Z_MEM_ERROR if the internal state could not be - allocated, or Z_VERSION_ERROR if the version of the library does not match - the version of the header file. -*/ - -typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); -typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); - -ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, - in_func in, void FAR *in_desc, - out_func out, void FAR *out_desc)); -/* - inflateBack() does a raw inflate with a single call using a call-back - interface for input and output. This is more efficient than inflate() for - file i/o applications in that it avoids copying between the output and the - sliding window by simply making the window itself the output buffer. This - function trusts the application to not change the output buffer passed by - the output function, at least until inflateBack() returns. - - inflateBackInit() must be called first to allocate the internal state - and to initialize the state with the user-provided window buffer. - inflateBack() may then be used multiple times to inflate a complete, raw - deflate stream with each call. inflateBackEnd() is then called to free the - allocated state. - - A raw deflate stream is one with no zlib or gzip header or trailer. - This routine would normally be used in a utility that reads zip or gzip - files and writes out uncompressed files. The utility would decode the - header and process the trailer on its own, hence this routine expects only - the raw deflate stream to decompress. This is different from the normal - behavior of inflate(), which expects either a zlib or gzip header and - trailer around the deflate stream. - - inflateBack() uses two subroutines supplied by the caller that are then - called by inflateBack() for input and output. inflateBack() calls those - routines until it reads a complete deflate stream and writes out all of the - uncompressed data, or until it encounters an error. The function's - parameters and return types are defined above in the in_func and out_func - typedefs. inflateBack() will call in(in_desc, &buf) which should return the - number of bytes of provided input, and a pointer to that input in buf. If - there is no input available, in() must return zero--buf is ignored in that - case--and inflateBack() will return a buffer error. inflateBack() will call - out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() - should return zero on success, or non-zero on failure. If out() returns - non-zero, inflateBack() will return with an error. Neither in() nor out() - are permitted to change the contents of the window provided to - inflateBackInit(), which is also the buffer that out() uses to write from. - The length written by out() will be at most the window size. Any non-zero - amount of input may be provided by in(). - - For convenience, inflateBack() can be provided input on the first call by - setting strm->next_in and strm->avail_in. If that input is exhausted, then - in() will be called. Therefore strm->next_in must be initialized before - calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called - immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in - must also be initialized, and then if strm->avail_in is not zero, input will - initially be taken from strm->next_in[0 .. strm->avail_in - 1]. - - The in_desc and out_desc parameters of inflateBack() is passed as the - first parameter of in() and out() respectively when they are called. These - descriptors can be optionally used to pass any information that the caller- - supplied in() and out() functions need to do their job. - - On return, inflateBack() will set strm->next_in and strm->avail_in to - pass back any unused input that was provided by the last in() call. The - return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR - if in() or out() returned an error, Z_DATA_ERROR if there was a format error - in the deflate stream (in which case strm->msg is set to indicate the nature - of the error), or Z_STREAM_ERROR if the stream was not properly initialized. - In the case of Z_BUF_ERROR, an input or output error can be distinguished - using strm->next_in which will be Z_NULL only if in() returned an error. If - strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning - non-zero. (in() will always be called before out(), so strm->next_in is - assured to be defined if out() returns non-zero.) Note that inflateBack() - cannot return Z_OK. -*/ - -ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); -/* - All memory allocated by inflateBackInit() is freed. - - inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream - state was inconsistent. -*/ - -ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); -/* Return flags indicating compile-time options. - - Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: - 1.0: size of uInt - 3.2: size of uLong - 5.4: size of voidpf (pointer) - 7.6: size of z_off_t - - Compiler, assembler, and debug options: - 8: DEBUG - 9: ASMV or ASMINF -- use ASM code - 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention - 11: 0 (reserved) - - One-time table building (smaller code, but not thread-safe if true): - 12: BUILDFIXED -- build static block decoding tables when needed - 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed - 14,15: 0 (reserved) - - Library content (indicates missing functionality): - 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking - deflate code when not needed) - 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect - and decode gzip streams (to avoid linking crc code) - 18-19: 0 (reserved) - - Operation variations (changes in library functionality): - 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate - 21: FASTEST -- deflate algorithm with only one, lowest compression level - 22,23: 0 (reserved) - - The sprintf variant used by gzprintf (zero is best): - 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format - 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! - 26: 0 = returns value, 1 = void -- 1 means inferred string length returned - - Remainder: - 27-31: 0 (reserved) - */ - - - /* utility functions */ - -/* - The following utility functions are implemented on top of the basic - stream-oriented functions. To simplify the interface, some default options - are assumed (compression level and memory usage, standard memory allocation - functions). The source code of these utility functions can be modified if - you need special options. -*/ - -ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); -/* - Compresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total size - of the destination buffer, which must be at least the value returned by - compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed buffer. - - compress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer. -*/ - -ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen, - int level)); -/* - Compresses the source buffer into the destination buffer. The level - parameter has the same meaning as in deflateInit. sourceLen is the byte - length of the source buffer. Upon entry, destLen is the total size of the - destination buffer, which must be at least the value returned by - compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed buffer. - - compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_BUF_ERROR if there was not enough room in the output buffer, - Z_STREAM_ERROR if the level parameter is invalid. -*/ - -ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); -/* - compressBound() returns an upper bound on the compressed size after - compress() or compress2() on sourceLen bytes. It would be used before a - compress() or compress2() call to allocate the destination buffer. -*/ - -ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); -/* - Decompresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total size - of the destination buffer, which must be large enough to hold the entire - uncompressed data. (The size of the uncompressed data must have been saved - previously by the compressor and transmitted to the decompressor by some - mechanism outside the scope of this compression library.) Upon exit, destLen - is the actual size of the uncompressed buffer. - - uncompress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. -*/ - - - /* gzip file access functions */ - -/* - This library supports reading and writing files in gzip (.gz) format with - an interface similar to that of stdio, using the functions that start with - "gz". The gzip format is different from the zlib format. gzip is a gzip - wrapper, documented in RFC 1952, wrapped around a deflate stream. -*/ - -typedef voidp gzFile; /* opaque gzip file descriptor */ - -/* -ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); - - Opens a gzip (.gz) file for reading or writing. The mode parameter is as - in fopen ("rb" or "wb") but can also include a compression level ("wb9") or - a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only - compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' - for fixed code compression as in "wb9F". (See the description of - deflateInit2 for more information about the strategy parameter.) Also "a" - can be used instead of "w" to request that the gzip stream that will be - written be appended to the file. "+" will result in an error, since reading - and writing to the same gzip file is not supported. - - gzopen can be used to read a file which is not in gzip format; in this - case gzread will directly read from the file without decompression. - - gzopen returns NULL if the file could not be opened, if there was - insufficient memory to allocate the gzFile state, or if an invalid mode was - specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). - errno can be checked to determine if the reason gzopen failed was that the - file could not be opened. -*/ - -ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); -/* - gzdopen associates a gzFile with the file descriptor fd. File descriptors - are obtained from calls like open, dup, creat, pipe or fileno (if the file - has been previously opened with fopen). The mode parameter is as in gzopen. - - The next call of gzclose on the returned gzFile will also close the file - descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor - fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, - mode);. The duplicated descriptor should be saved to avoid a leak, since - gzdopen does not close fd if it fails. - - gzdopen returns NULL if there was insufficient memory to allocate the - gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not - provided, or '+' was provided), or if fd is -1. The file descriptor is not - used until the next gz* read, write, seek, or close operation, so gzdopen - will not detect if fd is invalid (unless fd is -1). -*/ - -ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); -/* - Set the internal buffer size used by this library's functions. The - default buffer size is 8192 bytes. This function must be called after - gzopen() or gzdopen(), and before any other calls that read or write the - file. The buffer memory allocation is always deferred to the first read or - write. Two buffers are allocated, either both of the specified size when - writing, or one of the specified size and the other twice that size when - reading. A larger buffer size of, for example, 64K or 128K bytes will - noticeably increase the speed of decompression (reading). - - The new buffer size also affects the maximum length for gzprintf(). - - gzbuffer() returns 0 on success, or -1 on failure, such as being called - too late. -*/ - -ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); -/* - Dynamically update the compression level or strategy. See the description - of deflateInit2 for the meaning of these parameters. - - gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not - opened for writing. -*/ - -ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); -/* - Reads the given number of uncompressed bytes from the compressed file. If - the input file was not in gzip format, gzread copies the given number of - bytes into the buffer. - - After reaching the end of a gzip stream in the input, gzread will continue - to read, looking for another gzip stream, or failing that, reading the rest - of the input file directly without decompression. The entire input file - will be read if gzread is called until it returns less than the requested - len. - - gzread returns the number of uncompressed bytes actually read, less than - len for end of file, or -1 for error. -*/ - -ZEXTERN int ZEXPORT gzwrite OF((gzFile file, - voidpc buf, unsigned len)); -/* - Writes the given number of uncompressed bytes into the compressed file. - gzwrite returns the number of uncompressed bytes written or 0 in case of - error. -*/ - -ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); -/* - Converts, formats, and writes the arguments to the compressed file under - control of the format string, as in fprintf. gzprintf returns the number of - uncompressed bytes actually written, or 0 in case of error. The number of - uncompressed bytes written is limited to 8191, or one less than the buffer - size given to gzbuffer(). The caller should assure that this limit is not - exceeded. If it is exceeded, then gzprintf() will return an error (0) with - nothing written. In this case, there may also be a buffer overflow with - unpredictable consequences, which is possible only if zlib was compiled with - the insecure functions sprintf() or vsprintf() because the secure snprintf() - or vsnprintf() functions were not available. This can be determined using - zlibCompileFlags(). -*/ - -ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); -/* - Writes the given null-terminated string to the compressed file, excluding - the terminating null character. - - gzputs returns the number of characters written, or -1 in case of error. -*/ - -ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); -/* - Reads bytes from the compressed file until len-1 characters are read, or a - newline character is read and transferred to buf, or an end-of-file - condition is encountered. If any characters are read or if len == 1, the - string is terminated with a null character. If no characters are read due - to an end-of-file or len < 1, then the buffer is left untouched. - - gzgets returns buf which is a null-terminated string, or it returns NULL - for end-of-file or in case of error. If there was an error, the contents at - buf are indeterminate. -*/ - -ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); -/* - Writes c, converted to an unsigned char, into the compressed file. gzputc - returns the value that was written, or -1 in case of error. -*/ - -ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); -/* - Reads one byte from the compressed file. gzgetc returns this byte or -1 - in case of end of file or error. -*/ - -ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); -/* - Push one character back onto the stream to be read as the first character - on the next read. At least one character of push-back is allowed. - gzungetc() returns the character pushed, or -1 on failure. gzungetc() will - fail if c is -1, and may fail if a character has been pushed but not read - yet. If gzungetc is used immediately after gzopen or gzdopen, at least the - output buffer size of pushed characters is allowed. (See gzbuffer above.) - The pushed character will be discarded if the stream is repositioned with - gzseek() or gzrewind(). -*/ - -ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); -/* - Flushes all pending output into the compressed file. The parameter flush - is as in the deflate() function. The return value is the zlib error number - (see function gzerror below). gzflush is only permitted when writing. - - If the flush parameter is Z_FINISH, the remaining data is written and the - gzip stream is completed in the output. If gzwrite() is called again, a new - gzip stream will be started in the output. gzread() is able to read such - concatented gzip streams. - - gzflush should be called only when strictly necessary because it will - degrade compression if called too often. -*/ - -/* -ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, - z_off_t offset, int whence)); - - Sets the starting position for the next gzread or gzwrite on the given - compressed file. The offset represents a number of bytes in the - uncompressed data stream. The whence parameter is defined as in lseek(2); - the value SEEK_END is not supported. - - If the file is opened for reading, this function is emulated but can be - extremely slow. If the file is opened for writing, only forward seeks are - supported; gzseek then compresses a sequence of zeroes up to the new - starting position. - - gzseek returns the resulting offset location as measured in bytes from - the beginning of the uncompressed stream, or -1 in case of error, in - particular if the file is opened for writing and the new starting position - would be before the current position. -*/ - -ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); -/* - Rewinds the given file. This function is supported only for reading. - - gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) -*/ - -/* -ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); - - Returns the starting position for the next gzread or gzwrite on the given - compressed file. This position represents a number of bytes in the - uncompressed data stream, and is zero when starting, even if appending or - reading a gzip stream from the middle of a file using gzdopen(). - - gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) -*/ - -/* -ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); - - Returns the current offset in the file being read or written. This offset - includes the count of bytes that precede the gzip stream, for example when - appending or when using gzdopen() for reading. When reading, the offset - does not include as yet unused buffered input. This information can be used - for a progress indicator. On error, gzoffset() returns -1. -*/ - -ZEXTERN int ZEXPORT gzeof OF((gzFile file)); -/* - Returns true (1) if the end-of-file indicator has been set while reading, - false (0) otherwise. Note that the end-of-file indicator is set only if the - read tried to go past the end of the input, but came up short. Therefore, - just like feof(), gzeof() may return false even if there is no more data to - read, in the event that the last read request was for the exact number of - bytes remaining in the input file. This will happen if the input file size - is an exact multiple of the buffer size. - - If gzeof() returns true, then the read functions will return no more data, - unless the end-of-file indicator is reset by gzclearerr() and the input file - has grown since the previous end of file was detected. -*/ - -ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); -/* - Returns true (1) if file is being copied directly while reading, or false - (0) if file is a gzip stream being decompressed. This state can change from - false to true while reading the input file if the end of a gzip stream is - reached, but is followed by data that is not another gzip stream. - - If the input file is empty, gzdirect() will return true, since the input - does not contain a gzip stream. - - If gzdirect() is used immediately after gzopen() or gzdopen() it will - cause buffers to be allocated to allow reading the file to determine if it - is a gzip file. Therefore if gzbuffer() is used, it should be called before - gzdirect(). -*/ - -ZEXTERN int ZEXPORT gzclose OF((gzFile file)); -/* - Flushes all pending output if necessary, closes the compressed file and - deallocates the (de)compression state. Note that once file is closed, you - cannot call gzerror with file, since its structures have been deallocated. - gzclose must not be called more than once on the same file, just as free - must not be called more than once on the same allocation. - - gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a - file operation error, or Z_OK on success. -*/ - -ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); -ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); -/* - Same as gzclose(), but gzclose_r() is only for use when reading, and - gzclose_w() is only for use when writing or appending. The advantage to - using these instead of gzclose() is that they avoid linking in zlib - compression or decompression code that is not used when only reading or only - writing respectively. If gzclose() is used, then both compression and - decompression code will be included the application when linking to a static - zlib library. -*/ - -ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); -/* - Returns the error message for the last error which occurred on the given - compressed file. errnum is set to zlib error number. If an error occurred - in the file system and not in the compression library, errnum is set to - Z_ERRNO and the application may consult errno to get the exact error code. - - The application must not modify the returned string. Future calls to - this function may invalidate the previously returned string. If file is - closed, then the string previously returned by gzerror will no longer be - available. - - gzerror() should be used to distinguish errors from end-of-file for those - functions above that do not distinguish those cases in their return values. -*/ - -ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); -/* - Clears the error and end-of-file flags for file. This is analogous to the - clearerr() function in stdio. This is useful for continuing to read a gzip - file that is being written concurrently. -*/ - - - /* checksum functions */ - -/* - These functions are not related to compression but are exported - anyway because they might be useful in applications using the compression - library. -*/ - -ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); -/* - Update a running Adler-32 checksum with the bytes buf[0..len-1] and - return the updated checksum. If buf is Z_NULL, this function returns the - required initial value for the checksum. - - An Adler-32 checksum is almost as reliable as a CRC32 but can be computed - much faster. - - Usage example: - - uLong adler = adler32(0L, Z_NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - adler = adler32(adler, buffer, length); - } - if (adler != original_adler) error(); -*/ - -/* -ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, - z_off_t len2)); - - Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 - and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for - each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of - seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. -*/ - -ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); -/* - Update a running CRC-32 with the bytes buf[0..len-1] and return the - updated CRC-32. If buf is Z_NULL, this function returns the required - initial value for the for the crc. Pre- and post-conditioning (one's - complement) is performed within this function so it shouldn't be done by the - application. - - Usage example: - - uLong crc = crc32(0L, Z_NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - crc = crc32(crc, buffer, length); - } - if (crc != original_crc) error(); -*/ - -/* -ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); - - Combine two CRC-32 check values into one. For two sequences of bytes, - seq1 and seq2 with lengths len1 and len2, CRC-32 check values were - calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 - check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and - len2. -*/ - - - /* various hacks, don't look :) */ - -/* deflateInit and inflateInit are macros to allow checking the zlib version - * and the compiler's view of z_stream: - */ -ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, - int windowBits, int memLevel, - int strategy, const char *version, - int stream_size)); -ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, - unsigned char FAR *window, - const char *version, - int stream_size)); -#define deflateInit(strm, level) \ - deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) -#define inflateInit(strm) \ - inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) -#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ - deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ - (strategy), ZLIB_VERSION, sizeof(z_stream)) -#define inflateInit2(strm, windowBits) \ - inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) -#define inflateBackInit(strm, windowBits, window) \ - inflateBackInit_((strm), (windowBits), (window), \ - ZLIB_VERSION, sizeof(z_stream)) - -/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or - * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if - * both are true, the application gets the *64 functions, and the regular - * functions are changed to 64 bits) -- in case these are set on systems - * without large file support, _LFS64_LARGEFILE must also be true - */ -#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 - ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); - ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); - ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); - ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); - ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); -#endif - -#if !defined(ZLIB_INTERNAL) && _FILE_OFFSET_BITS-0 == 64 && _LFS64_LARGEFILE-0 -# define gzopen gzopen64 -# define gzseek gzseek64 -# define gztell gztell64 -# define gzoffset gzoffset64 -# define adler32_combine adler32_combine64 -# define crc32_combine crc32_combine64 -# ifdef _LARGEFILE64_SOURCE - ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); - ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); - ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); - ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); -# endif -#else - ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); - ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); - ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); - ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); -#endif - -/* hack for buggy compilers */ -#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) - struct internal_state {int dummy;}; -#endif - -/* undocumented functions */ -ZEXTERN const char * ZEXPORT zError OF((int)); -ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); -ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); -ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); - -#ifdef __cplusplus -} -#endif - -#endif /* ZLIB_H */ diff --git a/cdeps/win/amd/win32/png.h b/cdeps/win/png.h similarity index 100% rename from cdeps/win/amd/win32/png.h rename to cdeps/win/png.h diff --git a/cdeps/win/amd/win32/pngconf.h b/cdeps/win/pngconf.h similarity index 100% rename from cdeps/win/amd/win32/pngconf.h rename to cdeps/win/pngconf.h diff --git a/cdeps/win/amd/win32/pnglibconf.h b/cdeps/win/pnglibconf.h similarity index 100% rename from cdeps/win/amd/win32/pnglibconf.h rename to cdeps/win/pnglibconf.h diff --git a/cdeps/win/amd/win32/zconf.h b/cdeps/win/zconf.h similarity index 100% rename from cdeps/win/amd/win32/zconf.h rename to cdeps/win/zconf.h diff --git a/cdeps/win/amd/win32/zlib.h b/cdeps/win/zlib.h similarity index 100% rename from cdeps/win/amd/win32/zlib.h rename to cdeps/win/zlib.h From cae09b857789869cbbbae64cd8382dc0671446c9 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sat, 6 Nov 2021 15:42:36 -0400 Subject: [PATCH 119/327] move bitmap to bitmap.go and move ocr to img.go --- base/file_io_c.h | 2 +- bitmap.go | 555 ++++++++++++++++++++++++++++++++++++++++++ img.go | 22 ++ robotgo.go | 553 +---------------------------------------- screen/screengrab_c.h | 2 +- 5 files changed, 580 insertions(+), 554 deletions(-) create mode 100644 bitmap.go diff --git a/base/file_io_c.h b/base/file_io_c.h index e2d71802..492b2e74 100644 --- a/base/file_io_c.h +++ b/base/file_io_c.h @@ -1,6 +1,6 @@ #include "file_io.h" // #include "os.h" -// #include "bmp_io_c.h" +#include "bmp_io_c.h" #include "png_io_c.h" #include /* For fputs() */ #include /* For strcmp() */ diff --git a/bitmap.go b/bitmap.go new file mode 100644 index 00000000..e6e16746 --- /dev/null +++ b/bitmap.go @@ -0,0 +1,555 @@ +// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// https://github.com/go-vgo/robotgo/blob/master/LICENSE +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +package robotgo + +/* +#cgo darwin,amd64 LDFLAGS:-L${SRCDIR}/cdeps/mac/amd -lpng -lz +#cgo darwin,arm64 LDFLAGS:-L${SRCDIR}/cdeps/mac/m1 -lpng -lz +// +#cgo linux LDFLAGS: -L/usr/src -lpng -lz +// +#cgo windows,amd64 LDFLAGS: -L${SRCDIR}/cdeps/win/amd/win64 -lpng -lz +#cgo windows,386 LDFLAGS: -L${SRCDIR}/cdeps/win/amd/win32 -lpng -lz +#cgo windows,arm64 LDFLAGS:-L${SRCDIR}/cdeps/win/arm -lpng -lz +// +//#include "screen/goScreen.h" +#include "bitmap/goBitmap.h" +*/ +import "C" + +import ( + "image" + "unsafe" + + "github.com/vcaesar/tt" +) + +/* +.______ __ .___________..___ ___. ___ .______ +| _ \ | | | || \/ | / \ | _ \ +| |_) | | | `---| |----`| \ / | / ^ \ | |_) | +| _ < | | | | | |\/| | / /_\ \ | ___/ +| |_) | | | | | | | | | / _____ \ | | +|______/ |__| |__| |__| |__| /__/ \__\ | _| +*/ + +// ToBitmap trans C.MMBitmapRef to Bitmap +func ToBitmap(bit C.MMBitmapRef) Bitmap { + bitmap := Bitmap{ + ImgBuf: (*uint8)(bit.imageBuffer), + Width: int(bit.width), + Height: int(bit.height), + Bytewidth: int(bit.bytewidth), + BitsPixel: uint8(bit.bitsPerPixel), + BytesPerPixel: uint8(bit.bytesPerPixel), + } + + return bitmap +} + +// ToCBitmap trans Bitmap to C.MMBitmapRef +func ToCBitmap(bit Bitmap) C.MMBitmapRef { + cbitmap := C.createMMBitmap( + (*C.uint8_t)(bit.ImgBuf), + C.size_t(bit.Width), + C.size_t(bit.Height), + C.size_t(bit.Bytewidth), + C.uint8_t(bit.BitsPixel), + C.uint8_t(bit.BytesPerPixel), + ) + + return cbitmap +} + +// ToBitmapBytes saves Bitmap to bitmap format in bytes +func ToBitmapBytes(bit C.MMBitmapRef) []byte { + var len C.size_t + ptr := C.saveMMBitmapAsBytes(bit, &len) + if int(len) < 0 { + return nil + } + + bs := C.GoBytes(unsafe.Pointer(ptr), C.int(len)) + C.free(unsafe.Pointer(ptr)) + return bs +} + +// ToMMBitmapRef trans CBitmap to C.MMBitmapRef +func ToMMBitmapRef(bit CBitmap) C.MMBitmapRef { + return C.MMBitmapRef(bit) +} + +// TostringBitmap tostring bitmap to string +func TostringBitmap(bit C.MMBitmapRef) string { + strBit := C.tostring_bitmap(bit) + return C.GoString(strBit) +} + +// TocharBitmap tostring bitmap to C.char +func TocharBitmap(bit C.MMBitmapRef) *C.char { + strBit := C.tostring_bitmap(bit) + return strBit +} + +// ToImage convert C.MMBitmapRef to standard image.Image +func ToImage(bit C.MMBitmapRef) image.Image { + return ToRGBA(bit) +} + +// ToRGBA convert C.MMBitmapRef to standard image.RGBA +func ToRGBA(bit C.MMBitmapRef) *image.RGBA { + bmp1 := ToBitmap(bit) + return ToRGBAGo(bmp1) +} + +func internalFindBitmap(bit, sbit C.MMBitmapRef, tolerance float64) (int, int) { + pos := C.find_bitmap(bit, sbit, C.float(tolerance)) + // fmt.Println("pos----", pos) + return int(pos.x), int(pos.y) +} + +// FindCBitmap find bitmap's pos by CBitmap +func FindCBitmap(bmp CBitmap, args ...interface{}) (int, int) { + return FindBitmap(ToMMBitmapRef(bmp), args...) +} + +// FindBitmap find the bitmap's pos +// +// robotgo.FindBitmap(bitmap, source_bitamp C.MMBitmapRef, tolerance float64) +// +// |tolerance| should be in the range 0.0f - 1.0f, denoting how closely the +// colors in the bitmaps need to match, with 0 being exact and 1 being any. +// +// This method only automatically free the internal bitmap, +// use `defer robotgo.FreeBitmap(bit)` to free the bitmap +func FindBitmap(bit C.MMBitmapRef, args ...interface{}) (int, int) { + var ( + sbit C.MMBitmapRef + tolerance = 0.01 + ) + + if len(args) > 0 && args[0] != nil { + sbit = args[0].(C.MMBitmapRef) + } else { + sbit = CaptureScreen() + } + + if len(args) > 1 { + tolerance = args[1].(float64) + } + + fx, fy := internalFindBitmap(bit, sbit, tolerance) + // FreeBitmap(bit) + if len(args) <= 0 || (len(args) > 0 && args[0] == nil) { + FreeBitmap(sbit) + } + + return fx, fy +} + +// FindPic finding the image by path +// +// robotgo.FindPic(path string, source_bitamp C.MMBitmapRef, tolerance float64) +// +// This method only automatically free the internal bitmap, +// use `defer robotgo.FreeBitmap(bit)` to free the bitmap +func FindPic(path string, args ...interface{}) (int, int) { + var ( + sbit C.MMBitmapRef + tolerance = 0.01 + ) + + openbit := OpenBitmap(path) + + if len(args) > 0 && args[0] != nil { + sbit = args[0].(C.MMBitmapRef) + } else { + sbit = CaptureScreen() + } + + if len(args) > 1 { + tolerance = args[1].(float64) + } + + fx, fy := internalFindBitmap(openbit, sbit, tolerance) + FreeBitmap(openbit) + if len(args) <= 0 || (len(args) > 0 && args[0] == nil) { + FreeBitmap(sbit) + } + + return fx, fy +} + +// FreeMMPointArr free MMPoint array +func FreeMMPointArr(pointArray C.MMPointArrayRef) { + C.destroyMMPointArray(pointArray) +} + +// FindEveryBitmap find the every bitmap +func FindEveryBitmap(bit C.MMBitmapRef, args ...interface{}) (posArr []Point) { + var ( + sbit C.MMBitmapRef + tolerance C.float = 0.01 + lpos C.MMPoint + ) + + if len(args) > 0 && args[0] != nil { + sbit = args[0].(C.MMBitmapRef) + } else { + sbit = CaptureScreen() + } + + if len(args) > 1 { + tolerance = C.float(args[1].(float64)) + } + + if len(args) > 2 { + lpos.x = C.size_t(args[2].(int)) + lpos.y = 0 + } else { + lpos.x = 0 + lpos.y = 0 + } + + if len(args) > 3 { + lpos.x = C.size_t(args[2].(int)) + lpos.y = C.size_t(args[3].(int)) + } + + pos := C.find_every_bitmap(bit, sbit, tolerance, &lpos) + // FreeBitmap(bit) + if len(args) <= 0 || (len(args) > 0 && args[0] == nil) { + FreeBitmap(sbit) + } + if pos == nil { + return + } + defer FreeMMPointArr(pos) + + cSize := pos.count + cArray := pos.array + gSlice := (*[(1 << 28) - 1]C.MMPoint)(unsafe.Pointer(cArray))[:cSize:cSize] + for i := 0; i < len(gSlice); i++ { + posArr = append(posArr, Point{ + X: int(gSlice[i].x), + Y: int(gSlice[i].y), + }) + } + + // fmt.Println("pos----", pos) + return +} + +// CountBitmap count of the bitmap +func CountBitmap(bitmap, sbit C.MMBitmapRef, args ...float32) int { + var tolerance C.float = 0.01 + if len(args) > 0 { + tolerance = C.float(args[0]) + } + + count := C.count_of_bitmap(bitmap, sbit, tolerance) + return int(count) +} + +// BitmapClick find the bitmap and click +func BitmapClick(bitmap C.MMBitmapRef, args ...interface{}) { + x, y := FindBitmap(bitmap) + MovesClick(x, y, args...) +} + +// PointInBounds bitmap point in bounds +func PointInBounds(bitmap C.MMBitmapRef, x, y int) bool { + var point C.MMPoint + point.x = C.size_t(x) + point.y = C.size_t(y) + cbool := C.point_in_bounds(bitmap, point) + + return bool(cbool) +} + +// OpenBitmap open the bitmap return C.MMBitmapRef +// +// robotgo.OpenBitmap(path string, type int) +func OpenBitmap(gpath string, args ...int) C.MMBitmapRef { + path := C.CString(gpath) + var mtype C.uint16_t = 1 + + if len(args) > 0 { + mtype = C.uint16_t(args[0]) + } + + bit := C.bitmap_open(path, mtype) + C.free(unsafe.Pointer(path)) + + return bit +} + +// BitmapStr bitmap from string +func BitmapStr(str string) C.MMBitmapRef { + return BitmapFromStr(str) +} + +// BitmapFromStr bitmap from string +func BitmapFromStr(str string) C.MMBitmapRef { + cs := C.CString(str) + bit := C.bitmap_from_string(cs) + C.free(unsafe.Pointer(cs)) + + return bit +} + +// SaveBitmap save the bitmap to image +// +// robotgo.SaveBimap(bitmap C.MMBitmapRef, path string, type int) +func SaveBitmap(bitmap C.MMBitmapRef, gpath string, args ...int) string { + var mtype C.uint16_t = 1 + if len(args) > 0 { + mtype = C.uint16_t(args[0]) + } + + path := C.CString(gpath) + saveBit := C.bitmap_save(bitmap, path, mtype) + C.free(unsafe.Pointer(path)) + + return C.GoString(saveBit) +} + +// GetPortion get bitmap portion +func GetPortion(bit C.MMBitmapRef, x, y, w, h int) C.MMBitmapRef { + var rect C.MMRect + rect.origin.x = C.size_t(x) + rect.origin.y = C.size_t(y) + rect.size.width = C.size_t(w) + rect.size.height = C.size_t(h) + + pos := C.get_portion(bit, rect) + return pos +} + +// Convert convert the bitmap +// +// robotgo.Convert(opath, spath string, type int) +func Convert(opath, spath string, args ...int) { + var mtype = 1 + if len(args) > 0 { + mtype = args[0] + } + + // C.CString() + bitmap := OpenBitmap(opath) + // fmt.Println("a----", bit_map) + SaveBitmap(bitmap, spath, mtype) +} + +// FreeBitmap free and dealloc the C bitmap +func FreeBitmap(bitmap C.MMBitmapRef) { + // C.destroyMMBitmap(bitmap) + C.bitmap_dealloc(bitmap) +} + +// FreeBitmapArr free and dealloc the C bitmap array +func FreeBitmapArr(bit ...C.MMBitmapRef) { + for i := 0; i < len(bit); i++ { + FreeBitmap(bit[i]) + } +} + +// ReadBitmap returns false and sets error if |bitmap| is NULL +func ReadBitmap(bitmap C.MMBitmapRef) bool { + abool := C.bitmap_ready(bitmap) + gbool := bool(abool) + return gbool +} + +// CopyBitPB copy bitmap to pasteboard +func CopyBitPB(bitmap C.MMBitmapRef) bool { + abool := C.bitmap_copy_to_pboard(bitmap) + gbool := bool(abool) + + return gbool +} + +// Deprecated: CopyBitpb copy bitmap to pasteboard, Wno-deprecated +func CopyBitpb(bitmap C.MMBitmapRef) bool { + tt.Drop("CopyBitpb", "CopyBitPB") + return CopyBitPB(bitmap) +} + +// DeepCopyBit deep copy bitmap +func DeepCopyBit(bitmap C.MMBitmapRef) C.MMBitmapRef { + bit := C.bitmap_deepcopy(bitmap) + return bit +} + +// GetColor get bitmap color +func GetColor(bitmap C.MMBitmapRef, x, y int) C.MMRGBHex { + color := C.bitmap_get_color(bitmap, C.size_t(x), C.size_t(y)) + + return color +} + +// GetColors get bitmap color retrun string +func GetColors(bitmap C.MMBitmapRef, x, y int) string { + clo := GetColor(bitmap, x, y) + + return PadHex(clo) +} + +// FindColor find bitmap color +// +// robotgo.FindColor(color CHex, bitmap C.MMBitmapRef, tolerance float) +func FindColor(color CHex, args ...interface{}) (int, int) { + var ( + tolerance C.float = 0.01 + bitmap C.MMBitmapRef + ) + + if len(args) > 0 && args[0] != nil { + bitmap = args[0].(C.MMBitmapRef) + } else { + bitmap = CaptureScreen() + } + + if len(args) > 1 { + tolerance = C.float(args[1].(float64)) + } + + pos := C.bitmap_find_color(bitmap, C.MMRGBHex(color), tolerance) + if len(args) <= 0 || (len(args) > 0 && args[0] == nil) { + FreeBitmap(bitmap) + } + + x := int(pos.x) + y := int(pos.y) + + return x, y +} + +// FindColorCS findcolor by CaptureScreen +func FindColorCS(color CHex, x, y, w, h int, args ...float64) (int, int) { + var tolerance = 0.01 + + if len(args) > 0 { + tolerance = args[0] + } + + bitmap := CaptureScreen(x, y, w, h) + rx, ry := FindColor(color, bitmap, tolerance) + FreeBitmap(bitmap) + + return rx, ry +} + +// FindEveryColor find every color +func FindEveryColor(color CHex, args ...interface{}) (posArr []Point) { + var ( + bitmap C.MMBitmapRef + tolerance C.float = 0.01 + lpos C.MMPoint + ) + + if len(args) > 0 && args[0] != nil { + bitmap = args[0].(C.MMBitmapRef) + } else { + bitmap = CaptureScreen() + } + + if len(args) > 1 { + tolerance = C.float(args[1].(float64)) + } + + if len(args) > 2 { + lpos.x = C.size_t(args[2].(int)) + lpos.y = 0 + } else { + lpos.x = 0 + lpos.y = 0 + } + + if len(args) > 3 { + lpos.x = C.size_t(args[2].(int)) + lpos.y = C.size_t(args[3].(int)) + } + + pos := C.bitmap_find_every_color(bitmap, C.MMRGBHex(color), tolerance, &lpos) + if len(args) <= 0 || (len(args) > 0 && args[0] == nil) { + FreeBitmap(bitmap) + } + + if pos == nil { + return + } + defer FreeMMPointArr(pos) + + cSize := pos.count + cArray := pos.array + gSlice := (*[(1 << 28) - 1]C.MMPoint)(unsafe.Pointer(cArray))[:cSize:cSize] + for i := 0; i < len(gSlice); i++ { + posArr = append(posArr, Point{ + X: int(gSlice[i].x), + Y: int(gSlice[i].y), + }) + } + + return +} + +// CountColor count bitmap color +func CountColor(color CHex, args ...interface{}) int { + var ( + tolerance C.float = 0.01 + bitmap C.MMBitmapRef + ) + + if len(args) > 0 && args[0] != nil { + bitmap = args[0].(C.MMBitmapRef) + } else { + bitmap = CaptureScreen() + } + + if len(args) > 1 { + tolerance = C.float(args[1].(float64)) + } + + count := C.bitmap_count_of_color(bitmap, C.MMRGBHex(color), tolerance) + if len(args) <= 0 || (len(args) > 0 && args[0] == nil) { + FreeBitmap(bitmap) + } + + return int(count) +} + +// CountColorCS count bitmap color by CaptureScreen +func CountColorCS(color CHex, x, y, w, h int, args ...float64) int { + var tolerance = 0.01 + + if len(args) > 0 { + tolerance = args[0] + } + + bitmap := CaptureScreen(x, y, w, h) + rx := CountColor(color, bitmap, tolerance) + FreeBitmap(bitmap) + + return rx +} + +// GetImgSize get the image size +func GetImgSize(imgPath string) (int, int) { + bitmap := OpenBitmap(imgPath) + gbit := ToBitmap(bitmap) + + w := gbit.Width / 2 + h := gbit.Height / 2 + FreeBitmap(bitmap) + + return w, h +} diff --git a/img.go b/img.go index 6409cf82..0e2a3205 100644 --- a/img.go +++ b/img.go @@ -12,6 +12,7 @@ package robotgo import ( "image" + "os/exec" "unsafe" "github.com/vcaesar/imgo" @@ -157,3 +158,24 @@ func copyToVUint8A(dst []uint8, src *uint8) { dst[i+3] = val(src, i+3) } } + +// GetText get the image text by tesseract ocr +// +// robotgo.GetText(imgPath, lang string) +func GetText(imgPath string, args ...string) (string, error) { + var lang = "eng" + + if len(args) > 0 { + lang = args[0] + if lang == "zh" { + lang = "chi_sim" + } + } + + body, err := exec.Command("tesseract", imgPath, + "stdout", "-l", lang).Output() + if err != nil { + return "", err + } + return string(body), nil +} diff --git a/robotgo.go b/robotgo.go index c3849957..f22a7cc7 100644 --- a/robotgo.go +++ b/robotgo.go @@ -27,24 +27,17 @@ package robotgo #cgo darwin CFLAGS: -x objective-c -Wno-deprecated-declarations #cgo darwin LDFLAGS: -framework Cocoa -framework OpenGL -framework IOKit #cgo darwin LDFLAGS: -framework Carbon -framework CoreFoundation - #cgo darwin,amd64 LDFLAGS:-L${SRCDIR}/cdeps/mac/amd -lpng -lz - #cgo darwin,arm64 LDFLAGS:-L${SRCDIR}/cdeps/mac/m1 -lpng -lz //#elif defined(USE_X11) - // Drop -std=c11 #cgo linux CFLAGS: -I/usr/src - #cgo linux LDFLAGS: -L/usr/src -lpng -lz -lX11 -lXtst -lm + #cgo linux LDFLAGS: -L/usr/src -lX11 -lXtst -lm // #cgo linux LDFLAGS: -lX11-xcb -lxcb -lxcb-xkb -lxkbcommon -lxkbcommon-x11 //#endif // #cgo windows LDFLAGS: -lgdi32 -luser32 -lpng -lz #cgo windows LDFLAGS: -lgdi32 -luser32 - #cgo windows,amd64 LDFLAGS: -L${SRCDIR}/cdeps/win/amd/win64 -lpng -lz - #cgo windows,386 LDFLAGS: -L${SRCDIR}/cdeps/win/amd/win32 -lpng -lz - #cgo windows,arm64 LDFLAGS:-L${SRCDIR}/cdeps/win/arm -lpng -lz // #include #include "screen/goScreen.h" #include "mouse/goMouse.h" #include "key/goKey.h" -#include "bitmap/goBitmap.h" //#include "event/goEvent.h" #include "window/goWindow.h" */ @@ -64,7 +57,6 @@ import ( // "syscall" "math/rand" - "os/exec" "github.com/go-vgo/robotgo/clipboard" "github.com/vcaesar/tt" @@ -946,549 +938,6 @@ func SetDelay(d ...int) { SetKeyDelay(v) } -/* -.______ __ .___________..___ ___. ___ .______ -| _ \ | | | || \/ | / \ | _ \ -| |_) | | | `---| |----`| \ / | / ^ \ | |_) | -| _ < | | | | | |\/| | / /_\ \ | ___/ -| |_) | | | | | | | | | / _____ \ | | -|______/ |__| |__| |__| |__| /__/ \__\ | _| -*/ - -// GetText get the image text by tesseract ocr -// -// robotgo.GetText(imgPath, lang string) -func GetText(imgPath string, args ...string) (string, error) { - var lang = "eng" - - if len(args) > 0 { - lang = args[0] - if lang == "zh" { - lang = "chi_sim" - } - } - - body, err := exec.Command("tesseract", imgPath, - "stdout", "-l", lang).Output() - if err != nil { - return "", err - } - return string(body), nil -} - -// ToBitmap trans C.MMBitmapRef to Bitmap -func ToBitmap(bit C.MMBitmapRef) Bitmap { - bitmap := Bitmap{ - ImgBuf: (*uint8)(bit.imageBuffer), - Width: int(bit.width), - Height: int(bit.height), - Bytewidth: int(bit.bytewidth), - BitsPixel: uint8(bit.bitsPerPixel), - BytesPerPixel: uint8(bit.bytesPerPixel), - } - - return bitmap -} - -// ToCBitmap trans Bitmap to C.MMBitmapRef -func ToCBitmap(bit Bitmap) C.MMBitmapRef { - cbitmap := C.createMMBitmap( - (*C.uint8_t)(bit.ImgBuf), - C.size_t(bit.Width), - C.size_t(bit.Height), - C.size_t(bit.Bytewidth), - C.uint8_t(bit.BitsPixel), - C.uint8_t(bit.BytesPerPixel), - ) - - return cbitmap -} - -// ToBitmapBytes saves Bitmap to bitmap format in bytes -func ToBitmapBytes(bit C.MMBitmapRef) []byte { - var len C.size_t - ptr := C.saveMMBitmapAsBytes(bit, &len) - if int(len) < 0 { - return nil - } - - bs := C.GoBytes(unsafe.Pointer(ptr), C.int(len)) - C.free(unsafe.Pointer(ptr)) - return bs -} - -// ToMMBitmapRef trans CBitmap to C.MMBitmapRef -func ToMMBitmapRef(bit CBitmap) C.MMBitmapRef { - return C.MMBitmapRef(bit) -} - -// TostringBitmap tostring bitmap to string -func TostringBitmap(bit C.MMBitmapRef) string { - strBit := C.tostring_bitmap(bit) - return C.GoString(strBit) -} - -// TocharBitmap tostring bitmap to C.char -func TocharBitmap(bit C.MMBitmapRef) *C.char { - strBit := C.tostring_bitmap(bit) - return strBit -} - -// ToImage convert C.MMBitmapRef to standard image.Image -func ToImage(bit C.MMBitmapRef) image.Image { - return ToRGBA(bit) -} - -// ToRGBA convert C.MMBitmapRef to standard image.RGBA -func ToRGBA(bit C.MMBitmapRef) *image.RGBA { - bmp1 := ToBitmap(bit) - return ToRGBAGo(bmp1) -} - -func internalFindBitmap(bit, sbit C.MMBitmapRef, tolerance float64) (int, int) { - pos := C.find_bitmap(bit, sbit, C.float(tolerance)) - // fmt.Println("pos----", pos) - return int(pos.x), int(pos.y) -} - -// FindCBitmap find bitmap's pos by CBitmap -func FindCBitmap(bmp CBitmap, args ...interface{}) (int, int) { - return FindBitmap(ToMMBitmapRef(bmp), args...) -} - -// FindBitmap find the bitmap's pos -// -// robotgo.FindBitmap(bitmap, source_bitamp C.MMBitmapRef, tolerance float64) -// -// |tolerance| should be in the range 0.0f - 1.0f, denoting how closely the -// colors in the bitmaps need to match, with 0 being exact and 1 being any. -// -// This method only automatically free the internal bitmap, -// use `defer robotgo.FreeBitmap(bit)` to free the bitmap -func FindBitmap(bit C.MMBitmapRef, args ...interface{}) (int, int) { - var ( - sbit C.MMBitmapRef - tolerance = 0.01 - ) - - if len(args) > 0 && args[0] != nil { - sbit = args[0].(C.MMBitmapRef) - } else { - sbit = CaptureScreen() - } - - if len(args) > 1 { - tolerance = args[1].(float64) - } - - fx, fy := internalFindBitmap(bit, sbit, tolerance) - // FreeBitmap(bit) - if len(args) <= 0 || (len(args) > 0 && args[0] == nil) { - FreeBitmap(sbit) - } - - return fx, fy -} - -// FindPic finding the image by path -// -// robotgo.FindPic(path string, source_bitamp C.MMBitmapRef, tolerance float64) -// -// This method only automatically free the internal bitmap, -// use `defer robotgo.FreeBitmap(bit)` to free the bitmap -func FindPic(path string, args ...interface{}) (int, int) { - var ( - sbit C.MMBitmapRef - tolerance = 0.01 - ) - - openbit := OpenBitmap(path) - - if len(args) > 0 && args[0] != nil { - sbit = args[0].(C.MMBitmapRef) - } else { - sbit = CaptureScreen() - } - - if len(args) > 1 { - tolerance = args[1].(float64) - } - - fx, fy := internalFindBitmap(openbit, sbit, tolerance) - FreeBitmap(openbit) - if len(args) <= 0 || (len(args) > 0 && args[0] == nil) { - FreeBitmap(sbit) - } - - return fx, fy -} - -// FreeMMPointArr free MMPoint array -func FreeMMPointArr(pointArray C.MMPointArrayRef) { - C.destroyMMPointArray(pointArray) -} - -// FindEveryBitmap find the every bitmap -func FindEveryBitmap(bit C.MMBitmapRef, args ...interface{}) (posArr []Point) { - var ( - sbit C.MMBitmapRef - tolerance C.float = 0.01 - lpos C.MMPoint - ) - - if len(args) > 0 && args[0] != nil { - sbit = args[0].(C.MMBitmapRef) - } else { - sbit = CaptureScreen() - } - - if len(args) > 1 { - tolerance = C.float(args[1].(float64)) - } - - if len(args) > 2 { - lpos.x = C.size_t(args[2].(int)) - lpos.y = 0 - } else { - lpos.x = 0 - lpos.y = 0 - } - - if len(args) > 3 { - lpos.x = C.size_t(args[2].(int)) - lpos.y = C.size_t(args[3].(int)) - } - - pos := C.find_every_bitmap(bit, sbit, tolerance, &lpos) - // FreeBitmap(bit) - if len(args) <= 0 || (len(args) > 0 && args[0] == nil) { - FreeBitmap(sbit) - } - if pos == nil { - return - } - defer FreeMMPointArr(pos) - - cSize := pos.count - cArray := pos.array - gSlice := (*[(1 << 28) - 1]C.MMPoint)(unsafe.Pointer(cArray))[:cSize:cSize] - for i := 0; i < len(gSlice); i++ { - posArr = append(posArr, Point{ - X: int(gSlice[i].x), - Y: int(gSlice[i].y), - }) - } - - // fmt.Println("pos----", pos) - return -} - -// CountBitmap count of the bitmap -func CountBitmap(bitmap, sbit C.MMBitmapRef, args ...float32) int { - var tolerance C.float = 0.01 - if len(args) > 0 { - tolerance = C.float(args[0]) - } - - count := C.count_of_bitmap(bitmap, sbit, tolerance) - return int(count) -} - -// BitmapClick find the bitmap and click -func BitmapClick(bitmap C.MMBitmapRef, args ...interface{}) { - x, y := FindBitmap(bitmap) - MovesClick(x, y, args...) -} - -// PointInBounds bitmap point in bounds -func PointInBounds(bitmap C.MMBitmapRef, x, y int) bool { - var point C.MMPoint - point.x = C.size_t(x) - point.y = C.size_t(y) - cbool := C.point_in_bounds(bitmap, point) - - return bool(cbool) -} - -// OpenBitmap open the bitmap return C.MMBitmapRef -// -// robotgo.OpenBitmap(path string, type int) -func OpenBitmap(gpath string, args ...int) C.MMBitmapRef { - path := C.CString(gpath) - var mtype C.uint16_t = 1 - - if len(args) > 0 { - mtype = C.uint16_t(args[0]) - } - - bit := C.bitmap_open(path, mtype) - C.free(unsafe.Pointer(path)) - - return bit -} - -// BitmapStr bitmap from string -func BitmapStr(str string) C.MMBitmapRef { - return BitmapFromStr(str) -} - -// BitmapFromStr bitmap from string -func BitmapFromStr(str string) C.MMBitmapRef { - cs := C.CString(str) - bit := C.bitmap_from_string(cs) - C.free(unsafe.Pointer(cs)) - - return bit -} - -// SaveBitmap save the bitmap to image -// -// robotgo.SaveBimap(bitmap C.MMBitmapRef, path string, type int) -func SaveBitmap(bitmap C.MMBitmapRef, gpath string, args ...int) string { - var mtype C.uint16_t = 1 - if len(args) > 0 { - mtype = C.uint16_t(args[0]) - } - - path := C.CString(gpath) - saveBit := C.bitmap_save(bitmap, path, mtype) - C.free(unsafe.Pointer(path)) - - return C.GoString(saveBit) -} - -// GetPortion get bitmap portion -func GetPortion(bit C.MMBitmapRef, x, y, w, h int) C.MMBitmapRef { - var rect C.MMRect - rect.origin.x = C.size_t(x) - rect.origin.y = C.size_t(y) - rect.size.width = C.size_t(w) - rect.size.height = C.size_t(h) - - pos := C.get_portion(bit, rect) - return pos -} - -// Convert convert the bitmap -// -// robotgo.Convert(opath, spath string, type int) -func Convert(opath, spath string, args ...int) { - var mtype = 1 - if len(args) > 0 { - mtype = args[0] - } - - // C.CString() - bitmap := OpenBitmap(opath) - // fmt.Println("a----", bit_map) - SaveBitmap(bitmap, spath, mtype) -} - -// FreeBitmap free and dealloc the C bitmap -func FreeBitmap(bitmap C.MMBitmapRef) { - // C.destroyMMBitmap(bitmap) - C.bitmap_dealloc(bitmap) -} - -// FreeBitmapArr free and dealloc the C bitmap array -func FreeBitmapArr(bit ...C.MMBitmapRef) { - for i := 0; i < len(bit); i++ { - FreeBitmap(bit[i]) - } -} - -// ReadBitmap returns false and sets error if |bitmap| is NULL -func ReadBitmap(bitmap C.MMBitmapRef) bool { - abool := C.bitmap_ready(bitmap) - gbool := bool(abool) - return gbool -} - -// CopyBitPB copy bitmap to pasteboard -func CopyBitPB(bitmap C.MMBitmapRef) bool { - abool := C.bitmap_copy_to_pboard(bitmap) - gbool := bool(abool) - - return gbool -} - -// Deprecated: CopyBitpb copy bitmap to pasteboard, Wno-deprecated -func CopyBitpb(bitmap C.MMBitmapRef) bool { - tt.Drop("CopyBitpb", "CopyBitPB") - return CopyBitPB(bitmap) -} - -// DeepCopyBit deep copy bitmap -func DeepCopyBit(bitmap C.MMBitmapRef) C.MMBitmapRef { - bit := C.bitmap_deepcopy(bitmap) - return bit -} - -// GetColor get bitmap color -func GetColor(bitmap C.MMBitmapRef, x, y int) C.MMRGBHex { - color := C.bitmap_get_color(bitmap, C.size_t(x), C.size_t(y)) - - return color -} - -// GetColors get bitmap color retrun string -func GetColors(bitmap C.MMBitmapRef, x, y int) string { - clo := GetColor(bitmap, x, y) - - return PadHex(clo) -} - -// FindColor find bitmap color -// -// robotgo.FindColor(color CHex, bitmap C.MMBitmapRef, tolerance float) -func FindColor(color CHex, args ...interface{}) (int, int) { - var ( - tolerance C.float = 0.01 - bitmap C.MMBitmapRef - ) - - if len(args) > 0 && args[0] != nil { - bitmap = args[0].(C.MMBitmapRef) - } else { - bitmap = CaptureScreen() - } - - if len(args) > 1 { - tolerance = C.float(args[1].(float64)) - } - - pos := C.bitmap_find_color(bitmap, C.MMRGBHex(color), tolerance) - if len(args) <= 0 || (len(args) > 0 && args[0] == nil) { - FreeBitmap(bitmap) - } - - x := int(pos.x) - y := int(pos.y) - - return x, y -} - -// FindColorCS findcolor by CaptureScreen -func FindColorCS(color CHex, x, y, w, h int, args ...float64) (int, int) { - var tolerance = 0.01 - - if len(args) > 0 { - tolerance = args[0] - } - - bitmap := CaptureScreen(x, y, w, h) - rx, ry := FindColor(color, bitmap, tolerance) - FreeBitmap(bitmap) - - return rx, ry -} - -// FindEveryColor find every color -func FindEveryColor(color CHex, args ...interface{}) (posArr []Point) { - var ( - bitmap C.MMBitmapRef - tolerance C.float = 0.01 - lpos C.MMPoint - ) - - if len(args) > 0 && args[0] != nil { - bitmap = args[0].(C.MMBitmapRef) - } else { - bitmap = CaptureScreen() - } - - if len(args) > 1 { - tolerance = C.float(args[1].(float64)) - } - - if len(args) > 2 { - lpos.x = C.size_t(args[2].(int)) - lpos.y = 0 - } else { - lpos.x = 0 - lpos.y = 0 - } - - if len(args) > 3 { - lpos.x = C.size_t(args[2].(int)) - lpos.y = C.size_t(args[3].(int)) - } - - pos := C.bitmap_find_every_color(bitmap, C.MMRGBHex(color), tolerance, &lpos) - if len(args) <= 0 || (len(args) > 0 && args[0] == nil) { - FreeBitmap(bitmap) - } - - if pos == nil { - return - } - defer FreeMMPointArr(pos) - - cSize := pos.count - cArray := pos.array - gSlice := (*[(1 << 28) - 1]C.MMPoint)(unsafe.Pointer(cArray))[:cSize:cSize] - for i := 0; i < len(gSlice); i++ { - posArr = append(posArr, Point{ - X: int(gSlice[i].x), - Y: int(gSlice[i].y), - }) - } - - return -} - -// CountColor count bitmap color -func CountColor(color CHex, args ...interface{}) int { - var ( - tolerance C.float = 0.01 - bitmap C.MMBitmapRef - ) - - if len(args) > 0 && args[0] != nil { - bitmap = args[0].(C.MMBitmapRef) - } else { - bitmap = CaptureScreen() - } - - if len(args) > 1 { - tolerance = C.float(args[1].(float64)) - } - - count := C.bitmap_count_of_color(bitmap, C.MMRGBHex(color), tolerance) - if len(args) <= 0 || (len(args) > 0 && args[0] == nil) { - FreeBitmap(bitmap) - } - - return int(count) -} - -// CountColorCS count bitmap color by CaptureScreen -func CountColorCS(color CHex, x, y, w, h int, args ...float64) int { - var tolerance = 0.01 - - if len(args) > 0 { - tolerance = args[0] - } - - bitmap := CaptureScreen(x, y, w, h) - rx := CountColor(color, bitmap, tolerance) - FreeBitmap(bitmap) - - return rx -} - -// GetImgSize get the image size -func GetImgSize(imgPath string) (int, int) { - bitmap := OpenBitmap(imgPath) - gbit := ToBitmap(bitmap) - - w := gbit.Width / 2 - h := gbit.Height / 2 - FreeBitmap(bitmap) - - return w, h -} - /* ____ __ ____ __ .__ __. _______ ______ ____ __ ____ \ \ / \ / / | | | \ | | | \ / __ \ \ \ / \ / / diff --git a/screen/screengrab_c.h b/screen/screengrab_c.h index e3318c46..214d6bfb 100644 --- a/screen/screengrab_c.h +++ b/screen/screengrab_c.h @@ -1,5 +1,5 @@ #include "screengrab.h" -#include "../base/bmp_io_c.h" +// #include "../base/bmp_io_c.h" #include "../base/endian.h" #include /* malloc() */ From 335b3f50a20fe84fa2dc4f581c829d2ece4b2c23 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sat, 6 Nov 2021 15:45:35 -0400 Subject: [PATCH 120/327] Update README.md --- README.md | 3 ++- README_zh.md | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9eb02dc9..220a6a95 100644 --- a/README.md +++ b/README.md @@ -310,7 +310,8 @@ func opencv() { res1 := gcv.Find(img1, img) fmt.Println("find: ", res1) - x, y = gcv.FindX(img1, img) + img2, _, _ := robotgo.DecodeImg("test_001.png") + x, y = gcv.FindX(img2, img) fmt.Println(x, y) } ``` diff --git a/README_zh.md b/README_zh.md index e178ac25..474789ac 100644 --- a/README_zh.md +++ b/README_zh.md @@ -307,7 +307,8 @@ func opencv() { res1 := gcv.Find(img1, img) fmt.Println("find: ", res1) - x, y = gcv.FindX(img1, img) + img2, _, _ := robotgo.DecodeImg("test_001.png") + x, y = gcv.FindX(img2, img) fmt.Println(x, y) } ``` From 617b7b0dc8c9878d2d8575d0ffe7a6c75ca30987 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 7 Nov 2021 14:01:10 -0400 Subject: [PATCH 121/327] move FreeBitmap() and ToImage() to screen and optimize code, update godoc --- bitmap.go | 49 ++++++++++++------------------------------- bitmap/goBitmap.h | 12 +++++------ cmd/color-pos/main.go | 1 + robotgo.go | 33 ++++++++++++++++++++++++----- screen/goScreen.h | 7 +++++++ 5 files changed, 55 insertions(+), 47 deletions(-) diff --git a/bitmap.go b/bitmap.go index e6e16746..ca300bc0 100644 --- a/bitmap.go +++ b/bitmap.go @@ -26,7 +26,6 @@ package robotgo import "C" import ( - "image" "unsafe" "github.com/vcaesar/tt" @@ -41,18 +40,13 @@ import ( |______/ |__| |__| |__| |__| /__/ \__\ | _| */ -// ToBitmap trans C.MMBitmapRef to Bitmap -func ToBitmap(bit C.MMBitmapRef) Bitmap { - bitmap := Bitmap{ - ImgBuf: (*uint8)(bit.imageBuffer), - Width: int(bit.width), - Height: int(bit.height), - Bytewidth: int(bit.bytewidth), - BitsPixel: uint8(bit.bitsPerPixel), - BytesPerPixel: uint8(bit.bytesPerPixel), - } +// SaveCapture capture screen and save +func SaveCapture(spath string, args ...int) string { + bit := CaptureScreen(args...) - return bitmap + err := SaveBitmap(bit, spath) + FreeBitmap(bit) + return err } // ToCBitmap trans Bitmap to C.MMBitmapRef @@ -69,6 +63,11 @@ func ToCBitmap(bit Bitmap) C.MMBitmapRef { return cbitmap } +// ToMMBitmapRef trans CBitmap to C.MMBitmapRef +func ToMMBitmapRef(bit CBitmap) C.MMBitmapRef { + return C.MMBitmapRef(bit) +} + // ToBitmapBytes saves Bitmap to bitmap format in bytes func ToBitmapBytes(bit C.MMBitmapRef) []byte { var len C.size_t @@ -82,11 +81,6 @@ func ToBitmapBytes(bit C.MMBitmapRef) []byte { return bs } -// ToMMBitmapRef trans CBitmap to C.MMBitmapRef -func ToMMBitmapRef(bit CBitmap) C.MMBitmapRef { - return C.MMBitmapRef(bit) -} - // TostringBitmap tostring bitmap to string func TostringBitmap(bit C.MMBitmapRef) string { strBit := C.tostring_bitmap(bit) @@ -99,17 +93,6 @@ func TocharBitmap(bit C.MMBitmapRef) *C.char { return strBit } -// ToImage convert C.MMBitmapRef to standard image.Image -func ToImage(bit C.MMBitmapRef) image.Image { - return ToRGBA(bit) -} - -// ToRGBA convert C.MMBitmapRef to standard image.RGBA -func ToRGBA(bit C.MMBitmapRef) *image.RGBA { - bmp1 := ToBitmap(bit) - return ToRGBAGo(bmp1) -} - func internalFindBitmap(bit, sbit C.MMBitmapRef, tolerance float64) (int, int) { pos := C.find_bitmap(bit, sbit, C.float(tolerance)) // fmt.Println("pos----", pos) @@ -337,7 +320,7 @@ func GetPortion(bit C.MMBitmapRef, x, y, w, h int) C.MMBitmapRef { // Convert convert the bitmap // // robotgo.Convert(opath, spath string, type int) -func Convert(opath, spath string, args ...int) { +func Convert(opath, spath string, args ...int) string { var mtype = 1 if len(args) > 0 { mtype = args[0] @@ -346,13 +329,7 @@ func Convert(opath, spath string, args ...int) { // C.CString() bitmap := OpenBitmap(opath) // fmt.Println("a----", bit_map) - SaveBitmap(bitmap, spath, mtype) -} - -// FreeBitmap free and dealloc the C bitmap -func FreeBitmap(bitmap C.MMBitmapRef) { - // C.destroyMMBitmap(bitmap) - C.bitmap_dealloc(bitmap) + return SaveBitmap(bitmap, spath, mtype) } // FreeBitmapArr free and dealloc the C bitmap array diff --git a/bitmap/goBitmap.h b/bitmap/goBitmap.h index 429fa397..0a205c39 100644 --- a/bitmap/goBitmap.h +++ b/bitmap/goBitmap.h @@ -26,12 +26,12 @@ bool bitmap_ready(MMBitmapRef bitmap){ return true; } -void bitmap_dealloc(MMBitmapRef bitmap){ - if (bitmap != NULL) { - destroyMMBitmap(bitmap); - bitmap = NULL; - } -} +// void bitmap_dealloc(MMBitmapRef bitmap){ +// if (bitmap != NULL) { +// destroyMMBitmap(bitmap); +// bitmap = NULL; +// } +// } bool bitmap_copy_to_pboard(MMBitmapRef bitmap){ MMPasteError err; diff --git a/cmd/color-pos/main.go b/cmd/color-pos/main.go index 4383a45b..b4ec4f95 100644 --- a/cmd/color-pos/main.go +++ b/cmd/color-pos/main.go @@ -7,6 +7,7 @@ import ( ) func colorPicker() { + // click the left mouse button to get the value m := robotgo.AddEvent("mleft") if m { x, y := robotgo.GetMousePos() diff --git a/robotgo.go b/robotgo.go index f22a7cc7..22387cbd 100644 --- a/robotgo.go +++ b/robotgo.go @@ -371,12 +371,35 @@ func CaptureImg(args ...int) image.Image { return ToImage(bit) } -// SaveCapture capture screen and save -func SaveCapture(spath string, args ...int) { - bit := CaptureScreen(args...) +// FreeBitmap free and dealloc the C bitmap +func FreeBitmap(bitmap C.MMBitmapRef) { + // C.destroyMMBitmap(bitmap) + C.bitmap_dealloc(bitmap) +} + +// ToBitmap trans C.MMBitmapRef to Bitmap +func ToBitmap(bit C.MMBitmapRef) Bitmap { + bitmap := Bitmap{ + ImgBuf: (*uint8)(bit.imageBuffer), + Width: int(bit.width), + Height: int(bit.height), + Bytewidth: int(bit.bytewidth), + BitsPixel: uint8(bit.bitsPerPixel), + BytesPerPixel: uint8(bit.bytesPerPixel), + } + + return bitmap +} + +// ToImage convert C.MMBitmapRef to standard image.Image +func ToImage(bit C.MMBitmapRef) image.Image { + return ToRGBA(bit) +} - SaveBitmap(bit, spath) - FreeBitmap(bit) +// ToRGBA convert C.MMBitmapRef to standard image.RGBA +func ToRGBA(bit C.MMBitmapRef) *image.RGBA { + bmp1 := ToBitmap(bit) + return ToRGBAGo(bmp1) } /* diff --git a/screen/goScreen.h b/screen/goScreen.h index b2d64714..dd22a100 100644 --- a/screen/goScreen.h +++ b/screen/goScreen.h @@ -95,6 +95,13 @@ char* get_XDisplay_name(){ #endif } +void bitmap_dealloc(MMBitmapRef bitmap){ + if (bitmap != NULL) { + destroyMMBitmap(bitmap); + bitmap = NULL; + } +} + // capture_screen capture screen MMBitmapRef capture_screen(int32_t x, int32_t y, int32_t w, int32_t h){ // if () { From 1de0de6dca90f049cfecb299c85c6f4a81e67d13 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 7 Nov 2021 16:16:32 -0400 Subject: [PATCH 122/327] Update key docs --- docs/keys.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/keys.md b/docs/keys.md index fcfe3f62..27528336 100644 --- a/docs/keys.md +++ b/docs/keys.md @@ -100,18 +100,18 @@ "num_enter" "num_equal" - // "numpad_0" No Linux support - "numpad_0" - "numpad_1" - "numpad_2" - "numpad_3" - "numpad_4" - "numpad_5" - "numpad_6" - "numpad_7" - "numpad_8" - "numpad_9" - "numpad_lock" + // // "numpad_0" No Linux support + // "numpad_0" + // "numpad_1" + // "numpad_2" + // "numpad_3" + // "numpad_4" + // "numpad_5" + // "numpad_6" + // "numpad_7" + // "numpad_8" + // "numpad_9" + // "numpad_lock" "lights_mon_up" Turn up monitor brightness No Windows support "lights_mon_down" Turn down monitor brightness No Windows support From 3c8efddb74324c6d01b6d48701e936645f3f51a3 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 7 Nov 2021 16:24:54 -0400 Subject: [PATCH 123/327] add KeyTap() special key support --- keycode.go | 35 ++++++++++++++++++++++++++++++++--- robotgo.go | 7 +++++++ 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/keycode.go b/keycode.go index 4ec2d3b3..acc90bec 100644 --- a/keycode.go +++ b/keycode.go @@ -38,6 +38,7 @@ var Keycode = uMap{ "0": 11, "-": 12, "=": 13, + // "_": 12, "+": 13, // @@ -53,10 +54,11 @@ var Keycode = uMap{ "p": 25, "[": 26, "]": 27, - "{": 26, - "}": 27, "\\": 43, - "|": 43, + // + "{": 26, + "}": 27, + "|": 43, // "a": 30, "s": 31, @@ -69,6 +71,7 @@ var Keycode = uMap{ "l": 38, ";": 39, "'": 40, + // ":": 39, `"`: 40, // @@ -82,6 +85,7 @@ var Keycode = uMap{ ",": 51, ".": 52, "/": 53, + // "<": 51, ">": 52, "?": 53, @@ -120,3 +124,28 @@ var Keycode = uMap{ "left": 57419, "right": 57421, } + +// Special is the special key map +var Special = map[string]string{ + "~": "`", + "!": "1", + "@": "2", + "#": "3", + "$": "4", + "%": "5", + "^": "6", + "&": "7", + "*": "8", + "(": "9", + ")": "0", + "_": "-", + "+": "=", + "{": "[", + "}": "]", + "|": "\\", + ":": ";", + `"`: "'", + "<": ",", + ">": ".", + "?": "/", +} diff --git a/robotgo.go b/robotgo.go index 22387cbd..6d649b48 100644 --- a/robotgo.go +++ b/robotgo.go @@ -659,6 +659,13 @@ func KeyTap(tapKey string, args ...interface{}) string { keyDelay = 10 ) + if _, ok := Special[tapKey]; ok { + tapKey = Special[tapKey] + if len(args) <= 0 { + args = append(args, "shift") + } + } + // var ckeyArr []*C.char ckeyArr := make([](*C.char), 0) // zkey := C.CString(args[0]) From 19936348de261e1380fc51e7925b500b5da11ec9 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 8 Nov 2021 10:45:38 -0400 Subject: [PATCH 124/327] add KeyToggle() special key and default value support and Update godoc --- cmd/color-pos/main.go | 2 +- key/goKey.h | 19 ++++++++++--------- robotgo.go | 29 ++++++++++++++++++++++++++++- 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/cmd/color-pos/main.go b/cmd/color-pos/main.go index b4ec4f95..64e4dcb1 100644 --- a/cmd/color-pos/main.go +++ b/cmd/color-pos/main.go @@ -27,7 +27,7 @@ func colorPicker() { func main() { fmt.Println("color picker: ") - + fmt.Println("click the left mouse button to get the value.") for { colorPicker() } diff --git a/key/goKey.h b/key/goKey.h index 031162f0..29dfa310 100644 --- a/key/goKey.h +++ b/key/goKey.h @@ -108,15 +108,7 @@ struct KeyNames{ { "num9", K_NUMPAD_9 }, { "num_lock", K_NUMPAD_LOCK }, - {"num.", K_NUMPAD_DECIMAL }, - {"num+", K_NUMPAD_PLUS }, - {"num-", K_NUMPAD_MINUS }, - {"num*", K_NUMPAD_MUL }, - {"num/", K_NUMPAD_DIV }, - {"num_clear", K_NUMPAD_CLEAR }, - {"num_enter", K_NUMPAD_ENTER }, - {"num_equal", K_NUMPAD_EQUAL }, - + // todo: removed { "numpad_0", K_NUMPAD_0 }, { "numpad_1", K_NUMPAD_1 }, { "numpad_2", K_NUMPAD_2 }, @@ -129,6 +121,15 @@ struct KeyNames{ { "numpad_9", K_NUMPAD_9 }, { "numpad_lock", K_NUMPAD_LOCK }, + {"num.", K_NUMPAD_DECIMAL }, + {"num+", K_NUMPAD_PLUS }, + {"num-", K_NUMPAD_MINUS }, + {"num*", K_NUMPAD_MUL }, + {"num/", K_NUMPAD_DIV }, + {"num_clear", K_NUMPAD_CLEAR }, + {"num_enter", K_NUMPAD_ENTER }, + {"num_equal", K_NUMPAD_EQUAL }, + { "lights_mon_up", K_LIGHTS_MON_UP }, { "lights_mon_down", K_LIGHTS_MON_DOWN }, { "lights_kbd_toggle",K_LIGHTS_KBD_TOGGLE }, diff --git a/robotgo.go b/robotgo.go index 6d649b48..cc6f257b 100644 --- a/robotgo.go +++ b/robotgo.go @@ -650,6 +650,13 @@ func SetMouseDelay(delay int) { // See keys: // https://github.com/go-vgo/robotgo/blob/master/docs/keys.md // +// Examples: +// robotgo.KeyTap("a") +// robotgo.KeyTap("i", "alt", "command") +// +// arr := []string{"alt", "command"} +// robotgo.KeyTap("i", arr) +// func KeyTap(tapKey string, args ...interface{}) string { var ( akey string @@ -672,6 +679,7 @@ func KeyTap(tapKey string, args ...interface{}) string { zkey := C.CString(tapKey) defer C.free(unsafe.Pointer(zkey)) + // args not key delay if len(args) > 2 && (reflect.TypeOf(args[2]) != reflect.TypeOf(num)) { num = len(args) for i := 0; i < num; i++ { @@ -685,6 +693,7 @@ func KeyTap(tapKey string, args ...interface{}) string { return C.GoString(str) } + // key delay if len(args) > 0 { if reflect.TypeOf(args[0]) == reflect.TypeOf(keyArr) { @@ -736,12 +745,29 @@ func KeyTap(tapKey string, args ...interface{}) string { return C.GoString(str) } -// KeyToggle toggle the keyboard +// KeyToggle toggle the keyboard, if there not have args default is "down" // // See keys: // https://github.com/go-vgo/robotgo/blob/master/docs/keys.md // +// Examples: +// robotgo.KeyToggle("a") +// robotgo.KeyToggle("a", "up") +// +// robotgo.KeyToggle("a", "up", "alt", "cmd") +// func KeyToggle(key string, args ...string) string { + if len(args) <= 0 { + args = append(args, "down") + } + + if _, ok := Special[key]; ok { + key = Special[key] + if len(args) <= 1 { + args = append(args, "shift") + } + } + ckey := C.CString(key) defer C.free(unsafe.Pointer(ckey)) @@ -757,6 +783,7 @@ func KeyToggle(key string, args ...string) string { return C.GoString(str) } + // use key_toggle() var ( down, mKey, mKeyT = "null", "null", "null" // keyDelay = 10 From 19e5617166783aff49d1c0b00dedff6c629fc6e2 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 8 Nov 2021 11:15:06 -0400 Subject: [PATCH 125/327] remove KeyTap() legacy key delay default value and Update godoc --- bitmap.go | 2 ++ robotgo.go | 22 +++++++++++++++++----- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/bitmap.go b/bitmap.go index ca300bc0..ef3e8a46 100644 --- a/bitmap.go +++ b/bitmap.go @@ -355,6 +355,8 @@ func CopyBitPB(bitmap C.MMBitmapRef) bool { } // Deprecated: CopyBitpb copy bitmap to pasteboard, Wno-deprecated +// +// This function will be removed in version v1.0.0 func CopyBitpb(bitmap C.MMBitmapRef) bool { tt.Drop("CopyBitpb", "CopyBitPB") return CopyBitPB(bitmap) diff --git a/robotgo.go b/robotgo.go index cc6f257b..028cafb7 100644 --- a/robotgo.go +++ b/robotgo.go @@ -663,7 +663,7 @@ func KeyTap(tapKey string, args ...interface{}) string { keyT = "null" keyArr []string num int - keyDelay = 10 + keyDelay int // This is legacy and drop option, use robotgo.KeySleep ) if _, ok := Special[tapKey]; ok { @@ -891,7 +891,11 @@ func inputUTF(str string) { // TypeStr send a string, support UTF-8 // -// robotgo.TypeStr(string: The string to send, float64: microsleep time, x11) +// robotgo.TypeStr(string: The string to send, float64: microsleep time, x11 option) +// +// Examples: +// robotgo.TypeStr("abc@123, hi, こんにちは") +// func TypeStr(str string, args ...float64) { var tm, tm1 = 0.0, 7.0 @@ -931,7 +935,8 @@ func TypeStr(str string, args ...float64) { MilliSleep(KeySleep) } -// PasteStr paste a string, support UTF-8 +// PasteStr paste a string, support UTF-8, +// write the string to clipboard and tap `cmd + v` func PasteStr(str string) string { err := clipboard.WriteAll(str) if err != nil { @@ -945,8 +950,10 @@ func PasteStr(str string) string { return KeyTap("v", "control") } -// Deprecated: TypeString send a string, support unicode +// Deprecated: TypeString send a string, support unicode(no linux support) // TypeStr(string: The string to send), Wno-deprecated +// +// This function will be removed in version v1.0.0 func TypeString(str string, delay ...int) { tt.Drop("TypeString", "TypeStr") var cdelay C.size_t @@ -967,6 +974,8 @@ func TypeStrDelay(str string, delay int) { } // Deprecated: TypeStringDelayed type string delayed, Wno-deprecated +// +// This function will be removed in version v1.0.0 func TypeStringDelayed(str string, delay int) { tt.Drop("TypeStringDelayed", "TypeStrDelay") TypeStrDelay(str, delay) @@ -978,7 +987,8 @@ func SetKeyDelay(delay int) { } // Deprecated: SetKeyboardDelay set keyboard delay, Wno-deprecated, -// this function will be removed in version v1.0.0 +// +// This function will be removed in version v1.0.0 func SetKeyboardDelay(delay int) { tt.Drop("SetKeyboardDelay", "SetKeyDelay") SetKeyDelay(delay) @@ -1147,6 +1157,8 @@ func GetHandle() int { } // Deprecated: GetBHandle get the window handle, Wno-deprecated +// +// This function will be removed in version v1.0.0 func GetBHandle() int { tt.Drop("GetBHandle", "GetHandle") hwnd := C.bget_handle() From 39e066c5f78347b06846498ad145a23a3f2a083b Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 9 Nov 2021 17:01:01 -0400 Subject: [PATCH 126/327] Fixed windows warning and update godoc --- robotgo.go | 7 +++++-- screen/goScreen.h | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/robotgo.go b/robotgo.go index 028cafb7..da07d888 100644 --- a/robotgo.go +++ b/robotgo.go @@ -444,12 +444,14 @@ func Move(x, y int) { MilliSleep(MouseSleep) } -// DragMouse drag the mouse to (x, y) +// DragMouse drag the mouse to (x, y), +// It's not valid now, use the DragSmooth() func DragMouse(x, y int, args ...string) { Drag(x, y, args...) } -// Drag drag the mouse to (x, y) +// Drag drag the mouse to (x, y), +// It's not valid now, use the DragSmooth() func Drag(x, y int, args ...string) { var button C.MMMouseButton = C.LEFT_BUTTON cx := C.int32_t(x) @@ -466,6 +468,7 @@ func Drag(x, y int, args ...string) { // DragSmooth drag the mouse smooth func DragSmooth(x, y int, args ...interface{}) { MouseToggle("down") + MilliSleep(50) MoveSmooth(x, y, args...) MouseToggle("up") } diff --git a/screen/goScreen.h b/screen/goScreen.h index dd22a100..a983b358 100644 --- a/screen/goScreen.h +++ b/screen/goScreen.h @@ -12,6 +12,7 @@ #include "../base/rgb.h" #include "screengrab_c.h" #include "screen_c.h" +#include // #include "../MMBitmap_c.h" void padHex(MMRGBHex color, char* hex){ From dee7a282a07bc12619942f704793f24f58c2b4eb Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 10 Nov 2021 12:12:29 -0400 Subject: [PATCH 127/327] add more mouse button support and Toggle() function style with KeyToggle() --- mouse/mouse.h | 27 +++++++++++++++++------- robotgo.go | 57 +++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 62 insertions(+), 22 deletions(-) diff --git a/mouse/mouse.h b/mouse/mouse.h index 7dff62a8..ef061c51 100644 --- a/mouse/mouse.h +++ b/mouse/mouse.h @@ -23,10 +23,14 @@ extern "C" #include // #include - typedef enum { + typedef enum { LEFT_BUTTON = kCGMouseButtonLeft, RIGHT_BUTTON = kCGMouseButtonRight, - CENTER_BUTTON = kCGMouseButtonCenter + CENTER_BUTTON = kCGMouseButtonCenter, + WheelDown = 4, + WheelUp = 5, + WheelLeft = 6, + WheelRight = 7, } MMMouseButton; #elif defined(USE_X11) @@ -34,7 +38,11 @@ extern "C" enum _MMMouseButton { LEFT_BUTTON = 1, CENTER_BUTTON = 2, - RIGHT_BUTTON = 3 + RIGHT_BUTTON = 3, + WheelDown = 4, + WheelUp = 5, + WheelLeft = 6, + WheelRight = 7, }; typedef unsigned int MMMouseButton; @@ -43,7 +51,11 @@ extern "C" enum _MMMouseButton { LEFT_BUTTON = 1, CENTER_BUTTON = 2, - RIGHT_BUTTON = 3 + RIGHT_BUTTON = 3, + WheelDown = 4, + WheelUp = 5, + WheelLeft = 6, + WheelRight = 7, }; typedef unsigned int MMMouseButton; @@ -53,10 +65,11 @@ extern "C" #define MMMouseButtonIsValid(button) \ (button == LEFT_BUTTON || button == RIGHT_BUTTON || \ - button == CENTER_BUTTON) + button == CENTER_BUTTON || button == WheelDown || \ + button == WheelUp || button == WheelLeft || \ + button == WheelRight) -enum __MMMouseWheelDirection -{ +enum __MMMouseWheelDirection { DIRECTION_DOWN = -1, DIRECTION_UP = 1 }; diff --git a/robotgo.go b/robotgo.go index da07d888..8c2cfd10 100644 --- a/robotgo.go +++ b/robotgo.go @@ -415,16 +415,17 @@ func ToRGBA(bit C.MMBitmapRef) *image.RGBA { // CheckMouse check the mouse button func CheckMouse(btn string) C.MMMouseButton { // button = args[0].(C.MMMouseButton) - if btn == "left" { - return C.LEFT_BUTTON + m1 := map[string]C.MMMouseButton{ + "left": C.LEFT_BUTTON, + "center": C.CENTER_BUTTON, + "right": C.RIGHT_BUTTON, + "wheelDown": C.WheelDown, + "wheelUp": C.WheelUp, + "wheelLeft": C.WheelLeft, + "wheelRight": C.WheelRight, } - - if btn == "center" { - return C.CENTER_BUTTON - } - - if btn == "right" { - return C.RIGHT_BUTTON + if v, ok := m1[btn]; ok { + return v } return C.LEFT_BUTTON @@ -445,9 +446,13 @@ func Move(x, y int) { } // DragMouse drag the mouse to (x, y), -// It's not valid now, use the DragSmooth() -func DragMouse(x, y int, args ...string) { - Drag(x, y, args...) +// It's same with the DragSmooth() now +func DragMouse(x, y int, args ...interface{}) { + Toggle("left") + MilliSleep(50) + // Drag(x, y, args...) + MoveSmooth(x, y, args...) + Toggle("left", "up") } // Drag drag the mouse to (x, y), @@ -465,12 +470,12 @@ func Drag(x, y int, args ...string) { MilliSleep(MouseSleep) } -// DragSmooth drag the mouse smooth +// DragSmooth drag the mouse like smooth to (x, y) func DragSmooth(x, y int, args ...interface{}) { - MouseToggle("down") + Toggle("left") MilliSleep(50) MoveSmooth(x, y, args...) - MouseToggle("up") + Toggle("left", "up") } // MoveMouseSmooth move the mouse smooth, @@ -583,6 +588,28 @@ func MovesClick(x, y int, args ...interface{}) { MouseClick(args...) } +// Toggle toggle the mose, support: "left", "center", "right", +// "wheelDown", "wheelUp", "wheelLeft", "wheelRight" +// +// Examples: +// robotgo.Toggle("left", "up") +// robotgo.Toggle("left") // default is down +func Toggle(key ...string) int { + var button C.MMMouseButton = C.LEFT_BUTTON + if len(key) > 0 { + button = CheckMouse(key[0]) + } + down := C.CString("down") + if len(key) > 1 { + down = C.CString(key[1]) + } + + i := C.mouse_toggle(down, button) + C.free(unsafe.Pointer(down)) + MilliSleep(MouseSleep) + return int(i) +} + // MouseToggle toggle the mouse func MouseToggle(togKey string, args ...interface{}) int { var button C.MMMouseButton = C.LEFT_BUTTON From 6daec240271b8872d08b7aebac372ddf9ca61346 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 10 Nov 2021 12:49:23 -0400 Subject: [PATCH 128/327] Update godoc --- robotgo.go | 66 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 50 insertions(+), 16 deletions(-) diff --git a/robotgo.go b/robotgo.go index 8c2cfd10..5caeb9bc 100644 --- a/robotgo.go +++ b/robotgo.go @@ -437,6 +437,10 @@ func MoveMouse(x, y int) { } // Move move the mouse to (x, y) +// +// Examples: +// robotgo.MouseSleep = 100 // 100 millisecond +// robotgo.Move(10, 10) func Move(x, y int) { cx := C.int32_t(x) cy := C.int32_t(y) @@ -471,6 +475,9 @@ func Drag(x, y int, args ...string) { } // DragSmooth drag the mouse like smooth to (x, y) +// +// Examples: +// robotgo.DragSmooth(10, 10) func DragSmooth(x, y int, args ...interface{}) { Toggle("left") MilliSleep(50) @@ -488,6 +495,10 @@ func MoveMouseSmooth(x, y int, args ...interface{}) bool { // moves mouse to x, y human like, with the mouse button up. // // robotgo.MoveSmooth(x, y int, low, high float64, mouseDelay int) +// +// Examples: +// robotgo.MoveSmooth(10, 10) +// robotgo.MoveSmooth(10, 10, 1.0, 2.0) func MoveSmooth(x, y int, args ...interface{}) bool { cx := C.int32_t(x) cy := C.int32_t(y) @@ -516,7 +527,7 @@ func MoveSmooth(x, y int, args ...interface{}) bool { return bool(cbool) } -// MoveArgs move mouse relative args +// MoveArgs get the mouse relative args func MoveArgs(x, y int) (int, int) { mx, my := GetMousePos() mx = mx + x @@ -536,7 +547,7 @@ func MoveSmoothRelative(x, y int, args ...interface{}) { MoveSmooth(mx, my, args...) } -// GetMousePos get mouse's portion +// GetMousePos get mouse's portion return x, y func GetMousePos() (int, int) { pos := C.get_mouse_pos() @@ -553,9 +564,14 @@ func MouseClick(args ...interface{}) { Click(args...) } -// Click click the mouse +// Click click the mouse button // // robotgo.Click(button string, double bool) +// +// Examples: +// robotgo.Click() // default is left button +// robotgo.Click("right") +// robotgo.Click("wheelLeft") func Click(args ...interface{}) { var ( button C.MMMouseButton = C.LEFT_BUTTON @@ -588,12 +604,12 @@ func MovesClick(x, y int, args ...interface{}) { MouseClick(args...) } -// Toggle toggle the mose, support: "left", "center", "right", +// Toggle toggle the mouse, support button: "left", "center", "right", // "wheelDown", "wheelUp", "wheelLeft", "wheelRight" // // Examples: -// robotgo.Toggle("left", "up") -// robotgo.Toggle("left") // default is down +// robotgo.Toggle("left") // default is down +// robotgo.Toggle("left", "up") func Toggle(key ...string) int { var button C.MMMouseButton = C.LEFT_BUTTON if len(key) > 0 { @@ -611,6 +627,10 @@ func Toggle(key ...string) int { } // MouseToggle toggle the mouse +// +// Examples: +// robotgo.MouseToggle("down", "right") +// robotgo.MouseToggle("up", "right") func MouseToggle(togKey string, args ...interface{}) int { var button C.MMMouseButton = C.LEFT_BUTTON @@ -626,7 +646,11 @@ func MouseToggle(togKey string, args ...interface{}) int { return int(i) } -// ScrollMouse scroll the mouse +// ScrollMouse scroll the mouse to (x, "up") +// +// Examples: +// robotgo.ScrollMouse(10, "down") +// robotgo.ScrollMouse(10, "up") func ScrollMouse(x int, direction string) { cx := C.size_t(x) cy := C.CString(direction) @@ -639,6 +663,9 @@ func ScrollMouse(x int, direction string) { // Scroll scroll the mouse to (x, y) // // robotgo.Scroll(x, y, msDelay int) +// +// Examples: +// robotgo.Scroll(10, 10) func Scroll(x, y int, args ...int) { var msDelay = 10 if len(args) > 0 { @@ -654,6 +681,9 @@ func Scroll(x, y int, args ...int) { } // ScrollRelative scroll mouse with relative +// +// Examples: +// robotgo.ScrollRelative(10, 10) func ScrollRelative(x, y int, args ...int) { mx, my := MoveArgs(x, y) Scroll(mx, my, args...) @@ -681,11 +711,12 @@ func SetMouseDelay(delay int) { // https://github.com/go-vgo/robotgo/blob/master/docs/keys.md // // Examples: -// robotgo.KeyTap("a") -// robotgo.KeyTap("i", "alt", "command") +// robotgo.KeySleep = 100 // 100 millisecond +// robotgo.KeyTap("a") +// robotgo.KeyTap("i", "alt", "command") // -// arr := []string{"alt", "command"} -// robotgo.KeyTap("i", arr) +// arr := []string{"alt", "command"} +// robotgo.KeyTap("i", arr) // func KeyTap(tapKey string, args ...interface{}) string { var ( @@ -781,10 +812,10 @@ func KeyTap(tapKey string, args ...interface{}) string { // https://github.com/go-vgo/robotgo/blob/master/docs/keys.md // // Examples: -// robotgo.KeyToggle("a") -// robotgo.KeyToggle("a", "up") +// robotgo.KeyToggle("a") +// robotgo.KeyToggle("a", "up") // -// robotgo.KeyToggle("a", "up", "alt", "cmd") +// robotgo.KeyToggle("a", "up", "alt", "cmd") // func KeyToggle(key string, args ...string) string { if len(args) <= 0 { @@ -924,7 +955,7 @@ func inputUTF(str string) { // robotgo.TypeStr(string: The string to send, float64: microsleep time, x11 option) // // Examples: -// robotgo.TypeStr("abc@123, hi, こんにちは") +// robotgo.TypeStr("abc@123, hi, こんにちは") // func TypeStr(str string, args ...float64) { var tm, tm1 = 0.0, 7.0 @@ -1252,7 +1283,10 @@ func internalActive(pid int32, hwnd int) { // C.active_PID(C.uintptr(pid), C.uintptr(hwnd)) // } -// ActiveName active window by name +// ActiveName active the window by name +// +// Examples: +// robotgo.ActiveName("chrome") func ActiveName(name string) error { pids, err := FindIds(name) if err == nil && len(pids) > 0 { From 6fd41b9a7c33292caad6114a11c31c671eec56f9 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sat, 13 Nov 2021 15:22:50 -0400 Subject: [PATCH 129/327] add ScrollSmooth() support and Update godoc --- robotgo.go | 67 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 56 insertions(+), 11 deletions(-) diff --git a/robotgo.go b/robotgo.go index 5caeb9bc..eebf90f8 100644 --- a/robotgo.go +++ b/robotgo.go @@ -569,7 +569,7 @@ func MouseClick(args ...interface{}) { // robotgo.Click(button string, double bool) // // Examples: -// robotgo.Click() // default is left button +// robotgo.Click() // default is left button // robotgo.Click("right") // robotgo.Click("wheelLeft") func Click(args ...interface{}) { @@ -680,6 +680,40 @@ func Scroll(x, y int, args ...int) { MilliSleep(MouseSleep) } +// ScrollSmooth scroll the mouse smooth, +// default scroll 5 times and sleep 100 millisecond +// +// robotgo.ScrollSmooth(toy, num, sleep, tox) +// +// Examples: +// robotgo.ScrollSmooth(-10) +// robotgo.ScrollSmooth(-10, 6, 200, -10) +func ScrollSmooth(to int, args ...int) { + i := 0 + num := 5 + if len(args) > 0 { + num = args[0] + } + tm := 100 + if len(args) > 1 { + tm = args[1] + } + tox := 0 + if len(args) > 2 { + tox = args[2] + } + + for { + Scroll(tox, to) + MilliSleep(tm) + i++ + if i == num { + break + } + } + MilliSleep(MouseSleep) +} + // ScrollRelative scroll mouse with relative // // Examples: @@ -711,12 +745,12 @@ func SetMouseDelay(delay int) { // https://github.com/go-vgo/robotgo/blob/master/docs/keys.md // // Examples: -// robotgo.KeySleep = 100 // 100 millisecond +// robotgo.KeySleep = 100 // 100 millisecond // robotgo.KeyTap("a") -// robotgo.KeyTap("i", "alt", "command") +// robotgo.KeyTap("i", "alt", "command") // -// arr := []string{"alt", "command"} -// robotgo.KeyTap("i", arr) +// arr := []string{"alt", "command"} +// robotgo.KeyTap("i", arr) // func KeyTap(tapKey string, args ...interface{}) string { var ( @@ -812,10 +846,10 @@ func KeyTap(tapKey string, args ...interface{}) string { // https://github.com/go-vgo/robotgo/blob/master/docs/keys.md // // Examples: -// robotgo.KeyToggle("a") -// robotgo.KeyToggle("a", "up") +// robotgo.KeyToggle("a") +// robotgo.KeyToggle("a", "up") // -// robotgo.KeyToggle("a", "up", "alt", "cmd") +// robotgo.KeyToggle("a", "up", "alt", "cmd") // func KeyToggle(key string, args ...string) string { if len(args) <= 0 { @@ -955,7 +989,7 @@ func inputUTF(str string) { // robotgo.TypeStr(string: The string to send, float64: microsleep time, x11 option) // // Examples: -// robotgo.TypeStr("abc@123, hi, こんにちは") +// robotgo.TypeStr("abc@123, hi, こんにちは") // func TypeStr(str string, args ...float64) { var tm, tm1 = 0.0, 7.0 @@ -1077,6 +1111,11 @@ ____ __ ____ __ .__ __. _______ ______ ____ __ ____ */ // ShowAlert show a alert window +// Displays alert with the attributes. +// If cancel button is not given, only the default button is displayed +// +// Examples: +// robogo.ShowAlert("hi", "window", "ok", "cancel") func ShowAlert(title, msg string, args ...string) bool { var ( // title string @@ -1235,7 +1274,13 @@ func cgetTitle(hwnd, isHwnd int32) string { return gtitle } -// GetTitle get the window title +// GetTitle get the window title return string +// +// Examples: +// fmt.Println(robogo.GetTitle()) +// +// ids, _ := robogo.FindIds() +// robogo.GetTitle(ids[0]) func GetTitle(args ...int32) string { if len(args) <= 0 { title := C.get_main_title() @@ -1250,7 +1295,7 @@ func GetTitle(args ...int32) string { return internalGetTitle(args[0]) } -// GetPID get the process id +// GetPID get the process id return int32 func GetPID() int32 { pid := C.get_PID() return int32(pid) From c1e28220b5c5159823a20488cb05f84e5603f0d6 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 14 Nov 2021 16:33:30 -0400 Subject: [PATCH 130/327] Fixed window10 get scale error #393 --- robotgo.go | 4 ++-- robotgo_mac.go | 19 +++++++++++++++++++ robotgo_win.go | 28 +++++++++++++++++++++++----- 3 files changed, 44 insertions(+), 7 deletions(-) create mode 100644 robotgo_mac.go diff --git a/robotgo.go b/robotgo.go index eebf90f8..bcc4f6d9 100644 --- a/robotgo.go +++ b/robotgo.go @@ -305,8 +305,8 @@ func Mul(x int) int { // GetScaleSize get the screen scale size func GetScaleSize() (int, int) { x, y := GetScreenSize() - s := Scale() - return x * s / 100, y * s / 100 + f := ScaleF() + return int(float64(x) * f), int(float64(y) * f) } // SetXDisplayName set XDisplay name (Linux) diff --git a/robotgo_mac.go b/robotgo_mac.go new file mode 100644 index 00000000..d01706f4 --- /dev/null +++ b/robotgo_mac.go @@ -0,0 +1,19 @@ +// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// https://github.com/go-vgo/robotgo/blob/master/LICENSE +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//go:build !windows +// +build !windows + +package robotgo + +// ScaleF get the system scale val +func ScaleF() float64 { + return SysScale() +} diff --git a/robotgo_win.go b/robotgo_win.go index 46a3808a..ba7bb58e 100644 --- a/robotgo_win.go +++ b/robotgo_win.go @@ -21,16 +21,14 @@ import ( ) // FindWindow find window hwnd by name -func FindWindow(str string) win.HWND { - hwnd := win.FindWindow(nil, syscall.StringToUTF16Ptr(str)) - +func FindWindow(name string) win.HWND { + hwnd := win.FindWindow(nil, syscall.StringToUTF16Ptr(name)) return hwnd } // GetHWND get foreground window hwnd func GetHWND() win.HWND { hwnd := win.GetForegroundWindow() - return hwnd } @@ -50,6 +48,26 @@ func SetActiveWindow(hwnd win.HWND) win.HWND { } // SetFocus set window focus with hwnd -func SetFocus(hWnd win.HWND) win.HWND { +func SetFocus(hwnd win.HWND) win.HWND { return win.SetFocus(hWnd) } + +// ScaleF get the system scale val +func ScaleF() float64 { + return float64(GetMainDPI()) / 96.0 +} + +// GetMainDPI get the display dpi +func GetMainDPI() int { + return int(GetDPI(GetHWND())) +} + +// GetDPI get the window dpi +func GetDPI(hwnd win.HWND) uint32 { + return win.GetDpiForWindow(hwnd) +} + +// GetSysDPI get the system metrics dpi +func GetSysDPI(idx int32, dpi uint32) int32 { + return win.GetSystemMetricsForDpi(idex, dpi) +} From 0a69ed90af23e175c4099d0c571ea1799961531c Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 14 Nov 2021 16:36:48 -0400 Subject: [PATCH 131/327] fixed typo error --- robotgo_win.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/robotgo_win.go b/robotgo_win.go index ba7bb58e..a7abba8d 100644 --- a/robotgo_win.go +++ b/robotgo_win.go @@ -49,7 +49,7 @@ func SetActiveWindow(hwnd win.HWND) win.HWND { // SetFocus set window focus with hwnd func SetFocus(hwnd win.HWND) win.HWND { - return win.SetFocus(hWnd) + return win.SetFocus(hwnd) } // ScaleF get the system scale val @@ -69,5 +69,5 @@ func GetDPI(hwnd win.HWND) uint32 { // GetSysDPI get the system metrics dpi func GetSysDPI(idx int32, dpi uint32) int32 { - return win.GetSystemMetricsForDpi(idex, dpi) + return win.GetSystemMetricsForDpi(idx, dpi) } From e433e36e8aa190fcd73455731d3389cf154a0253 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 15 Nov 2021 18:22:54 -0400 Subject: [PATCH 132/327] Update CaptureScreen() use the scaled and some code --- robotgo.go | 151 +++++++++++++++++++++++------------------------ window/win_sys.h | 19 +++--- 2 files changed, 85 insertions(+), 85 deletions(-) diff --git a/robotgo.go b/robotgo.go index bcc4f6d9..e7fb44c7 100644 --- a/robotgo.go +++ b/robotgo.go @@ -221,25 +221,15 @@ func GetMouseColor() string { return GetPixelColor(x, y) } -// ScaleX get the primary display horizontal DPI scale factor -func ScaleX() int { - return int(C.scale_x()) -} - -// SysScale get the sys scale +// SysScale get the sys scale (x11 todo) func SysScale() float64 { s := C.sys_scale() return float64(s) } -// Scaled return x * sys_scale +// Scaled get the screen scaled size func Scaled(x int) int { - return int(float64(x) * SysScale()) -} - -// ScaleY get primary display vertical DPI scale factor -func ScaleY() int { - return int(C.scale_y()) + return int(float64(x) * ScaleF()) } // GetScreenSize get the screen size @@ -259,49 +249,16 @@ func GetScreenRect(displayId ...int) Rect { rect := C.getScreenRect(C.int32_t(display)) return Rect{ Point{ - X: int(rect.origin.x), - Y: int(rect.origin.y), + X: Scaled(int(rect.origin.x)), + Y: Scaled(int(rect.origin.y)), }, Size{ - W: int(rect.size.w), - H: int(rect.size.h), + W: Scaled(int(rect.size.w)), + H: Scaled(int(rect.size.h)), }, } } -// Scale get the screen scale -func Scale() int { - dpi := map[int]int{ - 0: 100, - // DPI Scaling Level - 96: 100, - 120: 125, - 144: 150, - 168: 175, - 192: 200, - 216: 225, - // Custom DPI - 240: 250, - 288: 300, - 384: 400, - 480: 500, - } - - x := ScaleX() - return dpi[x] -} - -// Scale0 return ScaleX() / 0.96 -func Scale0() int { - return int(float64(ScaleX()) / 0.96) -} - -// Mul mul the scale -func Mul(x int) int { - s := Scale() - return x * s / 100 -} - // GetScaleSize get the screen scale size func GetScaleSize() (int, int) { x, y := GetScreenSize() @@ -309,26 +266,6 @@ func GetScaleSize() (int, int) { return int(float64(x) * f), int(float64(y) * f) } -// SetXDisplayName set XDisplay name (Linux) -func SetXDisplayName(name string) string { - cname := C.CString(name) - str := C.set_XDisplay_name(cname) - - gstr := C.GoString(str) - C.free(unsafe.Pointer(cname)) - - return gstr -} - -// GetXDisplayName get XDisplay name (Linux) -func GetXDisplayName() string { - name := C.get_XDisplay_name() - gname := C.GoString(name) - C.free(unsafe.Pointer(name)) - - return gname -} - // CaptureScreen capture the screen return bitmap(c struct), // use `defer robotgo.FreeBitmap(bitmap)` to free the bitmap // @@ -342,13 +279,12 @@ func CaptureScreen(args ...int) C.MMBitmapRef { w = C.int32_t(args[2]) h = C.int32_t(args[3]) } else { - x = 0 - y = 0 + rect := GetScreenRect() - // Get the main screen size. - displaySize := C.getMainDisplaySize() - w = displaySize.w - h = displaySize.h + x = C.int32_t(rect.X) + y = C.int32_t(rect.Y) + w = C.int32_t(rect.W) + h = C.int32_t(rect.H) } bit := C.capture_screen(x, y, w, h) @@ -402,6 +338,69 @@ func ToRGBA(bit C.MMBitmapRef) *image.RGBA { return ToRGBAGo(bmp1) } +// SetXDisplayName set XDisplay name (Linux) +func SetXDisplayName(name string) string { + cname := C.CString(name) + str := C.set_XDisplay_name(cname) + + gstr := C.GoString(str) + C.free(unsafe.Pointer(cname)) + + return gstr +} + +// GetXDisplayName get XDisplay name (Linux) +func GetXDisplayName() string { + name := C.get_XDisplay_name() + gname := C.GoString(name) + C.free(unsafe.Pointer(name)) + + return gname +} + +// ScaleX get the primary display horizontal DPI scale factor, drop +func ScaleX() int { + return int(C.scale_x()) +} + +// ScaleY get primary display vertical DPI scale factor, drop +func ScaleY() int { + return int(C.scale_y()) +} + +// Scale get the screen scale (only windows old), drop +func Scale() int { + dpi := map[int]int{ + 0: 100, + // DPI Scaling Level + 96: 100, + 120: 125, + 144: 150, + 168: 175, + 192: 200, + 216: 225, + // Custom DPI + 240: 250, + 288: 300, + 384: 400, + 480: 500, + } + + x := ScaleX() + return dpi[x] +} + +// Scale0 return ScaleX() / 0.96, drop +func Scale0() int { + return int(float64(ScaleX()) / 0.96) +} + +// Mul mul the scale, drop +func Mul(x int) int { + s := Scale() + return x * s / 100 +} + /* .___ ___. ______ __ __ _______. _______ | \/ | / __ \ | | | | / || ____| diff --git a/window/win_sys.h b/window/win_sys.h index 4795d770..317f5bc1 100644 --- a/window/win_sys.h +++ b/window/win_sys.h @@ -39,19 +39,20 @@ double sys_scale() { return pixelWidth / targetWidth; #elif defined(USE_X11) - double xres; - Display *dpy; + // double xres; + // Display *dpy; - char *displayname = NULL; - int scr = 0; /* Screen number */ + // char *displayname = NULL; + // int scr = 0; /* Screen number */ - dpy = XOpenDisplay (displayname); - xres = ((((double) DisplayWidth(dpy, scr)) * 25.4) / - ((double) DisplayWidthMM(dpy, scr))); + // dpy = XOpenDisplay (displayname); + // xres = ((((double) DisplayWidth(dpy, scr)) * 25.4) / + // ((double) DisplayWidthMM(dpy, scr))); - XCloseDisplay (dpy); + // XCloseDisplay (dpy); - return xres + 0.5; + // return xres / 96.0; + return 1.0; #elif defined(IS_WINDOWS) double s = scaleX() / 96.0; return s; From faeb2b1e20a6fdff25df882d5f795b3cc9e29af2 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 16 Nov 2021 16:07:06 -0400 Subject: [PATCH 133/327] add Linux high DPI support and only windows use scaled() --- robotgo.go | 26 ++++++++++++++++---------- robotgo_mac.go | 6 +++++- robotgo_win.go | 6 +++++- window/win_sys.h | 46 ++++++++++++++++++++++++++++++++-------------- 4 files changed, 58 insertions(+), 26 deletions(-) diff --git a/robotgo.go b/robotgo.go index e7fb44c7..d73210cb 100644 --- a/robotgo.go +++ b/robotgo.go @@ -221,7 +221,7 @@ func GetMouseColor() string { return GetPixelColor(x, y) } -// SysScale get the sys scale (x11 todo) +// SysScale get the sys scale func SysScale() float64 { s := C.sys_scale() return float64(s) @@ -229,7 +229,12 @@ func SysScale() float64 { // Scaled get the screen scaled size func Scaled(x int) int { - return int(float64(x) * ScaleF()) + return Scaled0(x, ScaleF()) +} + +// Scaled0 return int(x * f) +func Scaled0(x int, f float64) int { + return int(float64(x) * f) } // GetScreenSize get the screen size @@ -247,15 +252,16 @@ func GetScreenRect(displayId ...int) Rect { } rect := C.getScreenRect(C.int32_t(display)) + x, y, w, h := int(rect.origin.x), int(rect.origin.y), + int(rect.size.w), int(rect.size.h) + + if runtime.GOOS == "windows" { + f := ScaleF() + x, y, w, h = Scaled0(x, f), Scaled0(y, f), Scaled0(w, f), Scaled0(h, f) + } return Rect{ - Point{ - X: Scaled(int(rect.origin.x)), - Y: Scaled(int(rect.origin.y)), - }, - Size{ - W: Scaled(int(rect.size.w)), - H: Scaled(int(rect.size.h)), - }, + Point{X: x, Y: y}, + Size{W: w, H: h}, } } diff --git a/robotgo_mac.go b/robotgo_mac.go index d01706f4..365914ba 100644 --- a/robotgo_mac.go +++ b/robotgo_mac.go @@ -15,5 +15,9 @@ package robotgo // ScaleF get the system scale val func ScaleF() float64 { - return SysScale() + f := SysScale() + if f == 0.0 { + f = 1.0 + } + return f } diff --git a/robotgo_win.go b/robotgo_win.go index a7abba8d..38268648 100644 --- a/robotgo_win.go +++ b/robotgo_win.go @@ -54,7 +54,11 @@ func SetFocus(hwnd win.HWND) win.HWND { // ScaleF get the system scale val func ScaleF() float64 { - return float64(GetMainDPI()) / 96.0 + f := float64(GetMainDPI()) / 96.0 + if f == 0.0 { + f = 1.0 + } + return f } // GetMainDPI get the display dpi diff --git a/window/win_sys.h b/window/win_sys.h index 317f5bc1..7d10e96b 100644 --- a/window/win_sys.h +++ b/window/win_sys.h @@ -9,6 +9,11 @@ // except according to those terms. // #include "../base/os.h" +#if defined(USE_X11) + // #include + // #include + #include +#endif Bounds get_client(uintptr pid, uintptr isHwnd); @@ -38,21 +43,34 @@ double sys_scale() { return pixelWidth / targetWidth; #elif defined(USE_X11) - - // double xres; - // Display *dpy; - - // char *displayname = NULL; - // int scr = 0; /* Screen number */ - - // dpy = XOpenDisplay (displayname); - // xres = ((((double) DisplayWidth(dpy, scr)) * 25.4) / - // ((double) DisplayWidthMM(dpy, scr))); - - // XCloseDisplay (dpy); + double xres; + Display *dpy; + + char *displayname = NULL; + int scr = 0; /* Screen number */ + + dpy = XOpenDisplay(displayname); + xres = ((((double) DisplayWidth(dpy, scr)) * 25.4) / + ((double) DisplayWidthMM(dpy, scr))); + + // https://github.com/glfw/glfw/issues/1019#issuecomment-302772498 + char *rms = XResourceManagerString(dpy); + if (rms) { + XrmDatabase db; + XrmValue value; + char *type = NULL; + + XrmInitialize(); /* Need to initialize the DB before calling Xrm* functions */ + db = XrmGetStringDatabase(rms); + if (XrmGetResource(db, "Xft.dpi", "String", &type, &value) == True) { + if (value.addr) { + xres = atof(value.addr); + } + } + } + XCloseDisplay (dpy); - // return xres / 96.0; - return 1.0; + return xres / 96.0; #elif defined(IS_WINDOWS) double s = scaleX() / 96.0; return s; From c99807378f3d367f14d127ff93757d47747b4e05 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 16 Nov 2021 16:35:55 -0400 Subject: [PATCH 134/327] add windows move mouse scaled() support and drop some function --- robotgo.go | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/robotgo.go b/robotgo.go index d73210cb..eff95817 100644 --- a/robotgo.go +++ b/robotgo.go @@ -364,16 +364,19 @@ func GetXDisplayName() string { return gname } +// Deprecated: // ScaleX get the primary display horizontal DPI scale factor, drop func ScaleX() int { return int(C.scale_x()) } +// Deprecated: // ScaleY get primary display vertical DPI scale factor, drop func ScaleY() int { return int(C.scale_y()) } +// Deprecated: // Scale get the screen scale (only windows old), drop func Scale() int { dpi := map[int]int{ @@ -396,11 +399,13 @@ func Scale() int { return dpi[x] } +// Deprecated: // Scale0 return ScaleX() / 0.96, drop func Scale0() int { return int(float64(ScaleX()) / 0.96) } +// Deprecated: // Mul mul the scale, drop func Mul(x int) int { s := Scale() @@ -447,6 +452,11 @@ func MoveMouse(x, y int) { // robotgo.MouseSleep = 100 // 100 millisecond // robotgo.Move(10, 10) func Move(x, y int) { + if runtime.GOOS == "windows" { + f := ScaleF() + x, y = Scaled0(x, f), Scaled0(y, f) + } + cx := C.int32_t(x) cy := C.int32_t(y) C.move_mouse(cx, cy) @@ -505,6 +515,11 @@ func MoveMouseSmooth(x, y int, args ...interface{}) bool { // robotgo.MoveSmooth(10, 10) // robotgo.MoveSmooth(10, 10, 1.0, 2.0) func MoveSmooth(x, y int, args ...interface{}) bool { + if runtime.GOOS == "windows" { + f := ScaleF() + x, y = Scaled0(x, f), Scaled0(y, f) + } + cx := C.int32_t(x) cy := C.int32_t(y) @@ -599,14 +614,14 @@ func Click(args ...interface{}) { // // robotgo.MoveClick(x, y int, button string, double bool) func MoveClick(x, y int, args ...interface{}) { - MoveMouse(x, y) - MouseClick(args...) + Move(x, y) + Click(args...) } // MovesClick move smooth and click the mouse func MovesClick(x, y int, args ...interface{}) { MoveSmooth(x, y) - MouseClick(args...) + Click(args...) } // Toggle toggle the mouse, support button: "left", "center", "right", From 15d5d147bc92398d2363e217af6b5e0a7d01fb08 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 17 Nov 2021 14:16:30 -0400 Subject: [PATCH 135/327] Update README.md --- README.md | 41 ++++++++++++++++++++++++++--------------- README_zh.md | 38 +++++++++++++++++++++++--------------- 2 files changed, 49 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 220a6a95..36eea263 100644 --- a/README.md +++ b/README.md @@ -36,9 +36,10 @@ RobotGo supports Mac, Windows, and Linux(X11); and robotgo supports arm64 and x8 - [License](#license) ## Docs - - [GoDoc](https://godoc.org/github.com/go-vgo/robotgo) - - [API Docs](https://github.com/go-vgo/robotgo/blob/master/docs/doc.md)     - - [Chinese Docs](https://github.com/go-vgo/robotgo/blob/master/docs/doc_zh.md) + - [GoDoc](https://godoc.org/github.com/go-vgo/robotgo)
+ + - [API Docs](https://github.com/go-vgo/robotgo/blob/master/docs/doc.md)     (Deprecated, no updated) + - [Chinese Docs](https://github.com/go-vgo/robotgo/blob/master/docs/doc_zh.md) (Deprecated, no updated) ## Binding: [ADB](https://github.com/vcaesar/adb), packaging android adb API. @@ -57,14 +58,17 @@ GCC ``` #### For Mac OS X: + +Xcode Command Line Tools (And Privacy setting: #277 ) + ``` -Xcode Command Line Tools +xcode-select --install ``` #### For Windows: -``` -MinGW-w64 (Use recommended) or other GCC -``` + +[MinGW-w64](https://sourceforge.net/projects/mingw-w64/files) (Use recommended) or other GCC + #### For everything else: @@ -81,12 +85,12 @@ xcb, xkb, libxkbcommon ##### Ubuntu: ```yml +# gcc sudo apt install gcc libc6-dev sudo apt install libx11-dev xorg-dev libxtst-dev libpng++-dev -sudo apt install xcb libxcb-xkb-dev x11-xkb-utils libx11-xcb-dev libxkbcommon-x11-dev -sudo apt install libxkbcommon-dev +sudo apt install xcb libxcb-xkb-dev x11-xkb-utils libx11-xcb-dev libxkbcommon-x11-dev libxkbcommon-dev sudo apt install xsel xclip ``` @@ -130,19 +134,25 @@ import ( ) func main() { - robotgo.ScrollMouse(10, "up") - robotgo.Scroll(100, 200) + // robotgo.ScrollMouse(10, "up") + robotgo.Scroll(0, -10) + robotgo.Scroll(100, 0) + robotgo.MilliSleep(100) - robotgo.ScrollRelative(10, -100) + robotgo.ScrollSmooth(-10, 6) + // robotgo.ScrollRelative(10, -100) robotgo.MouseSleep = 100 robotgo.Move(10, 20) robotgo.MoveRelative(0, -10) robotgo.Drag(10, 10) + robogo.Click("wheelRight") robotgo.Click("left", true) - robotgo.MoveSmooth(100, 200, 1.0, 100.0) - robotgo.MouseToggle("up") + robotgo.MoveSmooth(100, 200, 1.0, 10.0) + + robotgo.Toggle("left") + robotgo.Toggle("left", "up") } ``` @@ -177,7 +187,8 @@ func main() { robotgo.KeyTap("i", arr) robotgo.MilliSleep(100) - robotgo.KeyToggle("a", "down") + robogo.KeyToggle("a") + robotgo.KeyToggle("a", "up") robotgo.WriteAll("Test") text, err := robotgo.ReadAll() diff --git a/README_zh.md b/README_zh.md index 474789ac..8e013ff3 100644 --- a/README_zh.md +++ b/README_zh.md @@ -32,9 +32,10 @@ RobotGo 支持 Mac, Windows, and Linux(X11). - [License](#license) ## Docs -- [GoDoc](https://godoc.org/github.com/go-vgo/robotgo) -- [中文文档](https://github.com/go-vgo/robotgo/blob/master/docs/doc_zh.md)    -- [English Docs](https://github.com/go-vgo/robotgo/blob/master/docs/doc.md) +- [GoDoc](https://godoc.org/github.com/go-vgo/robotgo)
+ +- [中文文档](https://github.com/go-vgo/robotgo/blob/master/docs/doc_zh.md)    (弃用) +- [English Docs](https://github.com/go-vgo/robotgo/blob/master/docs/doc.md) (弃用) ## Binding: @@ -53,14 +54,17 @@ GCC ``` #### For Mac OS X: + +Xcode Command Line Tools (And Privacy setting: #277 ) + ``` -Xcode Command Line Tools +xcode-select --install ``` #### For Windows: -``` -MinGW-w64 (推荐使用) or other GCC -``` + +[MinGW-w64](https://sourceforge.net/projects/mingw-w64/files) (推荐使用) or other GCC + #### For everything else (Linux 等其他系统): @@ -81,8 +85,7 @@ sudo apt install gcc libc6-dev sudo apt install libx11-dev xorg-dev libxtst-dev libpng++-dev -sudo apt install xcb libxcb-xkb-dev x11-xkb-utils libx11-xcb-dev libxkbcommon-x11-dev -sudo apt install libxkbcommon-dev +sudo apt install xcb libxcb-xkb-dev x11-xkb-utils libx11-xcb-dev libxkbcommon-x11-dev libxkbcommon-dev sudo apt install xsel xclip @@ -127,10 +130,12 @@ import ( ) func main() { - robotgo.ScrollMouse(10, "up") - robotgo.Scroll(100, 200) + // robotgo.ScrollMouse(10, "up") + robotgo.Scroll(0, -10) + robotgo.Scroll(100, 0) robotgo.MilliSleep(100) - robotgo.ScrollRelative(10, -100) + // robotgo.ScrollRelative(10, -100) + robogo.ScrollSmooth(-10, 6) robotgo.MouseSleep = 100 robotgo.Move(10, 20) @@ -138,8 +143,10 @@ func main() { robotgo.Drag(10, 10) robotgo.Click("left", true) - robotgo.MoveSmooth(100, 200, 1.0, 100.0) - robotgo.MouseToggle("up") + robotgo.MoveSmooth(100, 200, 1.0, 10.0) + + robogo.Toggle("left") + robotgo.Toggle("left", "up") } ``` @@ -174,7 +181,8 @@ func main() { robotgo.KeyTap("i", arr) robotgo.MilliSleep(100) - robotgo.KeyToggle("a", "down") + robotgo.KeyToggle("a") + robotgo.KeyToggle("a", "up") robotgo.WriteAll("テストする") text, err := robotgo.ReadAll() From 4302f69b95cd852a3a7273ba4d2718ceb746c5db Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 17 Nov 2021 14:52:05 -0400 Subject: [PATCH 136/327] Update README.md --- README.md | 17 +++++++++++------ README_zh.md | 13 ++++++++----- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 36eea263..27c4225d 100644 --- a/README.md +++ b/README.md @@ -37,8 +37,8 @@ RobotGo supports Mac, Windows, and Linux(X11); and robotgo supports arm64 and x8 ## Docs - [GoDoc](https://godoc.org/github.com/go-vgo/robotgo)
- - - [API Docs](https://github.com/go-vgo/robotgo/blob/master/docs/doc.md)     (Deprecated, no updated) + + - [API Docs](https://github.com/go-vgo/robotgo/blob/master/docs/doc.md) (Deprecated, no updated) - [Chinese Docs](https://github.com/go-vgo/robotgo/blob/master/docs/doc_zh.md) (Deprecated, no updated) ## Binding: @@ -59,7 +59,7 @@ GCC #### For Mac OS X: -Xcode Command Line Tools (And Privacy setting: #277 ) +Xcode Command Line Tools (And Privacy setting: [#277](#277) ) ``` xcode-select --install @@ -67,8 +67,13 @@ xcode-select --install #### For Windows: -[MinGW-w64](https://sourceforge.net/projects/mingw-w64/files) (Use recommended) or other GCC +[MinGW-w64](https://sourceforge.net/projects/mingw-w64/files) (Use recommended) + +``` +Or the other GCC (But you should compile the "libpng" with yourself. Or you can removed the bitmap.go. +In the plans, the bitmap.go will moves to the bitmap dir, but break the API. ) +``` #### For everything else: @@ -147,7 +152,7 @@ func main() { robotgo.MoveRelative(0, -10) robotgo.Drag(10, 10) - robogo.Click("wheelRight") + robotgo.Click("wheelRight") robotgo.Click("left", true) robotgo.MoveSmooth(100, 200, 1.0, 10.0) @@ -187,7 +192,7 @@ func main() { robotgo.KeyTap("i", arr) robotgo.MilliSleep(100) - robogo.KeyToggle("a") + robotgo.KeyToggle("a") robotgo.KeyToggle("a", "up") robotgo.WriteAll("Test") diff --git a/README_zh.md b/README_zh.md index 8e013ff3..23a143a3 100644 --- a/README_zh.md +++ b/README_zh.md @@ -34,7 +34,7 @@ RobotGo 支持 Mac, Windows, and Linux(X11). ## Docs - [GoDoc](https://godoc.org/github.com/go-vgo/robotgo)
-- [中文文档](https://github.com/go-vgo/robotgo/blob/master/docs/doc_zh.md)    (弃用) +- [中文文档](https://github.com/go-vgo/robotgo/blob/master/docs/doc_zh.md) (弃用) - [English Docs](https://github.com/go-vgo/robotgo/blob/master/docs/doc.md) (弃用) ## Binding: @@ -55,7 +55,7 @@ GCC #### For Mac OS X: -Xcode Command Line Tools (And Privacy setting: #277 ) +Xcode Command Line Tools (And Privacy setting: [#277](#277) ) ``` xcode-select --install @@ -63,8 +63,11 @@ xcode-select --install #### For Windows: -[MinGW-w64](https://sourceforge.net/projects/mingw-w64/files) (推荐使用) or other GCC +[MinGW-w64](https://sourceforge.net/projects/mingw-w64/files) (推荐使用) +``` +Or the other GCC (But you should compile the "libpng" with yourself. Or you can removed the bitmap.go ) +``` #### For everything else (Linux 等其他系统): @@ -135,7 +138,7 @@ func main() { robotgo.Scroll(100, 0) robotgo.MilliSleep(100) // robotgo.ScrollRelative(10, -100) - robogo.ScrollSmooth(-10, 6) + robotgo.ScrollSmooth(-10, 6) robotgo.MouseSleep = 100 robotgo.Move(10, 20) @@ -145,7 +148,7 @@ func main() { robotgo.Click("left", true) robotgo.MoveSmooth(100, 200, 1.0, 10.0) - robogo.Toggle("left") + robotgo.Toggle("left") robotgo.Toggle("left", "up") } ``` From a6f18bc2b3420de5e2a508bb1c019661541b7dcc Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 17 Nov 2021 17:08:59 -0400 Subject: [PATCH 137/327] Update godoc and README.md --- README.md | 6 +++--- README_zh.md | 6 +++--- clipboard/clipboard_test.go | 3 +++ robotgo_mac_win.go | 4 ++++ 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 27c4225d..bf74a8b2 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ GCC #### For Mac OS X: -Xcode Command Line Tools (And Privacy setting: [#277](#277) ) +Xcode Command Line Tools (And Privacy setting: [#277](https://github.com/go-vgo/robotgo/issues/277) ) ``` xcode-select --install @@ -70,7 +70,8 @@ xcode-select --install [MinGW-w64](https://sourceforge.net/projects/mingw-w64/files) (Use recommended) ``` -Or the other GCC (But you should compile the "libpng" with yourself. Or you can removed the bitmap.go. +Or the other GCC (But you should compile the "libpng" with yourself. +Or you can removed the bitmap.go. In the plans, the bitmap.go will moves to the bitmap dir, but break the API. ) ``` @@ -114,7 +115,6 @@ sudo dnf install xsel xclip ``` go get github.com/go-vgo/robotgo ``` - It's that easy! png.h: No such file or directory? Please see [issues/47](https://github.com/go-vgo/robotgo/issues/47). diff --git a/README_zh.md b/README_zh.md index 23a143a3..350248ba 100644 --- a/README_zh.md +++ b/README_zh.md @@ -55,7 +55,7 @@ GCC #### For Mac OS X: -Xcode Command Line Tools (And Privacy setting: [#277](#277) ) +Xcode Command Line Tools (And Privacy setting: [#277](https://github.com/go-vgo/robotgo/issues/277) ) ``` xcode-select --install @@ -66,7 +66,8 @@ xcode-select --install [MinGW-w64](https://sourceforge.net/projects/mingw-w64/files) (推荐使用) ``` -Or the other GCC (But you should compile the "libpng" with yourself. Or you can removed the bitmap.go ) +Or the other GCC (But you should compile the "libpng" with yourself. +Or you can removed the bitmap.go ) ``` #### For everything else (Linux 等其他系统): @@ -108,7 +109,6 @@ sudo dnf install xsel xclip ``` go get github.com/go-vgo/robotgo ``` - It's that easy! png.h: No such file or directory? Please see [issues/47](https://github.com/go-vgo/robotgo/issues/47). diff --git a/clipboard/clipboard_test.go b/clipboard/clipboard_test.go index 993d3432..43f05ad9 100644 --- a/clipboard/clipboard_test.go +++ b/clipboard/clipboard_test.go @@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin || windows +// +build darwin windows + package clipboard_test import ( diff --git a/robotgo_mac_win.go b/robotgo_mac_win.go index de6d21ac..b0486c9f 100644 --- a/robotgo_mac_win.go +++ b/robotgo_mac_win.go @@ -37,6 +37,10 @@ func internalGetTitle(pid int32, args ...int32) string { // ActivePID active the window by PID, // // If args[0] > 0 on the Windows platform via a window handle to active +// +// Examples: +// ids, _ := robotgo.FindIds() +// robotgo.ActivePID(ids[0]) func ActivePID(pid int32, args ...int) error { var hwnd int if len(args) > 0 { From b25cecf984251d9cbe087a6b7b70655632aa7377 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 17 Nov 2021 17:29:31 -0400 Subject: [PATCH 138/327] remove move scaled and drop some API keep one, add toggle micro sleep --- base/microsleep.h | 3 +-- key/keypress_c.h | 5 +++++ mouse/mouse_c.h | 3 ++- robotgo.go | 23 +++++++++++++++-------- 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/base/microsleep.h b/base/microsleep.h index bbb8a4ff..777831c7 100644 --- a/base/microsleep.h +++ b/base/microsleep.h @@ -20,8 +20,7 @@ * * Pauses execution for the given amount of milliseconds. */ -H_INLINE void microsleep(double milliseconds) -{ +H_INLINE void microsleep(double milliseconds) { #if defined(IS_WINDOWS) Sleep((DWORD)milliseconds); /* (Unfortunately truncated to a 32-bit integer.) */ #else diff --git a/key/keypress_c.h b/key/keypress_c.h index da63ae4b..8fd05029 100644 --- a/key/keypress_c.h +++ b/key/keypress_c.h @@ -173,6 +173,7 @@ void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags){ void tapKeyCode(MMKeyCode code, MMKeyFlags flags){ toggleKeyCode(code, true, flags); + microsleep(5.0); toggleKeyCode(code, false, flags); } @@ -224,6 +225,7 @@ void toggleKey(char c, const bool down, MMKeyFlags flags){ void tapKey(char c, MMKeyFlags flags){ toggleKey(c, true, flags); + microsleep(5.0); toggleKey(c, false, flags); } @@ -289,6 +291,7 @@ void unicodeType(const unsigned value){ UniChar ch = (UniChar)value; // Convert to unsigned char toggleUnicode(ch, true); + microsleep(5.0); toggleUnicode(ch, false); #elif defined(IS_WINDOWS) INPUT input[2]; @@ -307,10 +310,12 @@ void unicodeType(const unsigned value){ SendInput(2, input, sizeof(INPUT)); #elif defined(USE_X11) toggleUniKey(value, true); + microsleep(5.0); toggleUniKey(value, false); #endif } +// todo: removed void typeStringDelayed(const char *str, const unsigned cpm){ /* Characters per second */ diff --git a/mouse/mouse_c.h b/mouse/mouse_c.h index 245f6186..1b72e747 100644 --- a/mouse/mouse_c.h +++ b/mouse/mouse_c.h @@ -206,6 +206,7 @@ void toggleMouse(bool down, MMMouseButton button){ void clickMouse(MMMouseButton button){ toggleMouse(true, button); + microsleep(5.0); toggleMouse(false, button); } @@ -309,7 +310,7 @@ void scrollMouse(int scrollMagnitude, MMMouseWheelDirection scrollDirection){ #endif } -void scrollMouseXY(int x, int y){ +void scrollMouseXY(int x, int y) { #if defined(IS_WINDOWS) // Fix for #97, // C89 needs variables declared on top of functions (mouseScrollInput) diff --git a/robotgo.go b/robotgo.go index eff95817..7d319e82 100644 --- a/robotgo.go +++ b/robotgo.go @@ -441,6 +441,7 @@ func CheckMouse(btn string) C.MMMouseButton { return C.LEFT_BUTTON } +// Deprecated: // MoveMouse move the mouse func MoveMouse(x, y int) { Move(x, y) @@ -452,10 +453,10 @@ func MoveMouse(x, y int) { // robotgo.MouseSleep = 100 // 100 millisecond // robotgo.Move(10, 10) func Move(x, y int) { - if runtime.GOOS == "windows" { - f := ScaleF() - x, y = Scaled0(x, f), Scaled0(y, f) - } + // if runtime.GOOS == "windows" { + // f := ScaleF() + // x, y = Scaled0(x, f), Scaled0(y, f) + // } cx := C.int32_t(x) cy := C.int32_t(y) @@ -464,6 +465,7 @@ func Move(x, y int) { MilliSleep(MouseSleep) } +// Deprecated: // DragMouse drag the mouse to (x, y), // It's same with the DragSmooth() now func DragMouse(x, y int, args ...interface{}) { @@ -474,6 +476,7 @@ func DragMouse(x, y int, args ...interface{}) { Toggle("left", "up") } +// Deprecated: // Drag drag the mouse to (x, y), // It's not valid now, use the DragSmooth() func Drag(x, y int, args ...string) { @@ -500,6 +503,7 @@ func DragSmooth(x, y int, args ...interface{}) { Toggle("left", "up") } +// Deprecated: // MoveMouseSmooth move the mouse smooth, // moves mouse to x, y human like, with the mouse button up. func MoveMouseSmooth(x, y int, args ...interface{}) bool { @@ -515,10 +519,10 @@ func MoveMouseSmooth(x, y int, args ...interface{}) bool { // robotgo.MoveSmooth(10, 10) // robotgo.MoveSmooth(10, 10, 1.0, 2.0) func MoveSmooth(x, y int, args ...interface{}) bool { - if runtime.GOOS == "windows" { - f := ScaleF() - x, y = Scaled0(x, f), Scaled0(y, f) - } + // if runtime.GOOS == "windows" { + // f := ScaleF() + // x, y = Scaled0(x, f), Scaled0(y, f) + // } cx := C.int32_t(x) cy := C.int32_t(y) @@ -577,6 +581,7 @@ func GetMousePos() (int, int) { return x, y } +// Deprecated: // MouseClick click the mouse // // robotgo.MouseClick(button string, double bool) @@ -646,6 +651,7 @@ func Toggle(key ...string) int { return int(i) } +// Deprecated: // MouseToggle toggle the mouse // // Examples: @@ -666,6 +672,7 @@ func MouseToggle(togKey string, args ...interface{}) int { return int(i) } +// Deprecated: // ScrollMouse scroll the mouse to (x, "up") // // Examples: From fb06a2929205cd76c4478ac83c262fe016a14e2a Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 23 Nov 2021 16:30:24 -0400 Subject: [PATCH 139/327] Update keycode.go use the public code and go mod --- go.mod | 11 +++-- go.sum | 21 ++++---- keycode.go | 139 +++-------------------------------------------------- 3 files changed, 25 insertions(+), 146 deletions(-) diff --git a/go.mod b/go.mod index 5de515bb..c86ca004 100644 --- a/go.mod +++ b/go.mod @@ -8,23 +8,24 @@ require ( github.com/robotn/gohook v0.31.2 github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 - github.com/vcaesar/gops v0.21.2 + github.com/vcaesar/gops v0.21.3 github.com/vcaesar/imgo v0.30.0 + github.com/vcaesar/keycode v0.10.0 github.com/vcaesar/tt v0.20.0 - golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d + golang.org/x/image v0.0.0-20211028202545-6944b10bf410 golang.org/x/net v0.0.0-20201110031124-69a78807bb2b // indirect ) require ( github.com/StackExchange/wmi v1.2.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/go-ole/go-ole v1.2.5 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect github.com/otiai10/mint v1.3.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/shirou/gopsutil v3.21.8+incompatible // indirect + github.com/shirou/gopsutil v3.21.10+incompatible // indirect github.com/tklauser/go-sysconf v0.3.9 // indirect github.com/tklauser/numcpus v0.3.0 // indirect - golang.org/x/sys v0.0.0-20210925032602-92d5a993a665 // indirect + golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) diff --git a/go.sum b/go.sum index 1ca03bc6..0c5cbab0 100644 --- a/go.sum +++ b/go.sum @@ -5,8 +5,9 @@ github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY= github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/lxn/win v0.0.0-20210218163916-a377121e959e h1:H+t6A/QJMbhCSEH5rAuRxh+CtW96g0Or0Fxa9IKr4uc= github.com/lxn/win v0.0.0-20210218163916-a377121e959e/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= @@ -22,8 +23,8 @@ github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 h1:2lhSR8N3T6I30q096DT7 github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934/go.mod h1:SxQhJskUJ4rleVU44YvnrdvxQr0tKy5SRSigBrCgyyQ= github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 h1:2uX8QRLkkxn2EpAQ6I3KhA79BkdRZfvugJUzJadiJwk= github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770/go.mod h1:svkDXUDQjUiWzLrA0OZgHc4lbOts3C+uRfP6/yjwYnU= -github.com/shirou/gopsutil v3.21.8+incompatible h1:sh0foI8tMRlCidUJR+KzqWYWxrkuuPIGiO6Vp+KXdCU= -github.com/shirou/gopsutil v3.21.8+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil v3.21.10+incompatible h1:AL2kpVykjkqeN+MFe1WcwSBVUjGjvdU8/ubvCuXAjrU= +github.com/shirou/gopsutil v3.21.10+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -31,16 +32,19 @@ github.com/tklauser/go-sysconf v0.3.9 h1:JeUVdAOWhhxVcU6Eqr/ATFHgXk/mmiItdKeJPev github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs= github.com/tklauser/numcpus v0.3.0 h1:ILuRUQBtssgnxw0XXIjKUC56fgnOrFoQQ/4+DeU2biQ= github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8= -github.com/vcaesar/gops v0.21.2 h1:OwWoJR0zb+AK41TN2adhZUP9lAmaRMzkWwf7Ux5Mx00= -github.com/vcaesar/gops v0.21.2/go.mod h1:BEJGigAc9GORbEegWX9rRon/qwibjDs8p50WYm2KlXw= +github.com/vcaesar/gops v0.21.3 h1:VR7amkxVv9CQfsotkXrmMyT19dVuNTa1PM/oopJeIc0= +github.com/vcaesar/gops v0.21.3/go.mod h1:3e2EnlZTI9/44bqzRwkeZ3s0ZQwK2Cn4QPLx8Ii8Agk= github.com/vcaesar/imgo v0.30.0 h1:ODQVX0EFJEh+WkKahCBtE0SqcDCIjl/kjiOplR0Ouh8= github.com/vcaesar/imgo v0.30.0/go.mod h1:8TGnt5hjaMgwDByvMFIzUDSh5uSea4n1tAbSvnhvA6U= +github.com/vcaesar/keycode v0.10.0 h1:Qx5QE8ZXHyRyjoA2QOxBp25OKMKB+zxMVqm0FWGV0d4= +github.com/vcaesar/keycode v0.10.0/go.mod h1:JNlY7xbKsh+LAGfY2j4M3znVrGEm5W1R8s/Uv6BJcfQ= github.com/vcaesar/tt v0.20.0 h1:9t2Ycb9RNHcP0WgQgIaRKJBB+FrRdejuaL6uWIHuoBA= github.com/vcaesar/tt v0.20.0/go.mod h1:GHPxQYhn+7OgKakRusH7KJ0M5MhywoeLb8Fcffs/Gtg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d h1:RNPAfi2nHY7C2srAV8A49jpsYr0ADedCk1wq6fTMTvs= golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20211028202545-6944b10bf410 h1:hTftEOvwiOq2+O8k2D5/Q7COC7k5Qcrgc2TFURJYnvQ= +golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= @@ -50,9 +54,8 @@ golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210915083310-ed5796bab164/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210925032602-92d5a993a665 h1:QOQNt6vCjMpXE7JSK5VvAzJC1byuN3FgTNSBwf+CJgI= -golang.org/x/sys v0.0.0-20210925032602-92d5a993a665/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab h1:rfJ1bsoJQQIAoAxTxB7bme+vHrNkRw8CqfsYh9w54cw= +golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= diff --git a/keycode.go b/keycode.go index acc90bec..bd4108fc 100644 --- a/keycode.go +++ b/keycode.go @@ -10,142 +10,17 @@ package robotgo +import ( + "github.com/vcaesar/keycode" +) + type uMap map[string]uint16 // MouseMap robotgo hook mouse's code map -var MouseMap = uMap{ - "left": 1, - "right": 2, - "center": 3, - "wheelDown": 4, - "wheelUp": 5, - "wheelLeft": 6, - "wheelRight": 7, -} +var MouseMap = keycode.MouseMap // Keycode robotgo hook key's code map -var Keycode = uMap{ - "`": 41, - "1": 2, - "2": 3, - "3": 4, - "4": 5, - "5": 6, - "6": 7, - "7": 8, - "8": 9, - "9": 10, - "0": 11, - "-": 12, - "=": 13, - // - "_": 12, - "+": 13, - // - "q": 16, - "w": 17, - "e": 18, - "r": 19, - "t": 20, - "y": 21, - "u": 22, - "i": 23, - "o": 24, - "p": 25, - "[": 26, - "]": 27, - "\\": 43, - // - "{": 26, - "}": 27, - "|": 43, - // - "a": 30, - "s": 31, - "d": 32, - "f": 33, - "g": 34, - "h": 35, - "j": 36, - "k": 37, - "l": 38, - ";": 39, - "'": 40, - // - ":": 39, - `"`: 40, - // - "z": 44, - "x": 45, - "c": 46, - "v": 47, - "b": 48, - "n": 49, - "m": 50, - ",": 51, - ".": 52, - "/": 53, - // - "<": 51, - ">": 52, - "?": 53, - // - "f1": 59, - "f2": 60, - "f3": 61, - "f4": 62, - "f5": 63, - "f6": 64, - "f7": 65, - "f8": 66, - "f9": 67, - "f10": 68, - "f11": 69, - "f12": 70, - // more - "esc": 1, - "delete": 14, - "tab": 15, - "enter": 28, - "ctrl": 29, - "control": 29, - "shift": 42, - "rshift": 54, - "space": 57, - // - "alt": 56, - "ralt": 3640, - "cmd": 3675, - "command": 3675, - "rcmd": 3676, - // - "up": 57416, - "down": 57424, - "left": 57419, - "right": 57421, -} +var Keycode = keycode.Keycode // Special is the special key map -var Special = map[string]string{ - "~": "`", - "!": "1", - "@": "2", - "#": "3", - "$": "4", - "%": "5", - "^": "6", - "&": "7", - "*": "8", - "(": "9", - ")": "0", - "_": "-", - "+": "=", - "{": "[", - "}": "]", - "|": "\\", - ":": ";", - `"`: "'", - "<": ",", - ">": ".", - "?": "/", -} +var Special = keycode.Special From b9cb452594153a2892de72c2678c45aeca0ae089 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 24 Nov 2021 15:42:08 -0400 Subject: [PATCH 140/327] optimize code, add ps.Run() function and update godoc --- README.md | 4 +-- README_zh.md | 4 +-- bitmap.go | 40 +++++++++++++++++++---------- hook.go | 4 ++- ps.go | 5 ++++ robotgo.go | 72 ++++++++++++++++++++++++++++------------------------ 6 files changed, 77 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index bf74a8b2..5c0b9b5e 100644 --- a/README.md +++ b/README.md @@ -259,8 +259,8 @@ func main() { fmt.Println("FindBitmap------ ", fx, fy) robotgo.Move(fx, fy) - arr := robotgo.FindEveryBitmap(bit2) - fmt.Println("Find every bitmap: ", arr) + arr := robotgo.FindAllBitmap(bit2) + fmt.Println("Find all bitmap: ", arr) robotgo.SaveBitmap(bitmap, "test.png") fx, fy = robotgo.FindBitmap(bitmap) diff --git a/README_zh.md b/README_zh.md index 350248ba..9bc54543 100644 --- a/README_zh.md +++ b/README_zh.md @@ -251,8 +251,8 @@ func main() { fmt.Println("FindBitmap------ ", fx, fy) robotgo.Move(fx, fy) - arr := robotgo.FindEveryBitmap(bit2) - fmt.Println("Find every bitmap: ", arr) + arr := robotgo.FindAllBitmap(bit2) + fmt.Println("Find all bitmap: ", arr) robotgo.SaveBitmap(bitmap, "test.png") fx, fy = robotgo.FindBitmap(bitmap) diff --git a/bitmap.go b/bitmap.go index ef3e8a46..cd86c1dd 100644 --- a/bitmap.go +++ b/bitmap.go @@ -49,6 +49,13 @@ func SaveCapture(spath string, args ...int) string { return err } +// FreeBitmapArr free and dealloc the C bitmap array +func FreeBitmapArr(bit ...C.MMBitmapRef) { + for i := 0; i < len(bit); i++ { + FreeBitmap(bit[i]) + } +} + // ToCBitmap trans Bitmap to C.MMBitmapRef func ToCBitmap(bit Bitmap) C.MMBitmapRef { cbitmap := C.createMMBitmap( @@ -108,8 +115,8 @@ func FindCBitmap(bmp CBitmap, args ...interface{}) (int, int) { // // robotgo.FindBitmap(bitmap, source_bitamp C.MMBitmapRef, tolerance float64) // -// |tolerance| should be in the range 0.0f - 1.0f, denoting how closely the -// colors in the bitmaps need to match, with 0 being exact and 1 being any. +// |tolerance| should be in the range 0.0f - 1.0f, denoting how closely the +// colors in the bitmaps need to match, with 0 being exact and 1 being any. // // This method only automatically free the internal bitmap, // use `defer robotgo.FreeBitmap(bit)` to free the bitmap @@ -176,8 +183,14 @@ func FreeMMPointArr(pointArray C.MMPointArrayRef) { C.destroyMMPointArray(pointArray) } -// FindEveryBitmap find the every bitmap -func FindEveryBitmap(bit C.MMBitmapRef, args ...interface{}) (posArr []Point) { +// Deprecated: use the FindAllBitmap() +// FindEveryBitmap find the every bitmap, same with the FindAllBitmap() +func FindEveryBitmap(bit C.MMBitmapRef, args ...interface{}) []Point { + return FindAllBitmap(bit, args...) +} + +// FindAllBitmap find the all bitmap +func FindAllBitmap(bit C.MMBitmapRef, args ...interface{}) (posArr []Point) { var ( sbit C.MMBitmapRef tolerance C.float = 0.01 @@ -332,13 +345,6 @@ func Convert(opath, spath string, args ...int) string { return SaveBitmap(bitmap, spath, mtype) } -// FreeBitmapArr free and dealloc the C bitmap array -func FreeBitmapArr(bit ...C.MMBitmapRef) { - for i := 0; i < len(bit); i++ { - FreeBitmap(bit[i]) - } -} - // ReadBitmap returns false and sets error if |bitmap| is NULL func ReadBitmap(bitmap C.MMBitmapRef) bool { abool := C.bitmap_ready(bitmap) @@ -368,7 +374,7 @@ func DeepCopyBit(bitmap C.MMBitmapRef) C.MMBitmapRef { return bit } -// GetColor get bitmap color +// GetColor get the bitmap color func GetColor(bitmap C.MMBitmapRef, x, y int) C.MMRGBHex { color := C.bitmap_get_color(bitmap, C.size_t(x), C.size_t(y)) @@ -427,8 +433,14 @@ func FindColorCS(color CHex, x, y, w, h int, args ...float64) (int, int) { return rx, ry } -// FindEveryColor find every color -func FindEveryColor(color CHex, args ...interface{}) (posArr []Point) { +// Deprecated: use the FindAllColor() +// FindEveryColor find the every color, same with the FindAllColor() +func FindEveryColor(color CHex, args ...interface{}) []Point { + return FindAllColor(color, args...) +} + +// FindAllColor find the all color +func FindAllColor(color CHex, args ...interface{}) (posArr []Point) { var ( bitmap C.MMBitmapRef tolerance C.float = 0.01 diff --git a/hook.go b/hook.go index f059c895..4f645aae 100644 --- a/hook.go +++ b/hook.go @@ -36,18 +36,20 @@ func EventEnd() { hook.End() } +// Deprecated: use the EventStart() // Start start global event hook // return event channel func Start() chan hook.Event { return hook.Start() } +// Deprecated: use the EventEnd() // End removes global event hook func End() { hook.End() } -// StopEvent stop event listener +// StopEvent stop event listener, use by AddEvent() func StopEvent() { hook.StopEvent() } diff --git a/ps.go b/ps.go index e6eddc12..9a453866 100644 --- a/ps.go +++ b/ps.go @@ -66,6 +66,11 @@ func FindPath(pid int32) (string, error) { return ps.FindPath(pid) } +// Run run a cmd shell +func Run(path string) ([]byte, error) { + return ps.Run(path) +} + // Kill kill the process by PID func Kill(pid int32) error { return ps.Kill(pid) diff --git a/robotgo.go b/robotgo.go index 7d319e82..33915fbb 100644 --- a/robotgo.go +++ b/robotgo.go @@ -205,14 +205,7 @@ func GetPxColor(x, y int) C.MMRGBHex { // GetPixelColor get the pixel color return string func GetPixelColor(x, y int) string { - cx := C.int32_t(x) - cy := C.int32_t(y) - - color := C.get_pixel_color(cx, cy) - gcolor := C.GoString(color) - C.free(unsafe.Pointer(color)) - - return gcolor + return PadHex(GetPxColor(x, y)) } // GetMouseColor get the mouse pos's color @@ -229,7 +222,8 @@ func SysScale() float64 { // Scaled get the screen scaled size func Scaled(x int) int { - return Scaled0(x, ScaleF()) + f := ScaleF() + return Scaled0(x, f) } // Scaled0 return int(x * f) @@ -244,7 +238,7 @@ func GetScreenSize() (int, int) { return int(size.w), int(size.h) } -// GetScreenRect get the screen rect +// GetScreenRect get the screen rect (x, y, w, h) func GetScreenRect(displayId ...int) Rect { display := 0 if len(displayId) > 0 { @@ -285,6 +279,7 @@ func CaptureScreen(args ...int) C.MMBitmapRef { w = C.int32_t(args[2]) h = C.int32_t(args[3]) } else { + // Get the main screen rect. rect := GetScreenRect() x = C.int32_t(rect.X) @@ -364,19 +359,19 @@ func GetXDisplayName() string { return gname } -// Deprecated: +// Deprecated: use the ScaledF() // ScaleX get the primary display horizontal DPI scale factor, drop func ScaleX() int { return int(C.scale_x()) } -// Deprecated: +// Deprecated: use the ScaledF() // ScaleY get primary display vertical DPI scale factor, drop func ScaleY() int { return int(C.scale_y()) } -// Deprecated: +// Deprecated: use the ScaledF() // Scale get the screen scale (only windows old), drop func Scale() int { dpi := map[int]int{ @@ -399,13 +394,13 @@ func Scale() int { return dpi[x] } -// Deprecated: +// Deprecated: use the ScaledF() // Scale0 return ScaleX() / 0.96, drop func Scale0() int { return int(float64(ScaleX()) / 0.96) } -// Deprecated: +// Deprecated: use the ScaledF() // Mul mul the scale, drop func Mul(x int) int { s := Scale() @@ -441,7 +436,7 @@ func CheckMouse(btn string) C.MMMouseButton { return C.LEFT_BUTTON } -// Deprecated: +// Deprecated: use the Move() // MoveMouse move the mouse func MoveMouse(x, y int) { Move(x, y) @@ -465,7 +460,7 @@ func Move(x, y int) { MilliSleep(MouseSleep) } -// Deprecated: +// Deprecated: use the DragSmooth() // DragMouse drag the mouse to (x, y), // It's same with the DragSmooth() now func DragMouse(x, y int, args ...interface{}) { @@ -476,7 +471,7 @@ func DragMouse(x, y int, args ...interface{}) { Toggle("left", "up") } -// Deprecated: +// Deprecated: use the DragSmooth() // Drag drag the mouse to (x, y), // It's not valid now, use the DragSmooth() func Drag(x, y int, args ...string) { @@ -503,7 +498,7 @@ func DragSmooth(x, y int, args ...interface{}) { Toggle("left", "up") } -// Deprecated: +// Deprecated: use the MoveSmooth() // MoveMouseSmooth move the mouse smooth, // moves mouse to x, y human like, with the mouse button up. func MoveMouseSmooth(x, y int, args ...interface{}) bool { @@ -528,7 +523,7 @@ func MoveSmooth(x, y int, args ...interface{}) bool { cy := C.int32_t(y) var ( - mouseDelay = 10 + mouseDelay = 5 low C.double high C.double ) @@ -571,17 +566,16 @@ func MoveSmoothRelative(x, y int, args ...interface{}) { MoveSmooth(mx, my, args...) } -// GetMousePos get mouse's portion return x, y +// GetMousePos get the mouse's portion return x, y func GetMousePos() (int, int) { pos := C.get_mouse_pos() - x := int(pos.x) y := int(pos.y) return x, y } -// Deprecated: +// Deprecated: use the Click() // MouseClick click the mouse // // robotgo.MouseClick(button string, double bool) @@ -618,14 +612,22 @@ func Click(args ...interface{}) { // MoveClick move and click the mouse // // robotgo.MoveClick(x, y int, button string, double bool) +// +// Examples: +// robotgo.MouseSleep = 100 +// robotgo.MoveClick(10, 10) func MoveClick(x, y int, args ...interface{}) { Move(x, y) + MilliSleep(50) Click(args...) } // MovesClick move smooth and click the mouse +// +// use the `robotgo.MouseSleep = 100` func MovesClick(x, y int, args ...interface{}) { MoveSmooth(x, y) + MilliSleep(50) Click(args...) } @@ -651,7 +653,7 @@ func Toggle(key ...string) int { return int(i) } -// Deprecated: +// Deprecated: use the Toggle() // MouseToggle toggle the mouse // // Examples: @@ -672,7 +674,7 @@ func MouseToggle(togKey string, args ...interface{}) int { return int(i) } -// Deprecated: +// Deprecated: use the Scroll() // ScrollMouse scroll the mouse to (x, "up") // // Examples: @@ -1072,7 +1074,8 @@ func PasteStr(str string) string { return KeyTap("v", "control") } -// Deprecated: TypeString send a string, support unicode(no linux support) +// Deprecated: use the TypeStr() +// TypeString send a string, support unicode(no linux support) // TypeStr(string: The string to send), Wno-deprecated // // This function will be removed in version v1.0.0 @@ -1095,7 +1098,8 @@ func TypeStrDelay(str string, delay int) { Sleep(delay) } -// Deprecated: TypeStringDelayed type string delayed, Wno-deprecated +// Deprecated: use the TypeStr() +// TypeStringDelayed type string delayed, Wno-deprecated // // This function will be removed in version v1.0.0 func TypeStringDelayed(str string, delay int) { @@ -1108,7 +1112,8 @@ func SetKeyDelay(delay int) { C.set_keyboard_delay(C.size_t(delay)) } -// Deprecated: SetKeyboardDelay set keyboard delay, Wno-deprecated, +// Deprecated: use the SetKeyDelay() +// SetKeyboardDelay set keyboard delay, Wno-deprecated, // // This function will be removed in version v1.0.0 func SetKeyboardDelay(delay int) { @@ -1142,7 +1147,7 @@ ____ __ ____ __ .__ __. _______ ______ ____ __ ____ // If cancel button is not given, only the default button is displayed // // Examples: -// robogo.ShowAlert("hi", "window", "ok", "cancel") +// robotgo.ShowAlert("hi", "window", "ok", "cancel") func ShowAlert(title, msg string, args ...string) bool { var ( // title string @@ -1283,7 +1288,8 @@ func GetHandle() int { return ghwnd } -// Deprecated: GetBHandle get the window handle, Wno-deprecated +// Deprecated: use the GetHandle() +// GetBHandle get the window handle, Wno-deprecated // // This function will be removed in version v1.0.0 func GetBHandle() int { @@ -1304,10 +1310,10 @@ func cgetTitle(hwnd, isHwnd int32) string { // GetTitle get the window title return string // // Examples: -// fmt.Println(robogo.GetTitle()) +// fmt.Println(robotgo.GetTitle()) // -// ids, _ := robogo.FindIds() -// robogo.GetTitle(ids[0]) +// ids, _ := robotgo.FindIds() +// robotgo.GetTitle(ids[0]) func GetTitle(args ...int32) string { if len(args) <= 0 { title := C.get_main_title() From f8539139b79b1290d116679e4f24cd725a12d4db Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 24 Nov 2021 15:49:00 -0400 Subject: [PATCH 141/327] Update examples and README.md --- examples/README.md | 5 +++-- examples/bitmap/imgToBitmap/main.go | 2 +- examples/bitmap/main.go | 4 ++-- examples/mouse/main.go | 14 +++++++------- test/main.go | 8 ++++---- 5 files changed, 17 insertions(+), 16 deletions(-) diff --git a/examples/README.md b/examples/README.md index e7ef0690..af5c8ab3 100644 --- a/examples/README.md +++ b/examples/README.md @@ -17,9 +17,10 @@ import ( ) func main() { - robotgo.ScrollMouse(10, "up") + // robotgo.ScrollMouse(10, "up") + robotgo.Scroll(0, 10) robotgo.MouseClick("left", true) - robotgo.MoveMouseSmooth(100, 200, 1.0, 100.0) + robotgo.MoveSmooth(100, 200, 1.0, 100.0) } ``` diff --git a/examples/bitmap/imgToBitmap/main.go b/examples/bitmap/imgToBitmap/main.go index 0d6d8a4c..17a3df6e 100644 --- a/examples/bitmap/imgToBitmap/main.go +++ b/examples/bitmap/imgToBitmap/main.go @@ -46,7 +46,7 @@ func test() { fx, fy := robotgo.FindBitmap(bit2) fmt.Println("FindBitmap------ ", fx, fy) - arr := robotgo.FindEveryBitmap(bit2) + arr := robotgo.FindAllBitmap(bit2) fmt.Println("Find every bitmap: ", arr) robotgo.SaveBitmap(bitmap, "test.png") } diff --git a/examples/bitmap/main.go b/examples/bitmap/main.go index 9c3662db..b9ae1ca4 100644 --- a/examples/bitmap/main.go +++ b/examples/bitmap/main.go @@ -59,7 +59,7 @@ func findColor(bmp robotgo.CBitmap) { cnt1 := robotgo.CountColorCS(0xAADCDC, 10, 20, 30, 40) fmt.Println("count...", cnt1) - arr := robotgo.FindEveryColor(0xAADCDC) + arr := robotgo.FindAllColor(0xAADCDC) fmt.Println("find all color: ", arr) for i := 0; i < len(arr); i++ { fmt.Println("pos is: ", arr[i].X, arr[i].Y) @@ -160,7 +160,7 @@ func findBitmap(bmp robotgo.CBitmap) { fx, fy = robotgo.FindPic("test.tif") fmt.Println("FindPic------", fx, fy) - arr := robotgo.FindEveryBitmap(openbit) + arr := robotgo.FindAllBitmap(openbit) fmt.Println("find all bitmap: ", arr) for i := 0; i < len(arr); i++ { fmt.Println("pos is: ", arr[i].X, arr[i].Y) diff --git a/examples/mouse/main.go b/examples/mouse/main.go index 9380fb6f..f797727e 100644 --- a/examples/mouse/main.go +++ b/examples/mouse/main.go @@ -33,7 +33,7 @@ func move() { // smooth move the mouse to 100, 200 robotgo.MoveSmooth(100, 200) - robotgo.MoveMouseSmooth(100, 200, 1.0, 100.0) + robotgo.MoveSmooth(100, 200, 1.0, 100.0) robotgo.MoveSmoothRelative(10, -100, 1.0, 30.0) for i := 0; i < 1080; i += 1000 { @@ -68,13 +68,13 @@ func get() { func toggleAndScroll() { // scrolls the mouse either up - robotgo.ScrollMouse(10, "up") - robotgo.Scroll(100, 200) + // robotgo.ScrollMouse(10, "up") + robotgo.Scroll(100, 10) + robotgo.Scroll(0, -10) - // toggles right mouse button - robotgo.MouseToggle("down", "right") - - robotgo.MouseToggle("up") + // toggles the right mouse button + robotgo.Toggle("right") + robotgo.Toggle("right", "up") } func mouse() { diff --git a/test/main.go b/test/main.go index 4640216e..27a6180f 100644 --- a/test/main.go +++ b/test/main.go @@ -26,14 +26,14 @@ func aRobotgo() { x, y := robotgo.GetMousePos() fmt.Println("pos:", x, y) - robotgo.MoveMouse(x, y) - robotgo.MoveMouse(100, 200) + robotgo.Move(x, y) + robotgo.Move(100, 200) robotgo.MouseToggle("up") for i := 0; i < 1080; i += 1000 { fmt.Println(i) - robotgo.MoveMouse(800, i) + robotgo.Move(800, i) } fmt.Println(robotgo.GetPixelColor(x, y)) @@ -65,7 +65,7 @@ func aRobotgo() { fmt.Println("...type", reflect.TypeOf(bitTest), reflect.TypeOf(bitmapTest)) // robotgo.MouseClick() - robotgo.ScrollMouse(10, "up") + robotgo.Scroll(0, 10) } func main() { From 506109e2418969874574b71455f6195a716315a5 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 24 Nov 2021 16:21:39 -0400 Subject: [PATCH 142/327] Update go mod --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c86ca004..c84c38f1 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.17 require ( github.com/lxn/win v0.0.0-20210218163916-a377121e959e github.com/otiai10/gosseract v2.2.1+incompatible - github.com/robotn/gohook v0.31.2 + github.com/robotn/gohook v0.31.3 github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 github.com/vcaesar/gops v0.21.3 diff --git a/go.sum b/go.sum index 0c5cbab0..c5017780 100644 --- a/go.sum +++ b/go.sum @@ -17,8 +17,8 @@ github.com/otiai10/mint v1.3.0 h1:Ady6MKVezQwHBkGzLFbrsywyp09Ah7rkmfjV3Bcr5uc= github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/robotn/gohook v0.31.2 h1:ADIppQ3T0Sd+kaDMb4Vnv6UeSmhNfK0H0HpPWCd8G5I= -github.com/robotn/gohook v0.31.2/go.mod h1:0BQit8783ey63WXFau8TvoaTYfNtsAhqZ0RJaqlYi6E= +github.com/robotn/gohook v0.31.3 h1:kGX8iukJ9ensVRwRKnTtdojAMQOpa6KFnXDi4OA4RaI= +github.com/robotn/gohook v0.31.3/go.mod h1:wyGik0yb4iwCfJjDprtNkTyxkgQWuKoVPQ3hkz6+6js= github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 h1:2lhSR8N3T6I30q096DT7/5AKEIcf1vvnnWAmS0wfnNY= github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934/go.mod h1:SxQhJskUJ4rleVU44YvnrdvxQr0tKy5SRSigBrCgyyQ= github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 h1:2uX8QRLkkxn2EpAQ6I3KhA79BkdRZfvugJUzJadiJwk= From d725cdc6f2fa5114ea88310d5ddf60c93bc0ef11 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 25 Nov 2021 15:54:54 -0400 Subject: [PATCH 143/327] Add more and optimize test code, fixed typo --- docs/doc.md | 8 ++++---- docs/doc_zh.md | 8 ++++---- robot_info_test.go | 8 +++++++- robotgo_test.go | 30 +++++++++++++++++++----------- 4 files changed, 34 insertions(+), 20 deletions(-) diff --git a/docs/doc.md b/docs/doc.md index cca93699..1a5d3b15 100644 --- a/docs/doc.md +++ b/docs/doc.md @@ -213,8 +213,8 @@ robotgo.MoveMouseSmooth(100, 200, 1.0, 100.0) #### Examples: ```Go -robogo.MouseClick() -robogo.MouseClick("left", true) +robotgo.MouseClick() +robotgo.MouseClick("left", true) ``` ###

.MoveClick(x, y, button, double)

@@ -231,8 +231,8 @@ robogo.MouseClick("left", true) #### Examples: ```Go -robogo.MoveClick(10, 20) -robogo.MoveClick(10, 20, "left", true) +robotgo.MoveClick(10, 20) +robotgo.MoveClick(10, 20, "left", true) ``` ###

.MouseToggle(down, button)

diff --git a/docs/doc_zh.md b/docs/doc_zh.md index 1f7e4390..a3dbebc1 100644 --- a/docs/doc_zh.md +++ b/docs/doc_zh.md @@ -221,8 +221,8 @@ robotgo.MoveMouseSmooth(100, 200, 1.0, 100.0) #### 示例: ```Go -robogo.MouseClick() -robogo.MouseClick("left", true) +robotgo.MouseClick() +robotgo.MouseClick("left", true) ``` ###

.MoveClick(x, y, button, double)

@@ -239,8 +239,8 @@ robogo.MouseClick("left", true) #### 示例: ```Go -robogo.MoveClick(10, 20) -robogo.MoveClick(10, 20, "left", true) +robotgo.MoveClick(10, 20) +robotgo.MoveClick(10, 20, "left", true) ``` ###

.MouseToggle(down, button)

diff --git a/robot_info_test.go b/robot_info_test.go index 91d9a472..0ce128d3 100644 --- a/robot_info_test.go +++ b/robot_info_test.go @@ -29,10 +29,16 @@ func TestGetVer(t *testing.T) { func TestGetScreenSize(t *testing.T) { x, y := robotgo.GetScreenSize() - log.Println("GetScreenSize: ", x, y) + log.Println("Get screen size: ", x, y) + + rect := robotgo.GetScreenRect() + fmt.Println("Get screen rect: ", rect) } func TestGetSysScale(t *testing.T) { s := robotgo.SysScale() log.Println("SysScale: ", s) + + f := robotgo.ScaleF() + log.Println("sclae: ", f) } diff --git a/robotgo_test.go b/robotgo_test.go index e7c09286..5852bc86 100644 --- a/robotgo_test.go +++ b/robotgo_test.go @@ -40,8 +40,8 @@ func TestSize(t *testing.T) { } func TestMoveMouse(t *testing.T) { - MoveMouse(20, 20) - MilliSleep(10) + Move(20, 20) + MilliSleep(50) x, y := GetMousePos() tt.Equal(t, 20, x) @@ -49,8 +49,8 @@ func TestMoveMouse(t *testing.T) { } func TestMoveMouseSmooth(t *testing.T) { - b := MoveMouseSmooth(100, 100) - MilliSleep(10) + b := MoveSmooth(100, 100) + MilliSleep(50) x, y := GetMousePos() tt.True(t, b) @@ -60,7 +60,7 @@ func TestMoveMouseSmooth(t *testing.T) { func TestDragMouse(t *testing.T) { DragMouse(500, 500) - MilliSleep(10) + MilliSleep(50) x, y := GetMousePos() tt.Equal(t, 500, x) @@ -68,18 +68,20 @@ func TestDragMouse(t *testing.T) { } func TestScrollMouse(t *testing.T) { - ScrollMouse(120, "up") + // ScrollMouse(120, "up") + Scroll(0, 120) MilliSleep(100) Scroll(210, 210) + MilliSleep(10) } func TestMoveRelative(t *testing.T) { Move(200, 200) - MilliSleep(10) + MilliSleep(50) MoveRelative(10, -10) - MilliSleep(10) + MilliSleep(50) x, y := GetMousePos() tt.Equal(t, 210, x) @@ -88,10 +90,10 @@ func TestMoveRelative(t *testing.T) { func TestMoveSmoothRelative(t *testing.T) { Move(200, 200) - MilliSleep(10) + MilliSleep(50) MoveSmoothRelative(10, -10) - MilliSleep(10) + MilliSleep(50) x, y := GetMousePos() tt.Equal(t, 210, x) @@ -99,7 +101,10 @@ func TestMoveSmoothRelative(t *testing.T) { } func TestMouseToggle(t *testing.T) { - e := MouseToggle("up", "right") + e := Toggle("right") + tt.Zero(t, e) + + e = Toggle("right", "up") tt.Zero(t, e) } @@ -141,6 +146,9 @@ func TestKeyCode(t *testing.T) { k := Keycode["1"] tt.Equal(t, 2, k) + + s := Special["+"] + tt.Equal(t, "=", s) } func TestBitmap(t *testing.T) { From 8a7d6a130674b4191adf952f948a812e328d1696 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 25 Nov 2021 16:03:39 -0400 Subject: [PATCH 144/327] Update godoc --- bitmap.go | 6 ++++-- hook.go | 6 ++++-- robotgo.go | 48 ++++++++++++++++++++++++++++++++---------------- 3 files changed, 40 insertions(+), 20 deletions(-) diff --git a/bitmap.go b/bitmap.go index cd86c1dd..4ee9f163 100644 --- a/bitmap.go +++ b/bitmap.go @@ -183,7 +183,8 @@ func FreeMMPointArr(pointArray C.MMPointArrayRef) { C.destroyMMPointArray(pointArray) } -// Deprecated: use the FindAllBitmap() +// Deprecated: use the FindAllBitmap(), +// // FindEveryBitmap find the every bitmap, same with the FindAllBitmap() func FindEveryBitmap(bit C.MMBitmapRef, args ...interface{}) []Point { return FindAllBitmap(bit, args...) @@ -433,7 +434,8 @@ func FindColorCS(color CHex, x, y, w, h int, args ...float64) (int, int) { return rx, ry } -// Deprecated: use the FindAllColor() +// Deprecated: use the FindAllColor(), +// // FindEveryColor find the every color, same with the FindAllColor() func FindEveryColor(color CHex, args ...interface{}) []Point { return FindAllColor(color, args...) diff --git a/hook.go b/hook.go index 4f645aae..e7ff9302 100644 --- a/hook.go +++ b/hook.go @@ -36,14 +36,16 @@ func EventEnd() { hook.End() } -// Deprecated: use the EventStart() +// Deprecated: use the EventStart(), +// // Start start global event hook // return event channel func Start() chan hook.Event { return hook.Start() } -// Deprecated: use the EventEnd() +// Deprecated: use the EventEnd(), +// // End removes global event hook func End() { hook.End() diff --git a/robotgo.go b/robotgo.go index 33915fbb..01ecc1c4 100644 --- a/robotgo.go +++ b/robotgo.go @@ -359,19 +359,22 @@ func GetXDisplayName() string { return gname } -// Deprecated: use the ScaledF() +// Deprecated: use the ScaledF(), +// // ScaleX get the primary display horizontal DPI scale factor, drop func ScaleX() int { return int(C.scale_x()) } -// Deprecated: use the ScaledF() +// Deprecated: use the ScaledF(), +// // ScaleY get primary display vertical DPI scale factor, drop func ScaleY() int { return int(C.scale_y()) } -// Deprecated: use the ScaledF() +// Deprecated: use the ScaledF(), +// // Scale get the screen scale (only windows old), drop func Scale() int { dpi := map[int]int{ @@ -394,13 +397,15 @@ func Scale() int { return dpi[x] } -// Deprecated: use the ScaledF() +// Deprecated: use the ScaledF(), +// // Scale0 return ScaleX() / 0.96, drop func Scale0() int { return int(float64(ScaleX()) / 0.96) } -// Deprecated: use the ScaledF() +// Deprecated: use the ScaledF(), +// // Mul mul the scale, drop func Mul(x int) int { s := Scale() @@ -436,7 +441,8 @@ func CheckMouse(btn string) C.MMMouseButton { return C.LEFT_BUTTON } -// Deprecated: use the Move() +// Deprecated: use the Move(), +// // MoveMouse move the mouse func MoveMouse(x, y int) { Move(x, y) @@ -460,7 +466,8 @@ func Move(x, y int) { MilliSleep(MouseSleep) } -// Deprecated: use the DragSmooth() +// Deprecated: use the DragSmooth(), +// // DragMouse drag the mouse to (x, y), // It's same with the DragSmooth() now func DragMouse(x, y int, args ...interface{}) { @@ -471,7 +478,8 @@ func DragMouse(x, y int, args ...interface{}) { Toggle("left", "up") } -// Deprecated: use the DragSmooth() +// Deprecated: use the DragSmooth(), +// // Drag drag the mouse to (x, y), // It's not valid now, use the DragSmooth() func Drag(x, y int, args ...string) { @@ -498,7 +506,8 @@ func DragSmooth(x, y int, args ...interface{}) { Toggle("left", "up") } -// Deprecated: use the MoveSmooth() +// Deprecated: use the MoveSmooth(), +// // MoveMouseSmooth move the mouse smooth, // moves mouse to x, y human like, with the mouse button up. func MoveMouseSmooth(x, y int, args ...interface{}) bool { @@ -575,7 +584,8 @@ func GetMousePos() (int, int) { return x, y } -// Deprecated: use the Click() +// Deprecated: use the Click(), +// // MouseClick click the mouse // // robotgo.MouseClick(button string, double bool) @@ -653,7 +663,8 @@ func Toggle(key ...string) int { return int(i) } -// Deprecated: use the Toggle() +// Deprecated: use the Toggle(), +// // MouseToggle toggle the mouse // // Examples: @@ -674,7 +685,8 @@ func MouseToggle(togKey string, args ...interface{}) int { return int(i) } -// Deprecated: use the Scroll() +// Deprecated: use the Scroll(), +// // ScrollMouse scroll the mouse to (x, "up") // // Examples: @@ -1074,7 +1086,8 @@ func PasteStr(str string) string { return KeyTap("v", "control") } -// Deprecated: use the TypeStr() +// Deprecated: use the TypeStr(), +// // TypeString send a string, support unicode(no linux support) // TypeStr(string: The string to send), Wno-deprecated // @@ -1098,7 +1111,8 @@ func TypeStrDelay(str string, delay int) { Sleep(delay) } -// Deprecated: use the TypeStr() +// Deprecated: use the TypeStr(), +// // TypeStringDelayed type string delayed, Wno-deprecated // // This function will be removed in version v1.0.0 @@ -1112,7 +1126,8 @@ func SetKeyDelay(delay int) { C.set_keyboard_delay(C.size_t(delay)) } -// Deprecated: use the SetKeyDelay() +// Deprecated: use the SetKeyDelay(), +// // SetKeyboardDelay set keyboard delay, Wno-deprecated, // // This function will be removed in version v1.0.0 @@ -1288,7 +1303,8 @@ func GetHandle() int { return ghwnd } -// Deprecated: use the GetHandle() +// Deprecated: use the GetHandle(), +// // GetBHandle get the window handle, Wno-deprecated // // This function will be removed in version v1.0.0 From 34fc3ffb38bc506f6d6de3aedd44aeaee992324f Mon Sep 17 00:00:00 2001 From: vcaesar Date: Fri, 26 Nov 2021 18:07:08 -0400 Subject: [PATCH 145/327] Optimize Linux get high DPI code --- window/win_sys.h | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/window/win_sys.h b/window/win_sys.h index 7d10e96b..0e1dd155 100644 --- a/window/win_sys.h +++ b/window/win_sys.h @@ -56,16 +56,18 @@ double sys_scale() { // https://github.com/glfw/glfw/issues/1019#issuecomment-302772498 char *rms = XResourceManagerString(dpy); if (rms) { - XrmDatabase db; - XrmValue value; - char *type = NULL; - - XrmInitialize(); /* Need to initialize the DB before calling Xrm* functions */ - db = XrmGetStringDatabase(rms); - if (XrmGetResource(db, "Xft.dpi", "String", &type, &value) == True) { - if (value.addr) { - xres = atof(value.addr); + XrmDatabase db = XrmGetStringDatabase(rms); + if (db) { + XrmValue value; + char *type = NULL; + + if (XrmGetResource(db, "Xft.dpi", "String", &type, &value)) { + if (value.addr) { + xres = atof(value.addr); + } } + + XrmDestroyDatabase(db); } } XCloseDisplay (dpy); From c466829dedd9ec621737ab5f375690f309f7fd73 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 28 Nov 2021 13:12:06 -0400 Subject: [PATCH 146/327] Update godoc and test --- bitmap.go | 4 +++- test/main.go | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/bitmap.go b/bitmap.go index 4ee9f163..75849ad3 100644 --- a/bitmap.go +++ b/bitmap.go @@ -289,12 +289,14 @@ func OpenBitmap(gpath string, args ...int) C.MMBitmapRef { return bit } +// Deprecated: use the BitmapFromStr(), +// // BitmapStr bitmap from string func BitmapStr(str string) C.MMBitmapRef { return BitmapFromStr(str) } -// BitmapFromStr bitmap from string +// BitmapFromStr read bitmap from the string func BitmapFromStr(str string) C.MMBitmapRef { cs := C.CString(str) bit := C.bitmap_from_string(cs) diff --git a/test/main.go b/test/main.go index 27a6180f..2ede969d 100644 --- a/test/main.go +++ b/test/main.go @@ -29,7 +29,8 @@ func aRobotgo() { robotgo.Move(x, y) robotgo.Move(100, 200) - robotgo.MouseToggle("up") + robotgo.Toggle("left") + robotgo.Toggle("left", "up") for i := 0; i < 1080; i += 1000 { fmt.Println(i) From 8d6e60ce67b91db02354d4b90516617476a30206 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 1 Dec 2021 11:43:32 -0400 Subject: [PATCH 147/327] add more test code --- robotgo_test.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/robotgo_test.go b/robotgo_test.go index 5852bc86..0a11e8e6 100644 --- a/robotgo_test.go +++ b/robotgo_test.go @@ -14,6 +14,7 @@ package robotgo import ( + "fmt" "testing" "github.com/vcaesar/tt" @@ -157,6 +158,20 @@ func TestBitmap(t *testing.T) { e := SaveBitmap(bit, "robot_test.png") tt.Empty(t, e) + bit0 := CaptureScreen(10, 10, 20, 20) + x, y := FindBitmap(bit0) + fmt.Println("Find bitmap: ", x, y) + + arr := FindAllBitmap(bit0) + fmt.Println("Find all bitmap:", arr) + tt.Equal(t, 1, len(arr)) + + c1 := CHex(0xAADCDC) + x, y = FindColor(c1) + fmt.Println("Find color: ", x, y) + arr = FindAllColor(c1) + fmt.Println("Find all color: ", arr) + img := ToImage(bit) err := SavePng(img, "robot_img.png") tt.Nil(t, err) From 0a95d7f9571072721527f4fa26edf1fe9162ae81 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 5 Dec 2021 15:15:20 -0400 Subject: [PATCH 148/327] Update dockerfile and CI to go1.7.4 --- .circleci/config.yml | 2 +- .circleci/images/primary/Dockerfile | 2 +- appveyor.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ae0745b5..f5748283 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,7 +5,7 @@ jobs: docker: # using custom image, see .circleci/images/primary/Dockerfile # - image: govgo/robotgoci:1.10.3 - - image: golang:1.17.3 + - image: golang:1.17.4 working_directory: /gopath/src/github.com/go-vgo/robotgo steps: - checkout diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index 3d2036ba..337e37cf 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.7.3-stretch AS build +FROM golang:1.17.4-stretch AS build # FROM govgo/go:1.11.1 RUN apt update && apt install -y --no-install-recommends \ diff --git a/appveyor.yml b/appveyor.yml index 1ca1af88..e4b22d0d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,7 +34,7 @@ environment: PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% # - COMPILER: MINGW_W64 # ARCHITECTURE: x64 - GOVERSION: 1.17.3 + GOVERSION: 1.17.4 # GOPATH: c:\gopath # scripts that run after cloning repository From 6bbf8390df303354049ccf62d248583bf8ac14d7 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 8 Dec 2021 17:49:26 -0400 Subject: [PATCH 149/327] Update README.md --- README.md | 9 +++++++++ README_zh.md | 8 ++++++++ 2 files changed, 17 insertions(+) diff --git a/README.md b/README.md index 5c0b9b5e..2929e634 100644 --- a/README.md +++ b/README.md @@ -112,6 +112,15 @@ sudo dnf install xsel xclip ``` ## Installation: + +With Go module support (Go 1.11+), just import: + +```go +import "github.com/go-vgo/robotgo" +``` + +Otherwise, to install the robotgo package, run the command: + ``` go get github.com/go-vgo/robotgo ``` diff --git a/README_zh.md b/README_zh.md index 9bc54543..37fc345c 100644 --- a/README_zh.md +++ b/README_zh.md @@ -106,6 +106,14 @@ sudo dnf install xsel xclip ``` ## Installation: +With Go module support (Go 1.11+), just import: + +```go +import "github.com/go-vgo/robotgo" +``` + +Otherwise, to install the robotgo package, run the command: + ``` go get github.com/go-vgo/robotgo ``` From 14aa4712b4a2f4ef93bc94587561b2c0c5c10c55 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 8 Dec 2021 17:56:08 -0400 Subject: [PATCH 150/327] Update godoc --- robotgo.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/robotgo.go b/robotgo.go index 01ecc1c4..75c0d3a6 100644 --- a/robotgo.go +++ b/robotgo.go @@ -18,6 +18,12 @@ See Requirements: https://github.com/go-vgo/robotgo#requirements Installation: +With Go module support (Go 1.11+), just import: +```go + import "github.com/go-vgo/robotgo" +``` + +Otherwise, to install the robotgo package, run the command: go get -u github.com/go-vgo/robotgo */ package robotgo @@ -641,7 +647,8 @@ func MovesClick(x, y int, args ...interface{}) { Click(args...) } -// Toggle toggle the mouse, support button: "left", "center", "right", +// Toggle toggle the mouse, support button: +// "left", "center", "right", // "wheelDown", "wheelUp", "wheelLeft", "wheelRight" // // Examples: From 903fad7d0200321d7cb328cbd3f4a8b0cba87411 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 12 Dec 2021 14:02:27 -0400 Subject: [PATCH 151/327] Update dockerfile and CI --- .circleci/config.yml | 2 +- .circleci/images/primary/Dockerfile | 2 +- appveyor.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index f5748283..5b6b8de2 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,7 +5,7 @@ jobs: docker: # using custom image, see .circleci/images/primary/Dockerfile # - image: govgo/robotgoci:1.10.3 - - image: golang:1.17.4 + - image: golang:1.17.5 working_directory: /gopath/src/github.com/go-vgo/robotgo steps: - checkout diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index 337e37cf..d9909c23 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.17.4-stretch AS build +FROM golang:1.17.5-stretch AS build # FROM govgo/go:1.11.1 RUN apt update && apt install -y --no-install-recommends \ diff --git a/appveyor.yml b/appveyor.yml index e4b22d0d..59ababdb 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,7 +34,7 @@ environment: PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% # - COMPILER: MINGW_W64 # ARCHITECTURE: x64 - GOVERSION: 1.17.4 + GOVERSION: 1.17.5 # GOPATH: c:\gopath # scripts that run after cloning repository From 21eeb1981861786f4e7c6e075454fb81e0d8fe29 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Fri, 24 Dec 2021 13:50:06 -0400 Subject: [PATCH 152/327] Update godoc and README.md --- README.md | 9 +++++++-- README_zh.md | 9 +++++++-- docs/keys.md | 4 ++-- robotgo.go | 2 -- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 2929e634..ae7ba915 100644 --- a/README.md +++ b/README.md @@ -79,13 +79,18 @@ In the plans, the bitmap.go will moves to the bitmap dir, but break the API. ) #### For everything else: ``` -GCC, libpng +GCC, +libpng (bitmap) X11 with the XTest extension (also known as the Xtst library) Event: xcb, xkb, libxkbcommon + +Clipboard: + +xsel xclip ``` ##### Ubuntu: @@ -104,7 +109,7 @@ sudo apt install xsel xclip ##### Fedora: ```yml -sudo dnf install libxkbcommon-devel libXtst-devel libxkbcommon-x11-devel xorg-x11-xkb-utils-devel +sudo dnf install libXtst-devel libxkbcommon-devel libxkbcommon-x11-devel xorg-x11-xkb-utils-devel sudo dnf install libpng-devel diff --git a/README_zh.md b/README_zh.md index 37fc345c..29aa363c 100644 --- a/README_zh.md +++ b/README_zh.md @@ -73,13 +73,18 @@ Or you can removed the bitmap.go ) #### For everything else (Linux 等其他系统): ``` -GCC, libpng +GCC, +libpng(bitmap) X11 with the XTest extension (also known as the Xtst library) 事件: xcb, xkb, libxkbcommon + +Clipboard: + +xsel xclip ``` ##### Ubuntu: @@ -98,7 +103,7 @@ sudo apt install xsel xclip ##### Fedora: ```yml -sudo dnf install libxkbcommon-devel libXtst-devel libxkbcommon-x11-devel xorg-x11-xkb-utils-devel +sudo dnf install libXtst-devel libxkbcommon-devel libxkbcommon-x11-devel xorg-x11-xkb-utils-devel sudo dnf install libpng-devel diff --git a/docs/keys.md b/docs/keys.md index 27528336..dff9e228 100644 --- a/docs/keys.md +++ b/docs/keys.md @@ -46,7 +46,7 @@ "cmd" is the "win" key for windows "lcmd" left command "rcmd" right command - "command" + // "command" "alt" "lalt" left alt "ralt" right alt @@ -57,7 +57,7 @@ "shift" "lshift" left shift "rshift" right shift - "right_shift" + // "right_shift" "capslock" "space" "print" diff --git a/robotgo.go b/robotgo.go index 75c0d3a6..21027f59 100644 --- a/robotgo.go +++ b/robotgo.go @@ -19,9 +19,7 @@ See Requirements: Installation: With Go module support (Go 1.11+), just import: -```go import "github.com/go-vgo/robotgo" -``` Otherwise, to install the robotgo package, run the command: go get -u github.com/go-vgo/robotgo From fe42b2a74c10c71b0369fad9eb42428e27371c5c Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sat, 1 Jan 2022 14:39:55 -0400 Subject: [PATCH 153/327] optimize x11 display code --- base/xdisplay_c.h | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/base/xdisplay_c.h b/base/xdisplay_c.h index f2178f3f..f96e835b 100644 --- a/base/xdisplay_c.h +++ b/base/xdisplay_c.h @@ -4,11 +4,11 @@ static Display *mainDisplay = NULL; static int registered = 0; + static char *displayName = NULL; static int hasDisplayNameChanged = 0; -Display *XGetMainDisplay(void) -{ +Display *XGetMainDisplay(void) { /* Close the display if displayName has changed */ if (hasDisplayNameChanged) { XCloseMainDisplay(); @@ -20,7 +20,7 @@ Display *XGetMainDisplay(void) mainDisplay = XOpenDisplay(displayName); /* Then try using environment variable DISPLAY */ - if (mainDisplay == NULL) { + if (mainDisplay == NULL && displayName != NULL) { mainDisplay = XOpenDisplay(NULL); } @@ -40,22 +40,19 @@ Display *XGetMainDisplay(void) return mainDisplay; } -void XCloseMainDisplay(void) -{ +void XCloseMainDisplay(void) { if (mainDisplay != NULL) { XCloseDisplay(mainDisplay); mainDisplay = NULL; } } -void setXDisplay(char *name) -{ +void setXDisplay(char *name) { displayName = strdup(name); hasDisplayNameChanged = 1; } -char *getXDisplay(void) -{ +char *getXDisplay(void) { return displayName; } From 6c249c12a32e0d601e0150bfbad0d1da3db7e1c6 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sat, 1 Jan 2022 16:11:41 -0400 Subject: [PATCH 154/327] rename some files --- robotgo_mac.go => robotgo_mac_unix.go | 0 robotgo_unix.go => robotgo_x11.go | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename robotgo_mac.go => robotgo_mac_unix.go (100%) rename robotgo_unix.go => robotgo_x11.go (100%) diff --git a/robotgo_mac.go b/robotgo_mac_unix.go similarity index 100% rename from robotgo_mac.go rename to robotgo_mac_unix.go diff --git a/robotgo_unix.go b/robotgo_x11.go similarity index 100% rename from robotgo_unix.go rename to robotgo_x11.go From 48f1adce7ebf3657456792a508bac57c03b02a47 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 2 Jan 2022 17:19:49 -0400 Subject: [PATCH 155/327] remove bitmap and hook code [ci skip] --- base/MMBitmap_c.h | 96 - base/MMPointArray.h | 33 - base/MMPointArray_c.h | 41 - base/UTHashTable.h | 83 - base/UTHashTable_c.h | 56 - base/base64.c | 109 - base/base64.h | 31 - base/base64_c.h | 111 - base/bmp_io.h | 54 - base/bmp_io_c.h | 441 --- base/color_find.h | 49 - base/color_find_c.h | 58 - base/file_io.h | 46 - base/file_io_c.h | 70 - base/io.c | 70 - base/pasteboard.h | 28 - base/pasteboard_c.h | 106 - base/png_io.h | 37 - base/png_io_c.h | 346 --- base/snprintf.h | 46 - base/snprintf_c.h | 1019 ------- base/str_io.h | 50 - base/str_io_c.h | 208 -- base/uthash.h | 929 ------ base/zlib_util.h | 32 - base/zlib_util_c.h | 98 - bitmap.go | 550 ---- cdeps/README.md | 1 - cdeps/mac/amd/libpng.a | Bin 255664 -> 0 bytes cdeps/mac/m1/libpng.a | Bin 258360 -> 0 bytes cdeps/mac/png.h | 3278 --------------------- cdeps/mac/pngconf.h | 622 ---- cdeps/mac/pnglibconf.h | 218 -- cdeps/win/amd/win32/libpng.a | Bin 188520 -> 0 bytes cdeps/win/amd/win64/libpng.a | Bin 205978 -> 0 bytes cdeps/win/png.h | 2309 --------------- cdeps/win/pngconf.h | 649 ---- cdeps/win/pnglibconf.h | 181 -- cdeps/win/zconf.h | 428 --- cdeps/win/zlib.h | 1613 ---------- examples/bitmap/bitmapTobytes/main.go | 34 - examples/bitmap/cbitmap/main.go | 53 - examples/bitmap/imgToBitmap/main.go | 52 - examples/bitmap/imgToBitmap/test_007.jpeg | Bin 3261 -> 0 bytes examples/bitmap/main.go | 207 -- examples/gohook/event/main.go | 114 - examples/gohook/hook/main.go | 42 - examples/gohook/main.go | 72 - hook.go | 195 -- 49 files changed, 14865 deletions(-) delete mode 100644 base/MMBitmap_c.h delete mode 100644 base/MMPointArray.h delete mode 100644 base/MMPointArray_c.h delete mode 100644 base/UTHashTable.h delete mode 100644 base/UTHashTable_c.h delete mode 100644 base/base64.c delete mode 100644 base/base64.h delete mode 100644 base/base64_c.h delete mode 100644 base/bmp_io.h delete mode 100644 base/bmp_io_c.h delete mode 100644 base/color_find.h delete mode 100644 base/color_find_c.h delete mode 100644 base/file_io.h delete mode 100644 base/file_io_c.h delete mode 100644 base/io.c delete mode 100644 base/pasteboard.h delete mode 100644 base/pasteboard_c.h delete mode 100644 base/png_io.h delete mode 100644 base/png_io_c.h delete mode 100644 base/snprintf.h delete mode 100644 base/snprintf_c.h delete mode 100644 base/str_io.h delete mode 100644 base/str_io_c.h delete mode 100644 base/uthash.h delete mode 100644 base/zlib_util.h delete mode 100644 base/zlib_util_c.h delete mode 100644 bitmap.go delete mode 100644 cdeps/README.md delete mode 100644 cdeps/mac/amd/libpng.a delete mode 100644 cdeps/mac/m1/libpng.a delete mode 100644 cdeps/mac/png.h delete mode 100644 cdeps/mac/pngconf.h delete mode 100644 cdeps/mac/pnglibconf.h delete mode 100644 cdeps/win/amd/win32/libpng.a delete mode 100644 cdeps/win/amd/win64/libpng.a delete mode 100755 cdeps/win/png.h delete mode 100755 cdeps/win/pngconf.h delete mode 100755 cdeps/win/pnglibconf.h delete mode 100755 cdeps/win/zconf.h delete mode 100755 cdeps/win/zlib.h delete mode 100644 examples/bitmap/bitmapTobytes/main.go delete mode 100644 examples/bitmap/cbitmap/main.go delete mode 100644 examples/bitmap/imgToBitmap/main.go delete mode 100644 examples/bitmap/imgToBitmap/test_007.jpeg delete mode 100644 examples/bitmap/main.go delete mode 100644 examples/gohook/event/main.go delete mode 100644 examples/gohook/hook/main.go delete mode 100644 examples/gohook/main.go delete mode 100644 hook.go diff --git a/base/MMBitmap_c.h b/base/MMBitmap_c.h deleted file mode 100644 index e300f2ae..00000000 --- a/base/MMBitmap_c.h +++ /dev/null @@ -1,96 +0,0 @@ -#include "MMBitmap.h" -#include -#include - - -//MMBitmapRef createMMBitmap() -MMBitmapRef createMMBitmap( - uint8_t *buffer, - size_t width, - size_t height, - size_t bytewidth, - uint8_t bitsPerPixel, - uint8_t bytesPerPixel -){ - MMBitmapRef bitmap = malloc(sizeof(MMBitmap)); - if (bitmap == NULL) return NULL; - - bitmap->imageBuffer = buffer; - bitmap->width = width; - bitmap->height = height; - bitmap->bytewidth = bytewidth; - bitmap->bitsPerPixel = bitsPerPixel; - bitmap->bytesPerPixel = bytesPerPixel; - - return bitmap; -} - -void destroyMMBitmap(MMBitmapRef bitmap) -{ - assert(bitmap != NULL); - - if (bitmap->imageBuffer != NULL) { - free(bitmap->imageBuffer); - bitmap->imageBuffer = NULL; - } - - free(bitmap); -} - -void destroyMMBitmapBuffer(char * bitmapBuffer, void * hint) -{ - if (bitmapBuffer != NULL) - { - free(bitmapBuffer); - } -} - -MMBitmapRef copyMMBitmap(MMBitmapRef bitmap) -{ - uint8_t *copiedBuf = NULL; - - assert(bitmap != NULL); - if (bitmap->imageBuffer != NULL) { - const size_t bufsize = bitmap->height * bitmap->bytewidth; - copiedBuf = malloc(bufsize); - if (copiedBuf == NULL) return NULL; - - memcpy(copiedBuf, bitmap->imageBuffer, bufsize); - } - - return createMMBitmap(copiedBuf, - bitmap->width, - bitmap->height, - bitmap->bytewidth, - bitmap->bitsPerPixel, - bitmap->bytesPerPixel); -} - -MMBitmapRef copyMMBitmapFromPortion(MMBitmapRef source, MMRect rect) -{ - assert(source != NULL); - - if (source->imageBuffer == NULL || !MMBitmapRectInBounds(source, rect)) { - return NULL; - } else { - uint8_t *copiedBuf = NULL; - const size_t bufsize = rect.size.height * source->bytewidth; - const size_t offset = (source->bytewidth * rect.origin.y) + - (rect.origin.x * source->bytesPerPixel); - - /* Don't go over the bounds, programmer! */ - assert((bufsize + offset) <= (source->bytewidth * source->height)); - - copiedBuf = malloc(bufsize); - if (copiedBuf == NULL) return NULL; - - memcpy(copiedBuf, source->imageBuffer + offset, bufsize); - - return createMMBitmap(copiedBuf, - rect.size.width, - rect.size.height, - source->bytewidth, - source->bitsPerPixel, - source->bytesPerPixel); - } -} diff --git a/base/MMPointArray.h b/base/MMPointArray.h deleted file mode 100644 index 447fc721..00000000 --- a/base/MMPointArray.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once -#ifndef MMARRAY_H -#define MMARRAY_H - -#include "types.h" - -struct _MMPointArray { - MMPoint *array; /* Pointer to actual data. */ - size_t count; /* Number of elements in array. */ - size_t _allocedCount; /* Private; do not use outside of MMPointArray.c. */ -}; - -typedef struct _MMPointArray MMPointArray; -typedef MMPointArray *MMPointArrayRef; - -/* Creates array of an initial size (the maximum size is still limitless). - * This follows the "Create" Rule; i.e., responsibility for "destroying" the - * array is given to the caller. */ -MMPointArrayRef createMMPointArray(size_t initialCount); - -/* Frees memory occupied by |pointArray|. Does not accept NULL. */ -void destroyMMPointArray(MMPointArrayRef pointArray); - -/* Appends a point to an array, increasing the internal size if necessary. */ -void MMPointArrayAppendPoint(MMPointArrayRef pointArray, MMPoint point); - -/* Retrieve point from array. */ -#define MMPointArrayGetItem(a, i) ((a)->array)[i] - -/* Set point in array. */ -#define MMPointArraySetItem(a, i, item) ((a)->array[i] = item) - -#endif /* MMARRAY_H */ diff --git a/base/MMPointArray_c.h b/base/MMPointArray_c.h deleted file mode 100644 index f77f3fc0..00000000 --- a/base/MMPointArray_c.h +++ /dev/null @@ -1,41 +0,0 @@ -#include "MMPointArray.h" -#include - -MMPointArrayRef createMMPointArray(size_t initialCount) -{ - MMPointArrayRef pointArray = calloc(1, sizeof(MMPointArray)); - - if (initialCount == 0) initialCount = 1; - - pointArray->_allocedCount = initialCount; - pointArray->array = malloc(pointArray->_allocedCount * sizeof(MMPoint)); - if (pointArray->array == NULL) return NULL; - - return pointArray; -} - -void destroyMMPointArray(MMPointArrayRef pointArray) -{ - if (pointArray->array != NULL) { - free(pointArray->array); - pointArray->array = NULL; - } - - free(pointArray); -} - -void MMPointArrayAppendPoint(MMPointArrayRef pointArray, MMPoint point) -{ - const size_t newCount = ++(pointArray->count); - if (pointArray->_allocedCount < newCount) { - do { - /* Double size each time to avoid calls to realloc(). */ - pointArray->_allocedCount <<= 1; - } while (pointArray->_allocedCount < newCount); - pointArray->array = realloc(pointArray->array, - sizeof(point) * - pointArray->_allocedCount); - } - - pointArray->array[pointArray->count - 1] = point; -} diff --git a/base/UTHashTable.h b/base/UTHashTable.h deleted file mode 100644 index 54cfbe8d..00000000 --- a/base/UTHashTable.h +++ /dev/null @@ -1,83 +0,0 @@ -#pragma once -#ifndef UTHASHTABLE_H -#define UTHASHTABLE_H - -#include -#include "uthash.h" - -/* All node structs must begin with this (note that there is NO semicolon). */ -#define UTHashNode_HEAD UT_hash_handle hh; - -/* This file contains convenience macros and a standard struct for working with - * uthash hash tables. - * - * The main purpose of this is for convenience of creating/freeing nodes. */ -struct _UTHashTable { - void *uttable; /* The uthash table -- must start out as NULL. */ - void *nodes; /* Contiguous array of nodes. */ - size_t allocedNodeCount; /* Node count currently allocated for. */ - size_t nodeCount; /* Current node count. */ - size_t nodeSize; /* Size of each node. */ -}; - -typedef struct _UTHashTable UTHashTable; - -/* Initiates a hash table to the default values. |table| should point to an - * already allocated UTHashTable struct. - * - * If the |initialCount| argument in initHashTable is given, |nodes| is - * allocated immediately to the maximum size and new nodes are simply slices of - * that array. This can save calls to malloc if many nodes are to be added, and - * the a reasonable maximum number is known ahead of time. - * - * If the node count goes over this maximum, or if |initialCount| is 0, the - * array is dynamically reallocated to fit the size. - */ -void initHashTable(UTHashTable *table, size_t initialCount, size_t nodeSize); - -/* Frees memory occupied by a UTHashTable's members. - * - * Note that this does NOT free memory for the UTHashTable pointed to by - * |table| itself; if that was allocated on the heap, you must free() it - * yourself after calling this. */ -void destroyHashTable(UTHashTable *table); - -/* Returns memory allocated for a new node. Responsibility for freeing this is - * up to the destroyHashTable() macro; this should NOT be freed by the caller. - * - * This is intended to be used with a HASH_ADD() macro, e.g.: - * {% - * struct myNode *uttable = utHashTable->uttable; - * struct myNode *node = getNewNode(utHashTable); - * node->key = 42; - * node->value = someValue; - * HASH_ADD_INT(uttable, key, node); - * utHashTable->uttable = uttable; - * %} - * - * Or, use the UTHASHTABLE_ADD_INT or UTHASHTABLE_ADD_STR macros - * for convenience (they are exactly equivalent): - * {% - * struct myNode *node = getNewNode(utHashTable); - * node->key = 42; - * node->value = someValue; - * UTHASHTABLE_ADD_INT(utHashTable, key, node, struct myNode); - * %} - */ -void *getNewNode(UTHashTable *table); - -#define UTHASHTABLE_ADD_INT(tablePtr, keyName, node, nodeType) \ -do { \ - nodeType *uttable = (tablePtr)->uttable; \ - HASH_ADD_INT(uttable, keyName, node); \ - (tablePtr)->uttable = uttable; \ -} while (0) - -#define UTHASHTABLE_ADD_STR(tablePtr, keyName, node, nodeType) \ -do { \ - nodeType *uttable = (tablePtr)->uttable; \ - HASH_ADD_STR(uttable, keyName, node); \ - (tablePtr)->uttable = uttable; \ -} while (0) - -#endif /* MMHASHTABLE_H */ diff --git a/base/UTHashTable_c.h b/base/UTHashTable_c.h deleted file mode 100644 index c0c482a8..00000000 --- a/base/UTHashTable_c.h +++ /dev/null @@ -1,56 +0,0 @@ -#include "UTHashTable.h" -#include -#include - -/* Base struct class (all nodes must contain at least the elements in - * this struct). */ -struct _UTHashNode { - UTHashNode_HEAD -}; - -typedef struct _UTHashNode UTHashNode; - -void initHashTable(UTHashTable *table, size_t initialCount, size_t nodeSize) -{ - assert(table != NULL); - assert(nodeSize >= sizeof(UTHashNode)); - - table->uttable = NULL; /* Must be set to NULL for uthash. */ - table->allocedNodeCount = (initialCount == 0) ? 1 : initialCount; - table->nodeCount = 0; - table->nodeSize = nodeSize; - table->nodes = calloc(table->nodeSize, nodeSize * table->allocedNodeCount); -} - -void destroyHashTable(UTHashTable *table) -{ - UTHashNode *uttable = table->uttable; - UTHashNode *node; - - /* Let uthash do its magic. */ - while (uttable != NULL) { - node = uttable; /* Grab pointer to first item. */ - HASH_DEL(uttable, node); /* Delete it (table advances to next). */ - } - - /* Only giant malloc'd block containing each node must be freed. */ - if (table->nodes != NULL) free(table->nodes); - table->uttable = table->nodes = NULL; -} - -void *getNewNode(UTHashTable *table) -{ - /* Increment node count, resizing table if necessary. */ - const size_t newNodeCount = ++(table->nodeCount); - if (table->allocedNodeCount < newNodeCount) { - do { - /* Double size each time to avoid calls to realloc(). */ - table->allocedNodeCount <<= 1; - } while (table->allocedNodeCount < newNodeCount); - - table->nodes = realloc(table->nodes, table->nodeSize * - table->allocedNodeCount); - } - - return (char *)table->nodes + (table->nodeSize * (table->nodeCount - 1)); -} diff --git a/base/base64.c b/base/base64.c deleted file mode 100644 index 2befad9d..00000000 --- a/base/base64.c +++ /dev/null @@ -1,109 +0,0 @@ -#include "base64.h" -#include -#include -#include -#include - -/* Encoding table as described in RFC1113. */ -const static uint8_t b64_encode_table[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz0123456789+/"; - -/* Decoding table. */ -const static int8_t b64_decode_table[256] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 00-0F */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 10-1F */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, /* 20-2F */ - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, /* 30-3F */ - -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 40-4F */ - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, /* 50-5F */ - -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 60-6F */ - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, /* 70-7F */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 80-8F */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 90-9F */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* A0-AF */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* B0-BF */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* C0-CF */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* D0-DF */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* E0-EF */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* F0-FF */ -}; - -uint8_t *base64decode(const uint8_t *src, const size_t buflen, size_t *retlen){ - int8_t digit, lastdigit; - size_t i, j; - uint8_t *decoded; - const size_t maxlen = ((buflen + 3) / 4) * 3; - - /* Sanity check */ - assert(src != NULL); - - digit = lastdigit = j = 0; - decoded = malloc(maxlen + 1); - if (decoded == NULL) return NULL; - for (i = 0; i < buflen; ++i) { - if ((digit = b64_decode_table[src[i]]) != -1) { - /* Decode block */ - switch (i % 4) { - case 1: - decoded[j++] = ((lastdigit << 2) | ((digit & 0x30) >> 4)); - break; - case 2: - decoded[j++] = (((lastdigit & 0xF) << 4) | ((digit & 0x3C) >> 2)); - break; - case 3: - decoded[j++] = (((lastdigit & 0x03) << 6) | digit); - break; - } - lastdigit = digit; - } - } - - if (retlen != NULL) *retlen = j; - decoded[j] = '\0'; - return decoded; /* Must be free()'d by caller */ -} - -uint8_t *base64encode(const uint8_t *src, const size_t buflen, size_t *retlen){ - size_t i, j; - const size_t maxlen = (((buflen + 3) & ~3)) * 4; - uint8_t *encoded = malloc(maxlen + 1); - if (encoded == NULL) return NULL; - - /* Sanity check */ - assert(src != NULL); - assert(buflen > 0); - - j = 0; - for (i = 0; i < buflen + 1; ++i) { - /* Encode block */ - switch (i % 3) { - case 0: - encoded[j++] = b64_encode_table[src[i] >> 2]; - encoded[j++] = b64_encode_table[((src[i] & 0x03) << 4) | - ((src[i + 1] & 0xF0) >> 4)]; - break; - case 1: - encoded[j++] = b64_encode_table[((src[i] & 0x0F) << 2) | - ((src[i + 1] & 0xC0) >> 6)]; - break; - case 2: - encoded[j++] = b64_encode_table[(src[i] & 0x3F)]; - break; - } - } - - /* Add padding if necessary */ - if ((j % 4) != 0) { - const size_t with_padding = ((j + 3) & ~3); /* Align to 4 bytes */ - do { - encoded[j++] = '='; - } while (j < with_padding); - } - - assert(j <= maxlen); - - if (retlen != NULL) *retlen = j; - encoded[j] = '\0'; - return encoded; /* Must be free()'d by caller */ -} diff --git a/base/base64.h b/base/base64.h deleted file mode 100644 index d12700c5..00000000 --- a/base/base64.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once -#ifndef BASE64_H -#define BASE64_H - -#include - -#if defined(_MSC_VER) - #include "ms_stdint.h" -#else - #include -#endif - -/* Decode a base64 encoded string discarding line breaks and noise. - * - * Returns a new string to be free()'d by caller, or NULL on error. - * Returned string is guaranteed to be NUL-terminated. - * - * If |retlen| is not NULL, it is set to the length of the returned string - * (minus the NUL-terminator) on successful return. */ -uint8_t *base64decode(const uint8_t *buf, const size_t buflen, size_t *retlen); - -/* Encode a base64 encoded string without line breaks or noise. - * - * Returns a new string to be free()'d by caller, or NULL on error. - * Returned string is guaranteed to be NUL-terminated with the correct padding. - * - * If |retlen| is not NULL, it is set to the length of the returned string - * (minus the NUL-terminator) on successful return. */ -uint8_t *base64encode(const uint8_t *buf, const size_t buflen, size_t *retlen); - -#endif /* BASE64_H */ diff --git a/base/base64_c.h b/base/base64_c.h deleted file mode 100644 index 5b384c44..00000000 --- a/base/base64_c.h +++ /dev/null @@ -1,111 +0,0 @@ -#include "base64.h" -#include -#include -#include -#include - -/* Encoding table as described in RFC1113. */ -const static uint8_t b64_encode_table[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz0123456789+/"; - -/* Decoding table. */ -const static int8_t b64_decode_table[256] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 00-0F */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 10-1F */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, /* 20-2F */ - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, /* 30-3F */ - -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 40-4F */ - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, /* 50-5F */ - -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 60-6F */ - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, /* 70-7F */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 80-8F */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 90-9F */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* A0-AF */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* B0-BF */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* C0-CF */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* D0-DF */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* E0-EF */ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* F0-FF */ -}; - -uint8_t *base64decode(const uint8_t *src, const size_t buflen, size_t *retlen) -{ - int8_t digit, lastdigit; - size_t i, j; - uint8_t *decoded; - const size_t maxlen = ((buflen + 3) / 4) * 3; - - /* Sanity check */ - assert(src != NULL); - - digit = lastdigit = j = 0; - decoded = malloc(maxlen + 1); - if (decoded == NULL) return NULL; - for (i = 0; i < buflen; ++i) { - if ((digit = b64_decode_table[src[i]]) != -1) { - /* Decode block */ - switch (i % 4) { - case 1: - decoded[j++] = ((lastdigit << 2) | ((digit & 0x30) >> 4)); - break; - case 2: - decoded[j++] = (((lastdigit & 0xF) << 4) | ((digit & 0x3C) >> 2)); - break; - case 3: - decoded[j++] = (((lastdigit & 0x03) << 6) | digit); - break; - } - lastdigit = digit; - } - } - - if (retlen != NULL) *retlen = j; - decoded[j] = '\0'; - return decoded; /* Must be free()'d by caller */ -} - -uint8_t *base64encode(const uint8_t *src, const size_t buflen, size_t *retlen) -{ - size_t i, j; - const size_t maxlen = (((buflen + 3) & ~3)) * 4; - uint8_t *encoded = malloc(maxlen + 1); - if (encoded == NULL) return NULL; - - /* Sanity check */ - assert(src != NULL); - assert(buflen > 0); - - j = 0; - for (i = 0; i < buflen + 1; ++i) { - /* Encode block */ - switch (i % 3) { - case 0: - encoded[j++] = b64_encode_table[src[i] >> 2]; - encoded[j++] = b64_encode_table[((src[i] & 0x03) << 4) | - ((src[i + 1] & 0xF0) >> 4)]; - break; - case 1: - encoded[j++] = b64_encode_table[((src[i] & 0x0F) << 2) | - ((src[i + 1] & 0xC0) >> 6)]; - break; - case 2: - encoded[j++] = b64_encode_table[(src[i] & 0x3F)]; - break; - } - } - - /* Add padding if necessary */ - if ((j % 4) != 0) { - const size_t with_padding = ((j + 3) & ~3); /* Align to 4 bytes */ - do { - encoded[j++] = '='; - } while (j < with_padding); - } - - assert(j <= maxlen); - - if (retlen != NULL) *retlen = j; - encoded[j] = '\0'; - return encoded; /* Must be free()'d by caller */ -} diff --git a/base/bmp_io.h b/base/bmp_io.h deleted file mode 100644 index fb510dbd..00000000 --- a/base/bmp_io.h +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once -#ifndef BMP_IO_H -#define BMP_IO_H - -#include "MMBitmap.h" -#include "file_io.h" - -enum _BMPReadError { - kBMPGenericError = 0, - kBMPAccessError, - kBMPInvalidKeyError, - kBMPUnsupportedHeaderError, - kBMPInvalidColorPanesError, - kBMPUnsupportedColorDepthError, - kBMPUnsupportedCompressionError, - kBMPInvalidPixelDataError -}; - -typedef MMIOError MMBMPReadError; - -/* Returns description of given MMBMPReadError. - * Returned string is constant and hence should not be freed. */ -const char *MMBMPReadErrorString(MMIOError error); - -/* Attempts to read bitmap file at path; returns new MMBitmap on success, or - * NULL on error. If |error| is non-NULL, it will be set to the error code - * on return. - * - * Currently supports: - * - Uncompressed Windows v3/v4/v5 24-bit or 32-bit BMP. - * - OS/2 v1 or v2 24-bit BMP. - * - Does NOT yet support: 1-bit, 4-bit, 8-bit, 16-bit, compressed bitmaps, - * or PNGs/JPEGs disguised as BMPs (and returns NULL if those are given). - * - * Responsibility for destroy()'ing returned MMBitmap is left up to caller. */ -MMBitmapRef newMMBitmapFromBMP(const char *path, MMBMPReadError *error); - -/* Returns a buffer containing the raw BMP file data in Windows v3 BMP format, - * ready to be saved to a file. If |len| is not NULL, it will be set to the - * number of bytes allocated in the returned buffer. - * - * Responsibility for free()'ing data is left up to the caller. */ -uint8_t *createBitmapData(MMBitmapRef bitmap, size_t *len); - -/* Saves bitmap to file in Windows v3 BMP format. - * Returns 0 on success, -1 on error. */ -int saveMMBitmapAsBMP(MMBitmapRef bitmap, const char *path); - -/* Swaps bitmap from Quadrant 1 to Quadran III format, or vice versa - * (upside-down Cartesian/PostScript/GL <-> right side up QD/CG raster format). - */ -void flipBitmapData(void *data, size_t width, size_t height, size_t bytewidth); - -#endif /* BMP_IO_H */ diff --git a/base/bmp_io_c.h b/base/bmp_io_c.h deleted file mode 100644 index 6812ae8f..00000000 --- a/base/bmp_io_c.h +++ /dev/null @@ -1,441 +0,0 @@ -#include "bmp_io.h" -#include "os.h" -#include "endian.h" -#include /* fopen() */ -#include /* memcpy() */ - -#if defined(_MSC_VER) - #include "ms_stdbool.h" - #include "ms_stdint.h" -#else - #include - #include -#endif - -#pragma pack(push, 1) /* The following structs should be continguous, so we can - * copy them in one read. */ -/* - * Standard, initial BMP Header - */ -struct BITMAP_FILE_HEADER { - uint16_t magic; /* First two byes of the file; should be 0x4D42. */ - uint32_t fileSize; /* Size of the BMP file in bytes (unreliable). */ - uint32_t reserved; /* Application-specific. */ - uint32_t imageOffset; /* Offset to bitmap data. */ -}; - -#define BMP_MAGIC 0x4D42 /* The starting key that marks the file as a BMP. */ - -enum _BMP_COMPRESSION { - kBMP_RGB = 0, /* No compression. */ - kBMP_RLE8 = 1, /* Can only be used with 8-bit bitmaps. */ - kBMP_RLE4 = 2, /* Can only be used with 4-bit bitmaps. */ - kBMP_BITFIELDS = 3, /* Can only be used with 16/32-bit bitmaps. */ - kBMP_JPEG = 4, /* Bitmap contains a JPEG image. */ - kBMP_PNG = 5 /* Bitmap contains a PNG image. */ -}; - -typedef uint32_t BMP_COMPRESSION; - -/* - * Windows 3 Header - */ -struct BITMAP_INFO_HEADER { - uint32_t headerSize; /* The size of this header (40 bytes). */ - int32_t width; /* The bitmap width in pixels. */ - int32_t height; /* The bitmap height in pixels. */ - /* (A negative value denotes that the image - * is flipped.) */ - uint16_t colorPlanes; /* The number of color planes; must be 1. */ - uint16_t bitsPerPixel; /* The color depth of the image (1, 4, 8, 16, - * 24, or 32). */ - BMP_COMPRESSION compression; /* The compression method being used. */ - uint32_t imageSize; /* Size of the bitmap in bytes (unreliable).*/ - int32_t xRes; /* The horizontal resolution (unreliable). */ - int32_t yRes; /* The vertical resolution (unreliable). */ - uint32_t colorsUsed; /* The number of colors in the color table, - * or 0 to default to 2^n. */ - uint32_t colorsImportant; /* Colors important for displaying bitmap, - * or 0 when every color is equally important; - * ignored. */ -}; - -/* - * OS/2 v1 Header - */ -struct BITMAP_CORE_HEADER { - uint32_t headerSize; /* The size of this header (12 bytes). */ - uint16_t width; /* The bitmap width in pixels. */ - uint16_t height; /* The bitmap height in pixels. */ - uint16_t colorPlanes; /* The number of color planes; must be 1. */ - uint16_t bitsPerPixel; /* Color depth of the image (1, 4, 8, or 24). */ -}; - -#pragma pack(pop) /* Let the compiler do what it wants now. */ - -/* BMP files are always saved in little endian format (x86), so we need to - * convert them if we're not on a little endian machine (e.g., ARM & ppc). */ - -#if __BYTE_ORDER == __BIG_ENDIAN - -/* Converts bitmap file header from to and from little endian, if and only if - * host is big endian. */ -static void convertBitmapFileHeader(struct BITMAP_FILE_HEADER *header) -{ - header->magic = swapLittleAndHost16(header->magic); - swapLittleAndHost32(header->fileSize); - swapLittleAndHost32(header->reserved); - swapLittleAndHost32(header->imageOffset); -} - -/* Converts bitmap info header from to and from little endian, if and only if - * host is big endian. */ -static void convertBitmapInfoHeader(struct BITMAP_INFO_HEADER *header) -{ - header->headerSize = swapLittleAndHost32(header->headerSize); - header->width = swapLittleAndHost32(header->width); - header->height = swapLittleAndHost32(header->height); - header->colorPlanes = swapLittleAndHost16(header->colorPlanes); - header->bitsPerPixel = swapLittleAndHost16(header->bitsPerPixel); - header->compression = swapLittleAndHost32(header->compression); - header->imageSize = swapLittleAndHost32(header->imageSize); - header->xRes = swapLittleAndHost32(header->xRes); - header->yRes = swapLittleAndHost32(header->yRes); - header->colorsUsed = swapLittleAndHost32(header->colorsUsed); - header->colorsImportant = swapLittleAndHost32(header->colorsImportant); -} - -#elif __BYTE_ORDER == __LITTLE_ENDIAN - /* No conversion necessary if we are already little endian. */ - #define convertBitmapFileHeader(header) - #define convertBitmapInfoHeader(header) -#endif - -/* Returns newly alloc'd image data from bitmap file. The current position of - * the file must be at the start of the image before calling this. */ -static uint8_t *readImageData(FILE *fp, size_t width, size_t height, - uint8_t bytesPerPixel, size_t bytewidth); - -/* Copys image buffer from |bitmap| to |dest| in BGR format. */ -static void copyBGRDataFromMMBitmap(MMBitmapRef bitmap, uint8_t *dest); - -const char *MMBMPReadErrorString(MMIOError error) -{ - switch (error) { - case kBMPAccessError: - return "Could not open file"; - case kBMPInvalidKeyError: - return "Not a BMP file"; - case kBMPUnsupportedHeaderError: - return "Unsupported BMP header"; - case kBMPInvalidColorPanesError: - return "Invalid number of color panes in BMP file"; - case kBMPUnsupportedColorDepthError: - return "Unsupported color depth in BMP file"; - case kBMPUnsupportedCompressionError: - return "Unsupported file compression in BMP file"; - case kBMPInvalidPixelDataError: - return "Could not read BMP pixel data"; - default: - return NULL; - } -} - -MMBitmapRef newMMBitmapFromBMP(const char *path, MMBMPReadError *err) -{ - FILE *fp; - struct BITMAP_FILE_HEADER fileHeader = {0}; /* Initialize elements to 0. */ - struct BITMAP_INFO_HEADER dibHeader = {0}; - uint32_t headerSize = 0; - uint8_t bytesPerPixel; - size_t bytewidth; - uint8_t *imageBuf; - - if ((fp = fopen(path, "rb")) == NULL) { - if (err != NULL) *err = kBMPAccessError; - return NULL; - } - - /* Initialize error code to generic value. */ - if (err != NULL) *err = kBMPGenericError; - - if (fread(&fileHeader, sizeof(fileHeader), 1, fp) == 0) goto bail; - - /* Convert from little-endian if it's not already. */ - convertBitmapFileHeader(&fileHeader); - - /* First two bytes should always be 0x4D42. */ - if (fileHeader.magic != BMP_MAGIC) { - if (err != NULL) *err = kBMPInvalidKeyError; - goto bail; - } - - /* Get header size. */ - if (fread(&headerSize, sizeof(headerSize), 1, fp) == 0) goto bail; - headerSize = swapLittleAndHost32(headerSize); - - /* Back up before reading header. */ - if (fseek(fp, -(long)sizeof(headerSize), SEEK_CUR) < 0) goto bail; - - if (headerSize == 12) { /* OS/2 v1 header */ - struct BITMAP_CORE_HEADER coreHeader = {0}; - if (fread(&coreHeader, sizeof(coreHeader), 1, fp) == 0) goto bail; - - dibHeader.width = coreHeader.width; - dibHeader.height = coreHeader.height; - dibHeader.colorPlanes = coreHeader.colorPlanes; - dibHeader.bitsPerPixel = coreHeader.bitsPerPixel; - } else if (headerSize == 40 || headerSize == 108 || headerSize == 124) { - /* Windows v3/v4/v5 header */ - /* Read only the common part (v3) and skip over the rest. */ - if (fread(&dibHeader, sizeof(dibHeader), 1, fp) == 0) goto bail; - } else { - if (err != NULL) *err = kBMPUnsupportedHeaderError; - goto bail; - } - - convertBitmapInfoHeader(&dibHeader); - - if (dibHeader.colorPlanes != 1) { - if (err != NULL) *err = kBMPInvalidColorPanesError; - goto bail; - } - - /* Currently only 24-bit and 32-bit are supported. */ - if (dibHeader.bitsPerPixel != 24 && dibHeader.bitsPerPixel != 32) { - if (err != NULL) *err = kBMPUnsupportedColorDepthError; - goto bail; - } - - if (dibHeader.compression != kBMP_RGB) { - if (err != NULL) *err = kBMPUnsupportedCompressionError; - goto bail; - } - - /* This can happen because we don't fully parse Windows v4/v5 headers. */ - if (ftell(fp) != (long)fileHeader.imageOffset) { - fseek(fp, fileHeader.imageOffset, SEEK_SET); - } - - /* Get bytes per row, including padding. */ - bytesPerPixel = dibHeader.bitsPerPixel / 8; - bytewidth = ADD_PADDING(dibHeader.width * bytesPerPixel); - - imageBuf = readImageData(fp, dibHeader.width, abs(dibHeader.height), - bytesPerPixel, bytewidth); - fclose(fp); - - if (imageBuf == NULL) { - if (err != NULL) *err = kBMPInvalidPixelDataError; - return NULL; - } - - /* A negative height indicates that the image is flipped. - * - * We store our bitmaps as "flipped" according to the BMP format; i.e., (0, 0) - * is the top left, not bottom left. So we only need to flip the bitmap if - * the height is NOT negative. */ - if (dibHeader.height < 0) { - dibHeader.height = -dibHeader.height; - } else { - flipBitmapData(imageBuf, dibHeader.width, dibHeader.height, bytewidth); - } - - return createMMBitmap(imageBuf, dibHeader.width, dibHeader.height, - bytewidth, (uint8_t)dibHeader.bitsPerPixel, - bytesPerPixel); - -bail: - fclose(fp); - return NULL; -} - -uint8_t *createBitmapData(MMBitmapRef bitmap, size_t *len) -{ - /* BMP files are always aligned to 4 bytes. */ - const size_t bytewidth = ((bitmap->width * bitmap->bytesPerPixel) + 3) & ~3; - - const size_t imageSize = bytewidth * bitmap->height; - struct BITMAP_FILE_HEADER *fileHeader; - struct BITMAP_INFO_HEADER *dibHeader; - - /* Should always be 54. */ - const size_t imageOffset = sizeof(*fileHeader) + sizeof(*dibHeader); - uint8_t *data; - const size_t dataLen = imageOffset + imageSize; - - data = calloc(1, dataLen); - if (data == NULL) return NULL; - - /* Save top header. */ - fileHeader = (struct BITMAP_FILE_HEADER *)data; - fileHeader->magic = BMP_MAGIC; - fileHeader->fileSize = (uint32_t)(sizeof(*dibHeader) + imageSize); - fileHeader->imageOffset = (uint32_t)imageOffset; - - /* BMP files are always stored as little-endian, so we need to convert back - * if necessary. */ - convertBitmapFileHeader(fileHeader); - - /* Copy Windows v3 header. */ - dibHeader = (struct BITMAP_INFO_HEADER *)(data + sizeof(*fileHeader)); - dibHeader->headerSize = sizeof(*dibHeader); /* Should always be 40. */ - dibHeader->width = (int32_t)bitmap->width; - dibHeader->height = -(int32_t)bitmap->height; /* Our bitmaps are "flipped". */ - dibHeader->colorPlanes = 1; - dibHeader->bitsPerPixel = bitmap->bitsPerPixel; - dibHeader->compression = kBMP_RGB; /* Don't save with compression. */ - dibHeader->imageSize = (uint32_t)imageSize; - - convertBitmapInfoHeader(dibHeader); - - /* Lastly, copy the pixel data. */ - copyBGRDataFromMMBitmap(bitmap, data + imageOffset); - - if (len != NULL) *len = dataLen; - return data; -} - -int saveMMBitmapAsBMP(MMBitmapRef bitmap, const char *path) -{ - FILE *fp; - size_t dataLen; - uint8_t *data; - - if ((fp = fopen(path, "wb")) == NULL) return -1; - - if ((data = createBitmapData(bitmap, &dataLen)) == NULL) { - fclose(fp); - return -1; - } - - if (fwrite(data, dataLen, 1, fp) == 0) { - free(data); - fclose(fp); - return -1; - } - - free(data); - fclose(fp); - return 0; -} - -uint8_t *saveMMBitmapAsBytes(MMBitmapRef bitmap, size_t *dataLen) -{ - uint8_t *data; - if ((data = createBitmapData(bitmap, dataLen)) == NULL) { - *dataLen = -1; - return NULL; - } - return data; -} - -static uint8_t *readImageData(FILE *fp, size_t width, size_t height, - uint8_t bytesPerPixel, size_t bytewidth) -{ - size_t imageSize = bytewidth * height; - uint8_t *imageBuf = calloc(1, imageSize); - - if (MMRGB_IS_BGR && (bytewidth % 4) == 0) { /* No conversion needed. */ - if (fread(imageBuf, imageSize, 1, fp) == 0) { - free(imageBuf); - return NULL; - } - } else { /* Convert from BGR with 4-byte alignment. */ - uint8_t *row = malloc(bytewidth); - size_t y; - const size_t bmp_bytewidth = (width * bytesPerPixel + 3) & ~3; - - if (row == NULL) return NULL; - assert(bmp_bytewidth <= bytewidth); - - /* Read image data row by row. */ - for (y = 0; y < height; ++y) { - const size_t rowOffset = y * bytewidth; - size_t x; - uint8_t *rowptr = row; - if (fread(row, bmp_bytewidth, 1, fp) == 0) { - free(imageBuf); - free(row); - return NULL; - } - - for (x = 0; x < width; ++x) { - const size_t colOffset = x * bytesPerPixel; - MMRGBColor *color = (MMRGBColor *)(imageBuf + - rowOffset + colOffset); - - /* BMP files are stored in BGR format. */ - color->blue = rowptr[0]; - color->green = rowptr[1]; - color->red = rowptr[2]; - rowptr += bytesPerPixel; - } - } - - free(row); - } - - return imageBuf; -} - -static void copyBGRDataFromMMBitmap(MMBitmapRef bitmap, uint8_t *dest) -{ - if (MMRGB_IS_BGR && (bitmap->bytewidth % 4) == 0) { /* No conversion needed. */ - memcpy(dest, bitmap->imageBuffer, bitmap->bytewidth * bitmap->height); - } else { /* Convert to RGB with other-than-4-byte alignment. */ - const size_t bytewidth = (bitmap->width * bitmap->bytesPerPixel + 3) & ~3; - size_t y; - - /* Copy image data row by row. */ - for (y = 0; y < bitmap->height; ++y) { - uint8_t *rowptr = dest + (y * bytewidth); - size_t x; - for (x = 0; x < bitmap->width; ++x) { - MMRGBColor *color = MMRGBColorRefAtPoint(bitmap, x, y); - - /* BMP files are stored in BGR format. */ - rowptr[0] = color->blue; - rowptr[1] = color->green; - rowptr[2] = color->red; - - rowptr += bitmap->bytesPerPixel; - } - } - } -} - -/* Perform an in-place swap from Quadrant 1 to Quadrant III format (upside-down - * PostScript/GL to right side up QD/CG raster format) We do this in-place, - * which requires more copying, but will touch only half the pages. - * - * This is blatantly copied from Apple's glGrab example code. */ -void flipBitmapData(void *data, size_t width, size_t height, size_t bytewidth) -{ - size_t top, bottom; - void *topP; - void *bottomP; - void *tempbuf; - - if (height <= 1) return; /* No flipping necessary if height is <= 1. */ - - top = 0; - bottom = height - 1; - tempbuf = malloc(bytewidth); - if (tempbuf == NULL) return; - - while (top < bottom) { - topP = (void *)((top * bytewidth) + (intptr_t)data); - bottomP = (void *)((bottom * bytewidth) + (intptr_t)data); - - /* Save and swap scanlines. - * Does a simple in-place exchange with a temp buffer. */ - memcpy(tempbuf, topP, bytewidth); - memcpy(topP, bottomP, bytewidth); - memcpy(bottomP, tempbuf, bytewidth); - - ++top; - --bottom; - } - free(tempbuf); -} diff --git a/base/color_find.h b/base/color_find.h deleted file mode 100644 index 3c732f64..00000000 --- a/base/color_find.h +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once -#ifndef COLOR_FIND_H -#define COLOR_FIND_H - -#include "MMBitmap.h" -#include "MMPointArray.h" - -/* Convenience wrapper around findColorInRect(), where |rect| is the bounds of - * the image. */ -#define findColorInImage(image, color, pointPtr, tolerance) \ - findColorInRect(image, color, pointPtr, MMBitmapGetBounds(image), tolerance) - -/* Attempt to find a pixel with the given color in |image| inside |rect|. - * Returns 0 on success, non-zero on failure. If the color was found and - * |point| is not NULL, it will be initialized to the (x, y) coordinates the - * RGB color. - * - * |tolerance| should be in the range 0.0f - 1.0f, denoting how closely the - * colors need to match, with 0 being exact and 1 being any. */ -int findColorInRect(MMBitmapRef image, MMRGBHex color, MMPoint *point, - MMRect rect, float tolerance); - -/* Convenience wrapper around findAllRGBInRect(), where |rect| is the bounds of - * the image. */ -#define findAllColorInImage(image, color, tolerance) \ - findAllColorInRect(image, color, MMBitmapGetBounds(image), tolerance) - -/* Returns MMPointArray of all pixels of given color in |image| inside of - * |rect|. Note that an array is returned regardless of whether the color was - * found; check array->count to see if it actually was. - * - * Responsibility for freeing the MMPointArray with destroyMMPointArray() is - * given to the caller. - * - * |tolerance| should be in the range 0.0f - 1.0f, denoting how closely the - * colors need to match, with 0 being exact and 1 being any. */ -MMPointArrayRef findAllColorInRect(MMBitmapRef image, MMRGBHex color, - MMRect rect, float tolerance); - -/* Convenience wrapper around countOfColorsInRect, where |rect| is the bounds - * of the image. */ -#define countOfColorsInImage(image, color, tolerance) \ - countOfColorsInRect(image, color, MMBitmapGetBounds(image), tolerance) - -/* Returns the count of the given color in |rect| inside of |image|. */ -size_t countOfColorsInRect(MMBitmapRef image, MMRGBHex color, MMRect rect, - float tolerance); - -#endif /* COLOR_FIND_H */ diff --git a/base/color_find_c.h b/base/color_find_c.h deleted file mode 100644 index 9953d82a..00000000 --- a/base/color_find_c.h +++ /dev/null @@ -1,58 +0,0 @@ -#include "color_find.h" -// #include "../screen/screen_init.h" -#include - -/* Abstracted, general function to avoid repeated code. */ -static int findColorInRectAt(MMBitmapRef image, MMRGBHex color, MMPoint *point, - MMRect rect, float tolerance, MMPoint startPoint) -{ - MMPoint scan = startPoint; - if (!MMBitmapRectInBounds(image, rect)) return -1; - - for (; scan.y < rect.size.height; ++scan.y) { - for (; scan.x < rect.size.width; ++scan.x) { - MMRGBHex found = MMRGBHexAtPoint(image, scan.x, scan.y); - if (MMRGBHexSimilarToColor(color, found, tolerance)) { - if (point != NULL) *point = scan; - return 0; - } - } - scan.x = rect.origin.x; - } - - return -1; -} - -int findColorInRect(MMBitmapRef image, MMRGBHex color, - MMPoint *point, MMRect rect, float tolerance) -{ - return findColorInRectAt(image, color, point, rect, tolerance, rect.origin); -} - -MMPointArrayRef findAllColorInRect(MMBitmapRef image, MMRGBHex color, - MMRect rect, float tolerance) -{ - MMPointArrayRef pointArray = createMMPointArray(0); - MMPoint point = MMPointZero; - - while (findColorInRectAt(image, color, &point, rect, tolerance, point) == 0) { - MMPointArrayAppendPoint(pointArray, point); - ITER_NEXT_POINT(point, rect.size.width, rect.origin.x); - } - - return pointArray; -} - -size_t countOfColorsInRect(MMBitmapRef image, MMRGBHex color, MMRect rect, - float tolerance) -{ - size_t count = 0; - MMPoint point = MMPointZero; - - while (findColorInRectAt(image, color, &point, rect, tolerance, point) == 0) { - ITER_NEXT_POINT(point, rect.size.width, rect.origin.x); - ++count; - } - - return count; -} diff --git a/base/file_io.h b/base/file_io.h deleted file mode 100644 index 427038be..00000000 --- a/base/file_io.h +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once -#ifndef FILE_IO_H -#define FILE_IO_H - -#include "MMBitmap.h" -#include -#include - - -enum _MMImageType { - kInvalidImageType = 0, - kPNGImageType, - kBMPImageType /* Currently only PNG and BMP are supported. */ -}; - -typedef uint16_t MMImageType; - -enum _MMIOError { - kMMIOUnsupportedTypeError = 0 -}; - -typedef uint16_t MMIOError; - -const char *getExtension(const char *fname, size_t len); - -/* Returns best guess at the MMImageType based on a file extension, or - * |kInvalidImageType| if no matching type was found. */ -MMImageType imageTypeFromExtension(const char *ext); - -/* Attempts to parse the file of the given type at the given path. - * |filepath| is an ASCII string describing the absolute POSIX path. - * Returns new bitmap (to be destroy()'d by caller) on success, NULL on error. - * If |error| is non-NULL, it will be set to the error code on return. - */ -MMBitmapRef newMMBitmapFromFile(const char *path, MMImageType type, MMIOError *err); - -/* Saves |bitmap| to a file of the given type at the given path. - * |filepath| is an ASCII string describing the absolute POSIX path. - * Returns 0 on success, -1 on error. */ -int saveMMBitmapToFile(MMBitmapRef bitmap, const char *path, MMImageType type); - -/* Returns description of given error code. - * Returned string is constant and hence should not be freed. */ -const char *MMIOErrorString(MMImageType type, MMIOError error); - -#endif /* IO_H */ diff --git a/base/file_io_c.h b/base/file_io_c.h deleted file mode 100644 index 492b2e74..00000000 --- a/base/file_io_c.h +++ /dev/null @@ -1,70 +0,0 @@ -#include "file_io.h" -// #include "os.h" -#include "bmp_io_c.h" -#include "png_io_c.h" -#include /* For fputs() */ -#include /* For strcmp() */ -#include /* For tolower() */ - -const char *getExtension(const char *fname, size_t len){ - if (fname == NULL || len <= 0) return NULL; - - while (--len > 0 && fname[len] != '.' && fname[len] != '\0') - ; - - return fname + len + 1; -} - -MMImageType imageTypeFromExtension(const char *extension){ - char ext[4]; - const size_t maxlen = sizeof(ext) / sizeof(ext[0]); - size_t i; - - for (i = 0; extension[i] != '\0'; ++i) { - if (i >= maxlen) return kInvalidImageType; - ext[i] = tolower(extension[i]); - } - ext[i] = '\0'; - - if (strcmp(ext, "png") == 0) { - return kPNGImageType; - } else if (strcmp(ext, "bmp") == 0) { - return kBMPImageType; - } else { - return kInvalidImageType; - } -} - -MMBitmapRef newMMBitmapFromFile(const char *path, MMImageType type, MMIOError *err){ - switch (type) { - case kBMPImageType: - return newMMBitmapFromBMP(path, err); - case kPNGImageType: - return newMMBitmapFromPNG(path, err); - default: - if (err != NULL) *err = kMMIOUnsupportedTypeError; - return NULL; - } -} - -int saveMMBitmapToFile(MMBitmapRef bitmap, const char *path, MMImageType type){ - switch (type) { - case kBMPImageType: - return saveMMBitmapAsBMP(bitmap, path); - case kPNGImageType: - return saveMMBitmapAsPNG(bitmap, path); - default: - return -1; - } -} - -const char *MMIOErrorString(MMImageType type, MMIOError error){ - switch (type) { - case kBMPImageType: - return MMBMPReadErrorString(error); - case kPNGImageType: - return MMPNGReadErrorString(error); - default: - return "Unsupported image type"; - } -} diff --git a/base/io.c b/base/io.c deleted file mode 100644 index 1a10dbb3..00000000 --- a/base/io.c +++ /dev/null @@ -1,70 +0,0 @@ -#include "file_io.h" -#include "os.h" -#include "bmp_io.h" -#include "png_io.h" -#include /* For fputs() */ -#include /* For strcmp() */ -#include /* For tolower() */ - -const char *getExtension(const char *fname, size_t len){ - if (fname == NULL || len <= 0) return NULL; - - while (--len > 0 && fname[len] != '.' && fname[len] != '\0') - ; - - return fname + len + 1; -} - -MMImageType imageTypeFromExtension(const char *extension){ - char ext[4]; - const size_t maxlen = sizeof(ext) / sizeof(ext[0]); - size_t i; - - for (i = 0; extension[i] != '\0'; ++i) { - if (i >= maxlen) return kInvalidImageType; - ext[i] = tolower(extension[i]); - } - ext[i] = '\0'; - - if (strcmp(ext, "png") == 0) { - return kPNGImageType; - } else if (strcmp(ext, "bmp") == 0) { - return kBMPImageType; - } else { - return kInvalidImageType; - } -} - -MMBitmapRef newMMBitmapFromFile(const char *path, MMImageType type, MMIOError *err){ - switch (type) { - case kBMPImageType: - return newMMBitmapFromBMP(path, err); - case kPNGImageType: - return newMMBitmapFromPNG(path, err); - default: - if (err != NULL) *err = kMMIOUnsupportedTypeError; - return NULL; - } -} - -int saveMMBitmapToFile(MMBitmapRef bitmap, const char *path, MMImageType type){ - switch (type) { - case kBMPImageType: - return saveMMBitmapAsBMP(bitmap, path); - case kPNGImageType: - return saveMMBitmapAsPNG(bitmap, path); - default: - return -1; - } -} - -const char *MMIOErrorString(MMImageType type, MMIOError error){ - switch (type) { - case kBMPImageType: - return MMBMPReadErrorString(error); - case kPNGImageType: - return MMPNGReadErrorString(error); - default: - return "Unsupported image type"; - } -} diff --git a/base/pasteboard.h b/base/pasteboard.h deleted file mode 100644 index 7ef55075..00000000 --- a/base/pasteboard.h +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once -#ifndef PASTEBOARD_H -#define PASTEBOARD_H - -#include "MMBitmap.h" -#include "file_io.h" - -enum _MMBitmapPasteError { - kMMPasteNoError = 0, - kMMPasteGenericError, - kMMPasteOpenError, - kMMPasteClearError, - kMMPasteDataError, - kMMPastePasteError, - kMMPasteUnsupportedError -}; - -typedef MMIOError MMPasteError; - -/* Copies |bitmap| to the pasteboard as a PNG. - * Returns 0 on success, non-zero on error. */ -MMPasteError copyMMBitmapToPasteboard(MMBitmapRef bitmap); - -/* Returns description of given MMPasteError. - * Returned string is constant and hence should not be freed. */ -const char *MMPasteErrorString(MMPasteError error); - -#endif /* PASTEBOARD_H */ diff --git a/base/pasteboard_c.h b/base/pasteboard_c.h deleted file mode 100644 index c829c1d1..00000000 --- a/base/pasteboard_c.h +++ /dev/null @@ -1,106 +0,0 @@ -#include "pasteboard.h" -#include "os.h" - -#if defined(IS_MACOSX) - #include "png_io.h" - #include -#elif defined(IS_WINDOWS) - #include "bmp_io.h" -#endif - -MMPasteError copyMMBitmapToPasteboard(MMBitmapRef bitmap) -{ -#if defined(IS_MACOSX) - PasteboardRef clipboard; - - size_t len; - uint8_t *pngbuf; - CFDataRef data; - OSStatus err; - - if (PasteboardCreate(kPasteboardClipboard, &clipboard) != noErr) { - return kMMPasteOpenError; - } - - if (PasteboardClear(clipboard) != noErr) { - CFRelease(clipboard); - return kMMPasteClearError; - } - - pngbuf = createPNGData(bitmap, &len); - if (pngbuf == NULL) { - CFRelease(clipboard); - return kMMPasteDataError; - } - - data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, pngbuf, len, - kCFAllocatorNull); - if (data == NULL) { - CFRelease(clipboard); - free(pngbuf); - return kMMPasteDataError; - } - - err = PasteboardPutItemFlavor(clipboard, bitmap, kUTTypePNG, data, 0); - CFRelease(data); - CFRelease(clipboard); - free(pngbuf); - return (err == noErr) ? kMMPasteNoError : kMMPastePasteError; -#elif defined(IS_WINDOWS) - MMPasteError ret = kMMPasteNoError; - uint8_t *bmpData; - size_t len; - HGLOBAL handle; - - if (!OpenClipboard(NULL)) return kMMPasteOpenError; - if (!EmptyClipboard()) return kMMPasteClearError; - - bmpData = createBitmapData(bitmap, &len); - if (bmpData == NULL) return kMMPasteDataError; - - /* CF_DIB does not include the BITMAPFILEHEADER struct (and displays a - * cryptic error if it is included). */ - len -= sizeof(BITMAPFILEHEADER); - - /* SetClipboardData() needs a "handle", not just a buffer, so we have to - * allocate one with GlobalAlloc(). */ - if ((handle = GlobalAlloc(GMEM_MOVEABLE, len)) == NULL) { - CloseClipboard(); - free(bmpData); - return kMMPasteDataError; - } - - memcpy(GlobalLock(handle), bmpData + sizeof(BITMAPFILEHEADER), len); - GlobalUnlock(handle); - free(bmpData); - - if (SetClipboardData(CF_DIB, handle) == NULL) { - ret = kMMPastePasteError; - } - - CloseClipboard(); - GlobalFree(handle); - return ret; -#elif defined(USE_X11) - /* TODO (X11's clipboard is _weird_.) */ - return kMMPasteUnsupportedError; -#endif -} - -const char *MMPasteErrorString(MMPasteError err) -{ - switch (err) { - case kMMPasteOpenError: - return "Could not open pasteboard"; - case kMMPasteClearError: - return "Could not clear pasteboard"; - case kMMPasteDataError: - return "Could not create image data from bitmap"; - case kMMPastePasteError: - return "Could not paste data"; - case kMMPasteUnsupportedError: - return "Unsupported platform"; - default: - return NULL; - } -} diff --git a/base/png_io.h b/base/png_io.h deleted file mode 100644 index 0187ce35..00000000 --- a/base/png_io.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once -#ifndef PNG_IO_H -#define PNG_IO_H - -// #include "MMBitmap_c.h" -// #include "file_io_c.h" - -enum _PNGReadError { - kPNGGenericError = 0, - kPNGReadError, - kPNGAccessError, - kPNGInvalidHeaderError -}; - -typedef MMIOError MMPNGReadError; - -/* Returns description of given MMPNGReadError. - * Returned string is constant and hence should not be freed. */ -const char *MMPNGReadErrorString(MMIOError error); - -/* Attempts to read PNG file at path; returns new MMBitmap on success, or - * NULL on error. If |error| is non-NULL, it will be set to the error code - * on return. - * Responsibility for destroy()'ing returned MMBitmap is left up to caller. */ -MMBitmapRef newMMBitmapFromPNG(const char *path, MMPNGReadError *error); - -/* Attempts to write PNG at path; returns 0 on success, -1 on error. */ -int saveMMBitmapAsPNG(MMBitmapRef bitmap, const char *path); - -/* Returns a buffer containing the raw PNG file data, ready to be saved to a - * file. |len| will be set to the number of bytes allocated in the returned - * buffer (it cannot be NULL). - * - * Responsibility for free()'ing data is left up to the caller. */ -uint8_t *createPNGData(MMBitmapRef bitmap, size_t *len); - -#endif /* PNG_IO_H */ diff --git a/base/png_io_c.h b/base/png_io_c.h deleted file mode 100644 index 4968de69..00000000 --- a/base/png_io_c.h +++ /dev/null @@ -1,346 +0,0 @@ -#include "png_io.h" -#include "os.h" -// #include "libpng/png.c" -#if defined(IS_MACOSX) - #include "../cdeps/mac/png.h" -#elif defined(USE_X11) - #include -#elif defined(IS_WINDOWS) - #include "../cdeps/win/png.h" -#endif - -#include /* fopen() */ -#include /* malloc/realloc */ -#include - -#if defined(_MSC_VER) - #include "ms_stdint.h" - #include "ms_stdbool.h" -#else - #include - #include -#endif - -const char *MMPNGReadErrorString(MMIOError error) -{ - switch (error) { - case kPNGAccessError: - return "Could not open file"; - case kPNGReadError: - return "Could not read file"; - case kPNGInvalidHeaderError: - return "Not a PNG file"; - default: - return NULL; - } -} - -MMBitmapRef newMMBitmapFromPNG(const char *path, MMPNGReadError *err) -{ - FILE *fp; - uint8_t header[8]; - png_struct *png_ptr = NULL; - png_info *info_ptr = NULL; - png_byte bit_depth, color_type; - uint8_t *row, *bitmapData; - uint8_t bytesPerPixel; - png_uint_32 width, height, y; - uint32_t bytewidth; - - if ((fp = fopen(path, "rb")) == NULL) { - if (err != NULL) *err = kPNGAccessError; - return NULL; - } - - /* Initialize error code to generic value. */ - if (err != NULL) *err = kPNGGenericError; - - /* Validate the PNG. */ - if (fread(header, 1, sizeof header, fp) == 0) { - if (err != NULL) *err = kPNGReadError; - goto bail; - } else if (png_sig_cmp(header, 0, sizeof(header)) != 0) { - if (err != NULL) *err = kPNGInvalidHeaderError; - goto bail; - } - - png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (png_ptr == NULL) goto bail; - - info_ptr = png_create_info_struct(png_ptr); - if (info_ptr == NULL) goto bail; - - /* Set up error handling. */ - if (setjmp(png_jmpbuf(png_ptr))) { - goto bail; - } - - png_init_io(png_ptr, fp); - - /* Skip past the header. */ - png_set_sig_bytes(png_ptr, sizeof header); - - png_read_info(png_ptr, info_ptr); - - /* Convert different image types to common type to be read. */ - bit_depth = png_get_bit_depth(png_ptr, info_ptr); - color_type = png_get_color_type(png_ptr, info_ptr); - - /* Convert color palettes to RGB. */ - if (color_type == PNG_COLOR_TYPE_PALETTE) { - png_set_palette_to_rgb(png_ptr); - } - - /* Convert PNG to bit depth of 8. */ - if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { - png_set_expand_gray_1_2_4_to_8(png_ptr); - } else if (bit_depth == 16) { - png_set_strip_16(png_ptr); - } - - /* Convert transparency chunk to alpha channel. */ - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { - png_set_tRNS_to_alpha(png_ptr); - } - - /* Convert gray images to RGB. */ - if (color_type == PNG_COLOR_TYPE_GRAY || - color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { - png_set_gray_to_rgb(png_ptr); - } - - /* Ignore alpha for now. */ - if (color_type & PNG_COLOR_MASK_ALPHA) { - png_set_strip_alpha(png_ptr); - } - - /* Get image attributes. */ - width = png_get_image_width(png_ptr, info_ptr); - height = png_get_image_height(png_ptr, info_ptr); - bytesPerPixel = 3; /* All images decompress to this size. */ - bytewidth = ADD_PADDING(width * bytesPerPixel); /* Align width. */ - - /* Decompress the PNG row by row. */ - bitmapData = calloc(1, bytewidth * height); - row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); - if (bitmapData == NULL || row == NULL) goto bail; - for (y = 0; y < height; ++y) { - png_uint_32 x; - const uint32_t rowOffset = y * bytewidth; - uint8_t *rowptr = row; - png_read_row(png_ptr, (png_byte *)row, NULL); - - for (x = 0; x < width; ++x) { - const uint32_t colOffset = x * bytesPerPixel; - MMRGBColor *color = (MMRGBColor *)(bitmapData + rowOffset + colOffset); - color->red = *rowptr++; - color->green = *rowptr++; - color->blue = *rowptr++; - } - } - free(row); - - /* Finish reading. */ - png_read_end(png_ptr, NULL); - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - fclose(fp); - - return createMMBitmap(bitmapData, width, height, - bytewidth, bytesPerPixel * 8, bytesPerPixel); - -bail: - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - fclose(fp); - return NULL; -} - -struct _PNGWriteInfo { - png_struct *png_ptr; - png_info *info_ptr; - png_byte **row_pointers; - size_t row_count; - bool free_row_pointers; -}; - -typedef struct _PNGWriteInfo PNGWriteInfo; -typedef PNGWriteInfo *PNGWriteInfoRef; - -/* Returns pointer to PNGWriteInfo struct containing data ready to be used with - * functions such as png_write_png(). - * - * It is the caller's responsibility to destroy() the returned structure with - * destroyPNGWriteInfo(). */ -static PNGWriteInfoRef createPNGWriteInfo(MMBitmapRef bitmap) -{ - PNGWriteInfoRef info = malloc(sizeof(PNGWriteInfo)); - png_uint_32 y; - - if (info == NULL) return NULL; - info->png_ptr = NULL; - info->info_ptr = NULL; - info->row_pointers = NULL; - - assert(bitmap != NULL); - - /* Initialize the write struct. */ - info->png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, - NULL, NULL, NULL); - if (info->png_ptr == NULL) goto bail; - - /* Set up error handling. */ - if (setjmp(png_jmpbuf(info->png_ptr))) { - png_destroy_write_struct(&(info->png_ptr), &(info->info_ptr)); - goto bail; - } - - /* Initialize the info struct. */ - info->info_ptr = png_create_info_struct(info->png_ptr); - if (info->info_ptr == NULL) { - png_destroy_write_struct(&(info->png_ptr), NULL); - goto bail; - } - - /* Set image attributes. */ - png_set_IHDR(info->png_ptr, - info->info_ptr, - (png_uint_32)bitmap->width, - (png_uint_32)bitmap->height, - 8, - PNG_COLOR_TYPE_RGB, - PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, - PNG_FILTER_TYPE_DEFAULT); - - info->row_count = bitmap->height; - info->row_pointers = png_malloc(info->png_ptr, - sizeof(png_byte *) * info->row_count); - - if (bitmap->bytesPerPixel == 3) { - /* No alpha channel; image data can be copied directly. */ - for (y = 0; y < info->row_count; ++y) { - info->row_pointers[y] = bitmap->imageBuffer + (bitmap->bytewidth * y); - } - info->free_row_pointers = false; - - /* Convert BGR to RGB if necessary. */ - if (MMRGB_IS_BGR) { - png_set_bgr(info->png_ptr); - } - } else { - /* Ignore alpha channel; copy image data row by row. */ - const size_t bytesPerPixel = 3; - const size_t bytewidth = ADD_PADDING(bitmap->width * bytesPerPixel); - - for (y = 0; y < info->row_count; ++y) { - png_uint_32 x; - png_byte *row_ptr = png_malloc(info->png_ptr, bytewidth); - info->row_pointers[y] = row_ptr; - for (x = 0; x < bitmap->width; ++x) { - MMRGBColor *color = MMRGBColorRefAtPoint(bitmap, x, y); - row_ptr[0] = color->red; - row_ptr[1] = color->green; - row_ptr[2] = color->blue; - - row_ptr += bytesPerPixel; - } - } - info->free_row_pointers = true; - } - - png_set_rows(info->png_ptr, info->info_ptr, info->row_pointers); - return info; - -bail: - if (info != NULL) free(info); - return NULL; -} - -/* Free memory in use by |info|. */ -static void destroyPNGWriteInfo(PNGWriteInfoRef info) -{ - assert(info != NULL); - if (info->row_pointers != NULL) { - if (info->free_row_pointers) { - size_t y; - for (y = 0; y < info->row_count; ++y) { - free(info->row_pointers[y]); - } - } - png_free(info->png_ptr, info->row_pointers); - } - - png_destroy_write_struct(&(info->png_ptr), &(info->info_ptr)); - free(info); -} - -int saveMMBitmapAsPNG(MMBitmapRef bitmap, const char *path) -{ - FILE *fp = fopen(path, "wb"); - PNGWriteInfoRef info; - if (fp == NULL) return -1; - - if ((info = createPNGWriteInfo(bitmap)) == NULL) { - fclose(fp); - return -1; - } - - png_init_io(info->png_ptr, fp); - png_write_png(info->png_ptr, info->info_ptr, PNG_TRANSFORM_IDENTITY, NULL); - fclose(fp); - - destroyPNGWriteInfo(info); - return 0; -} - -/* Structure to store PNG image bytes. */ -struct io_data -{ - uint8_t *buffer; /* Pointer to raw file data. */ - size_t size; /* Number of bytes actually written to buffer. */ - size_t allocedSize; /* Number of bytes allocated for buffer. */ -}; - -/* Called each time libpng attempts to write data in createPNGData(). */ -void png_append_data(png_struct *png_ptr, - png_byte *new_data, - png_size_t length) -{ - struct io_data *data = png_get_io_ptr(png_ptr); - data->size += length; - - /* Allocate or grow buffer. */ - if (data->buffer == NULL) { - data->allocedSize = data->size; - data->buffer = png_malloc(png_ptr, data->allocedSize); - assert(data->buffer != NULL); - } else if (data->allocedSize < data->size) { - do { - /* Double size each time to avoid calls to realloc. */ - data->allocedSize <<= 1; - } while (data->allocedSize < data->size); - - data->buffer = realloc(data->buffer, data->allocedSize); - } - - /* Copy new bytes to end of buffer. */ - memcpy(data->buffer + data->size - length, new_data, length); -} - -uint8_t *createPNGData(MMBitmapRef bitmap, size_t *len) -{ - PNGWriteInfoRef info = NULL; - struct io_data data = {NULL, 0, 0}; - - assert(bitmap != NULL); - assert(len != NULL); - - if ((info = createPNGWriteInfo(bitmap)) == NULL) return NULL; - - png_set_write_fn(info->png_ptr, &data, &png_append_data, NULL); - png_write_png(info->png_ptr, info->info_ptr, PNG_TRANSFORM_IDENTITY, NULL); - - destroyPNGWriteInfo(info); - - *len = data.size; - return data.buffer; -} diff --git a/base/snprintf.h b/base/snprintf.h deleted file mode 100644 index 60046e56..00000000 --- a/base/snprintf.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef _PORTABLE_SNPRINTF_H_ -#define _PORTABLE_SNPRINTF_H_ - -#define PORTABLE_SNPRINTF_VERSION_MAJOR 2 -#define PORTABLE_SNPRINTF_VERSION_MINOR 2 - -#include "os.h" -#if defined(IS_MACOSX) - #define HAVE_SNPRINTF -#else - #define HAVE_SNPRINTF - #define PREFER_PORTABLE_SNPRINTF -#endif - -#include -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -#ifdef HAVE_SNPRINTF -#include -#else -extern int snprintf(char *, size_t, const char *, /*args*/ ...); -extern int vsnprintf(char *, size_t, const char *, va_list); -#endif - -#if defined(HAVE_SNPRINTF) && defined(PREFER_PORTABLE_SNPRINTF) -extern int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args*/ ...); -extern int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap); -#define snprintf portable_snprintf -#define vsnprintf portable_vsnprintf -#endif - -extern int asprintf (char **ptr, const char *fmt, /*args*/ ...); -extern int vasprintf (char **ptr, const char *fmt, va_list ap); -extern int asnprintf (char **ptr, size_t str_m, const char *fmt, /*args*/ ...); -extern int vasnprintf(char **ptr, size_t str_m, const char *fmt, va_list ap); - -#endif - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/base/snprintf_c.h b/base/snprintf_c.h deleted file mode 100644 index 22ae3677..00000000 --- a/base/snprintf_c.h +++ /dev/null @@ -1,1019 +0,0 @@ -/* - * snprintf.c - a portable implementation of snprintf - * - * AUTHOR - * Mark Martinec , April 1999. - * - * Copyright 1999, Mark Martinec. All rights reserved. - * - * TERMS AND CONDITIONS - * This program is free software; you can redistribute it and/or modify - * it under the terms of the "Frontier Artistic License" which comes - * with this Kit. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the Frontier Artistic License for more details. - * - * You should have received a copy of the Frontier Artistic License - * with this Kit in the file named LICENSE.txt . - * If not, I'll be glad to provide one. - * - * FEATURES - * - careful adherence to specs regarding flags, field width and precision; - * - good performance for large string handling (large format, large - * argument or large paddings). Performance is similar to system's sprintf - * and in several cases significantly better (make sure you compile with - * optimizations turned on, tell the compiler the code is strict ANSI - * if necessary to give it more freedom for optimizations); - * - return value semantics per ISO/IEC 9899:1999 ("ISO C99"); - * - written in standard ISO/ANSI C - requires an ANSI C compiler. - * - * SUPPORTED CONVERSION SPECIFIERS AND DATA TYPES - * - * This snprintf only supports the following conversion specifiers: - * s, c, d, u, o, x, X, p (and synonyms: i, D, U, O - see below) - * with flags: '-', '+', ' ', '0' and '#'. - * An asterisk is supported for field width as well as precision. - * - * Length modifiers 'h' (short int), 'l' (long int), - * and 'll' (long long int) are supported. - * NOTE: - * If macro SNPRINTF_LONGLONG_SUPPORT is not defined (default) the - * length modifier 'll' is recognized but treated the same as 'l', - * which may cause argument value truncation! Defining - * SNPRINTF_LONGLONG_SUPPORT requires that your system's sprintf also - * handles length modifier 'll'. long long int is a language extension - * which may not be portable. - * - * Conversion of numeric data (conversion specifiers d, u, o, x, X, p) - * with length modifiers (none or h, l, ll) is left to the system routine - * sprintf, but all handling of flags, field width and precision as well as - * c and s conversions is done very carefully by this portable routine. - * If a string precision (truncation) is specified (e.g. %.8s) it is - * guaranteed the string beyond the specified precision will not be referenced. - * - * Length modifiers h, l and ll are ignored for c and s conversions (data - * types wint_t and wchar_t are not supported). - * - * The following common synonyms for conversion characters are supported: - * - i is a synonym for d - * - D is a synonym for ld, explicit length modifiers are ignored - * - U is a synonym for lu, explicit length modifiers are ignored - * - O is a synonym for lo, explicit length modifiers are ignored - * The D, O and U conversion characters are nonstandard, they are supported - * for backward compatibility only, and should not be used for new code. - * - * The following is specifically NOT supported: - * - flag ' (thousands' grouping character) is recognized but ignored - * - numeric conversion specifiers: f, e, E, g, G and synonym F, - * as well as the new a and A conversion specifiers - * - length modifier 'L' (long double) and 'q' (quad - use 'll' instead) - * - wide character/string conversions: lc, ls, and nonstandard - * synonyms C and S - * - writeback of converted string length: conversion character n - * - the n$ specification for direct reference to n-th argument - * - locales - * - * It is permitted for str_m to be zero, and it is permitted to specify NULL - * pointer for resulting string argument if str_m is zero (as per ISO C99). - * - * The return value is the number of characters which would be generated - * for the given input, excluding the trailing null. If this value - * is greater or equal to str_m, not all characters from the result - * have been stored in str, output bytes beyond the (str_m-1) -th character - * are discarded. If str_m is greater than zero it is guaranteed - * the resulting string will be null-terminated. - * - * NOTE that this matches the ISO C99, OpenBSD, and GNU C library 2.1, - * but is different from some older and vendor implementations, - * and is also different from XPG, XSH5, SUSv2 specifications. - * For historical discussion on changes in the semantics and standards - * of snprintf see printf(3) man page in the Linux programmers manual. - * - * Routines asprintf and vasprintf return a pointer (in the ptr argument) - * to a buffer sufficiently large to hold the resulting string. This pointer - * should be passed to free(3) to release the allocated storage when it is - * no longer needed. If sufficient space cannot be allocated, these functions - * will return -1 and set ptr to be a NULL pointer. These two routines are a - * GNU C library extensions (glibc). - * - * Routines asnprintf and vasnprintf are similar to asprintf and vasprintf, - * yet, like snprintf and vsnprintf counterparts, will write at most str_m-1 - * characters into the allocated output string, the last character in the - * allocated buffer then gets the terminating null. If the formatted string - * length (the return value) is greater than or equal to the str_m argument, - * the resulting string was truncated and some of the formatted characters - * were discarded. These routines present a handy way to limit the amount - * of allocated memory to some sane value. - * - * AVAILABILITY - * http://www.ijs.si/software/snprintf/ - * - * REVISION HISTORY - * 1999-04 V0.9 Mark Martinec - * - initial version, some modifications after comparing printf - * man pages for Digital Unix 4.0, Solaris 2.6 and HPUX 10, - * and checking how Perl handles sprintf (differently!); - * 1999-04-09 V1.0 Mark Martinec - * - added main test program, fixed remaining inconsistencies, - * added optional (long long int) support; - * 1999-04-12 V1.1 Mark Martinec - * - support the 'p' conversion (pointer to void); - * - if a string precision is specified - * make sure the string beyond the specified precision - * will not be referenced (e.g. by strlen); - * 1999-04-13 V1.2 Mark Martinec - * - support synonyms %D=%ld, %U=%lu, %O=%lo; - * - speed up the case of long format string with few conversions; - * 1999-06-30 V1.3 Mark Martinec - * - fixed runaway loop (eventually crashing when str_l wraps - * beyond 2^31) while copying format string without - * conversion specifiers to a buffer that is too short - * (thanks to Edwin Young for - * spotting the problem); - * - added macros PORTABLE_SNPRINTF_VERSION_(MAJOR|MINOR) - * to snprintf.h - * 2000-02-14 V2.0 (never released) Mark Martinec - * - relaxed license terms: The Artistic License now applies. - * You may still apply the GNU GENERAL PUBLIC LICENSE - * as was distributed with previous versions, if you prefer; - * - changed REVISION HISTORY dates to use ISO 8601 date format; - * - added vsnprintf (patch also independently proposed by - * Caolan McNamara 2000-05-04, and Keith M Willenson 2000-06-01) - * 2000-06-27 V2.1 Mark Martinec - * - removed POSIX check for str_m<1; value 0 for str_m is - * allowed by ISO C99 (and GNU C library 2.1) - (pointed out - * on 2000-05-04 by Caolan McNamara, caolan@ csn dot ul dot ie). - * Besides relaxed license this change in standards adherence - * is the main reason to bump up the major version number; - * - added nonstandard routines asnprintf, vasnprintf, asprintf, - * vasprintf that dynamically allocate storage for the - * resulting string; these routines are not compiled by default, - * see comments where NEED_V?ASN?PRINTF macros are defined; - * - autoconf contributed by Caolan McNamara - * 2000-10-06 V2.2 Mark Martinec - * - BUG FIX: the %c conversion used a temporary variable - * that was no longer in scope when referenced, - * possibly causing incorrect resulting character; - * - BUG FIX: make precision and minimal field width unsigned - * to handle huge values (2^31 <= n < 2^32) correctly; - * also be more careful in the use of signed/unsigned/size_t - * internal variables - probably more careful than many - * vendor implementations, but there may still be a case - * where huge values of str_m, precision or minimal field - * could cause incorrect behaviour; - * - use separate variables for signed/unsigned arguments, - * and for short/int, long, and long long argument lengths - * to avoid possible incompatibilities on certain - * computer architectures. Also use separate variable - * arg_sign to hold sign of a numeric argument, - * to make code more transparent; - * - some fiddling with zero padding and "0x" to make it - * Linux compatible; - * - systematically use macros fast_memcpy and fast_memset - * instead of case-by-case hand optimization; determine some - * breakeven string lengths for different architectures; - * - terminology change: 'format' -> 'conversion specifier', - * 'C9x' -> 'ISO/IEC 9899:1999 ("ISO C99")', - * 'alternative form' -> 'alternate form', - * 'data type modifier' -> 'length modifier'; - * - several comments rephrased and new ones added; - * - make compiler not complain about 'credits' defined but - * not used; - */ - - -/* Define HAVE_SNPRINTF if your system already has snprintf and vsnprintf. - * - * If HAVE_SNPRINTF is defined this module will not produce code for - * snprintf and vsnprintf, unless PREFER_PORTABLE_SNPRINTF is defined as well, - * causing this portable version of snprintf to be called portable_snprintf - * (and portable_vsnprintf). - */ -/* #define HAVE_SNPRINTF */ - -/* Define PREFER_PORTABLE_SNPRINTF if your system does have snprintf and - * vsnprintf but you would prefer to use the portable routine(s) instead. - * In this case the portable routine is declared as portable_snprintf - * (and portable_vsnprintf) and a macro 'snprintf' (and 'vsnprintf') - * is defined to expand to 'portable_v?snprintf' - see file snprintf.h . - * Defining this macro is only useful if HAVE_SNPRINTF is also defined, - * but does does no harm if defined nevertheless. - */ -/* #define PREFER_PORTABLE_SNPRINTF */ - -/* Define SNPRINTF_LONGLONG_SUPPORT if you want to support - * data type (long long int) and length modifier 'll' (e.g. %lld). - * If undefined, 'll' is recognized but treated as a single 'l'. - * - * If the system's sprintf does not handle 'll' - * the SNPRINTF_LONGLONG_SUPPORT must not be defined! - * - * This is off by default as (long long int) is a language extension. - */ -/* #define SNPRINTF_LONGLONG_SUPPORT */ - -/* Define NEED_SNPRINTF_ONLY if you only need snprintf, and not vsnprintf. - * If NEED_SNPRINTF_ONLY is defined, the snprintf will be defined directly, - * otherwise both snprintf and vsnprintf routines will be defined - * and snprintf will be a simple wrapper around vsnprintf, at the expense - * of an extra procedure call. - */ -/* #define NEED_SNPRINTF_ONLY */ - -/* Define NEED_V?ASN?PRINTF macros if you need library extension - * routines asprintf, vasprintf, asnprintf, vasnprintf respectively, - * and your system library does not provide them. They are all small - * wrapper routines around portable_vsnprintf. Defining any of the four - * NEED_V?ASN?PRINTF macros automatically turns off NEED_SNPRINTF_ONLY - * and turns on PREFER_PORTABLE_SNPRINTF. - * - * Watch for name conflicts with the system library if these routines - * are already present there. - * - * NOTE: vasprintf and vasnprintf routines need va_copy() from stdarg.h, as - * specified by C99, to be able to traverse the same list of arguments twice. - * I don't know of any other standard and portable way of achieving the same. - * With some versions of gcc you may use __va_copy(). You might even get away - * with "ap2 = ap", in this case you must not call va_end(ap2) ! - * #define va_copy(ap2,ap) ap2 = ap - */ -/* #define NEED_ASPRINTF */ -/* #define NEED_ASNPRINTF */ -/* #define NEED_VASPRINTF */ -/* #define NEED_VASNPRINTF */ - - -/* Define the following macros if desired: - * SOLARIS_COMPATIBLE, SOLARIS_BUG_COMPATIBLE, - * HPUX_COMPATIBLE, HPUX_BUG_COMPATIBLE, LINUX_COMPATIBLE, - * DIGITAL_UNIX_COMPATIBLE, DIGITAL_UNIX_BUG_COMPATIBLE, - * PERL_COMPATIBLE, PERL_BUG_COMPATIBLE, - * - * - For portable applications it is best not to rely on peculiarities - * of a given implementation so it may be best not to define any - * of the macros that select compatibility and to avoid features - * that vary among the systems. - * - * - Selecting compatibility with more than one operating system - * is not strictly forbidden but is not recommended. - * - * - 'x'_BUG_COMPATIBLE implies 'x'_COMPATIBLE . - * - * - 'x'_COMPATIBLE refers to (and enables) a behaviour that is - * documented in a sprintf man page on a given operating system - * and actually adhered to by the system's sprintf (but not on - * most other operating systems). It may also refer to and enable - * a behaviour that is declared 'undefined' or 'implementation specific' - * in the man page but a given implementation behaves predictably - * in a certain way. - * - * - 'x'_BUG_COMPATIBLE refers to (and enables) a behaviour of system's sprintf - * that contradicts the sprintf man page on the same operating system. - * - * - I do not claim that the 'x'_COMPATIBLE and 'x'_BUG_COMPATIBLE - * conditionals take into account all idiosyncrasies of a particular - * implementation, there may be other incompatibilities. - */ - - - -/* ============================================= */ -/* NO USER SERVICABLE PARTS FOLLOWING THIS POINT */ -/* ============================================= */ - -#define PORTABLE_SNPRINTF_VERSION_MAJOR 2 -#define PORTABLE_SNPRINTF_VERSION_MINOR 2 - -#if defined(NEED_ASPRINTF) || defined(NEED_ASNPRINTF) || defined(NEED_VASPRINTF) || defined(NEED_VASNPRINTF) -# if defined(NEED_SNPRINTF_ONLY) -# undef NEED_SNPRINTF_ONLY -# endif -# if !defined(PREFER_PORTABLE_SNPRINTF) -# define PREFER_PORTABLE_SNPRINTF -# endif -#endif - -#if defined(SOLARIS_BUG_COMPATIBLE) && !defined(SOLARIS_COMPATIBLE) -#define SOLARIS_COMPATIBLE -#endif - -#if defined(HPUX_BUG_COMPATIBLE) && !defined(HPUX_COMPATIBLE) -#define HPUX_COMPATIBLE -#endif - -#if defined(DIGITAL_UNIX_BUG_COMPATIBLE) && !defined(DIGITAL_UNIX_COMPATIBLE) -#define DIGITAL_UNIX_COMPATIBLE -#endif - -#if defined(PERL_BUG_COMPATIBLE) && !defined(PERL_COMPATIBLE) -#define PERL_COMPATIBLE -#endif - -#if defined(LINUX_BUG_COMPATIBLE) && !defined(LINUX_COMPATIBLE) -#define LINUX_COMPATIBLE -#endif - -#include "snprintf.h" -#include -#include -#include -#include -#include -#include -#include - -#ifdef isdigit -#undef isdigit -#endif -#define isdigit(c) ((c) >= '0' && (c) <= '9') - -/* For copying strings longer or equal to 'breakeven_point' - * it is more efficient to call memcpy() than to do it inline. - * The value depends mostly on the processor architecture, - * but also on the compiler and its optimization capabilities. - * The value is not critical, some small value greater than zero - * will be just fine if you don't care to squeeze every drop - * of performance out of the code. - * - * Small values favor memcpy, large values favor inline code. - */ -#if defined(__alpha__) || defined(__alpha) -# define breakeven_point 2 /* AXP (DEC Alpha) - gcc or cc or egcs */ -#endif -#if defined(__i386__) || defined(__i386) -# define breakeven_point 12 /* Intel Pentium/Linux - gcc 2.96 */ -#endif -#if defined(__hppa) -# define breakeven_point 10 /* HP-PA - gcc */ -#endif -#if defined(__sparc__) || defined(__sparc) -# define breakeven_point 33 /* Sun Sparc 5 - gcc 2.8.1 */ -#endif - -/* some other values of possible interest: */ -/* #define breakeven_point 8 */ /* VAX 4000 - vaxc */ -/* #define breakeven_point 19 */ /* VAX 4000 - gcc 2.7.0 */ - -#ifndef breakeven_point -# define breakeven_point 6 /* some reasonable one-size-fits-all value */ -#endif - -#define fast_memcpy(d,s,n) \ - { register size_t nn = (size_t)(n); \ - if (nn >= breakeven_point) memcpy((d), (s), nn); \ - else if (nn > 0) { /* proc call overhead is worth only for large strings*/\ - register char *dd; register const char *ss; \ - for (ss=(s), dd=(d); nn>0; nn--) *dd++ = *ss++; } } - -#define fast_memset(d,c,n) \ - { register size_t nn = (size_t)(n); \ - if (nn >= breakeven_point) memset((d), (int)(c), nn); \ - else if (nn > 0) { /* proc call overhead is worth only for large strings*/\ - register char *dd; register const int cc=(int)(c); \ - for (dd=(d); nn>0; nn--) *dd++ = cc; } } - -/* prototypes */ - -#if defined(NEED_ASPRINTF) -int asprintf (char **ptr, const char *fmt, /*args*/ ...); -#endif -#if defined(NEED_VASPRINTF) -int vasprintf (char **ptr, const char *fmt, va_list ap); -#endif -#if defined(NEED_ASNPRINTF) -int asnprintf (char **ptr, size_t str_m, const char *fmt, /*args*/ ...); -#endif -#if defined(NEED_VASNPRINTF) -int vasnprintf (char **ptr, size_t str_m, const char *fmt, va_list ap); -#endif - -#if defined(HAVE_SNPRINTF) -/* declare our portable snprintf routine under name portable_snprintf */ -/* declare our portable vsnprintf routine under name portable_vsnprintf */ -#else -/* declare our portable routines under names snprintf and vsnprintf */ -#define portable_snprintf snprintf -#if !defined(NEED_SNPRINTF_ONLY) -#define portable_vsnprintf vsnprintf -#endif -#endif - -#if !defined(HAVE_SNPRINTF) || defined(PREFER_PORTABLE_SNPRINTF) -int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args*/ ...); -#if !defined(NEED_SNPRINTF_ONLY) -int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap); -#endif -#endif - -/* declarations */ - -#if defined(NEED_ASPRINTF) -int asprintf(char **ptr, const char *fmt, /*args*/ ...) { - va_list ap; - size_t str_m; - int str_l; - - *ptr = NULL; - va_start(ap, fmt); /* measure the required size */ - str_l = portable_vsnprintf(NULL, (size_t)0, fmt, ap); - va_end(ap); - assert(str_l >= 0); /* possible integer overflow if str_m > INT_MAX */ - *ptr = (char *) malloc(str_m = (size_t)str_l + 1); - if (*ptr == NULL) { errno = ENOMEM; str_l = -1; } - else { - int str_l2; - va_start(ap, fmt); - str_l2 = portable_vsnprintf(*ptr, str_m, fmt, ap); - va_end(ap); - assert(str_l2 == str_l); - } - return str_l; -} -#endif - -#if defined(NEED_VASPRINTF) -int vasprintf(char **ptr, const char *fmt, va_list ap) { - size_t str_m; - int str_l; - - *ptr = NULL; - { va_list ap2; - va_copy(ap2, ap); /* don't consume the original ap, we'll need it again */ - str_l = portable_vsnprintf(NULL, (size_t)0, fmt, ap2);/*get required size*/ - va_end(ap2); - } - assert(str_l >= 0); /* possible integer overflow if str_m > INT_MAX */ - *ptr = (char *) malloc(str_m = (size_t)str_l + 1); - if (*ptr == NULL) { errno = ENOMEM; str_l = -1; } - else { - int str_l2 = portable_vsnprintf(*ptr, str_m, fmt, ap); - assert(str_l2 == str_l); - } - return str_l; -} -#endif - -#if defined(NEED_ASNPRINTF) -int asnprintf (char **ptr, size_t str_m, const char *fmt, /*args*/ ...) { - va_list ap; - int str_l; - - *ptr = NULL; - va_start(ap, fmt); /* measure the required size */ - str_l = portable_vsnprintf(NULL, (size_t)0, fmt, ap); - va_end(ap); - assert(str_l >= 0); /* possible integer overflow if str_m > INT_MAX */ - if ((size_t)str_l + 1 < str_m) str_m = (size_t)str_l + 1; /* truncate */ - /* if str_m is 0, no buffer is allocated, just set *ptr to NULL */ - if (str_m == 0) { /* not interested in resulting string, just return size */ - } else { - *ptr = (char *) malloc(str_m); - if (*ptr == NULL) { errno = ENOMEM; str_l = -1; } - else { - int str_l2; - va_start(ap, fmt); - str_l2 = portable_vsnprintf(*ptr, str_m, fmt, ap); - va_end(ap); - assert(str_l2 == str_l); - } - } - return str_l; -} -#endif - -#if defined(NEED_VASNPRINTF) -int vasnprintf (char **ptr, size_t str_m, const char *fmt, va_list ap) { - int str_l; - - *ptr = NULL; - { va_list ap2; - va_copy(ap2, ap); /* don't consume the original ap, we'll need it again */ - str_l = portable_vsnprintf(NULL, (size_t)0, fmt, ap2);/*get required size*/ - va_end(ap2); - } - assert(str_l >= 0); /* possible integer overflow if str_m > INT_MAX */ - if ((size_t)str_l + 1 < str_m) str_m = (size_t)str_l + 1; /* truncate */ - /* if str_m is 0, no buffer is allocated, just set *ptr to NULL */ - if (str_m == 0) { /* not interested in resulting string, just return size */ - } else { - *ptr = (char *) malloc(str_m); - if (*ptr == NULL) { errno = ENOMEM; str_l = -1; } - else { - int str_l2 = portable_vsnprintf(*ptr, str_m, fmt, ap); - assert(str_l2 == str_l); - } - } - return str_l; -} -#endif - -/* - * If the system does have snprintf and the portable routine is not - * specifically required, this module produces no code for snprintf/vsnprintf. - */ -#if !defined(HAVE_SNPRINTF) || defined(PREFER_PORTABLE_SNPRINTF) - -#if !defined(NEED_SNPRINTF_ONLY) -int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args*/ ...) { - va_list ap; - int str_l; - - va_start(ap, fmt); - str_l = portable_vsnprintf(str, str_m, fmt, ap); - va_end(ap); - return str_l; -} -#endif - -#if defined(NEED_SNPRINTF_ONLY) -int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args*/ ...) { -#else -int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap) { -#endif - -#if defined(NEED_SNPRINTF_ONLY) - va_list ap; -#endif - size_t str_l = 0; - const char *p = fmt; - -/* In contrast with POSIX, the ISO C99 now says - * that str can be NULL and str_m can be 0. - * This is more useful than the old: if (str_m < 1) return -1; */ - -#if defined(NEED_SNPRINTF_ONLY) - va_start(ap, fmt); -#endif - if (!p) p = ""; - while (*p) { - if (*p != '%') { - /* if (str_l < str_m) str[str_l++] = *p++; -- this would be sufficient */ - /* but the following code achieves better performance for cases - * where format string is long and contains few conversions */ - const char *q = strchr(p+1,'%'); - size_t n = !q ? strlen(p) : (q-p); - if (str_l < str_m) { - size_t avail = str_m-str_l; - fast_memcpy(str+str_l, p, (n>avail?avail:n)); - } - p += n; str_l += n; - } else { - const char *starting_p; - size_t min_field_width = 0, precision = 0; - int zero_padding = 0, precision_specified = 0, justify_left = 0; - int alternate_form = 0, force_sign = 0; - int space_for_positive = 1; /* If both the ' ' and '+' flags appear, - the ' ' flag should be ignored. */ - char length_modifier = '\0'; /* allowed values: \0, h, l, L */ - char tmp[32];/* temporary buffer for simple numeric->string conversion */ - - const char *str_arg; /* string address in case of string argument */ - size_t str_arg_l; /* natural field width of arg without padding - and sign */ - unsigned char uchar_arg; - /* unsigned char argument value - only defined for c conversion. - N.B. standard explicitly states the char argument for - the c conversion is unsigned */ - - size_t number_of_zeros_to_pad = 0; - /* number of zeros to be inserted for numeric conversions - as required by the precision or minimal field width */ - - size_t zero_padding_insertion_ind = 0; - /* index into tmp where zero padding is to be inserted */ - - char fmt_spec = '\0'; - /* current conversion specifier character */ - - starting_p = p; p++; /* skip '%' */ - /* parse flags */ - while (*p == '0' || *p == '-' || *p == '+' || - *p == ' ' || *p == '#' || *p == '\'') { - switch (*p) { - case '0': zero_padding = 1; break; - case '-': justify_left = 1; break; - case '+': force_sign = 1; space_for_positive = 0; break; - case ' ': force_sign = 1; - /* If both the ' ' and '+' flags appear, the ' ' flag should be ignored */ -#ifdef PERL_COMPATIBLE - /* ... but in Perl the last of ' ' and '+' applies */ - space_for_positive = 1; -#endif - break; - case '#': alternate_form = 1; break; - case '\'': break; - } - p++; - } - /* If the '0' and '-' flags both appear, the '0' flag should be ignored. */ - - /* parse field width */ - if (*p == '*') { - int j; - p++; j = va_arg(ap, int); - if (j >= 0) min_field_width = j; - else { min_field_width = -j; justify_left = 1; } - } else if (isdigit((int)(*p))) { - /* size_t could be wider than unsigned int; - make sure we treat argument like common implementations do */ - unsigned int uj = *p++ - '0'; - while (isdigit((int)(*p))) uj = 10*uj + (unsigned int)(*p++ - '0'); - min_field_width = uj; - } - /* parse precision */ - if (*p == '.') { - p++; precision_specified = 1; - if (*p == '*') { - int j = va_arg(ap, int); - p++; - if (j >= 0) precision = j; - else { - precision_specified = 0; precision = 0; - /* NOTE: - * Solaris 2.6 man page claims that in this case the precision - * should be set to 0. Digital Unix 4.0, HPUX 10 and BSD man page - * claim that this case should be treated as unspecified precision, - * which is what we do here. - */ - } - } else if (isdigit((int)(*p))) { - /* size_t could be wider than unsigned int; - make sure we treat argument like common implementations do */ - unsigned int uj = *p++ - '0'; - while (isdigit((int)(*p))) uj = 10*uj + (unsigned int)(*p++ - '0'); - precision = uj; - } - } - /* parse 'h', 'l' and 'll' length modifiers */ - if (*p == 'h' || *p == 'l') { - length_modifier = *p; p++; - if (length_modifier == 'l' && *p == 'l') { /* double l = long long */ -#ifdef SNPRINTF_LONGLONG_SUPPORT - length_modifier = '2'; /* double l encoded as '2' */ -#else - length_modifier = 'l'; /* treat it as a single 'l' */ -#endif - p++; - } - } - fmt_spec = *p; - /* common synonyms: */ - switch (fmt_spec) { - case 'i': fmt_spec = 'd'; break; - case 'D': fmt_spec = 'd'; length_modifier = 'l'; break; - case 'U': fmt_spec = 'u'; length_modifier = 'l'; break; - case 'O': fmt_spec = 'o'; length_modifier = 'l'; break; - default: break; - } - /* get parameter value, do initial processing */ - switch (fmt_spec) { - case '%': /* % behaves similar to 's' regarding flags and field widths */ - case 'c': /* c behaves similar to 's' regarding flags and field widths */ - case 's': - length_modifier = '\0'; /* wint_t and wchar_t not supported */ - /* the result of zero padding flag with non-numeric conversion specifier*/ - /* is undefined. Solaris and HPUX 10 does zero padding in this case, */ - /* Digital Unix and Linux does not. */ -#if !defined(SOLARIS_COMPATIBLE) && !defined(HPUX_COMPATIBLE) - zero_padding = 0; /* turn zero padding off for string conversions */ -#endif - str_arg_l = 1; - switch (fmt_spec) { - case '%': - str_arg = p; break; - case 'c': { - int j = va_arg(ap, int); - uchar_arg = (unsigned char) j; /* standard demands unsigned char */ - str_arg = (const char *) &uchar_arg; - break; - } - case 's': - str_arg = va_arg(ap, const char *); - if (!str_arg) str_arg_l = 0; - /* make sure not to address string beyond the specified precision !!! */ - else if (!precision_specified) str_arg_l = strlen(str_arg); - /* truncate string if necessary as requested by precision */ - else if (precision == 0) str_arg_l = 0; - else { - /* memchr on HP does not like n > 2^31 !!! */ - const char *q = memchr(str_arg, '\0', - precision <= 0x7fffffff ? precision : 0x7fffffff); - str_arg_l = !q ? precision : (q-str_arg); - } - break; - default: break; - } - break; - case 'd': case 'u': case 'o': case 'x': case 'X': case 'p': { - /* NOTE: the u, o, x, X and p conversion specifiers imply - the value is unsigned; d implies a signed value */ - - int arg_sign = 0; - /* 0 if numeric argument is zero (or if pointer is NULL for 'p'), - +1 if greater than zero (or nonzero for unsigned arguments), - -1 if negative (unsigned argument is never negative) */ - - int int_arg = 0; unsigned int uint_arg = 0; - /* only defined for length modifier h, or for no length modifiers */ - - long int long_arg = 0; unsigned long int ulong_arg = 0; - /* only defined for length modifier l */ - - void *ptr_arg = NULL; - /* pointer argument value -only defined for p conversion */ - -#ifdef SNPRINTF_LONGLONG_SUPPORT - long long int long_long_arg = 0; - unsigned long long int ulong_long_arg = 0; - /* only defined for length modifier ll */ -#endif - if (fmt_spec == 'p') { - /* HPUX 10: An l, h, ll or L before any other conversion character - * (other than d, i, u, o, x, or X) is ignored. - * Digital Unix: - * not specified, but seems to behave as HPUX does. - * Solaris: If an h, l, or L appears before any other conversion - * specifier (other than d, i, u, o, x, or X), the behavior - * is undefined. (Actually %hp converts only 16-bits of address - * and %llp treats address as 64-bit data which is incompatible - * with (void *) argument on a 32-bit system). - */ -#ifdef SOLARIS_COMPATIBLE -# ifdef SOLARIS_BUG_COMPATIBLE - /* keep length modifiers even if it represents 'll' */ -# else - if (length_modifier == '2') length_modifier = '\0'; -# endif -#else - length_modifier = '\0'; -#endif - ptr_arg = va_arg(ap, void *); - if (ptr_arg != NULL) arg_sign = 1; - } else if (fmt_spec == 'd') { /* signed */ - switch (length_modifier) { - case '\0': - case 'h': - /* It is non-portable to specify a second argument of char or short - * to va_arg, because arguments seen by the called function - * are not char or short. C converts char and short arguments - * to int before passing them to a function. - */ - int_arg = va_arg(ap, int); - if (int_arg > 0) arg_sign = 1; - else if (int_arg < 0) arg_sign = -1; - break; - case 'l': - long_arg = va_arg(ap, long int); - if (long_arg > 0) arg_sign = 1; - else if (long_arg < 0) arg_sign = -1; - break; -#ifdef SNPRINTF_LONGLONG_SUPPORT - case '2': - long_long_arg = va_arg(ap, long long int); - if (long_long_arg > 0) arg_sign = 1; - else if (long_long_arg < 0) arg_sign = -1; - break; -#endif - } - } else { /* unsigned */ - switch (length_modifier) { - case '\0': - case 'h': - uint_arg = va_arg(ap, unsigned int); - if (uint_arg) arg_sign = 1; - break; - case 'l': - ulong_arg = va_arg(ap, unsigned long int); - if (ulong_arg) arg_sign = 1; - break; -#ifdef SNPRINTF_LONGLONG_SUPPORT - case '2': - ulong_long_arg = va_arg(ap, unsigned long long int); - if (ulong_long_arg) arg_sign = 1; - break; -#endif - } - } - str_arg = tmp; str_arg_l = 0; - /* NOTE: - * For d, i, u, o, x, and X conversions, if precision is specified, - * the '0' flag should be ignored. This is so with Solaris 2.6, - * Digital UNIX 4.0, HPUX 10, Linux, FreeBSD, NetBSD; but not with Perl. - */ -#ifndef PERL_COMPATIBLE - if (precision_specified) zero_padding = 0; -#endif - if (fmt_spec == 'd') { - if (force_sign && arg_sign >= 0) - tmp[str_arg_l++] = space_for_positive ? ' ' : '+'; - /* leave negative numbers for sprintf to handle, - to avoid handling tricky cases like (short int)(-32768) */ -#ifdef LINUX_COMPATIBLE - } else if (fmt_spec == 'p' && force_sign && arg_sign > 0) { - tmp[str_arg_l++] = space_for_positive ? ' ' : '+'; -#endif - } else if (alternate_form) { - if (arg_sign != 0 && (fmt_spec == 'x' || fmt_spec == 'X') ) - { tmp[str_arg_l++] = '0'; tmp[str_arg_l++] = fmt_spec; } - /* alternate form should have no effect for p conversion, but ... */ -#ifdef HPUX_COMPATIBLE - else if (fmt_spec == 'p' - /* HPUX 10: for an alternate form of p conversion, - * a nonzero result is prefixed by 0x. */ -#ifndef HPUX_BUG_COMPATIBLE - /* Actually it uses 0x prefix even for a zero value. */ - && arg_sign != 0 -#endif - ) { tmp[str_arg_l++] = '0'; tmp[str_arg_l++] = 'x'; } -#endif - } - zero_padding_insertion_ind = str_arg_l; - if (!precision_specified) precision = 1; /* default precision is 1 */ - if (precision == 0 && arg_sign == 0 -#if defined(HPUX_BUG_COMPATIBLE) || defined(LINUX_COMPATIBLE) - && fmt_spec != 'p' - /* HPUX 10 man page claims: With conversion character p the result of - * converting a zero value with a precision of zero is a null string. - * Actually HP returns all zeroes, and Linux returns "(nil)". */ -#endif - ) { - /* converted to null string */ - /* When zero value is formatted with an explicit precision 0, - the resulting formatted string is empty (d, i, u, o, x, X, p). */ - } else { - char f[5]; int f_l = 0; - f[f_l++] = '%'; /* construct a simple format string for sprintf */ - if (!length_modifier) { } - else if (length_modifier=='2') { f[f_l++] = 'l'; f[f_l++] = 'l'; } - else f[f_l++] = length_modifier; - f[f_l++] = fmt_spec; f[f_l++] = '\0'; - if (fmt_spec == 'p') str_arg_l += sprintf(tmp+str_arg_l, f, ptr_arg); - else if (fmt_spec == 'd') { /* signed */ - switch (length_modifier) { - case '\0': - case 'h': str_arg_l+=sprintf(tmp+str_arg_l, f, int_arg); break; - case 'l': str_arg_l+=sprintf(tmp+str_arg_l, f, long_arg); break; -#ifdef SNPRINTF_LONGLONG_SUPPORT - case '2': str_arg_l+=sprintf(tmp+str_arg_l,f,long_long_arg); break; -#endif - } - } else { /* unsigned */ - switch (length_modifier) { - case '\0': - case 'h': str_arg_l+=sprintf(tmp+str_arg_l, f, uint_arg); break; - case 'l': str_arg_l+=sprintf(tmp+str_arg_l, f, ulong_arg); break; -#ifdef SNPRINTF_LONGLONG_SUPPORT - case '2': str_arg_l+=sprintf(tmp+str_arg_l,f,ulong_long_arg);break; -#endif - } - } - /* include the optional minus sign and possible "0x" - in the region before the zero padding insertion point */ - if (zero_padding_insertion_ind < str_arg_l && - tmp[zero_padding_insertion_ind] == '-') { - zero_padding_insertion_ind++; - } - if (zero_padding_insertion_ind+1 < str_arg_l && - tmp[zero_padding_insertion_ind] == '0' && - (tmp[zero_padding_insertion_ind+1] == 'x' || - tmp[zero_padding_insertion_ind+1] == 'X') ) { - zero_padding_insertion_ind += 2; - } - } - { size_t num_of_digits = str_arg_l - zero_padding_insertion_ind; - if (alternate_form && fmt_spec == 'o' -#ifdef HPUX_COMPATIBLE /* ("%#.o",0) -> "" */ - && (str_arg_l > 0) -#endif -#ifdef DIGITAL_UNIX_BUG_COMPATIBLE /* ("%#o",0) -> "00" */ -#else - /* unless zero is already the first character */ - && !(zero_padding_insertion_ind < str_arg_l - && tmp[zero_padding_insertion_ind] == '0') -#endif - ) { /* assure leading zero for alternate-form octal numbers */ - if (!precision_specified || precision < num_of_digits+1) { - /* precision is increased to force the first character to be zero, - except if a zero value is formatted with an explicit precision - of zero */ - precision = num_of_digits+1; precision_specified = 1; - } - } - /* zero padding to specified precision? */ - if (num_of_digits < precision) - number_of_zeros_to_pad = precision - num_of_digits; - } - /* zero padding to specified minimal field width? */ - if (!justify_left && zero_padding) { - int n = min_field_width - (str_arg_l+number_of_zeros_to_pad); - if (n > 0) number_of_zeros_to_pad += n; - } - break; - } - default: /* unrecognized conversion specifier, keep format string as-is*/ - zero_padding = 0; /* turn zero padding off for non-numeric convers. */ -#ifndef DIGITAL_UNIX_COMPATIBLE - justify_left = 1; min_field_width = 0; /* reset flags */ -#endif -#if defined(PERL_COMPATIBLE) || defined(LINUX_COMPATIBLE) - /* keep the entire format string unchanged */ - str_arg = starting_p; str_arg_l = p - starting_p; - /* well, not exactly so for Linux, which does something inbetween, - * and I don't feel an urge to imitate it: "%+++++hy" -> "%+y" */ -#else - /* discard the unrecognized conversion, just keep * - * the unrecognized conversion character */ - str_arg = p; str_arg_l = 0; -#endif - if (*p) str_arg_l++; /* include invalid conversion specifier unchanged - if not at end-of-string */ - break; - } - if (*p) p++; /* step over the just processed conversion specifier */ - /* insert padding to the left as requested by min_field_width; - this does not include the zero padding in case of numerical conversions*/ - if (!justify_left) { /* left padding with blank or zero */ - int n = min_field_width - (str_arg_l+number_of_zeros_to_pad); - if (n > 0) { - if (str_l < str_m) { - size_t avail = str_m-str_l; - fast_memset(str+str_l, (zero_padding?'0':' '), (n>avail?avail:n)); - } - str_l += n; - } - } - /* zero padding as requested by the precision or by the minimal field width - * for numeric conversions required? */ - if (number_of_zeros_to_pad <= 0) { - /* will not copy first part of numeric right now, * - * force it to be copied later in its entirety */ - zero_padding_insertion_ind = 0; - } else { - /* insert first part of numerics (sign or '0x') before zero padding */ - int n = zero_padding_insertion_ind; - if (n > 0) { - if (str_l < str_m) { - size_t avail = str_m-str_l; - fast_memcpy(str+str_l, str_arg, (n>avail?avail:n)); - } - str_l += n; - } - /* insert zero padding as requested by the precision or min field width */ - n = number_of_zeros_to_pad; - if (n > 0) { - if (str_l < str_m) { - size_t avail = str_m-str_l; - fast_memset(str+str_l, '0', (n>avail?avail:n)); - } - str_l += n; - } - } - /* insert formatted string - * (or as-is conversion specifier for unknown conversions) */ - { int n = str_arg_l - zero_padding_insertion_ind; - if (n > 0) { - if (str_l < str_m) { - size_t avail = str_m-str_l; - fast_memcpy(str+str_l, str_arg+zero_padding_insertion_ind, - (n>avail?avail:n)); - } - str_l += n; - } - } - /* insert right padding */ - if (justify_left) { /* right blank padding to the field width */ - int n = min_field_width - (str_arg_l+number_of_zeros_to_pad); - if (n > 0) { - if (str_l < str_m) { - size_t avail = str_m-str_l; - fast_memset(str+str_l, ' ', (n>avail?avail:n)); - } - str_l += n; - } - } - } - } -#if defined(NEED_SNPRINTF_ONLY) - va_end(ap); -#endif - if (str_m > 0) { /* make sure the string is null-terminated - even at the expense of overwriting the last character - (shouldn't happen, but just in case) */ - str[str_l <= str_m-1 ? str_l : str_m-1] = '\0'; - } - /* Return the number of characters formatted (excluding trailing null - * character), that is, the number of characters that would have been - * written to the buffer if it were large enough. - * - * The value of str_l should be returned, but str_l is of unsigned type - * size_t, and snprintf is int, possibly leading to an undetected - * integer overflow, resulting in a negative return value, which is illegal. - * Both XSH5 and ISO C99 (at least the draft) are silent on this issue. - * Should errno be set to EOVERFLOW and EOF returned in this case??? - */ - return (int) str_l; -} -#endif diff --git a/base/str_io.h b/base/str_io.h deleted file mode 100644 index 048d055f..00000000 --- a/base/str_io.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once -#ifndef STR_IO_H -#define STR_IO_H - -#include "MMBitmap.h" -#include "file_io.h" -#include - - -enum _MMBMPStringError { - kMMBMPStringGenericError = 0, - kMMBMPStringInvalidHeaderError, - kMMBMPStringDecodeError, - kMMBMPStringDecompressError, - kMMBMPStringSizeError, /* Size does not match header. */ - MMMBMPStringEncodeError, - kMMBMPStringCompressError -}; - -typedef MMIOError MMBMPStringError; - -/* Creates a 24-bit bitmap from a compressed, printable string. - * - * String should be in the format: "b[width],[height],[data]", - * where [width] and [height] are the image width & height, and [data] - * is the raw image data run through zlib_compress() and base64_encode(). - * - * Returns NULL on error; follows the Create Rule (that is, the caller is - * responsible for destroy'()ing object). - * If |error| is non-NULL, it will be set to the error code on return. - */ -MMBitmapRef createMMBitmapFromString(const uint8_t *buffer, size_t buflen, - MMBMPStringError *error); - -/* Inverse of createMMBitmapFromString(). - * - * Creates string in the format: "b[width],[height],[data]", where [width] and - * [height] are the image width & height, and [data] is the raw image data run - * through zlib_compress() and base64_encode(). - * - * Returns NULL on error, or new string on success (to be free'()d by caller). - * If |error| is non-NULL, it will be set to the error code on return. - */ -uint8_t *createStringFromMMBitmap(MMBitmapRef bitmap, MMBMPStringError *error); - -/* Returns description of given error code. - * Returned string is constant and hence should not be freed. */ -const char *MMBitmapStringErrorString(MMBMPStringError err); - -#endif /* STR_IO_H */ diff --git a/base/str_io_c.h b/base/str_io_c.h deleted file mode 100644 index fa80f8ef..00000000 --- a/base/str_io_c.h +++ /dev/null @@ -1,208 +0,0 @@ -#include "str_io.h" -#include "zlib_util_c.h" -#include "base64_c.h" -#include "snprintf_c.h" /* snprintf() */ -#include /* fputs() */ -#include /* isdigit() */ -#include /* atoi() */ -#include /* strlen() */ -#include - -#if defined(_MSC_VER) - #include "ms_stdbool.h" -#else - #include -#endif - -#define STR_BITS_PER_PIXEL 24 -#define STR_BYTES_PER_PIXEL ((STR_BITS_PER_PIXEL) / 8) - -#define MAX_DIMENSION_LEN 5 /* Maximum length for [width] or [height] - * in string. */ - -const char *MMBitmapStringErrorString(MMBMPStringError err) -{ - switch (err) { - case kMMBMPStringInvalidHeaderError: - return "Invalid header for string"; - case kMMBMPStringDecodeError: - return "Error decoding string"; - case kMMBMPStringDecompressError: - return "Error decompressing string"; - case kMMBMPStringSizeError: - return "String not of expected size"; - case MMMBMPStringEncodeError: - return "Error encoding string"; - case kMMBMPStringCompressError: - return "Error compressing string"; - default: - return NULL; - } -} - -/* Parses beginning of string in the form of "[width],[height],*". - * - * If successful, |width| and |height| are set to the appropropriate values, - * |len| is set to the length of [width] + the length of [height] + 2, - * and true is returned; otherwise, false is returned. - */ -static bool getSizeFromString(const uint8_t *buf, size_t buflen, - size_t *width, size_t *height, - size_t *len); - -MMBitmapRef createMMBitmapFromString(const uint8_t *buffer, size_t buflen, - MMBMPStringError *err) -{ - uint8_t *decoded, *decompressed; - size_t width, height; - size_t len, bytewidth; - - if (*buffer++ != 'b' || !getSizeFromString(buffer, --buflen, - &width, &height, &len)) { - if (err != NULL) *err = kMMBMPStringInvalidHeaderError; - return NULL; - } - buffer += len; - buflen -= len; - - decoded = base64decode(buffer, buflen, NULL); - if (decoded == NULL) { - if (err != NULL) *err = kMMBMPStringDecodeError; - return NULL; - } - - decompressed = zlib_decompress(decoded, &len); - free(decoded); - - if (decompressed == NULL) { - if (err != NULL) *err = kMMBMPStringDecompressError; - return NULL; - } - - bytewidth = width * STR_BYTES_PER_PIXEL; /* Note that bytewidth is NOT - * aligned to a padding. */ - if (height * bytewidth != len) { - if (err != NULL) *err = kMMBMPStringSizeError; - return NULL; - } - - return createMMBitmap(decompressed, width, height, - bytewidth, STR_BITS_PER_PIXEL, STR_BYTES_PER_PIXEL); -} - -/* Returns bitmap data suitable for encoding to a string; that is, 24-bit BGR - * bitmap with no padding and 3 bytes per pixel. - * - * Caller is responsible for free()'ing returned buffer. */ -static uint8_t *createRawBitmapData(MMBitmapRef bitmap); - -uint8_t *createStringFromMMBitmap(MMBitmapRef bitmap, MMBMPStringError *err) -{ - uint8_t *raw, *compressed; - uint8_t *ret, *encoded; - size_t len, retlen; - - assert(bitmap != NULL); - - raw = createRawBitmapData(bitmap); - if (raw == NULL) { - if (err != NULL) *err = kMMBMPStringGenericError; - return NULL; - } - - compressed = zlib_compress(raw, - bitmap->width * bitmap->height * - STR_BYTES_PER_PIXEL, - 9, &len); - free(raw); - if (compressed == NULL) { - if (err != NULL) *err = kMMBMPStringCompressError; - return NULL; - } - - encoded = base64encode(compressed, len - 1, &retlen); - free(compressed); - if (encoded == NULL) { - if (err != NULL) *err = MMMBMPStringEncodeError; - return NULL; - } - - retlen += 3 + (MAX_DIMENSION_LEN * 2); - ret = calloc(sizeof(char), (retlen + 1)); - snprintf((char *)ret, retlen, "b%lu,%lu,%s", (unsigned long)bitmap->width, - (unsigned long)bitmap->height, - encoded); - ret[retlen] = '\0'; - free(encoded); - return ret; -} - -static uint32_t parseDimension(const uint8_t *buf, size_t buflen, - size_t *numlen); - -static bool getSizeFromString(const uint8_t *buf, size_t buflen, - size_t *width, size_t *height, - size_t *len) -{ - size_t numlen; - assert(buf != NULL); - assert(width != NULL); - assert(height != NULL); - - if ((*width = parseDimension(buf, buflen, &numlen)) == 0) { - return false; - } - *len = numlen + 1; - - if ((*height = parseDimension(buf + *len, buflen, &numlen)) == 0) { - return false; - } - *len += numlen + 1; - - return true; -} - -/* Parses one dimension from string as described in getSizeFromString(). - * Returns dimension on success, or 0 on error. */ -static uint32_t parseDimension(const uint8_t *buf, - size_t buflen, size_t *numlen){ - char num[MAX_DIMENSION_LEN + 1]; - size_t i; - // ssize_t len; - // size_t len; - // uint8_t *len; - - assert(buf != NULL); - // assert(len != NULL); - for (i = 0; i < buflen && buf[i] != ',' && buf[i] != '\0'; ++i) { - if (!isdigit(buf[i]) || i > MAX_DIMENSION_LEN) return 0; - num[i] = buf[i]; - } - num[i] = '\0'; - *numlen = i; - - return (uint32_t)atoi(num); -} - -static uint8_t *createRawBitmapData(MMBitmapRef bitmap) -{ - uint8_t *raw = calloc(STR_BYTES_PER_PIXEL, bitmap->width * bitmap->height); - size_t y; - - for (y = 0; y < bitmap->height; ++y) { - /* No padding is added to string bitmaps. */ - const size_t rowOffset = y * bitmap->width * STR_BYTES_PER_PIXEL; - size_t x; - for (x = 0; x < bitmap->width; ++x) { - /* Copy in BGR format. */ - const size_t colOffset = x * STR_BYTES_PER_PIXEL; - uint8_t *dest = raw + rowOffset + colOffset; - MMRGBColor *srcColor = MMRGBColorRefAtPoint(bitmap, x, y); - dest[0] = srcColor->blue; - dest[1] = srcColor->green; - dest[2] = srcColor->red; - } - } - - return raw; -} diff --git a/base/uthash.h b/base/uthash.h deleted file mode 100644 index 1ea0fea1..00000000 --- a/base/uthash.h +++ /dev/null @@ -1,929 +0,0 @@ -/* - * Copyright (c) 2003-2009, Troy D. Hanson http://uthash.sourceforge.net - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER - * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#pragma once -#ifndef UTHASH_H -#define UTHASH_H - -#include /* memcmp, strlen */ -#include /* ptrdiff_t */ -#include - - -#define UTHASH_VERSION 1.8 - -/* C++ requires extra stringent casting */ -#if defined __cplusplus -#define TYPEOF(x) (typeof(x)) -#else -#define TYPEOF(x) -#endif - - -#define uthash_fatal(msg) exit(-1) /* fatal error (out of memory,etc) */ -#define uthash_malloc(sz) malloc(sz) /* malloc fcn */ -#define uthash_free(ptr) free(ptr) /* free fcn */ - -#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */ -#define uthash_expand_fyi(tbl) /* can be defined to log expands */ - -/* initial number of buckets */ -#define HASH_INITIAL_NUM_BUCKETS 32 /* initial number of buckets */ -#define HASH_INITIAL_NUM_BUCKETS_LOG2 5 /* lg2 of initial number of buckets */ -#define HASH_BKT_CAPACITY_THRESH 10 /* expand when bucket count reaches */ - -/* calculate the element whose hash handle address is hhe */ -#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)hhp) - (tbl)->hho)) - -#define HASH_FIND(hh,head,keyptr,keylen,out) \ -do { \ - unsigned _hf_bkt,_hf_hashv; \ - out=TYPEOF(out)NULL; \ - if (head) { \ - HASH_FCN(keyptr,keylen, (head)->hh.tbl->num_buckets, _hf_hashv, _hf_bkt); \ - if (HASH_BLOOM_TEST((head)->hh.tbl, _hf_hashv)) { \ - HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], \ - keyptr,keylen,out); \ - } \ - } \ -} while (0) - -#if defined(HASH_BLOOM) -#define HASH_BLOOM_BITLEN (1ULL << HASH_BLOOM) -#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8) + ((HASH_BLOOM_BITLEN%8) ? 1:0) -#define HASH_BLOOM_MAKE(tbl) \ -do { \ - (tbl)->bloom_nbits = HASH_BLOOM; \ - (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \ - if (!((tbl)->bloom_bv)) { uthash_fatal( "out of memory"); } \ - memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN); \ - (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \ -} while (0); - -#define HASH_BLOOM_FREE(tbl) \ -do { \ - uthash_free((tbl)->bloom_bv); \ -} while (0); - -#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8] |= (1U << ((idx)%8))) -#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8] & (1U << ((idx)%8))) - -#define HASH_BLOOM_ADD(tbl,hashv) \ - HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1))) - -#define HASH_BLOOM_TEST(tbl,hashv) \ - HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1))) - -#else -#define HASH_BLOOM_MAKE(tbl) -#define HASH_BLOOM_FREE(tbl) -#define HASH_BLOOM_ADD(tbl,hashv) -#define HASH_BLOOM_TEST(tbl,hashv) (1) -#endif - -#define HASH_MAKE_TABLE(hh,head) \ -do { \ - (head)->hh.tbl = (UT_hash_table*)uthash_malloc( \ - sizeof(UT_hash_table)); \ - if (!((head)->hh.tbl)) { uthash_fatal( "out of memory"); } \ - memset((head)->hh.tbl, 0, sizeof(UT_hash_table)); \ - (head)->hh.tbl->tail = &((head)->hh); \ - (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \ - (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \ - (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \ - (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \ - HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ - if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); } \ - memset((head)->hh.tbl->buckets, 0, \ - HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ - HASH_BLOOM_MAKE((head)->hh.tbl); \ - (head)->hh.tbl->signature = HASH_SIGNATURE; \ -} while(0) - -#define HASH_ADD(hh,head,fieldname,keylen_in,add) \ - HASH_ADD_KEYPTR(hh,head,&add->fieldname,keylen_in,add) - -#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \ -do { \ - unsigned _ha_bkt; \ - (add)->hh.next = NULL; \ - (add)->hh.key = (char*)keyptr; \ - (add)->hh.keylen = keylen_in; \ - if (!(head)) { \ - head = (add); \ - (head)->hh.prev = NULL; \ - HASH_MAKE_TABLE(hh,head); \ - } else { \ - (head)->hh.tbl->tail->next = (add); \ - (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \ - (head)->hh.tbl->tail = &((add)->hh); \ - } \ - (head)->hh.tbl->num_items++; \ - (add)->hh.tbl = (head)->hh.tbl; \ - HASH_FCN(keyptr,keylen_in, (head)->hh.tbl->num_buckets, \ - (add)->hh.hashv, _ha_bkt); \ - HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt],&(add)->hh); \ - HASH_BLOOM_ADD((head)->hh.tbl,(add)->hh.hashv); \ - HASH_EMIT_KEY(hh,head,keyptr,keylen_in); \ - HASH_FSCK(hh,head); \ -} while(0) - -#define HASH_TO_BKT( hashv, num_bkts, bkt ) \ -do { \ - bkt = ((hashv) & ((num_bkts) - 1)); \ -} while(0) - -/* delete "delptr" from the hash table. - * "the usual" patch-up process for the app-order doubly-linked-list. - * The use of _hd_hh_del below deserves special explanation. - * These used to be expressed using (delptr) but that led to a bug - * if someone used the same symbol for the head and deletee, like - * HASH_DELETE(hh,users,users); - * We want that to work, but by changing the head (users) below - * we were forfeiting our ability to further refer to the deletee (users) - * in the patch-up process. Solution: use scratch space in the table to - * copy the deletee pointer, then the latter references are via that - * scratch pointer rather than through the repointed (users) symbol. - */ -#define HASH_DELETE(hh,head,delptr) \ -do { \ - unsigned _hd_bkt; \ - struct UT_hash_handle *_hd_hh_del; \ - if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) ) { \ - uthash_free((head)->hh.tbl->buckets ); \ - HASH_BLOOM_FREE((head)->hh.tbl); \ - uthash_free((head)->hh.tbl); \ - head = NULL; \ - } else { \ - _hd_hh_del = &((delptr)->hh); \ - if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) { \ - (head)->hh.tbl->tail = \ - (UT_hash_handle*)((char*)((delptr)->hh.prev) + \ - (head)->hh.tbl->hho); \ - } \ - if ((delptr)->hh.prev) { \ - ((UT_hash_handle*)((char*)((delptr)->hh.prev) + \ - (head)->hh.tbl->hho))->next = (delptr)->hh.next; \ - } else { \ - head = TYPEOF(head)((delptr)->hh.next); \ - } \ - if (_hd_hh_del->next) { \ - ((UT_hash_handle*)((char*)_hd_hh_del->next + \ - (head)->hh.tbl->hho))->prev = \ - _hd_hh_del->prev; \ - } \ - HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ - HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \ - (head)->hh.tbl->num_items--; \ - } \ - HASH_FSCK(hh,head); \ -} while (0) - - -/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */ -#define HASH_FIND_STR(head,findstr,out) \ - HASH_FIND(hh,head,findstr,strlen(findstr),out) -#define HASH_ADD_STR(head,strfield,add) \ - HASH_ADD(hh,head,strfield,strlen(add->strfield),add) -#define HASH_FIND_INT(head,findint,out) \ - HASH_FIND(hh,head,findint,sizeof(int),out) -#define HASH_ADD_INT(head,intfield,add) \ - HASH_ADD(hh,head,intfield,sizeof(int),add) -#define HASH_DEL(head,delptr) \ - HASH_DELETE(hh,head,delptr) - -/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined. - * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined. - */ -#if defined(HASH_DEBUG) -#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0) -#define HASH_FSCK(hh,head) \ -do { \ - unsigned _bkt_i; \ - unsigned _count, _bkt_count; \ - char *_prev; \ - struct UT_hash_handle *_thh; \ - if (head) { \ - _count = 0; \ - for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) { \ - _bkt_count = 0; \ - _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \ - _prev = NULL; \ - while (_thh) { \ - if (_prev != (char*)(_thh->hh_prev)) { \ - HASH_OOPS("invalid hh_prev %p, actual %p\n", \ - _thh->hh_prev, _prev ); \ - } \ - _bkt_count++; \ - _prev = (char*)(_thh); \ - _thh = _thh->hh_next; \ - } \ - _count += _bkt_count; \ - if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \ - HASH_OOPS("invalid bucket count %d, actual %d\n", \ - (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \ - } \ - } \ - if (_count != (head)->hh.tbl->num_items) { \ - HASH_OOPS("invalid hh item count %d, actual %d\n", \ - (head)->hh.tbl->num_items, _count ); \ - } \ - /* traverse hh in app order; check next/prev integrity, count */ \ - _count = 0; \ - _prev = NULL; \ - _thh = &(head)->hh; \ - while (_thh) { \ - _count++; \ - if (_prev !=(char*)(_thh->prev)) { \ - HASH_OOPS("invalid prev %p, actual %p\n", \ - _thh->prev, _prev ); \ - } \ - _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \ - _thh = ( _thh->next ? (UT_hash_handle*)((char*)(_thh->next) + \ - (head)->hh.tbl->hho) : NULL ); \ - } \ - if (_count != (head)->hh.tbl->num_items) { \ - HASH_OOPS("invalid app item count %d, actual %d\n", \ - (head)->hh.tbl->num_items, _count ); \ - } \ - } \ -} while (0) -#else -#define HASH_FSCK(hh,head) -#endif - -/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to - * the descriptor to which this macro is defined for tuning the hash function. - * The app can #include to get the prototype for write(2). */ -#if defined(HASH_EMIT_KEYS) -#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \ -do { \ - unsigned _klen = fieldlen; \ - write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \ - write(HASH_EMIT_KEYS, keyptr, fieldlen); \ -} while (0) -#else -#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) -#endif - -/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */ -#if defined(HASH_FUNCTION) -#define HASH_FCN HASH_FUNCTION -#else -#define HASH_FCN HASH_JEN -#endif - -/* The Bernstein hash function, used in Perl prior to v5.6 */ -#define HASH_BER(key,keylen,num_bkts,hashv,bkt) \ -do { \ - unsigned _hb_keylen=keylen; \ - char *_hb_key=(char*)key; \ - (hashv) = 0; \ - while (_hb_keylen--) { (hashv) = ((hashv) * 33) + *_hb_key++; } \ - bkt = (hashv) & (num_bkts-1); \ -} while (0) - - -/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at - * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */ -#define HASH_SAX(key,keylen,num_bkts,hashv,bkt) \ -do { \ - unsigned _sx_i; \ - char *_hs_key=(char*)key; \ - hashv = 0; \ - for(_sx_i=0; _sx_i < keylen; _sx_i++) \ - hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \ - bkt = hashv & (num_bkts-1); \ -} while (0) - -#define HASH_FNV(key,keylen,num_bkts,hashv,bkt) \ -do { \ - unsigned _fn_i; \ - char *_hf_key=(char*)key; \ - hashv = 2166136261UL; \ - for(_fn_i=0; _fn_i < keylen; _fn_i++) \ - hashv = (hashv * 16777619) ^ _hf_key[_fn_i]; \ - bkt = hashv & (num_bkts-1); \ -} while(0); - -#define HASH_OAT(key,keylen,num_bkts,hashv,bkt) \ -do { \ - unsigned _ho_i; \ - char *_ho_key=(char*)key; \ - hashv = 0; \ - for(_ho_i=0; _ho_i < keylen; _ho_i++) { \ - hashv += _ho_key[_ho_i]; \ - hashv += (hashv << 10); \ - hashv ^= (hashv >> 6); \ - } \ - hashv += (hashv << 3); \ - hashv ^= (hashv >> 11); \ - hashv += (hashv << 15); \ - bkt = hashv & (num_bkts-1); \ -} while(0) - -#define HASH_JEN_MIX(a,b,c) \ -do { \ - a -= b; a -= c; a ^= ( c >> 13 ); \ - b -= c; b -= a; b ^= ( a << 8 ); \ - c -= a; c -= b; c ^= ( b >> 13 ); \ - a -= b; a -= c; a ^= ( c >> 12 ); \ - b -= c; b -= a; b ^= ( a << 16 ); \ - c -= a; c -= b; c ^= ( b >> 5 ); \ - a -= b; a -= c; a ^= ( c >> 3 ); \ - b -= c; b -= a; b ^= ( a << 10 ); \ - c -= a; c -= b; c ^= ( b >> 15 ); \ -} while (0) - -#define HASH_JEN(key,keylen,num_bkts,hashv,bkt) \ -do { \ - unsigned _hj_i,_hj_j,_hj_k; \ - char *_hj_key=(char*)key; \ - hashv = 0xfeedbeef; \ - _hj_i = _hj_j = 0x9e3779b9; \ - _hj_k = keylen; \ - while (_hj_k >= 12) { \ - _hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \ - + ( (unsigned)_hj_key[2] << 16 ) \ - + ( (unsigned)_hj_key[3] << 24 ) ); \ - _hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \ - + ( (unsigned)_hj_key[6] << 16 ) \ - + ( (unsigned)_hj_key[7] << 24 ) ); \ - hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \ - + ( (unsigned)_hj_key[10] << 16 ) \ - + ( (unsigned)_hj_key[11] << 24 ) ); \ - \ - HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ - \ - _hj_key += 12; \ - _hj_k -= 12; \ - } \ - hashv += keylen; \ - switch ( _hj_k ) { \ - case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); \ - case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); \ - case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); \ - case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); \ - case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); \ - case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); \ - case 5: _hj_j += _hj_key[4]; \ - case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); \ - case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); \ - case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); \ - case 1: _hj_i += _hj_key[0]; \ - } \ - HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ - bkt = hashv & (num_bkts-1); \ -} while(0) - -/* The Paul Hsieh hash function */ -#undef get16bits -#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ - || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) -#define get16bits(d) (*((const uint16_t *) (d))) -#endif - -#if !defined (get16bits) -#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \ - +(uint32_t)(((const uint8_t *)(d))[0]) ) -#endif -#define HASH_SFH(key,keylen,num_bkts,hashv,bkt) \ -do { \ - char *_sfh_key=(char*)key; \ - uint32_t _sfh_tmp, _sfh_len = keylen; \ - \ - int _sfh_rem = _sfh_len & 3; \ - _sfh_len >>= 2; \ - hashv = 0xcafebabe; \ - \ - /* Main loop */ \ - for (;_sfh_len > 0; _sfh_len--) { \ - hashv += get16bits (_sfh_key); \ - _sfh_tmp = (get16bits (_sfh_key+2) << 11) ^ hashv; \ - hashv = (hashv << 16) ^ _sfh_tmp; \ - _sfh_key += 2*sizeof (uint16_t); \ - hashv += hashv >> 11; \ - } \ - \ - /* Handle end cases */ \ - switch (_sfh_rem) { \ - case 3: hashv += get16bits (_sfh_key); \ - hashv ^= hashv << 16; \ - hashv ^= _sfh_key[sizeof (uint16_t)] << 18; \ - hashv += hashv >> 11; \ - break; \ - case 2: hashv += get16bits (_sfh_key); \ - hashv ^= hashv << 11; \ - hashv += hashv >> 17; \ - break; \ - case 1: hashv += *_sfh_key; \ - hashv ^= hashv << 10; \ - hashv += hashv >> 1; \ - } \ - \ - /* Force "avalanching" of final 127 bits */ \ - hashv ^= hashv << 3; \ - hashv += hashv >> 5; \ - hashv ^= hashv << 4; \ - hashv += hashv >> 17; \ - hashv ^= hashv << 25; \ - hashv += hashv >> 6; \ - bkt = hashv & (num_bkts-1); \ -} while(0); - -#if defined(HASH_USING_NO_STRICT_ALIASING) -/* The MurmurHash exploits some CPU's (e.g. x86) tolerance for unaligned reads. - * For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error. - * So MurmurHash comes in two versions, the faster unaligned one and the slower - * aligned one. We only use the faster one on CPU's where we know it's safe. - * - * Note the preprocessor built-in defines can be emitted using: - * - * gcc -m64 -dM -E - < /dev/null (on gcc) - * cc -## a.c (where a.c is a simple test file) (Sun Studio) - */ -#if (defined(__i386__) || defined(__x86_64__)) -#define HASH_MUR HASH_MUR_UNALIGNED -#else -#define HASH_MUR HASH_MUR_ALIGNED -#endif - -/* Appleby's MurmurHash fast version for unaligned-tolerant archs like i386 */ -#define HASH_MUR_UNALIGNED(key,keylen,num_bkts,hashv,bkt) \ -do { \ - const unsigned int _mur_m = 0x5bd1e995; \ - const int _mur_r = 24; \ - hashv = 0xcafebabe ^ keylen; \ - char *_mur_key = (char *)key; \ - uint32_t _mur_tmp, _mur_len = keylen; \ - \ - for (;_mur_len >= 4; _mur_len-=4) { \ - _mur_tmp = *(uint32_t *)_mur_key; \ - _mur_tmp *= _mur_m; \ - _mur_tmp ^= _mur_tmp >> _mur_r; \ - _mur_tmp *= _mur_m; \ - hashv *= _mur_m; \ - hashv ^= _mur_tmp; \ - _mur_key += 4; \ - } \ - \ - switch(_mur_len) \ - { \ - case 3: hashv ^= _mur_key[2] << 16; \ - case 2: hashv ^= _mur_key[1] << 8; \ - case 1: hashv ^= _mur_key[0]; \ - hashv *= _mur_m; \ - }; \ - \ - hashv ^= hashv >> 13; \ - hashv *= _mur_m; \ - hashv ^= hashv >> 15; \ - \ - bkt = hashv & (num_bkts-1); \ -} while(0) - -/* Appleby's MurmurHash version for alignment-sensitive archs like Sparc */ -#define HASH_MUR_ALIGNED(key,keylen,num_bkts,hashv,bkt) \ -do { \ - const unsigned int _mur_m = 0x5bd1e995; \ - const int _mur_r = 24; \ - hashv = 0xcafebabe ^ keylen; \ - char *_mur_key = (char *)key; \ - uint32_t _mur_len = keylen; \ - int _mur_align = (int)_mur_key & 3; \ - \ - if (_mur_align && (_mur_len >= 4)) { \ - unsigned _mur_t = 0, _mur_d = 0; \ - switch(_mur_align) { \ - case 1: _mur_t |= _mur_key[2] << 16; \ - case 2: _mur_t |= _mur_key[1] << 8; \ - case 3: _mur_t |= _mur_key[0]; \ - } \ - _mur_t <<= (8 * _mur_align); \ - _mur_key += 4-_mur_align; \ - _mur_len -= 4-_mur_align; \ - int _mur_sl = 8 * (4-_mur_align); \ - int _mur_sr = 8 * _mur_align; \ - \ - for (;_mur_len >= 4; _mur_len-=4) { \ - _mur_d = *(unsigned *)_mur_key; \ - _mur_t = (_mur_t >> _mur_sr) | (_mur_d << _mur_sl); \ - unsigned _mur_k = _mur_t; \ - _mur_k *= _mur_m; \ - _mur_k ^= _mur_k >> _mur_r; \ - _mur_k *= _mur_m; \ - hashv *= _mur_m; \ - hashv ^= _mur_k; \ - _mur_t = _mur_d; \ - _mur_key += 4; \ - } \ - _mur_d = 0; \ - if(_mur_len >= _mur_align) { \ - switch(_mur_align) { \ - case 3: _mur_d |= _mur_key[2] << 16; \ - case 2: _mur_d |= _mur_key[1] << 8; \ - case 1: _mur_d |= _mur_key[0]; \ - } \ - unsigned _mur_k = (_mur_t >> _mur_sr) | (_mur_d << _mur_sl); \ - _mur_k *= _mur_m; \ - _mur_k ^= _mur_k >> _mur_r; \ - _mur_k *= _mur_m; \ - hashv *= _mur_m; \ - hashv ^= _mur_k; \ - _mur_k += _mur_align; \ - _mur_len -= _mur_align; \ - \ - switch(_mur_len) \ - { \ - case 3: hashv ^= _mur_key[2] << 16; \ - case 2: hashv ^= _mur_key[1] << 8; \ - case 1: hashv ^= _mur_key[0]; \ - hashv *= _mur_m; \ - } \ - } else { \ - switch(_mur_len) \ - { \ - case 3: _mur_d ^= _mur_key[2] << 16; \ - case 2: _mur_d ^= _mur_key[1] << 8; \ - case 1: _mur_d ^= _mur_key[0]; \ - case 0: hashv ^= (_mur_t >> _mur_sr) | (_mur_d << _mur_sl); \ - hashv *= _mur_m; \ - } \ - } \ - \ - hashv ^= hashv >> 13; \ - hashv *= _mur_m; \ - hashv ^= hashv >> 15; \ - } else { \ - for (;_mur_len >= 4; _mur_len-=4) { \ - unsigned _mur_k = *(unsigned*)_mur_key; \ - _mur_k *= _mur_m; \ - _mur_k ^= _mur_k >> _mur_r; \ - _mur_k *= _mur_m; \ - hashv *= _mur_m; \ - hashv ^= _mur_k; \ - _mur_key += 4; \ - } \ - switch(_mur_len) \ - { \ - case 3: hashv ^= _mur_key[2] << 16; \ - case 2: hashv ^= _mur_key[1] << 8; \ - case 1: hashv ^= _mur_key[0]; \ - hashv *= _mur_m; \ - } \ - \ - hashv ^= hashv >> 13; \ - hashv *= _mur_m; \ - hashv ^= hashv >> 15; \ - } \ - bkt = hashv & (num_bkts-1); \ -} while(0) -#endif /* HASH_USING_NO_STRICT_ALIASING */ - -/* key comparison function; return 0 if keys equal */ -#define HASH_KEYCMP(a,b,len) memcmp(a,b,len) - -/* iterate over items in a known bucket to find desired item */ -#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,out) \ -out = TYPEOF(out)((head.hh_head) ? ELMT_FROM_HH(tbl,head.hh_head) : NULL); \ -while (out) { \ - if (out->hh.keylen == keylen_in) { \ - if ((HASH_KEYCMP(out->hh.key,keyptr,keylen_in)) == 0) break; \ - } \ - out= TYPEOF(out)((out->hh.hh_next) ? \ - ELMT_FROM_HH(tbl,out->hh.hh_next) : NULL); \ -} - -/* add an item to a bucket */ -#define HASH_ADD_TO_BKT(head,addhh) \ -do { \ - head.count++; \ - (addhh)->hh_next = head.hh_head; \ - (addhh)->hh_prev = NULL; \ - if (head.hh_head) { (head).hh_head->hh_prev = (addhh); } \ - (head).hh_head=addhh; \ - if (head.count >= ((head.expand_mult+1) * HASH_BKT_CAPACITY_THRESH) \ - && (addhh)->tbl->noexpand != 1) { \ - HASH_EXPAND_BUCKETS((addhh)->tbl); \ - } \ -} while(0) - -/* remove an item from a given bucket */ -#define HASH_DEL_IN_BKT(hh,head,hh_del) \ - (head).count--; \ - if ((head).hh_head == hh_del) { \ - (head).hh_head = hh_del->hh_next; \ - } \ - if (hh_del->hh_prev) { \ - hh_del->hh_prev->hh_next = hh_del->hh_next; \ - } \ - if (hh_del->hh_next) { \ - hh_del->hh_next->hh_prev = hh_del->hh_prev; \ - } - -/* Bucket expansion has the effect of doubling the number of buckets - * and redistributing the items into the new buckets. Ideally the - * items will distribute more or less evenly into the new buckets - * (the extent to which this is true is a measure of the quality of - * the hash function as it applies to the key domain). - * - * With the items distributed into more buckets, the chain length - * (item count) in each bucket is reduced. Thus by expanding buckets - * the hash keeps a bound on the chain length. This bounded chain - * length is the essence of how a hash provides constant time lookup. - * - * The calculation of tbl->ideal_chain_maxlen below deserves some - * explanation. First, keep in mind that we're calculating the ideal - * maximum chain length based on the *new* (doubled) bucket count. - * In fractions this is just n/b (n=number of items,b=new num buckets). - * Since the ideal chain length is an integer, we want to calculate - * ceil(n/b). We don't depend on floating point arithmetic in this - * hash, so to calculate ceil(n/b) with integers we could write - * - * ceil(n/b) = (n/b) + ((n%b)?1:0) - * - * and in fact a previous version of this hash did just that. - * But now we have improved things a bit by recognizing that b is - * always a power of two. We keep its base 2 log handy (call it lb), - * so now we can write this with a bit shift and logical AND: - * - * ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0) - * - */ -#define HASH_EXPAND_BUCKETS(tbl) \ -do { \ - unsigned _he_bkt; \ - unsigned _he_bkt_i; \ - struct UT_hash_handle *_he_thh, *_he_hh_nxt; \ - UT_hash_bucket *_he_new_buckets, *_he_newbkt; \ - _he_new_buckets = (UT_hash_bucket*)uthash_malloc( \ - 2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ - if (!_he_new_buckets) { uthash_fatal( "out of memory"); } \ - memset(_he_new_buckets, 0, \ - 2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ - tbl->ideal_chain_maxlen = \ - (tbl->num_items >> (tbl->log2_num_buckets+1)) + \ - ((tbl->num_items & ((tbl->num_buckets*2)-1)) ? 1 : 0); \ - tbl->nonideal_items = 0; \ - for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++) \ - { \ - _he_thh = tbl->buckets[ _he_bkt_i ].hh_head; \ - while (_he_thh) { \ - _he_hh_nxt = _he_thh->hh_next; \ - HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2, _he_bkt); \ - _he_newbkt = &(_he_new_buckets[ _he_bkt ]); \ - if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) { \ - tbl->nonideal_items++; \ - _he_newbkt->expand_mult = _he_newbkt->count / \ - tbl->ideal_chain_maxlen; \ - } \ - _he_thh->hh_prev = NULL; \ - _he_thh->hh_next = _he_newbkt->hh_head; \ - if (_he_newbkt->hh_head) _he_newbkt->hh_head->hh_prev = \ - _he_thh; \ - _he_newbkt->hh_head = _he_thh; \ - _he_thh = _he_hh_nxt; \ - } \ - } \ - tbl->num_buckets *= 2; \ - tbl->log2_num_buckets++; \ - uthash_free( tbl->buckets ); \ - tbl->buckets = _he_new_buckets; \ - tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ? \ - (tbl->ineff_expands+1) : 0; \ - if (tbl->ineff_expands > 1) { \ - tbl->noexpand=1; \ - uthash_noexpand_fyi(tbl); \ - } \ - uthash_expand_fyi(tbl); \ -} while(0) - - -/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */ -/* Note that HASH_SORT assumes the hash handle name to be hh. - * HASH_SRT was added to allow the hash handle name to be passed in. */ -#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn) -#define HASH_SRT(hh,head,cmpfcn) \ -do { \ - unsigned _hs_i; \ - unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \ - struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \ - if (head) { \ - _hs_insize = 1; \ - _hs_looping = 1; \ - _hs_list = &((head)->hh); \ - while (_hs_looping) { \ - _hs_p = _hs_list; \ - _hs_list = NULL; \ - _hs_tail = NULL; \ - _hs_nmerges = 0; \ - while (_hs_p) { \ - _hs_nmerges++; \ - _hs_q = _hs_p; \ - _hs_psize = 0; \ - for ( _hs_i = 0; _hs_i < _hs_insize; _hs_i++ ) { \ - _hs_psize++; \ - _hs_q = (UT_hash_handle*)((_hs_q->next) ? \ - ((void*)((char*)(_hs_q->next) + \ - (head)->hh.tbl->hho)) : NULL); \ - if (! (_hs_q) ) break; \ - } \ - _hs_qsize = _hs_insize; \ - while ((_hs_psize > 0) || ((_hs_qsize > 0) && _hs_q )) { \ - if (_hs_psize == 0) { \ - _hs_e = _hs_q; \ - _hs_q = (UT_hash_handle*)((_hs_q->next) ? \ - ((void*)((char*)(_hs_q->next) + \ - (head)->hh.tbl->hho)) : NULL); \ - _hs_qsize--; \ - } else if ( (_hs_qsize == 0) || !(_hs_q) ) { \ - _hs_e = _hs_p; \ - _hs_p = (UT_hash_handle*)((_hs_p->next) ? \ - ((void*)((char*)(_hs_p->next) + \ - (head)->hh.tbl->hho)) : NULL); \ - _hs_psize--; \ - } else if (( \ - cmpfcn(TYPEOF(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \ - TYPEOF(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \ - ) <= 0) { \ - _hs_e = _hs_p; \ - _hs_p = (UT_hash_handle*)((_hs_p->next) ? \ - ((void*)((char*)(_hs_p->next) + \ - (head)->hh.tbl->hho)) : NULL); \ - _hs_psize--; \ - } else { \ - _hs_e = _hs_q; \ - _hs_q = (UT_hash_handle*)((_hs_q->next) ? \ - ((void*)((char*)(_hs_q->next) + \ - (head)->hh.tbl->hho)) : NULL); \ - _hs_qsize--; \ - } \ - if ( _hs_tail ) { \ - _hs_tail->next = ((_hs_e) ? \ - ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL); \ - } else { \ - _hs_list = _hs_e; \ - } \ - _hs_e->prev = ((_hs_tail) ? \ - ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL); \ - _hs_tail = _hs_e; \ - } \ - _hs_p = _hs_q; \ - } \ - _hs_tail->next = NULL; \ - if ( _hs_nmerges <= 1 ) { \ - _hs_looping=0; \ - (head)->hh.tbl->tail = _hs_tail; \ - (head) = TYPEOF(head)ELMT_FROM_HH((head)->hh.tbl, _hs_list); \ - } \ - _hs_insize *= 2; \ - } \ - HASH_FSCK(hh,head); \ - } \ -} while (0) - -/* This function selects items from one hash into another hash. - * The end result is that the selected items have dual presence - * in both hashes. There is no copy of the items made; rather - * they are added into the new hash through a secondary hash - * hash handle that must be present in the structure. */ -#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \ -do { \ - unsigned _src_bkt, _dst_bkt; \ - void *_last_elt=NULL, *_elt; \ - UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \ - ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \ - if (src) { \ - for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \ - for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \ - _src_hh; \ - _src_hh = _src_hh->hh_next) { \ - _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \ - if (cond(_elt)) { \ - _dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \ - _dst_hh->key = _src_hh->key; \ - _dst_hh->keylen = _src_hh->keylen; \ - _dst_hh->hashv = _src_hh->hashv; \ - _dst_hh->prev = _last_elt; \ - _dst_hh->next = NULL; \ - if (_last_elt_hh) { _last_elt_hh->next = _elt; } \ - if (!dst) { \ - dst = TYPEOF(dst)_elt; \ - HASH_MAKE_TABLE(hh_dst,dst); \ - } else { \ - _dst_hh->tbl = (dst)->hh_dst.tbl; \ - } \ - HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \ - HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh); \ - (dst)->hh_dst.tbl->num_items++; \ - _last_elt = _elt; \ - _last_elt_hh = _dst_hh; \ - } \ - } \ - } \ - } \ - HASH_FSCK(hh_dst,dst); \ -} while (0) - -#define HASH_CLEAR(hh,head) \ -do { \ - if (head) { \ - uthash_free((head)->hh.tbl->buckets ); \ - uthash_free((head)->hh.tbl); \ - (head)=NULL; \ - } \ -} while(0) - -/* obtain a count of items in the hash */ -#define HASH_COUNT(head) HASH_CNT(hh,head) -#define HASH_CNT(hh,head) (head?(head->hh.tbl->num_items):0) - -typedef struct UT_hash_bucket { - struct UT_hash_handle *hh_head; - unsigned count; - - /* expand_mult is normally set to 0. In this situation, the max chain length - * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If - * the bucket's chain exceeds this length, bucket expansion is triggered). - * However, setting expand_mult to a non-zero value delays bucket expansion - * (that would be triggered by additions to this particular bucket) - * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH. - * (The multiplier is simply expand_mult+1). The whole idea of this - * multiplier is to reduce bucket expansions, since they are expensive, in - * situations where we know that a particular bucket tends to be overused. - * It is better to let its chain length grow to a longer yet-still-bounded - * value, than to do an O(n) bucket expansion too often. - */ - unsigned expand_mult; - -} UT_hash_bucket; - -/* random signature used only to find hash tables in external analysis */ -#define HASH_SIGNATURE 0xa0111fe1 -#define HASH_BLOOM_SIGNATURE 0xb12220f2 - -typedef struct UT_hash_table { - UT_hash_bucket *buckets; - unsigned num_buckets, log2_num_buckets; - unsigned num_items; - struct UT_hash_handle *tail; /* tail hh in app order, for fast append */ - ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */ - - /* in an ideal situation (all buckets used equally), no bucket would have - * more than ceil(#items/#buckets) items. that's the ideal chain length. */ - unsigned ideal_chain_maxlen; - - /* nonideal_items is the number of items in the hash whose chain position - * exceeds the ideal chain maxlen. these items pay the penalty for an uneven - * hash distribution; reaching them in a chain traversal takes >ideal steps */ - unsigned nonideal_items; - - /* ineffective expands occur when a bucket doubling was performed, but - * afterward, more than half the items in the hash had nonideal chain - * positions. If this happens on two consecutive expansions we inhibit any - * further expansion, as it's not helping; this happens when the hash - * function isn't a good fit for the key domain. When expansion is inhibited - * the hash will still work, albeit no longer in constant time. */ - unsigned ineff_expands, noexpand; - - uint32_t signature; /* used only to find hash tables in external analysis */ -#if defined(HASH_BLOOM) - uint32_t bloom_sig; /* used only to test bloom exists in external analysis */ - uint8_t *bloom_bv; - char bloom_nbits; -#endif - -} UT_hash_table; - -typedef struct UT_hash_handle { - struct UT_hash_table *tbl; - void *prev; /* prev element in app order */ - void *next; /* next element in app order */ - struct UT_hash_handle *hh_prev; /* previous hh in bucket order */ - struct UT_hash_handle *hh_next; /* next hh in bucket order */ - void *key; /* ptr to enclosing struct's key */ - unsigned keylen; /* enclosing struct's key len */ - unsigned hashv; /* result of hash-fcn(key) */ -} UT_hash_handle; - -#endif /* UTHASH_H */ diff --git a/base/zlib_util.h b/base/zlib_util.h deleted file mode 100644 index b0cee028..00000000 --- a/base/zlib_util.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once -#ifndef ZLIB_UTIL_H -#define ZLIB_UTIL_H - -#include - -#if defined(_MSC_VER) - #include "ms_stdint.h" -#else - #include -#endif - -/* Attempts to decompress given deflated NUL-terminated buffer. - * - * If successful and |len| is not NULL, |len| will be set to the number of - * bytes in the returned buffer. - * Returns new string to be free()'d by caller, or NULL on error. */ -uint8_t *zlib_decompress(const uint8_t *buf, size_t *len); - -/* Attempt to compress given buffer. - * - * The compression level is passed directly to zlib: it must between 0 and 9, - * where 1 gives best speed, 9 gives best compression, and 0 gives no - * compression at all. - * - * If successful and |len| is not NULL, |len| will be set to the number of - * bytes in the returned buffer. - * Returns new string to be free()'d by caller, or NULL on error. */ -uint8_t *zlib_compress(const uint8_t *buf, const size_t buflen, int level, - size_t *len); - -#endif /* ZLIB_UTIL_H */ diff --git a/base/zlib_util_c.h b/base/zlib_util_c.h deleted file mode 100644 index 101cc9c5..00000000 --- a/base/zlib_util_c.h +++ /dev/null @@ -1,98 +0,0 @@ -#include "zlib_util.h" -#include -#include /* fprintf() */ -#include /* malloc() */ -#include - -#define ZLIB_CHUNK (16 * 1024) - -uint8_t *zlib_decompress(const uint8_t *buf, size_t *len){ - size_t output_size = ZLIB_CHUNK; - uint8_t *output = malloc(output_size); - int err; - z_stream zst; - - /* Sanity check */ - if (output == NULL) return NULL; - assert(buf != NULL); - - /* Set inflate state */ - zst.zalloc = Z_NULL; - zst.zfree = Z_NULL; - zst.opaque = Z_NULL; - zst.next_out = (Byte *)output; - zst.next_in = (Byte *)buf; - zst.avail_out = ZLIB_CHUNK; - - if (inflateInit(&zst) != Z_OK) goto error; - - /* Decompress input buffer */ - do { - if ((err = inflate(&zst, Z_NO_FLUSH)) == Z_OK) { /* Need more memory */ - zst.avail_out = (uInt)output_size; - - /* Double size each time to avoid calls to realloc() */ - output_size <<= 1; - output = realloc(output, output_size + 1); - if (output == NULL) return NULL; - - zst.next_out = (Byte *)(output + zst.avail_out); - } else if (err != Z_STREAM_END) { /* Error decompressing */ - if (zst.msg != NULL) { - fprintf(stderr, "Could not decompress data: %s\n", zst.msg); - } - inflateEnd(&zst); - goto error; - } - } while (err != Z_STREAM_END); - - if (len != NULL) *len = zst.total_out; - if (inflateEnd(&zst) != Z_OK) goto error; - return output; /* To be free()'d by caller */ - -error: - if (output != NULL) free(output); - return NULL; -} - -uint8_t *zlib_compress(const uint8_t *buf, const size_t buflen, int level, - size_t *len) -{ - z_stream zst; - uint8_t *output = NULL; - - /* Sanity check */ - assert(buf != NULL); - assert(len != NULL); - assert(level <= 9 && level >= 0); - - zst.avail_out = (uInt)((buflen + (buflen / 10)) + 12); - output = malloc(zst.avail_out); - if (output == NULL) return NULL; - - /* Set deflate state */ - zst.zalloc = Z_NULL; - zst.zfree = Z_NULL; - zst.next_out = (Byte *)output; - zst.next_in = (Byte *)buf; - zst.avail_in = (uInt)buflen; - - if (deflateInit(&zst, level) != Z_OK) goto error; - - /* Compress input buffer */ - if (deflate(&zst, Z_FINISH) != Z_STREAM_END) { - if (zst.msg != NULL) { - fprintf(stderr, "Could not compress data: %s\n", zst.msg); - } - deflateEnd(&zst); - goto error; - } - - if (len != NULL) *len = zst.total_out; - if (deflateEnd(&zst) != Z_OK) goto error; - return output; /* To be free()'d by caller */ - -error: - if (output != NULL) free(output); - return NULL; -} diff --git a/bitmap.go b/bitmap.go deleted file mode 100644 index 75849ad3..00000000 --- a/bitmap.go +++ /dev/null @@ -1,550 +0,0 @@ -// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// https://github.com/go-vgo/robotgo/blob/master/LICENSE -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -package robotgo - -/* -#cgo darwin,amd64 LDFLAGS:-L${SRCDIR}/cdeps/mac/amd -lpng -lz -#cgo darwin,arm64 LDFLAGS:-L${SRCDIR}/cdeps/mac/m1 -lpng -lz -// -#cgo linux LDFLAGS: -L/usr/src -lpng -lz -// -#cgo windows,amd64 LDFLAGS: -L${SRCDIR}/cdeps/win/amd/win64 -lpng -lz -#cgo windows,386 LDFLAGS: -L${SRCDIR}/cdeps/win/amd/win32 -lpng -lz -#cgo windows,arm64 LDFLAGS:-L${SRCDIR}/cdeps/win/arm -lpng -lz -// -//#include "screen/goScreen.h" -#include "bitmap/goBitmap.h" -*/ -import "C" - -import ( - "unsafe" - - "github.com/vcaesar/tt" -) - -/* -.______ __ .___________..___ ___. ___ .______ -| _ \ | | | || \/ | / \ | _ \ -| |_) | | | `---| |----`| \ / | / ^ \ | |_) | -| _ < | | | | | |\/| | / /_\ \ | ___/ -| |_) | | | | | | | | | / _____ \ | | -|______/ |__| |__| |__| |__| /__/ \__\ | _| -*/ - -// SaveCapture capture screen and save -func SaveCapture(spath string, args ...int) string { - bit := CaptureScreen(args...) - - err := SaveBitmap(bit, spath) - FreeBitmap(bit) - return err -} - -// FreeBitmapArr free and dealloc the C bitmap array -func FreeBitmapArr(bit ...C.MMBitmapRef) { - for i := 0; i < len(bit); i++ { - FreeBitmap(bit[i]) - } -} - -// ToCBitmap trans Bitmap to C.MMBitmapRef -func ToCBitmap(bit Bitmap) C.MMBitmapRef { - cbitmap := C.createMMBitmap( - (*C.uint8_t)(bit.ImgBuf), - C.size_t(bit.Width), - C.size_t(bit.Height), - C.size_t(bit.Bytewidth), - C.uint8_t(bit.BitsPixel), - C.uint8_t(bit.BytesPerPixel), - ) - - return cbitmap -} - -// ToMMBitmapRef trans CBitmap to C.MMBitmapRef -func ToMMBitmapRef(bit CBitmap) C.MMBitmapRef { - return C.MMBitmapRef(bit) -} - -// ToBitmapBytes saves Bitmap to bitmap format in bytes -func ToBitmapBytes(bit C.MMBitmapRef) []byte { - var len C.size_t - ptr := C.saveMMBitmapAsBytes(bit, &len) - if int(len) < 0 { - return nil - } - - bs := C.GoBytes(unsafe.Pointer(ptr), C.int(len)) - C.free(unsafe.Pointer(ptr)) - return bs -} - -// TostringBitmap tostring bitmap to string -func TostringBitmap(bit C.MMBitmapRef) string { - strBit := C.tostring_bitmap(bit) - return C.GoString(strBit) -} - -// TocharBitmap tostring bitmap to C.char -func TocharBitmap(bit C.MMBitmapRef) *C.char { - strBit := C.tostring_bitmap(bit) - return strBit -} - -func internalFindBitmap(bit, sbit C.MMBitmapRef, tolerance float64) (int, int) { - pos := C.find_bitmap(bit, sbit, C.float(tolerance)) - // fmt.Println("pos----", pos) - return int(pos.x), int(pos.y) -} - -// FindCBitmap find bitmap's pos by CBitmap -func FindCBitmap(bmp CBitmap, args ...interface{}) (int, int) { - return FindBitmap(ToMMBitmapRef(bmp), args...) -} - -// FindBitmap find the bitmap's pos -// -// robotgo.FindBitmap(bitmap, source_bitamp C.MMBitmapRef, tolerance float64) -// -// |tolerance| should be in the range 0.0f - 1.0f, denoting how closely the -// colors in the bitmaps need to match, with 0 being exact and 1 being any. -// -// This method only automatically free the internal bitmap, -// use `defer robotgo.FreeBitmap(bit)` to free the bitmap -func FindBitmap(bit C.MMBitmapRef, args ...interface{}) (int, int) { - var ( - sbit C.MMBitmapRef - tolerance = 0.01 - ) - - if len(args) > 0 && args[0] != nil { - sbit = args[0].(C.MMBitmapRef) - } else { - sbit = CaptureScreen() - } - - if len(args) > 1 { - tolerance = args[1].(float64) - } - - fx, fy := internalFindBitmap(bit, sbit, tolerance) - // FreeBitmap(bit) - if len(args) <= 0 || (len(args) > 0 && args[0] == nil) { - FreeBitmap(sbit) - } - - return fx, fy -} - -// FindPic finding the image by path -// -// robotgo.FindPic(path string, source_bitamp C.MMBitmapRef, tolerance float64) -// -// This method only automatically free the internal bitmap, -// use `defer robotgo.FreeBitmap(bit)` to free the bitmap -func FindPic(path string, args ...interface{}) (int, int) { - var ( - sbit C.MMBitmapRef - tolerance = 0.01 - ) - - openbit := OpenBitmap(path) - - if len(args) > 0 && args[0] != nil { - sbit = args[0].(C.MMBitmapRef) - } else { - sbit = CaptureScreen() - } - - if len(args) > 1 { - tolerance = args[1].(float64) - } - - fx, fy := internalFindBitmap(openbit, sbit, tolerance) - FreeBitmap(openbit) - if len(args) <= 0 || (len(args) > 0 && args[0] == nil) { - FreeBitmap(sbit) - } - - return fx, fy -} - -// FreeMMPointArr free MMPoint array -func FreeMMPointArr(pointArray C.MMPointArrayRef) { - C.destroyMMPointArray(pointArray) -} - -// Deprecated: use the FindAllBitmap(), -// -// FindEveryBitmap find the every bitmap, same with the FindAllBitmap() -func FindEveryBitmap(bit C.MMBitmapRef, args ...interface{}) []Point { - return FindAllBitmap(bit, args...) -} - -// FindAllBitmap find the all bitmap -func FindAllBitmap(bit C.MMBitmapRef, args ...interface{}) (posArr []Point) { - var ( - sbit C.MMBitmapRef - tolerance C.float = 0.01 - lpos C.MMPoint - ) - - if len(args) > 0 && args[0] != nil { - sbit = args[0].(C.MMBitmapRef) - } else { - sbit = CaptureScreen() - } - - if len(args) > 1 { - tolerance = C.float(args[1].(float64)) - } - - if len(args) > 2 { - lpos.x = C.size_t(args[2].(int)) - lpos.y = 0 - } else { - lpos.x = 0 - lpos.y = 0 - } - - if len(args) > 3 { - lpos.x = C.size_t(args[2].(int)) - lpos.y = C.size_t(args[3].(int)) - } - - pos := C.find_every_bitmap(bit, sbit, tolerance, &lpos) - // FreeBitmap(bit) - if len(args) <= 0 || (len(args) > 0 && args[0] == nil) { - FreeBitmap(sbit) - } - if pos == nil { - return - } - defer FreeMMPointArr(pos) - - cSize := pos.count - cArray := pos.array - gSlice := (*[(1 << 28) - 1]C.MMPoint)(unsafe.Pointer(cArray))[:cSize:cSize] - for i := 0; i < len(gSlice); i++ { - posArr = append(posArr, Point{ - X: int(gSlice[i].x), - Y: int(gSlice[i].y), - }) - } - - // fmt.Println("pos----", pos) - return -} - -// CountBitmap count of the bitmap -func CountBitmap(bitmap, sbit C.MMBitmapRef, args ...float32) int { - var tolerance C.float = 0.01 - if len(args) > 0 { - tolerance = C.float(args[0]) - } - - count := C.count_of_bitmap(bitmap, sbit, tolerance) - return int(count) -} - -// BitmapClick find the bitmap and click -func BitmapClick(bitmap C.MMBitmapRef, args ...interface{}) { - x, y := FindBitmap(bitmap) - MovesClick(x, y, args...) -} - -// PointInBounds bitmap point in bounds -func PointInBounds(bitmap C.MMBitmapRef, x, y int) bool { - var point C.MMPoint - point.x = C.size_t(x) - point.y = C.size_t(y) - cbool := C.point_in_bounds(bitmap, point) - - return bool(cbool) -} - -// OpenBitmap open the bitmap return C.MMBitmapRef -// -// robotgo.OpenBitmap(path string, type int) -func OpenBitmap(gpath string, args ...int) C.MMBitmapRef { - path := C.CString(gpath) - var mtype C.uint16_t = 1 - - if len(args) > 0 { - mtype = C.uint16_t(args[0]) - } - - bit := C.bitmap_open(path, mtype) - C.free(unsafe.Pointer(path)) - - return bit -} - -// Deprecated: use the BitmapFromStr(), -// -// BitmapStr bitmap from string -func BitmapStr(str string) C.MMBitmapRef { - return BitmapFromStr(str) -} - -// BitmapFromStr read bitmap from the string -func BitmapFromStr(str string) C.MMBitmapRef { - cs := C.CString(str) - bit := C.bitmap_from_string(cs) - C.free(unsafe.Pointer(cs)) - - return bit -} - -// SaveBitmap save the bitmap to image -// -// robotgo.SaveBimap(bitmap C.MMBitmapRef, path string, type int) -func SaveBitmap(bitmap C.MMBitmapRef, gpath string, args ...int) string { - var mtype C.uint16_t = 1 - if len(args) > 0 { - mtype = C.uint16_t(args[0]) - } - - path := C.CString(gpath) - saveBit := C.bitmap_save(bitmap, path, mtype) - C.free(unsafe.Pointer(path)) - - return C.GoString(saveBit) -} - -// GetPortion get bitmap portion -func GetPortion(bit C.MMBitmapRef, x, y, w, h int) C.MMBitmapRef { - var rect C.MMRect - rect.origin.x = C.size_t(x) - rect.origin.y = C.size_t(y) - rect.size.width = C.size_t(w) - rect.size.height = C.size_t(h) - - pos := C.get_portion(bit, rect) - return pos -} - -// Convert convert the bitmap -// -// robotgo.Convert(opath, spath string, type int) -func Convert(opath, spath string, args ...int) string { - var mtype = 1 - if len(args) > 0 { - mtype = args[0] - } - - // C.CString() - bitmap := OpenBitmap(opath) - // fmt.Println("a----", bit_map) - return SaveBitmap(bitmap, spath, mtype) -} - -// ReadBitmap returns false and sets error if |bitmap| is NULL -func ReadBitmap(bitmap C.MMBitmapRef) bool { - abool := C.bitmap_ready(bitmap) - gbool := bool(abool) - return gbool -} - -// CopyBitPB copy bitmap to pasteboard -func CopyBitPB(bitmap C.MMBitmapRef) bool { - abool := C.bitmap_copy_to_pboard(bitmap) - gbool := bool(abool) - - return gbool -} - -// Deprecated: CopyBitpb copy bitmap to pasteboard, Wno-deprecated -// -// This function will be removed in version v1.0.0 -func CopyBitpb(bitmap C.MMBitmapRef) bool { - tt.Drop("CopyBitpb", "CopyBitPB") - return CopyBitPB(bitmap) -} - -// DeepCopyBit deep copy bitmap -func DeepCopyBit(bitmap C.MMBitmapRef) C.MMBitmapRef { - bit := C.bitmap_deepcopy(bitmap) - return bit -} - -// GetColor get the bitmap color -func GetColor(bitmap C.MMBitmapRef, x, y int) C.MMRGBHex { - color := C.bitmap_get_color(bitmap, C.size_t(x), C.size_t(y)) - - return color -} - -// GetColors get bitmap color retrun string -func GetColors(bitmap C.MMBitmapRef, x, y int) string { - clo := GetColor(bitmap, x, y) - - return PadHex(clo) -} - -// FindColor find bitmap color -// -// robotgo.FindColor(color CHex, bitmap C.MMBitmapRef, tolerance float) -func FindColor(color CHex, args ...interface{}) (int, int) { - var ( - tolerance C.float = 0.01 - bitmap C.MMBitmapRef - ) - - if len(args) > 0 && args[0] != nil { - bitmap = args[0].(C.MMBitmapRef) - } else { - bitmap = CaptureScreen() - } - - if len(args) > 1 { - tolerance = C.float(args[1].(float64)) - } - - pos := C.bitmap_find_color(bitmap, C.MMRGBHex(color), tolerance) - if len(args) <= 0 || (len(args) > 0 && args[0] == nil) { - FreeBitmap(bitmap) - } - - x := int(pos.x) - y := int(pos.y) - - return x, y -} - -// FindColorCS findcolor by CaptureScreen -func FindColorCS(color CHex, x, y, w, h int, args ...float64) (int, int) { - var tolerance = 0.01 - - if len(args) > 0 { - tolerance = args[0] - } - - bitmap := CaptureScreen(x, y, w, h) - rx, ry := FindColor(color, bitmap, tolerance) - FreeBitmap(bitmap) - - return rx, ry -} - -// Deprecated: use the FindAllColor(), -// -// FindEveryColor find the every color, same with the FindAllColor() -func FindEveryColor(color CHex, args ...interface{}) []Point { - return FindAllColor(color, args...) -} - -// FindAllColor find the all color -func FindAllColor(color CHex, args ...interface{}) (posArr []Point) { - var ( - bitmap C.MMBitmapRef - tolerance C.float = 0.01 - lpos C.MMPoint - ) - - if len(args) > 0 && args[0] != nil { - bitmap = args[0].(C.MMBitmapRef) - } else { - bitmap = CaptureScreen() - } - - if len(args) > 1 { - tolerance = C.float(args[1].(float64)) - } - - if len(args) > 2 { - lpos.x = C.size_t(args[2].(int)) - lpos.y = 0 - } else { - lpos.x = 0 - lpos.y = 0 - } - - if len(args) > 3 { - lpos.x = C.size_t(args[2].(int)) - lpos.y = C.size_t(args[3].(int)) - } - - pos := C.bitmap_find_every_color(bitmap, C.MMRGBHex(color), tolerance, &lpos) - if len(args) <= 0 || (len(args) > 0 && args[0] == nil) { - FreeBitmap(bitmap) - } - - if pos == nil { - return - } - defer FreeMMPointArr(pos) - - cSize := pos.count - cArray := pos.array - gSlice := (*[(1 << 28) - 1]C.MMPoint)(unsafe.Pointer(cArray))[:cSize:cSize] - for i := 0; i < len(gSlice); i++ { - posArr = append(posArr, Point{ - X: int(gSlice[i].x), - Y: int(gSlice[i].y), - }) - } - - return -} - -// CountColor count bitmap color -func CountColor(color CHex, args ...interface{}) int { - var ( - tolerance C.float = 0.01 - bitmap C.MMBitmapRef - ) - - if len(args) > 0 && args[0] != nil { - bitmap = args[0].(C.MMBitmapRef) - } else { - bitmap = CaptureScreen() - } - - if len(args) > 1 { - tolerance = C.float(args[1].(float64)) - } - - count := C.bitmap_count_of_color(bitmap, C.MMRGBHex(color), tolerance) - if len(args) <= 0 || (len(args) > 0 && args[0] == nil) { - FreeBitmap(bitmap) - } - - return int(count) -} - -// CountColorCS count bitmap color by CaptureScreen -func CountColorCS(color CHex, x, y, w, h int, args ...float64) int { - var tolerance = 0.01 - - if len(args) > 0 { - tolerance = args[0] - } - - bitmap := CaptureScreen(x, y, w, h) - rx := CountColor(color, bitmap, tolerance) - FreeBitmap(bitmap) - - return rx -} - -// GetImgSize get the image size -func GetImgSize(imgPath string) (int, int) { - bitmap := OpenBitmap(imgPath) - gbit := ToBitmap(bitmap) - - w := gbit.Width / 2 - h := gbit.Height / 2 - FreeBitmap(bitmap) - - return w, h -} diff --git a/cdeps/README.md b/cdeps/README.md deleted file mode 100644 index caebabbb..00000000 --- a/cdeps/README.md +++ /dev/null @@ -1 +0,0 @@ -C language dependent package, better to compilation. ( zlib and libpng ) \ No newline at end of file diff --git a/cdeps/mac/amd/libpng.a b/cdeps/mac/amd/libpng.a deleted file mode 100644 index e2dc965936d22e2ce37cdb34282ce7ee5fb1b6c3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 255664 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 Ie~WznKjq3KbN~PV diff --git a/cdeps/mac/m1/libpng.a b/cdeps/mac/m1/libpng.a deleted file mode 100644 index ce2fd03eb76a47c4b39a4a3f512b84c3df49b81a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 258360 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

$%_QGS`Wd8QKd&W7> z>5NyS`=gd8GrH$m)<>Uuw(fSdSUp*bU2VHK`?`y>ud-h+BOG4z`-$w2W8Yo}W5+t? zslD#87rJKrD8U|2|>b#Ru)5B z)uY4pYOkKG8M$dA5?Q`)Ms1c@0XYQ zl(^2j$VuD5=y`~Gk2K4k;B+--Lk{mC&vzugDjVl-JFN6M>}hGsVcopydKdC!{hU3f zp&9ILq`tRP-!jh@z9RcpSxc&*{F0|LA0W+C=U#Y>=EIjvJ<(tIlHF|y-G$U~LiHPr z(G-7-!Mo7$zIm9tt$di+n=R~dG2Ry*Ll4cDF`IgB5<$i?JD95|yPAB{Z)${=bcbRO z>{aXn@a?2@?SB=v4dXoN6zp}}&EJRgzn47IazAvXBwb4Qc}7j5yRGIY#RZ4iYqRc? z!nPX1Jj35~cS_Q4JyUb1x`!qGD&a)Ny3br~y{@6v9{QViT`ARX@JE+O1=SBvDb_D@wx=`03-vEQ~5`wwN*_53Z{Gpcqc z6m0%Mg6bE2>&B1ddu#3j`fBWo?eRT+V2||MbD8IqY^mR!W8{ zG2djoQ}M?_`as=>RNO56p}r3x;}X^xg?9EmNFO9+TZK)Sxm&DtLn+5F_HF-S%hMTi zud~(-XTSOf)1S`ROc`@VJe{$R^1q3k&i6b#yPC3#yV&Hcp1vUQCDc_sWo?`z>509B z3hcMey%pJzUJ~hwd>3^8)f`!WjOL;Ik1oZd!&CXq%-Jb}Z;Q3#9OIar4<7po^TdYG zNEdxpjN33*PhBqIc_tX={g}NCrSgn8&xfp!KF^#pdY`bgH_3ks&+ZnUU7_3gW~29y zXQ*d8x(!P?Cv#?DHRplv;5=~S<1aH8ulOe=6UHEQlxOY)-G*|uG-O1}C5O2+wmZ|r z?rG9s#+JyUfqAx?iz1Ul#Fw~LTN*P~e)v~&HWSwAw`6@m`a`GwuC}i{zPP zV~lqeT>4{KE7$Le`1{kP?tR!QNnqZzf>-sW zzY_lmjJu={m$+TXM&`~7_@)c5Nja&O%=tc&`JM_x+KHq+U&dX8PaL}7?F8O|7dVqN znRs^)uW`^FNt20(T@MxSDg4iQ65eL+_jWE}77}JM{7B!nV9>&(T%E@b;l<_TL)r@n zE4*MoBxy2pW#&L1CDG?+Ti7&$|AqWD@-A3CI)H7J#OiOm5*MDh@0t61d5%B2@7wot zrt`*MK+kojR3G|rW5!KCY07xlHN1KO_hRo1+t5jqvF&u;GxVV3{UUw8Q%1&fI})Y8 zg7=){l7=qEd`S`q-i7ZZ;z^qk+s)Fp#XkX_Wu77KZumU!Nql=@Xk~sfHl;)^KVn|+ zZCBFg@;F8DIJCMN9+Szh8Xl8aTS(#^$r=HCCS9m7e2RU84Qtk8egZ2BRcq=hS70zKOZO2d$u0)9#)^x567s&!zic2 z1jKr=+mNlTP~?a;4>90TvkE17j^zexb=CUyVhUq^N%10U`37w>1aC2sp}16bFO+&M z;mZH9^Y1NM&N{tu{hIKC3F%tf&h` z`_xvh+fW5_*ae{&8_)1Bj`^aeWe*H%SVRX&8l4JUw7We8>T z8&c(Ul~X7Xjb%NySE?SYLg-H5nu^+r)s

=BTjzmp_jiXAHo&PqUgJeweQe2qT_NC75rO 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

Vi}b_TA$Q8>uOyOr*A;DJK;@`r+#()m!`P&0nI~ zhRygQ=Rc5#l(H_{MTe{V|2tHSWK?kc=?Fxftu+pP5;U*A?%0NtzGJFe&+bU$#(56> z#r>PUI9agjd2LQQ(U&^4@9g)vwJ&p*+}i&Ih*$eTrT|j=%eAs{PGIR?pYJG{GhdSM zTI~m<+8=z)t@iK!-c8j~|yVvc0SjsCMGKC^_D%jO=9s+_I9mqW?l@g{SGQ2S{T z2}>L5j^4UtlZ?7%|JqsQ|DDuac`+Q-(|e(|B0@^jC%j3SDC}OIM6-2DvAS-ZVkCxB z?WrjRrfW^jEW|ym?p9P(GF&mSa-)f&t=_B1#02VR$LEAQhHK7#cD)bkJ2-ox-O*u_ zCt>wS7*Q4wUQ^SIbblF++p$DMrXweQWqh_%rV-BkCFXO_3Ah%A>>O!HnUN)aPrmcN zIp^uv7BN!hjM%o1k#ilnQZ^XG?8i$V^MoU1PieK}d;#!}-*(^*waIkV8@wl@r_pS7 zjDA%++9^5P$`9zaG93#OZ<&z0pGerETk^RWqX!~3{-3dm?Tu3@>a37>bT(W+Yf!KB zrj_=4gVc`s%rH*Ipp}eImBG+cQwPaeq&b`|q_j7P@S@F-bb7uI5r8lisEghO6vkcT zIfvMD*8i2h{Pp#>vSnEw>44ZI3C8&;aUlc5?KJjDo$-wmi7bxUVbN^LRQ zCbHLBV%otriQ!G=yVTpSg?`D>cm;5 zK6<+lkB%O^G@os+Wq-|fc%6Jg zvOwNWq!xPKB%CZkMr$qUaXwNCwS6QNYrQ&EKC#eCN7{qgPL)hJ@|e<+(wB4xx>zC| zW$Jkp!TO}3X2+=ZulZu6{p~4UFPvhDy|F42`&lIU@!%z2!0bST#$K`XD2zo?$IZLw zzxBGtLPBf4&3RTwJ|e1xTMzs3WzJlSIGI?i%R@?y^rYJ8@?#Qg%wn>t{w3PdEuq&XtztXKQ&w{WlH z=Szv1+hbVGh@~G3^OF9x9QkC!TT~&yhZo|R>w_3m6HB&jC(Eb$bSfs z?Ir7>br;BK-4saV<+oeb%Q}zNZHz?x*M?M_f$o>z?USa`HsRAgS zrU(*Q+l>(T4JL-;n*4ZB=zANv9TwUCeyo-+_aiQk(vbzXBb_Z=XiSgzcB-@IOqpMB z&*792Mf>^x$YI+f9YT(ICN^@#j-%(14ciJ>5xw4eP}r$9 zo<|f#I*#pm#?Hqn9fA@*brimmVB^18+my*7w=*fA4NkGUsmg$4*cgx^57s2 zp(?9I;qtGgYLf@aN1dTUp%t=i8&Bc?Ad)Ac@?&;VPmPBC|Y(y zoDC7jybKqKO1d!EM03o+ky7#;HgKwgn`0Gk zF8N(qCtGGC@*^E1kVLsNx}*91?0mdA?NiEj&c70jO#J9!o@iuu5xjp8N07LPcjYm7 z-o>pfUCsmbf7o)Y?vo%2u$zXeHvzQ&3UUUeNQEM5Tk(+j? z`JK3wu?5*m|lwfQ>a`LM!&cPTq zI=D;Z`vBGc-mRl+QXf`{$-GJ$*LJ;XbWlYplH3}sW=k)~b=tpidpD2IVKSpEj?m3j z2mcYR2rvCL-x`mNrP+_1FjTUaI&aDO+*J{)>qaX)Aa`QaCc+GFhR^j5GZ_?TLQhCt zB3yS|l&R=$ekm@;RH`ao zNSsg=d^^U$7nrs+7_GQqX`0RDW3$hY(RnMyyiZl?A3bkUOe%ILLqJYZv03OV>K{b} zC@SR}8hMg}VoQ-y%KjMRM{?It5w7FlhZIy$HL>g~V~{e&{bd~f|3Lwd?_0n-wSe99 zUbcLHqI}!CeMQ^eol~+G$gHWv(HWWkNx715=SQBTXX%YRB@m~M>T`oCMBACuFZ`V2;%l*}2U;atOHB$g6Z9rs=pCb}sc0%PFgIw@54bV{m~ zyZ_b5lavnGqn33*B>?ripAm0p_BiCmaB4wbL{5(dA_UOk*uisQ`sBLiSg~R-d!s{ z61@ZeCimYsB=^;)=qgjK>YN#TmwCH~z_>kZ-d3Bpk^du&a??<;=M$m(j%QAM2&g7h z#RbmRHF)Z|%eTMG`ffN$FfzfT3pfYO0!xw5?dL(aJf>4obKY{F-i-~LJuE&F;4aLQ z?W?n$`}MKR6SKgif5B$Qd`M=~&5h~gR1)baHai^?H#3YdYkeHMEUiz-bYIqqDfJU- z|03^94PJ5Y@0x3~Tt|}wK1ArK0$4K4yz0H6o!y5viY*CoFVT2(>cxqGm~*^Ow=b^8 zSvCf?@Z^Ju^EM4>U>G}#A;MjDnEWR7>|jAsZI6W8J57-(aUgLX0VeqZxEo_m5O*nJ z;)!J*7N)R^{*1{Y#e1<&1UK`QZfB06~<@J zA)ys7ir38Gwd98mNNgt!mowi#=RM86WLaK}I3kjX2761on1k>CV4qqe;$!W`RI-5h znkN$cCwSMO>Ez!D6Uj^u!j{4R4$SypP_i*)0=IXjU?yOj9L~a+M5yhX5YZ0Jnp<*e zPxvd7yd#VtFe;4uU$8lQH?7WzEcrV3U)t3Z9o-oZ50`jA0n^5TAol5Ps~iGWkF<0uNNyt5}mTHTP1vl9d`?t z3|Hfskr{b|-G%Ud#4(dH(E^vnhOs?g_SSDEVkfLg%S4V`OC`u{&vmP$y(dB~Pc-lx zs>`a->>U(*iAcK9vlZ>$YM8aw)!&2MZ#Pg(;%iKZ}IE zx_#f%m5H;hk(4$$peJ#*$%l;O!NSmYZi9GSf_V9r(GVL>n4D1~O(b#|o|rkY4vTj& zm<{b%B|5-kwHqVJT?dkwgiOi;I}p0_KK_p}zOtO@l(|25b~hYEfr%I;D=dv&@Nfg& zP-umm52OM`>N!!s)uhveN~c|!FEa;QP5Y}f%UN$f(H;s5wf%&MI9JfNfTzsoWc4Gg zYTJP<8D54m`NzP?>=qEyA8Y2wq-0QyqDs#o#vk2?nGo*c6>i=(t?Z=U|9llpbYR#sQxlW|gOh0Tw>8=YgDnm7(avgV#CfON|WiAWH zQrN@{#l-X~<~uhgcZXuBwCs$;_P>PU82VbNjI69`Ti*U>N?So=9|j1&@0vx%)tJV>tUY@n_qo8%d}w0v^o_|DNRjadQEA8w!F> z+W&5}@aHP+CpG}6owjadq!<@s|eaLrgO8DdYEL#?X2L%R; z?F_$tix9@Bf@kE~f%sfO;ByblC-Toilc@GjtUkBa%^8nd2V-o5O3cwl1`&ze?!YMCATbocRzhNTOh-S z28Q46w~FDE#ZBXgA%P>tdN~aC&7bhDu@CS3ym0Hxk4au8_T?<;3jUJ;aH(&9_#t_L zArpa7P^J!tNd+)7QMMA@g1NGI?VI-LNMr+ zJlFEUc@MNaw_tYwb_cq6{``yBB!OPbbHj<0QE;An&|X^(y_e@7PNpY;-o-QTRLTNf z$ny(Da~K&^&)M#(b(-&GR3nwl*tZg(J3p+^Y;kO^8)@3Kv(kI$zOmv*~Rm>6GS^1eB=3z2zFGU8+d-gpJ=9+ zO8-lgaL{{sJ|ClwpeL&JAY+dTYer$wOW0V~)KoWD?Ny=mvTpW5f=6d3X8&tnY)E6Y zXkkNrU83%=Q4t$FxpWF9jYPj6DWP_-?)tjM9Q#m#OR?NEJ1qXt$XKU=oN)3^?2V1h z4Px19&W+*7v`N*~K%&#J2{T#&&&HN(*Qs`X^P(H->lR&~5K#+MEvv1on@i{>v3OL! zVBvy9c)-TUZiARs5lnQWTJe>la_Ypf<;Nm*lc;(cyxHN#~PO4qhT&ng;VYrRd z(KhLYM&=uv7uBLUlDsUSs#V2eSaggUPhpqC1Nsxqo&$Kkbg{9YB^lAW79lb*S65vc z&5d~=PFx?UiP%ibi=PuY{8dL&Cmx4r?l6s(9 z(t%R0ja^=2Q(Hb;XrsqbtXjgd2-1&lz1guH^dS%JHKs&n=l#TzTGTEHHmYB}muQxCrZg z#>gF7J?GYI-yj_D*`9MV@>%}Rx@gANt{%8rsej8{6$W2Z&JkdB?8{sq=rPv=UFN#I zkh(}l5wgSa&B*8fJK${*e`uU@ z$&{$gy}bAt=?3s;Mgw@o(jbPzUa>sTEf)D4(0PF<4i0M*8j!j3tEYMOEHD2mdm6yY zo(AcgJr8uV=N8n@nTFWcnk;AJ#h@lg~gL6dnw4vz$vIp-xNIXvr=f7 z6p4Ff;AP+x#GBJ~&>EfDnY2H3XlQO!1>A0PQ_#~%oC7z^Zk)Z4DQ#nuwqM#2Sb7;V*JeKW^{2Kg6xk@%Yi6qP1_S>$kQ!IO#S*F7U zGt(7K-AwgmIP(HI<#Efe4hv+`SU2~4Ix{mfZAPEF@tEUJGZ41Er8io-U@ns*>9}TV zh|ls*m#!uQb(q(H(!NZJUIugHpI^7&`uPbjfzR@v6Tb=Q^2N-)6V)|Uj>LFP!3TPc z-2+`gb@=vK{eGfq#=x^WbubZllFB;5si1J8Zdt-g@&N0N0sK`jYGP%_B#A-ZmHmNZ zwCNspyt--nVe+jGCVZ}Z`6NsHIC*#01T+vI=l47c2-pU~pi`7*YK2UuPQ za@=+5RXe-Bwwcwq@XHt&$nj%39OFP0xk+j+tmy+|`IvQj1G@oHyIPkhs~Q_I7vp26 zns(OB5H<~n!Ol35V;wJYQHjGFMgo^pESZ_%K>^tHge_H}dGO#x5&%Xj`{t4IC_t-m0@LVic{i}FJO<`t;L{6(H9 z*yKO?mGV1>-}C&~F5?%{fAXLF_VR1tM@|Yl_?^N};*hvH1D$L-1v=$7oS(!YaqZQ3 z_Oh1<#eedXxD@vNC%A->_yWCwUiY1=A-tJ)2`6z%dV;y{t{-{#MVUkXpW34x1e>N1 zV}4*J6q{yHO;FWJWuPurs>@;rpe8Cdm`X8Jp`~uO)C#Ce)ZcXWKxMx)Kd=C*MyVB+ z`Yx1-<%duv#3qY9XR*IRnONfNof_)DEOjz_s3w+kpuVbUL@o9;C{vDSpr)#;D8Dly zUWd9&v3H;@S86CiH%+PKP{!Y#P}3Frsl|R_u}7gy*f*hK>TfW+xduB4%3zm5nfR`R zGV#eJcavJPrB+#g|8D)so#87q<|~eLW4Rj2aBa55=2`5=7Tam5ccDzW4-F3luGIKG zgfh802xVN4WuMt#7h0+c%D7%>v9Cj2qOsIjY@x*(E%h_&`YR|C%X1d%vi|b917gyZ z+aQKI7s`Z~W-+mGZLr6nuF@QcO=}b4cb59S^|v3&)czssI*hhuYJVh@3HwDTQ=%&@ z_5(}(2b4)yYzE6Ne}3Q`C=<3E%D6@?CYG~}>$jjx%)hnRUo5p3%7p#=(Qb(2p$zu@ zW8B<7XsL~s+F_~pEj8p=H^i4LHO^8OK$%=khB7>uX0cjJ-2i2BFl`ovOspLcV0DwIj1*kY&g z&BI`4K~2~EeFN%RrIuLNTdnKALrqoJpIF!bhBAD4(qbE+OgZ*j?0h~SP1CSdP}eCH zJ1!9Tx>DCb8P_H#ldGGdOs;-vu{9Rk3}r$*XIT->*@Pt5MmQp7{nbgj+ z)FddA#wAcreOT9TTGuw~I*G4SCd4&RCcc|2)oNYuhBEQ3w%8hrJz}vZp-egcVX%}^#pm&IO%GHDDu#r1cJr7A5IgEC>8EcPB$t)}s@#STH4_{vUo zJ(r(v&yGO^5oGO_&7 zVx3S%BA$aX^7oQ;9do)HHgtyTx&+F^cPo@hHv?s2*=${(x2~^S*Sumk?2%9=>~Eo* zu-5f`OMPPfjVmD3gOpP^LsnEOxi0)eyP)Q) z>$BGN4NJXc{oOK}RgC)UfHLLCKwYBP$51Ax`DeL&ITFgLON%`QHCaQv4D}7A-hwh= z4_fNfF>crimWo1|JWqo%AsVb}vvpl*v3sCQ{`Nze5QENk^Y=4L9fC4>IkMFC_eD#U zLYZ=uLz(y{S?m%hldG$tOd3h++F@OPYOx0_w#j18S?mpqbz5pLlu7rxGB=I+P)7b< zhBEnk9m?e8UF+|Hv94>>Qq@q#Uz5ddw%B`6rjCN=xM|FWG8|e2WlH%iOZ@=K zL78$qc)pA6wAA1WT`ja1R~Z}H`GIqxOif2E^)rOjzNHGFE>di`#R@Go!n!i;bi$rssjzh| zvKYxa{^(epnCS!@Y@DSeA0}PIz;Ug#6pVCSDWu~nQf+cS)w)W#3^v13*IL(E7Mp9S z`PQ}GVhxr`Sl4A1yTwv1*0s%I9hSPox~{a?-Ilt?y54KC)t0*7x~{R+=@tveYZqb%({?u+%Q=`j*AIEw#tG?zPz8Ep@=Uerhq@VO{UA*h)*?ZC&rN z*u9ooZC&rT*cwYcXkFJ@>=8??x2{iGtkY7Pt?M?6J#VQl>-vhtc3A2S>$=NgZ&|9_ zy6&;qUQ7Mmx*o9Dr3T-XoYkwh! z3I@UfximP?j}AF7l|S{P9wd#H9OO#gqz!p~ZsBb;F?z^w%cJn7ENIYII zAH@&*4<7QK_&L#!{1Ze@uX=utg1Ng+_9Jq=T~4xke$E1s^Q<0nA&8u6^^h76Ios+X z*MZ0hR}YbkCUVZzL%t;lW4ecAK;+D;hx`acPQH4`TJgg?&_kXEkyEf9@;Zo|h4qjg z5V?p?wbEh+JCo()uQdTwC&x z!~(n%;v%KhU&KrBIfKfgU_ zSTJCF_uGOdfr0(_>_F2D@iRlB%lVCI@IHXi=W7G_rrb~y`XRA? z$kqLjZ}vm(?1$W+gQyku#=5%P)E~+5BW}_=nx9*)7y2Q8=!d-54>{NmIYuf|e{RgD z^+QVgA(!++uIz`@_Cs#(hkU0Wa&JH6=lzg%{Sf(fmRkxL8FG<7_Cr4ChiK!|U@kX~ z5<$*EPUwf6*AKb0AM*7a1nF(6bDMX-O{+e~k0ko-9OQevjnOt%bkj{Y=^=Jb^3R>g z)PQqLGx^#+v#EK`fOxYpYv0%V>?PL^=)GZfU1I*sGWo7Ovthw9WAlDy-_XX_!shzK zf<8Xo_A2syeO-baE~}e6vtcn`^~Z3czbU~fhK4a?HEnTk#$o0;WqsZ~cXjq&)jK;4 z61`@MI|uqw+gPiBeKBVS#Gg3LTd-(B(|mRGj`PnnXB)(io&>I&DQD}{lk+Zz3jObL zfZhKthrj*ra`@W+E{B%=?{Zex|1QT;{qJ(V)BmogDt-CWgN?p-JxS<$*YkkBcRju5 zdzXW2{`ln_mj7K2Lgl>687E(OIcnp7mm?$@MZ}Btnyv0{ViED|A!<>Nf?Mw7<4a+4Vi zd!y&mFP;*7phU)(8kyIyZqV`Uk@}kX%$W-oHq5N&)(&TCBkoXmIrj++(+wY&&Td@9 zp+C)?C-how9k``*w33;%3r$Z@>zuf$lZK(8OgwYy7ID^ZrWb`1F|2XUOG-3c@X;{l z3?LVFX8P0TR5Qn56jEP)H*)Q@FL|+zOJ1ZUna)B33S=7-=j><7@$Q++ZbY7tDkl%( zNm`gM99`1f1xvgrXm2KJPIs$cbu!tszHBS(Ut;%Cll5y`s3dNir@Yv!99D zY$k+P*>Xz-ZaNY{Z;8~(2xAXf=@Bg_tk!bi2qcR@V-}wsHovlQ=bcx2?m6Y-%fjJO zh0OnDrKRVddu}*fc5Z3eSjA@@F?YGl0l8_&{_(|1cBU&4LwVetT^=H$-Kiw9-El7S~)hnshVHA~D4Kq-NOtzBQopN8 zZHcDuFY4kA^-oo)132yAC7Sv${bbQDsPrR6vTG++9K%tJAa?4@+@fNDQuLXZqt3ii ze2AirucX@?4-c;fNnTQrA5A@RKV&rZfNV*ol56zkr)%Zqfk)*3CqzzC4?oHO+{@2Z zHl*4q;AiuZA9=U+MPK#a>NGi?*oa1`%7Wy@1>t$Ai8qOtsL^&!kOI^eDZj-3N4#W3 zH6rz)whyJ0M2zN!Sn9Rr;bOuS4Ot0!hat-$I}BM0*=ERM z$QDC}yMMz~eKmCp0H3%w4?#YRj#$6-z^i=va9j6Cx}g%JBvf(>JPehHdD2ixyr_Zy z?=EV=8O<}N^Y}0tD!f~{r`3Y}n-4>UcPIlt3>}SPCh>5GGMjgFGvWM5Q2-7=JXusA z1U^j7DMN^OED@8*d67`@vk@%m@+#@cMw$boqH&80%Qq1R#$MmkE<6KxUZ@zAU|5OY z?4q>>#p=dR$1C|DTfCEkd_GHUC6v((f)gb$PB)9w7Mz~dsA6bHM(i`L6{~H}@7`r)4|I)f=4LST5^-aYad&sb<1MgC6_iAIvsd$lX zuj234w&SaK$){GlWZYD|l*tH*6kM4r6;B(N8W9H#AbzC{x#A-5 zHUo>;xZ>gn1fE4|TxkInfdIWvQ6nvW!4P3eJ&nKqf*}$`8!g7sh=$l17I{+npl+!b z;fmHabtwIZ5f>b!Yq51L%<<~l5d*KTg;6-0T98T?9#Y#?z(j)1EQKB|++((7R^*MJa0fr+_Sf38S*O8iz2NwnSP7^3&>+wMk3Oc zI$`_~RZ<4joUc^=#KH(&KkbL~*S_Qy(H_<*s*Vj3L=!L48S#;9=zgwpLCP8*W$b z+c>ECoGp_|g6k;?dR_AqLzsnhOe)z|TQp&4$D}VWIR!0(A=M#BStb=a{Cz8~M#EAY;^-Q_U>_QIQd`x;xfrxd zK3Q~taCxeiQJQCH#fivB`flwb+h4l%BF0I{U`^_sSo%b~ig;CLZrNNQ<*81GdSB+h zSZ$YbvmNz9V)~~#xwW9WqPO`^(zt2lS#?#3Ti!_=p|*N_#f1svDwf)y?j*Gr$7t%8 z+jztn;H6u4l1(jtUIJ2=lHrc!yPP-4T*vZ1^VW;X;%sJFFjkA+G@~!lq}U~1+eDRX zjDks=ViLkjRHE>LZg>ZMq5j}IH27cmzwD*{0V(pGDcl@BmG#1(cxK$w1znhHm*aU)N#vv*#gI!)?R%)fRBzR(p;#|axAgFGs=Rp} zjZBmbxxCCC!HiG(Bk3nC_zxyBt(O)A@-YW~r?k-){<41p#pi0j&*u!b&5u25u)Til zrv_W*!-(oi->Y96x^H%r+!J<1mD%?eu_?^FTk;cX`v?Ei3PNprAn0j(lPCpV5hc+u+19dyKWCC!F~;d{?%Z#klRA@+v== zyv$U$)1f+Hv|q(>u1^+ty)5_jE4->89mZPB<`$X8G|UTK)j2OT1_KyOBVJ`7e?-?y zRao~*-bE&G+tPG{8Xb(Rm(M5|B?`-iwdii0>gp~xPFn1pt_KFfH#Gw>7E)nM8dnJi z;rz~SF($QAM)?MGtGAdQi@vIbXrRc-Fu#xx6)c~Ozv5R3Ps9+@tdmD z(=6?z(cikbec!E^e7HqS2ul9Nx)S*|ty`v)1~nPe49H@zI`wf?s$1o2XLpHYmpWMH z_N_A9d6~>{k@o22?^&6@K9eYt{{AG>-{0OrB6RsJJm~Ueh0<}m3}DjbN4aBS2KZua zIn1>f;Gag}a;WV-{Ai202cqSs(@Zw^c zI#Nw!^HMj5nH|V{K$G^?v*=LX(0!69ofDhcUM3yc6#n#I|3=b*)I_l)SDDY$Yf#6; zYwdU_{45lH9x3By0Zis^gGcFa|y|MEB(^$%sgS%Avi zp-lp?x|=UXDSbVUTH^Z|PTKR(z)W??Mu-_&{GMZ}rxVx87%0hW0OMQ5f{LWVtwKD; zGl?Lc`p*MAk~*4TwBwf|Z!*N-y|Uw};k>1m%aEEaq=ua~LjY;2l`2@K3|X;-F6~1s z0ZTU^ezI=>e#UxBQdYJy-;uelHia{UGctI534%r+Y8wd=>X5l@y!NIE>-S?yFIsXS zQn4ZQogQ))ul+{lq)dKAJUu5Ct>_MY=M%tKhP{aD)IY>VJxf=rK9-iAEl{?P9&5B9 zm9dPsZxQP`OXgFoSxPBH2ZhiQB)6br`RQ^jpN$UPDd#cb>DpMl_T~xI>6!wO#5W`9 zDs&;MD%%aZ)aib74;B4%OhzWrpjDN=LiW8vcYc)@f)$tbO2FabIoADc@w^qd6lJ=C zA0hg#D|@@*wQLmC6keRk|EFZTdc!+dV%b^~{8T&*!z2vK>oxWoWzwA|^Ag#bUql{7 zPq9;y>1XF-m?a*x^POr6Ucg9;Z_TaRdNWc|O~M6R@{7rF6>&1}Ig!W|m1$8XUW{&T z)^yeBD~gpl;#6Fd+PfvcT)h?Jr(FG%;-}R5DP=l3QS9+a0F1@NOVtzFJpW2&aj6JI z(!-0W>N{nWuckGQ;)w(^wj?J_2xgmg`>Rrfu3qKKOgJ$+(z;oM$nCquKIA5yO3104 z%+!L^v`SUDng6Oph@HzJv679NF&)(>#X@Zo{^HDt_r!x~Gu0b*!Rsz}qM$-=5_D@n z`y)mT1SvuN?!10t1?RDMzR?>YWOK!_JD-o4pB;1W&U zP`MThgSD~jL(+cN2D8858OdB$uyqn=TWI|Mih+sGI|D@}rB7{^wvoLJbnJ*OOIizRR$6f_SD3w^Ux+u zQty(Kj-JdftaUw7iZO*vytU$Azk8V$M70aVDz=9<>S!O5?P}e(2Gvf_bS)4H_&|wH5jlhUh}4F36H{mU%+tTHk&;@fApX z!gX~se6ZR_v0mT&LlPfU(bbsbnP1Trx_v1E13d&fDawws^Z3uyXS{Z+whq&QWKYJS z9sBDypOR?N`p(W5ub#Yq)_NCfs@ngz2p6UQ7bU*Z|932hNPl+}|F0*y+e*5$>u=ya z8hloo_lDhr-8Nl~QJppsm3ZxP3BiCFOMhP$(X?vEmw9(5qWJcbq^VdM^iz^*_rn-` z)xkdTyy&g2u6==-ml|eZSwUYB3;rGz=qA&Wg7lEz1gkkR;QJUGtDQ88>|!UT zB^EU5fYs*|I+r^o>Dp&C*$S!gjZFWMZL28^9hUMad%T~YrC=(uRUL2{=aon0VEA-D;sHB z5Qe`c=EQ1$B+;ga#ITvN;V*;Z!M~*PwoJ-LLMAiAnp7A`ub57LJE+t&hSKQX9<}j{ z08A=K%)_NXt8{BHF2RUg6DEb`A4h|~krd*op9$8Qd5izGlS}robwpKcqk4$lox8hc zkhI~;e9dv!$SF>tM3o&)#kl)fr%49G%m85S9Co#3d8H^$>KhW(^cg|9Tfu zP019MP0Eb8e@bTDI@-L+Z+cZXPBpdrs%66UQsOjbBXG^{=*~r1dy8NBVfuX?GxAH+ znqIAGBVWx#$LF(}JTCcu5Sz!D_`1P0!3~j)!s=w_;2O+U|GhOWV^jckMpHkP9K}-) zNQ_=*8o4g=^-Yn{)@`Tt_8#iRNEz>ayo&bdyyh<+6`;#YX@EW+ zTApv|>GbnY`1?5w7>G5sSn4iO9>MC!>tD@&wenT>j?WXOjE$vlFO}38vW|^cbSA#2 z<5newF^p>8hm|?;kr*mF8ZDYpR(hLO`uC${>656ArSDpg&;LO{dQIqxLrX76J=`e? zc&iJ~NB~>P5`aeokF9E)fRtTc$bftRo>EP&k%FyEr$t2vmg4@K!uKuza4FN!$o{VA z$rB5t^uF>7e~wDsB}Xfxsn$v!>cNh0;yxsGS5zIOKj(cYjEotdD_PVHZ@o{digBiQ z)5_MA(5%Si^L3P7@?h||&Qz;x&TJBO+v50{+LZH9l~OurRkB>~xM2OT!}uTB-@oL^r@1*tE4Sdc z8;#DIch#VMbpJR$hqmdleY8!B7VP;$14n%5(^4&3t#|j)YAxya)fO(8{No_#GKnY! zrt-XrzZ0No+<_nQ7lvNVb05Mp8d_$Af5CG( zXwgRS8~&b$?&KNz5;qs13whqfpWLHa>XYy2TIASNPily^H62{OyI_%kvO_a(5=c z`JdzYI{+P)vq1dG{Ta@Kg;gD6lhxB(=cw78JqMl7jk6bBUl&k?u@mc?>%w32(K8G^ zg`?MtTnF>wxLjU0*Tsc&(5po8tc#l$$3;`P+8?X)BB8IQ5LR2CX3HoOHraP|-`V3` zdYqIwv7=DTRoEW;LC8S__?8 zVPe7o#IRq*-@?UnQGn*PN^OU(&NlV^zsa}J>L=d)`iza}B^E5KGmS^;+tq&VCc)uJ zb70YW(E|Il&x-Q4#m$Mc7SB7&G{>gdqTk+V0-eL5N25f})7vQRNVV=d)zK7?w}C4n zS8HN_p&(#RJ^Ty*Ru!KruBRlCM51nCLqc@YbM7)c$0++(HF|UEZd{E1;)S!9*-pjO zwfz5osx|E+;y9nb{D9ch;krFk7HYgwA3#k|YCL17!B#+BsMwtr`?1A-X0hK`>`99~ zZ?Tsxw%cM^i|w}<#xb09<<5^u_Y{krWw9}AHJki>8_M|mH;b*d*sm-m_f3qyr!Dq^ z#on;kTNeA!Vh1fI7BNh^a!1j`7q-}$7Q4V=F^lCfzc68svs5vZiKW(J_gU%*sIMsR zw?S1ZbsRGj6U&QG5yb*W1Olj7pe|24(F z5Enw3uydhIe78cG94v>rNd2v{*uPusw-$TaV%seyTHQ?8w=MRb#Xh!JkXe?I$pR>c z_ZC|SWlFvZ%9Q+BOLaq;JP%@iX3B9il)=ul*fmg9S`N|vX43e!rM?Sga`0~!yU${4 zEcV|PJDM5bWQ}i(rD~x}%=4j4$&(iAu-G$DQ#9-!EmgqG(S$t;%7i`DV#OA_*J52z zMsofL71Q|kK^Y!Im}Q#ys-aBTzQJtMV2w~FjWkrHhW#0o3A^56FI(&#D3jV5%u@{~ z$3U6*&V@4ZO|sY}7W)&FslkF{-4I7XnGml-nH+o!WpeQ45iWJ9rG5%!QhNZ(gnb9f zggtts8{z~glRwe#X5zaCYP^>6M^Gm0Mktdj(adIIxe3bnyB*4K?QM%y@HN!%U@}y- z#&s9k-H$Bw36#mf z11Go~+6HBE|9dDC-#&|daH7l8v%loJRzVr=E`c&>v_f4Jkp8cLe$r6iwA7jOlLkxD zLJjpGZNX6QQiF#2(AH6p%_)%v&g9Q%HZc^@$)#v8x);ZlX5>%^o#RRcIv53VsIYY{ zvRJXDMqAfXi;c5Xxpkdju}Vuxe{FIlt=;4_ZmFr(b-Kl7Sn68qI?G~nEj8b|)?2K> zQVHw2%wo4#s>QmtS**iScUaez7Q5S0_gL3^EwjUV;g_62Vq=CTddSl!uGd;@mZfBO!{lnd#p*59U|kayTV|o$u$Z>cWp`ijMNSn3VyI-rITx!F~VNcnzr zfBFjs!UJj(5XY1GlXj_o1km-uRMHY;kRmbuZ^=Qf0a=}cG>XqWf2i94WJk`6N7C8F zOxZ(z3L?969=1&cJ@5vd=S~+^N=YZvdiZob3kOT&qEf2$c~?f+$snom4~E3 zWcSZQL|$bN&_jMEp+@V=4SI-Fw(Jmk$O#~_Pv{}%fyi#5 zheSbS&(K3;TVHk#JtQHaa*z%X*+umHtOk+2L=SlkM0ONC(6buU+Ra9>4%i}Lnih^F71b0+YhPlhuoZl^w$H@ zU$=tXeV*4(%f@$d;*kR0*AH3O5804|$S#HNsJH@Y@4y$6#ih?BWO=pe zshcW!uu#r*=bTI4_C~kH>gqypUk13SEl&1!w!Fx$pmXQheYNT4UXB)vS8kzmE^QBR z8Cs&sfoG~Q2X@&tiiWyI3`)*iD8f`XJJHNtX&dzob#)E7VLdm!KrN;!94!d*OmvbO zDh)h;zAe<5W>b%w_BR=o2IAS--n40IlxpPC7l&*T&a4%yWavs*X8oFb-p;*zzk~m} zzdssL+Q6o#nAUALH;|unB;o%H_t>u`o#&aw_^IbxvUk9FOTXw`^iG{;TP1;{yq<4mxE^q^F$obC>- zo0#9x`Z3f;n`CaShYdd8@>o4cAaRuOJ!tJvGGR_B^f|{+=_J#_HYz7d=B4hsm5_<( z|I^!>z(-YN`{Uh70}Y}b1Qivv(V#?86BbQI)V`q`I@rMosJN045V-|^XCQPr&hBTA?W4Jqy?rxNioB3OJ zXNE0wnm=0L^fx;CF!VDzPoz=-e_m_opEz6el9o|^xx*QB;%`O}egrM({weenbPh=EsT5K%+N5&9xFyw89wQ70K_4jQ=G7*1j?Bb%4I#=w7v_jJA`npa(^A zJZ_C5`)s2f!QMZtqXja+_vQ1p)O;rcv*Y}#19uy{fD0w@Lvj>h$2-QonMq`*K;Ifj zFK~`dbJaf~19qZZg#3y4ajcuO_0bvSO`)%Ne!JmIM%j3yGthWr&w{+2b8juwclh-k zR0^-w&Q5} zal8eIqxPQk!p1>kHfa5`=CpfFG_#jK(?d$&e_)(Fnp_8sf4uuHj}}^(+T-Td1Ne43-g zr96ecMhb(wH3^ixXwqP@mF=|#n;g$4R%koNPrUTWLkuI07f zQ&P@!-h@KV?_U^w&fOS>kc`Bvytbap#^!Z zt}rLmkPq#$2RY$f&`Z+=;Acyd*B1Ih^api^?5>7OKnXA9P1QX*_W01!t<3Q1E!z*{ z0NiofMsW-c6gWyJeSXZ+tOJ6cs!xbJ;V8?~;#Z66j8@aPYvIpbTHYHAPW0)I5rv=; z!S=&meP_#IN8Xkc&Q^B||8d0h>*1##BYei*@>3c(NcZOLyyqw!ND2ojjuA%7;hw2H zx*G0)6#TG`|1ABLv?k<%JPufe=b*to-N)yaQh* z;5wKO;$s}kVE#A0VSu^5crKEi4LBR-?f6Cl<^XInzFfdU;m=PtUh*+x>ld|8qu+nN(U6Ui#-3)@}d%2giWS zk>1JEgY^$R`QrL_zxc7oNkc~Yt}P2SJp7k`y#C&o|Ll44xtEN+u6*v|NB+8U!~0)# z_B!RfOUGS5qjt&f{`S(w557L&95^)BKV{~;$fL_wZQ2n#*!$G1yn-8M-KjtJ_tl$s z#t-#5?fl=2zwx%ae*2&QXU&!mzd3x|=@(pf)lIkG9ew<%wQua|_^I!pVWR^#SIocf ziKkzF^P@dSjz8nV%L{LreNW@>pLyl2kN5t3!kHIcG2zxZ3-15Jf4}sOb|UD?@Z{BO6McH@73c>Znw z=bPW$wdU{%6YhWe%v=BP$whPi``arPy!uP}nDDy(la_8jr}WRCkEnU!hhF2BY&_-q z-+gf2jK6(-Y3)k~j=L)Q#_2abzUzY9pX#{m?zKO;u72R1v!?#nrx#Z~``wibU+c2f zd79nJirX`qirTVQRPA#{{F{a@pBWqY=#(9~tL7ba)O*)wJ~{o10S`@ncjSw~AN$@H zcyrj(6?+Cfaq~x`U!H#??cV&>v;Q=0_lf^8aoh0ctH1B_+woh@|39~VbJ~C2_~CEX z+;zC;;;|df{cHJGCqHuC`TGjH{shk7*lULW$8vM*11_}ceI{Uh|x;~NX#y6~CV zd(Zg&EgxV0$~`})hsUft=g*~|_g^|``-m56emE|A)f*Q)b$iF@kKeTGvbA^r)N9GO zjpzMs#@DC(?)ncdeW~_<>w&A^x%k=2@6P(Ksh?i?+QP2?>G_)_sFOobjU2Xz6tqr3 ztYFxBw8`B@38CWI1`8b95{Y9=A|bXT(v_`<#IX&LkXyO3Es?mP3Sv7V{jwF2u53dj z#1=%lvi*=akAm2aNLRnYu?>-QY(bmi|=m20uWO;^xNxHi?Z*<% zz-PCa>&!!8%TB`N!d8@oDS)ji33EMcO-UH;A~h#r7QvPcJ`!;)1*SL&^H*T%k}zw5 zS(b$1go^!XBAkzbVXvCN#DQVon!p?ahCg(ssIUA{rv?Zt7+$8b!B>Ljd|=owC&IZB z81~Ky%y?it@RGpH0ERtv0uv@p66O!Uu-8t|tOkaCx5T9GiLg(XoRfS0{(XBQH_Het ze^d8Fj=+`cRf(Tmm6vvrhxTp^8>H_crTiUhPoy30-B$Ry7&~o-)LBcornW>bG}2O4 zQhK|&6lvO%2x?}|Dwm2|>8v!@rmE}2!P^Rp4$zY6)2EhHRLv|=i@FT98wzX0WzaO6 zOlKfxSI(&vexWs2qD-6O4=&_i*vl(J)zhk~2nTtd-WIH_OtM$bDNC|*DHQ>5DYgo0 z!6kF%7;2+|G_wn!T(dRK(aLpY%R;(X)K=O?;ao0x7D}SIhMsV%3d$m&Q)#HW8jqrL zLEWl5)#@Zv>>7GilMA$VR;9V-3+<$)_EN0vX1n>5f0g#qOS5wX+Oq09!C|vuV-&yC zRbRF;9I4MVstYQP&He9K_3gGw%Qo?5v=-K%2dl5$wVb*^@Ma2Ks+QBypxXmFp>7K> zTXYXrk&mXmbZBzZ0J>` zXx=@G(Ui(`l4prf)1Wf|wy?%DPpul_GW$?W65Vj--8vDfzpEXg_64yDGC?0*v<%53 ztpjwpjh;Mfl8X%$V(=_^aAuhs$KCNKSRE?mHkOD#>2?(`;x<@5djR>7 zNaG*;*aMg1V@^`eI1;2C?HY-{oIg9n%oK<2 z0R2|s9sne9+>w`bw*W_ecz@4k!{J6i{IMR&v9g5tmuZkE^CXUT2@O!L3`^peG6}hr zYo@{tRnRcynyqk5hxE%4jg0rGV=1;x%xcSzHIF~L4dW!F>1e-mfh@u&XaoV{sY=3( zgKb$7<{H?V6(+UUXL*wA#P5Ht*SEA@ET43HMIsUdvbJ0p^nk`~xFihg$Uye`Y`4rD zOVCX-z+?6L<)W6E^yYYUwuxZQ+sex;LU>HT_?a}dCPL7JVN338aJ8ho1TQ8`6)_}s zI!&|;lznM8f`kLd4bl-?$=yOvY_FP|s?^UdsLei3^>8E1zO7piH)2GN#3c4L?;0ZC zZDj4S%7sWQswR856|4~W&BN#Z|DlI#M!Px;)xCJIh}P(lQhT^T;B5~pzU9ZB%PK2$ znh825CLx_hcsBxftRAk)NUIqndpLO?y9gbH&?T`wcmgj&_m;|098jGVUS9;o9$2!J zEq;uiJC{%&Mn>?2=n~$^=f)7v=0P6>G&df?D)v>G-sl)dv_G{Z0ec=yDAgQuE)`Y4 z90JoVLW+)YF2}O;1_lZRkq!4Cn9lXs-|+%io(BDx4V+Ufceon<0UCd4cpnU|%`c!e z`T|4oLveuLzR#aW)pNWten^CkEzY3Fweq@w_1l8E;oT>MMs$u%cZW_0A52FAm)wYO z?ZLAG(Fqwshu}!qp%?)=5>yDh&n;u5wgeFkl*2H_ybaY4FM41yys%|XWRfj9X`~rH z(iT4tJ!>@lGQH@BqDz+n@J6G{g%N%d26Dm^4X=_=ZZ!O>DXI6%ra64L>a*nPc&T z*pW$$D3IA>hWHyNO|i!Mme{nZgEw0=>;#iot%timy7VAW7{IWDw3b2qLE*#8GMtoa z4XP3jYEUEdb)zVB1};=e!j;Xm>52Ine~~fw9gp1dQ&)_!F1{`J zZEP+y2T>Ft0dpWwb$3%;9gi_BhbSBZv&-GChGD2W%RR0J56sT>kecfS0MX#)bmw|F zQOn-)I#uv>cgPtZebmZpUJ$gX_Hkosx8R5gWh0nX{cOdle z;jYjp{%DaCnh~I^1VLwjUdSZ_+vvzalDi;Q^uMrKji@XV{w}k=yM$L?7=Kx2uB?y8 zluuXqA^N8<$5nOMYE*~K`quDgJ+Yw_dM&)$8Cqkl7!9&w{FMbMy|Y$`AUYnzKDYTGDFDW(($8pq5uQ%NauW1EbssEn#nZFTdw z>YL$)s_>`~+BiZQquL^hRsG*7jFaZW7ea_Ko4wI+9So65M9{h3;i|t+gc4?1gA(C2 z147+?QyAe*0xy)rh1(1mOnbIV0j> zI6%kq*|y*iwjHhh^hw2?CpL;R4|tdXxv%AIUHBEVI37f)LLkH>D?Woo+;~#4() z)%R+&2h>n2+JpC9^;?j_&P8Mi*}4ISu}hjKwj*5+JO&ihV7uziBH`HHX|9HHK;G!s z(cGoIe=(xU*~Q8{!QYYhuTu+|^_1Jf?MrXBvgbv4uFK0MWECMx7ew72Y^hM^h; z&+8nM=%0*g*gp`x3Kfo?0uVispGGuP&LsP!#UiS_b=7|ii=ss<7Dp?a%T`uS*wl;> z?UJjZ2bo6o1sM{^bjom%fkwu}cOzlkx9n^XTGCt%jiOwyQ*soa4+PFJHJ-E_=@kCs z*OA7Ems8=W>5|aD2Cd@*%6nAwD%WvtAU^}A86sL*G{0{|ONa8!h~|jqJ0e<-Xj(+; z$$e5&znfpjn*dOOmzgUy(z#yp4`_U_0z+ZfN`FSV-oNo0dt_2tw5V@nQaX|rndFET zIUb;29s5bin6@gT$w#%vm!Wid9PC_rkeI0P_MaHTqyfD|b| zxUZv&SdpQ|R_Oe5)h|Nq-sof8F!w=u{*b!W+#0uq1{vd5SN)%0r|b+hm;_X}wt_@K zZ)cdt`O<=y)vcwsp0&f#-V?$)NiJOcrF|oQ`=+k;&M;%Zh~qzi4X@pYzjoK+1{gS( z6y}LJ^b}!^LZZSBynypDrpSh=X|89Rp&8zrImWeQJ6M3P=78(j798s7 zRlsvkXy@UF`rIJvemPt)**%eQkUKn+)5Eox{-YuR6sd<{bFD_g5KLD>PCfLySQ7`_cc1P`uD|noSj`4TmTn=4zY4iRnvEc!)DJ*8iv|%5Zyn_+VOS zL;P}hm!+E?S|v+1ZSJ%2bAguQSChV1_@E>7Nc?z3-zyZ6^bXhJyAgQ&dvqw}O)@Yj z-1{6>v|sV5a8vU0Hjwc`V9;`iv5&zytQ<&)w23uC)m~fmWl@=A@NAwGI)kT}#y8Gy zb^4?Ip&$}nfiw0Q`|`Y>LVJ)6RK_UA*B0$)Qb+VV1^RozD@9BV&3M0M!HAr_(f|4p zB7()uvjY0JIe35NWQ^v+>!^Uv8T&1Q%@YK*UqO$ZH}A{PJBUH(ZKm!wvE-=uMa>Kz zpVN$@DQMLfEk`MfHA&@e(Iq2=fMp*^NvC0g;uf?4bNIuvne7Q!%x$z@SXHxhB@ApDNCGl zMG$q2ACqEqmvU7XrNz-o$9LdQXy9kO+gO_p9eXzC~m8MHu)wPgWAhg1>5TmHbEcTEedUh>Z zb^RN;j)qd(6+DAE#({}RVdSn<9GN7@;+&RL0BC0OMiBwS>iE6rKXZ0L&7?2qi})1q zV}PvCruS?VR2DiyH?pOA3W4BwZgcoxui6_RLd%%#rH*_3_SUZ5iTNLf&U7$D zZ9{ktiWPd&*HTiTPER3tgc|Y}KI{qo(Fk_#-*FB%B7AhbW%QSlKBME6B)hxgnIyZ1 zsjEW-Hc4OC(FhKO;2VrI8SZj}A+i3@-7e~XSSYzm(;wV~q$JmWi@QUA@ZDc?x9bn? zNO8BeAJ85+D16wp@XYYxUJK3(A9e!iS78Lx17TM2r^sXL>VCrGGYL$wweVmYDLA z?2asn{hB+ngu^$B|8D%9#r(K{`Edz3)fS2TK)E7IzOXQ;+T*0m*;>y0NMuious2!r z=f8hFe+H-IkKzDX)SlqLnttj_qH#>bZ*2r?kfRggr;|HbcTvL*VTn8J2$3< zYCG3CLksJ^2I&$~jO$(JYT*8ic&dUAB`}(J?*2r5?;Ph$3;xO9cs(W*vODT{NQ}Of z^^ZB*v{gt00+9rWF8H9bY)lL4%CgQGTx43vMm_b}nh3#8Jx`%u7gU~QxG@v( zOYB8(H{M-aQsbUehGPcqQX~!xOe+Hm2vBWV@cmx=#LI z6`-4ZJZ^{M8-}kxJ_kPP4q62Bu8LXHOv-EL+&-tWc8(jtGbzyFCel6|FI87gcW2v7 z_tFqlhs`!gq%-;XGww;p@EyUIfg949_?82H8s7?hSI?=q(`~tg=dMNG;DVle^yTgm z!*6%jgsQ44tMS&Yd)l2WN`}ebG5uX}xqJAiOOEMpOyz87BtjSIe@Km}LPzMmj_mZ}v?_ZM=4jLzI?ZAS zQ+D$#bZw9+=l;V0sL=7^WZc`vmD>W_0C@z|3tQcqfGz}-FQ9rrV+8aJAg_Sl1LPCXUO;07 zL_KqCrX02@fF$?DfcygY9U#f+s9q*7wSXk2D*(y7ayrd)i~=-P_@!ob8J-`|c!9e` z;idud3*3u42^l&>sL53Fs+6*9hn%KobQ7 z<-)c}0`dWxETA$#*9z!vK-mKN2GDf^8i+nc^85!t*9+WPePx|<*eU?sAaD^t-1~Ld zo(FW3fHncTSwNoyxDp`Oa{?gb>%t1I073U?6Dtuj2+;Hd(74N$RwIuwo?LS!hH z0+Jz52Q*F4%>yJ;xkN#aDCjQ=dQm~^6tqo2p97L9cV);kJUB@MNaEH2nl57721w@Q zj|w^+ZHwgKEB?6a=mS(VkMk|P;bcy56y@dP<3Mi;Z zLCX~Mq=J?!=xGJ5P|%AC;&^(n;NWEi!76a_d=y>N#krp>0igmIt`H3aLPm;v@9E;K zmGm)4xw@5Wros(X&@knit#Bh1#CBN5%eGX8>`@TgKIuw1ldb^;6)D%r3O7YTtk2SK zvBFXMWhg9V>B@4HxGDt&mFql(o3Efcc`Aq73ET%S<5WeR#yxh_|@ zrxmn9xxT1ys}%IIa&1<)^$OagT;Eipq41Q9%cl z>k)N>}T?MKr|)dXSd-5 z8hjt^cRrBC7@-InLBKH$$F2#?IAWYu4Er69V-qxY0mIR30z)to;R!{KffJYXDhcyvV49LJ&A_Zk!n6b9Mjw?3nXlayCt*%QIn*U#E(c~=5@sqe z%}JPgU^tdeg#0AKNy5Ag49C?8nva0t=vrc|=k~xB&QEgGJr7Xg_wPH;`6_rZWmU$P zdY+RtHu+~gqX%&X&oe=DV=@tJ-yn4U(8Yp=N($!96wIy^3?Euc=I2lf#_8xzb4m*4 z+!V~H6bzqqNsjB<6wLG#Oic>r-W1GzDVWDoFi$68Dk|s9xNUY-H-4IvXr|(XZ7R+7 zBpL>=I|cJY3Z@TcWAbN~`{_v-E}Nz5Cc7YshWwGtV+Ucg00)RY~V)LWh>T zu`x9`TM#BW@kNBG@>*Fb7MFu%#tCu5%W&x<)x{Demu-_4aiu;mgFP-R3um4_Pn<=U zuHEg^%Mfqnor2zgllVylB-U}eS*Ok{3sujm3C=1_Xe5&hz806M3H4#*$g*xbwF0Zt z6)H@t3&iVJT){IkZiZyLd!TahbSfT)NHCQgG?$@OtU^Pb)jgT16z5dVQbX_N(66NEy$8r%?436S`1*YON@>4p%jQZ5z3O`S2DqIk(jo3#7p%?cJ( zSC(R(TLf)HH*1E)rqsFN&fxTlvZ*CCrYb!PkoH zGOLpB2P2)+^5#$l)?@kO=-vJAxH)9ev&(pL@y*8^)%x=sada;&qV=C!Y@8e{a6Q{rpkL!eKw311 z$G*Af;n%nOa<=6(ujWv-<8+?XiKIX0z_~YjPICd&`g!x-cP;)Fj$>Ub2c0MsQEmU+ z+j|F&U%VfVJ34kzLtQfihuW}S{+4gjJ08=br}F&KCiucjlsq-NOIuUN2u|e5uC0gt z;TC(|8?MERfb;4*yuI7%M)$#~P2Ua;?=~*{*c&-hdcZ+BJng%y<88rm@J_`pM_3&L z#mOP?i*v{pe&?QH@|v!hynYytr*(WP=);G4y6U%Lmp+mn-vUDmx8mG?GayDA?H6AK zFnkDy1fG^ee}R#+E&fLs%pdJK^%ga58)z9&_BR^0YQ6zSI9|E(ntrYZ7LL!gate=Z zZhH;cZ1ZJ(=+$q|gi^2pnadq`*AuP|*UHvF=?6IY?# z!{H+jPOi>!jz;nFLHoMH;OQ((O<%>41L(Bc8@w|*Ix}E@%ZoROGc^5(PhY1U_((f| zqg30xd7mPHQ@#3b4M+d=gA32@$j9LrFK$V+c(a;Z`Ll6 zSSHf056VoS1`w5ojBpqkGSG`N#LjpedFzc1hGMp_>kdO3;d9KghA)DT=Im|C*`~*k zlsoJP4#2Rtv^(t^@T{yiiVX8c9S?c+T?ck)c{>)AdG%JL-1SoDfe$+dsgpoZmgdXa z;kADVm2kaVNq8!bdg}WYex+|U91co{gLSPG&A$Z@+pixWvUO@E+$MFpT4=0CM({XUMJKIEMuw7@ll0y!`+&sP({yU}oW< zj!OiGZC?8}a<~piU*yyUZe*3gC`!baCEUTN;l8k)Zy%#Lcy5$Oh0SxLx2}UUHtfWK z*jKUiWs^_NTQ#0hW=Ho7PJy~h2Tuk;qoxze2J2r0bwhJ`Q}7!qscQ_}>yYw-lFg@1 zK#1#jDg^x53&ns$Qne;jV!{gjep^Bx7#a%A@E$V5`%f7jv^|@Sb(HryIwz)ePE2R0RExU* zhjlVjf@2z*n}S;;m6;!%6MJ?}ghm3KIhM2t=x>q)x=hcqbxtIE(3sj95*kzC95Lfz zdt`}7xLZ%I@gd;5ql>t>{CD0g54rvp_WI0~ke%XOXNEPoGI zJ)_1+ICw(OAPEl)FKIcIJ`gbw$;Vlgy|;QTakO7?pXTwZwWcE-kzd zU%NcXFN2H^M|j;%7E(j4p<=Y3sbcgvsu&&1gRdSaDR$K_M{J{eYT|A~D259G!Oy9^ zw~kz}zCdDz_8B@pEnsi;LJ{U3Xtz}-AEk!Twb&W3g`T0;)J`ckKI@4eyVTkUC)*Pw zz;7AMNf;tAQN=KShxM*O#KXJ-@woweU|s`)Owzy{*ISMSXU!?Cgg%SH>h=8LEWb%9Z&eaYGd}Ou2IOEL}$`h$D3F7GT#+;XDfR z0+Oyr-z5`smQoO@pSklOc0!C2R*nY1TwtjS8i6CXEc*n;LmEgx0>ixs%0U8COJB%1 ziAmjcp_Fi@llc9w?YdazIba(*At;B{N&oDv?FPtIXB^GfgUhm zrsi0?F8`_M&GqlUreJt&LHk}w=UcUyDCl$|qKbCDo1u~u_= z&X_H8UxiPZJS&%DtTD)`KGp%urGaj&SQnQJw$yALb}MX7@qzB9rK`JQt=dpv;u1LFmzbNs9FQk}jy5-MA0g-Fn>;d`Ux4v%nVWZ;OV>e|`i{cwiE%Ps z$`~zN1Ma9qed^s@w&bgbNuGvBi+&TRz*CdNcJ&H3gw62cIYn%W)`g{XS_0G z+#0mrl-d|34S$&ZY;@J%$^lK|g?)hFJwOk7=`|i$0*%KHCC)fiU!cbYxQQ@v5 zu(|600mo#rR=o{jnU<8CD&4FVQOYxZ^{U8=8 z+)?6>jveT49M%S{2?A~0$tt}LSKWQgHi0Hlv@dQ#iz|R4@zNzcHp70jfTK&v0ETi4 zbGDiKNGRmgDie*)qub`thkis8oiiZs8`pijksOGY599<$->F|W0P|me%kK0-PLXc{ zz0C2_*KxP3prt*Xk3HyP2TH8ITL}j_MX2$i2#;e^am6;lL1>|QKQZ)WBKF2dnA88B zoQU7Wa#v$rEWL&9mYFT{0gqTbJ2oS4%iNy+tSx?f8*cHrkz9F;ZymIJ93xNI>HUAq zlQY2yim(pB^A;sEb;!~d!7w+Nqw#McMG1ZbjngyT^45&dvlq}mld(4TSS939Wqmvd zk4;`y`je9rfeQRCGx(^{>0-X2@`tyIWaa1-%_XD(w^Nx|Ys(b=Gh3#gI5BS&PM34R zF?{eyaInAe@~;K_3$(yDUj9!39|jAblF;P^h>M?^-eO6V+2|DL2b1ozqOyq0()Z)h zj-TOw4cDu1{W<`>eP%XfFgp`>w0RBFC_vr{M8qBt2;yX?dIW|3Q%t_IMYf@1@HfuS zbhpF?^0N9l_}p-4iDg74XPyV!VA!-(PI%k6s175vvjJi82`*>rZSVyklRyT5A$YDp zKP+9(716U^y^w(hL)sdzcgX3QSuPvH3^N~LVg{KF0Tld)_vA`48RfljjxL&vQ1n*B za!$)P1HqhIZ*BR8Tn;AS1aP*$5ojaXP()#_MeA*mYtqT8T{5Z(6Y3_?K;cEG|AM=n zsj^FY-tx?rc>;C(A@Bu(*?^4GCBGb*!aBGJf6kr&rW|f9s~MJa#ub**%sd`{hV;Ro zb5Fyc^ZE#$>((-;wAwz4qC9(tg%Fu3>oE5ev(c9Jfm+LF8JL99iiayErU7o*?d;vg zi-bvpn;!%d5JxFkhEp7jKy4gnhnhLnqznG)jKy;k5V9~)Y+z@arVPy!fZbs7Jx(ya@ z^y&;~0dUpxFq=O*4(&bW?HPJoxZM>#2yIZ)fY;lGFr@IoD%TP|8PM{LgPn=3aeS}s z?f%kDczb8=2_5~n#=_s&^%lOw)9dmsxYzD&+3g5#aUz1?nJRE+-j?94kqp`cQCr7J zqWt~Q#SAi%5s(1ZH2rpDtG4K~c7&AQ*tgG`hKzitzDdj4d|E#A9cQpp0fOB3&?At?i1~_5D~1^+p#n{r>2Hfw6KFmEl6WxWtdxY?oDL z%*SH+xB*!I4ULU1X2)gt!?pHm#XE2XhELt#BGeln=!S`n5lljKXv`$R0RK;Cyl-rFGW z6AgK96Y>sGrz#2Q-*U@5*BgB@vkAEF`)dqquy*(wTsDMjPz4>{=tG&0A`qct;!$8ag{llka7brZ=)MaL^6Ks3_MfOm zqF?ys%w-_u+1W#)6M(-0CUJ!?PHw;6_AX*MryKBkY2oLG07j~!|VT_*0Q(PSM zM*dtWj4*YScq308flqzYhHx$#Nt^50*Yy|nAv5*0KjJS`iAZf9i=O~7_Rm}^+fW?X z<6@yKwE?NE#)(z5)&nC^swY`9(d#cj1L`KhPBhtU@rU6Xj2EehMH{ETa0FokceZ{I z9>Ey(n82P%dxj?x6n(@H+MJ%qe9=do>xook4)sQ+XJ(-}J0F}^WL^;a2c)8IEpM0&BGl!GWSm|q%$15r+*7^=RM^C6-#fRclMF)2z+YBq-1wBtXUcA=q3 zs7=rs3$U5zaxJ+4POO_Y|MvF3N9(|8{Xkevft2!Tr(D+0WTk67X$7*$>`mj7fx~!T z$nzG2BI(oP7Z9)7Zy8&!+P-E?%cG&+BPgdOC>chJ3L`E4wW_Zm<+HVBtm4+V#V!Xq z@xhE!_OIV#^A&>GiuGTy`5M15i629&K|B+U5$hwu-);#n-i(;R4<;eQIGSuci8(J? z6u_cAHAZ=o=u$R6mOJ_qJ4$-ZM!>>rQzAc)VuAG=nj%Qa*3_W8PW)Iv8@uKmIq3$u&0G#gD4E^dVig`KqRt2>N-TD&tA<{)4{^G*K|eit1| zi~_K7z;;YCac_VMP2y5=34<*nHc`KKJ^Ma%CT$J3y0Bpnz|@5_DBRMkC7!M!X5Xos zHRv+b!Yw_qExXxk--2*93Ay&^TQqdhniweLwa)F&o%lM$WZN3kFj&ZIHAf2Hp_jqS zP#7!ZZ4Krl=Bw8vr86jradZ(Mb46-cLU>7p;bic^;+Yd;446p#HJun z8Cr(uYSD$N`io2v-HTtK7BnHrv7v; zHN1o6hh~%k7Ey{=7BDB%q!zF#Cg3pvKLM#L4Exra{<^E-J7D|`U2=XF{w3XY|FgiL z)K77(9A|f}ygm&DH?XBW1H0wGq;nkCyVa+^ul0W472(wiEw9t{z+!lE-N#WV)D?BQ z8om(0?kXt#Ie6mOM(@zHHAQ2_%wiMw_V>`4&QY<@JG0_PHZIUVrLBULvJFI!myI58 zdS*^+DI6O*L#5O_)0=*W{~&XvSWd0ATQq3OYRc*K<#dvZ`#DcX?oL7Xo@h#gK+ zKF5~Fq=<_RJn-NNltM54&R7L`f&#S0j)&xU7VWbP(W`fgQWI&cA0%Rfb~38{qgSZn zM3cfGc0y$af>Fz3-3q@kXZ& z^tc{=U6vr0e4gQg5=zfsx+8cpD(shQ&d>tjP}^9CZwyo{R?m(94WT2yTr1yY6UjLu)O+Hz3$5pHf(WZa zT8F@z2`k?4qw9IFo(n6s`)SRBbtqST^cZ7Y3lR`8hS&9h8rV84+c4%LDt5f2Zh;dU zf9W9|{zQB*2Qwm=jIbxna}q&|h&%p_OrVGyin)+xRyXZ5`@Y{(}n0Vd;KGzVvQJZhaUYS$;V2=h2bZwEb^1x^1T`gA5a_vssa`diVL zGdbHsBXN*MeJ00BUVS=7rx;=C^E0#cU}i3))+18O#hA+k#X&E|qLZ}MZg|7E)r)cJ z^=k?z`b)uHk(bqXCr70>F@Z&Lwc;9}(fqOMP6gFOF9*OF@m6Hg(_~@AfOmf83|Oxf zR*ZOqnYY7womY=>T#ZIcKwSN}K|ov?xe>Di>3Xw(=z5EQ=z6Q^wU_|iN(j(tnizBg zm@Y=!0Llc90Lle-0A>=PuUTTi4&XK;pJbF3%0{Bu%Es{LaNfZz1zZ^$0I{aL%uBRR z+ElbpVtoUrwTcV$EfB!q)tHE0thrt)a;`uFE5;Jo18?QymCf^~p>=?!4XhGxRRWlO z(>lzIpavBU5uB`e$`fbD8HSoyEw9CO|5GS5(C&Z`cMC?eXE-{*rg=XPO*Awlo*~H-L!o-)b`FVK~@h$3QeV?qRD_4G$!>387<69I)|y{ zT$-t)eI>O|ww8PITIS9N3r172hLMYy8Pdk@WCk&E4JRO2OoIi9m)S1pWC4=;F$;B5 z?;o64Z{=PEg#ejoau&aseNauTDN@8$u?P+k5p5 zSU{OyGOp2KTQhl5!OYkX->|=40BxHUneOnnX#J+wQ0x3l7LXreq?%B z5boI1d$4bi_jw4fK_7};-C+twqWwmXj{LQVz3C+LSMleDDmghe5--erAbj}s*P(M6 zI`DebU15`Bi4(mTk=WM+r}%>GtVe_GK%);)s0;LCm@fQf~*Rs1snfU08bu0G1q}d0WK!G^e3}M_$^_Owt zn>jx%mV;qG`eU~bTA6=|J@z?EX_vn=7Cbu|!21uAGyM?Semz)B97cQ75uRpmjxGF} zn{Hr9l*P^hZ1%-&LOEcSt}ECFe{ndEb7c&xiy$1+GmFf+xDx|1V6U;oE&x5!SEwH> zaCv`3=z+(s8VoUq2Is~uHl$B1Hc9zTk~b*BMsk`FGp2iZq5;jjmlEU0P;3XVUOkXG+V#L% zAs=YSWtE1cw81eD9fH5eVoY2;NSilvsMhr^MsJ&dyzcl( zh_QV`Vcvnz$COi?FyFT(ppB_Q+_C;>J1A>IVevyG-Ld^&;h-bbh_lXmqQT73+A1C` z&^Muv8iQPC13wN~>d`mJL6)X(f@e88%Qy2`4h=!(GxHf|`Rhd{0_i8r1OP6GEkumu zAzSe9kjS>!Z9saXPsn8A7Q+3*L2e{Fr_fz=`nCGx#Niv^D^Z_r@K^mW)~8RA z`Q*q_pX7Q8=2U6kMo$+MbRSn+fdNx~y06g>>!CAiZ-I5Z1K=sO69G=_iM6ZIwc}hb zody}f5H!CBhfC+I@f8*XIb6y#hD$t2#97t3u9XMS8p!bnD2K$RfQ^p+D!;PLWE-q; zM@6j%$@M&JRdN#mT?!UC#YFPiR%oMj-Tw?CiRxUC^Ov^qZVZ-cxB45aG1gy7b>flm zT;XqLWGOX@vzcYFU=hm=>jsVwh1OXfz_uflocNZt_12>8AOaY z2TYjT4Pu;%b~={7i|3HJq{fUd#!7VJ}8;xX2uFv^Z-B7cm*k&!6sPcu{GmI^?ZdqOwWH@o!n5jZnef8z_q$Rl$+ZJcM3wGnf{D=p_)QWSK* z#y&Oaz>l>+J6^#02Fl;n!10I-$2jnVvAOGBF${qq%=)COYh!phX!tV<-sGoKTop*$ zDA=caa4LkG%JGr3(LEyq#45BXttiWrJC19RGpqoR>V)+BA9dYNX^t)xB1J9y*ry1f zGehqs#4XMUP-jJ;vc74E2DKcUiksku-K;xN`!uXOgRHL;O>H&oQoda)2lV0Ya936v z6u}2^EG2xi^#EYYziB~#GH>|Py9(poRLoM#h^C$kzS@X?m}2*xLw$rK^k~^hRZ)* zB+c4CxUnYH!+5;q0X7{tsNbKb@p)cmH10j%AUpI9x$192;o-OgE=*~7KC|(pTbN1B z-=?Fh9F~SH_D)~k9@k>gBsKQ9j(MSfhb|%?H~4J&VcgYw-*5lE04wq*1oX`q(1~Of z=q>h73+?;0yd$+AdZT5Cy|90NqxT%#ee-6;4*XDesF$WU;~1H1@q1vXIi8L)fGann zR9kSk%slWQl$CQWR*vTydyqLW8_gqkEKH=`l($ehvlw*lBPr9**$4 zrvnMLb(|*4HzhH>=JIq9ZhS#N4&d1+B<8bTMoR1|B^zZ*aJg$^Z5vY3OTI)ApAJF$ zRem_{>&}nk*Z6VF9VIgt$2@kU2?alg?Wb-If95claw(=-B~uPE^#+)NMDjT(l$I$j z@i(P}vxre?$w*p!6>u{5$w>SjBtcr)1c{4tiTa-uvGQ5G8 zb?`ug=p^;6=*021>rysG8n&;rmP6^CE!fd)M(}mq+B_BU1{$Z>aTLc@&sz`U8!K$~ zoXxLsxenE(zy6Ci>wVljUFdaP{XQknYu{Rcjla+FX2(!;y^9f2K)xCv!YSR1>r(~j z#)GHhy5Y(|25t)mPUI~uJ1)Xi?=7^y5wO2qh~qO@>E7Z$@L`~Fz{xlhQP9}8Kk{Ti zZ|(facKevffIeIpF3f8QVGJFXj}l-w8@~iek@bh#`4>tq>baxQi4k{(7~;!~Q>gc+ zw?N}OdqHU&Bh^A2heHeTGX{CMf5>X}3R7vyH)0PCw4*u5IuQP4;h0Epkll6l0VY{v zi_lU1NrC;l0{gcGc`+O_LdXSrhsdUa1G_M89$3gG;u9Y3k@dwN#wA43t_Ll$a?r*4 zFJsTYc?fp-23-XEE^pQ+TKFes>?c0^hu*xcHE#;`nI^ZZzAt!Vn%wd=-RN3&wXXU< zFf?3C?i9>-oUH06ZzLDywPL*j6p*5uk@fl>#CW28Y~obYY27+|06n;J2eGeJ^Jl%Nm112t9>?5(MZZn`YmPX6IyW z>mhH}=1AXDyj($QMUHK%eGes0PDE~Wj5Ee75K#!4%!Gi+PrzySo*(FgJjEX}5`e^f z4gaJQ{#E|?F&*+4Cxl;tykNXg<=hya$*P7QowGTd!w8eZ5NuvGhfenAed}7>3TH_u zyk&ixeA4$7IGbaW-~y}=L`9&X*AT#3up);7%{ZiKzP%wIn9)VOWJkFb8|Zj)5iH}X zS~R>IfWDMg^t^-eTB|WF=ki+8R9t6OCn1!v(6UPEM9|#3KHsC%rg{zybuTGgq-s2LbTdjT@6KW5zpx5 zbc*&pZ@+8tA0#ykLkOCn*7v*Wd4QY3?QzwAEHYn+UI0Q@Sc>KKyU-wQ^F#Ew*n?#x z4P0^ma+mh9tg>Fw;8hGqt2{p&!noI)^_@@u68k2j>}V0Yw5*@QT?;kW)jzXHHTzG2 zy!Wf$3fS?WSE2p=Li-1WxR9{;24qM;e^1n6|ACJS8;4zt3La=gqnTcjncH!^tW%)8 z7?fksKn$>tLyVN(1F(*S_;z`-e$n)<{7CR5DBWAxsfp$TF(1(EKX~(Y)~sd9>s$>k zMizaXWA;GfOr&$OOy}mp#u|GtQ&cZhEbsY~DbACR6XINedi8Z78ch3Jh4y#2Dwnkx z>&iKsQL9{w7b5El^do*;8Xww(q2MqVSnPv5xfvBy@6fV-(DV;|`c5tDdo=xL;Ru~q z|DdJoEMLwJU)Cl~Kjh2Vil#@)IwbL0&S5R`GTH;#UiX)v&;U2FY9vy?alezoAo)ax%Yqyfd##_JY0PLjuOkYBW*1O9pPh0esE00fs$?3 zvarF$q^;9zN7-)rr(K(+|aAz9;#kb5R_So*A6VN2n6q}Dsy{stgj{*+}LEO zHW|Ckh}Cw}oJzMyJNH&+>qDi5W*=qPk6kB7Ev z++OR8FB{(!eDm-Hj!W=?_d=#2lFD+)vnW67`ymB0=2TY8CoS#>K`k6BkGL)AE^$*; zl`LbHdZNtuxQ3YsA)eO69z|Y69qyK{8WwFe>U5cioynXNbSE-Xy%y5F{(uvz2s32Q z=0ozPPe-M%s;)$ambndSOd{h89CONMK=0ICG!^1^EPuhuN_Ry`^$bX6Qbd!hLvu32q#6&}qt@Au?LX&|3n~1TU}|ULNgCyqnU`xD zQ!?kgp!rk`W2~Kpx?C~`FX*sBl|nb%9H`t<>6%tjdi#v(%Fvv|lQ^?b*kb371@Qmm zhbq~OWF3v4WBa#w{I&cr+Pg&l&zyyKX&~h23vf?(R#{T^qdkYhfXW$j(4$Pp^FPcm zw&u)as)sYhF_{i;00~`Z30mroQ?$$nYrayGoO|fBPoYi8 zGQu(4O#ghLW}5Zw8PL(6_4OO8?g;Z08j}yYO*3A;Il*Z=;rTwpGIsaPKCZY=RqrBabI&$Mdm8p!#Vb2Zi#6QtVbDI@ z5+>8o+AR%uFrz>6xqA#LX(Jzh>P`hdj+U0A<%^kiYaUr)hBLfdo*W}i6p8HwjIsI4 zfH?&7;|##rFnQ=E6R;cREBHnNZid+#t34jT889!v=LgIUovZM17r6-LP56oc7sG7B z$3wF;)12~^j|`a9>rqS^m{($36HSlJ1M@L_^8qh|`8>V|;AWV7XXHM>`(U1nD-lhA z`JzW27=9A42j&}4&-5bTHkkj!*9@4d7p}m!2_UtS*WqgeOtW$TUIhYN1@o1Y5H{du znDr+EfN(d#yka2EWdZiU)S>3XO+3tlQ1mgB6#!~29>q5j@G_WJ48k0f^f3Q;2GS0A z1v-i1pDTpx4 ztA^sGAiza1ue$*J11^U7K8B8twEy{QKVy)*OYu2ucPJ)+W0%AN4+gRl~LE(6TN%{yY==Xp;!UwnFr0YgNGQ8~y$6S&j z^IDFih)6wt$fCJ5+n zfUXu$mvVgpt%9V>b(+wc-e$g>hPp0uXgDAl$8P}1^gf_)4=LQB<4n4T`^q-RVf!1}WTNg{xM$djQFJ&qG@${f-1A{ZciZ#BBg1ag)%-N!%1b((hJ4SBl(t zuD|KJ8jy6|u5h~)j&A|UP)-0O=_V=MO$xUZkPP_;w4u_+K|s>SS7=Koig@opODbLO z1SDPWQ@95eZk56{E8IM^ywYzSAnErUw8Rp30U(KcMd4moxQ`U>3xx}##g={}fTZ6w zfF=n}N1+XuDT)G;xR(@e16pF03_)SD%`Y8lY>i#$bK0wa{-cEJ)of1 z6!e{fZaCL$3GX=140(}){-&T;6=XxdBqh-YNb>TCf?iP22Y`Gcl_M}%mULbP9Z-<- zeA9J_f*w`SdFc71-~AVvoIZWA3B3(S^3pKEq$_lqEz$(=e68T13Ut>Ah_`QZ1mspw zrhUABVwhK0l-00Bv@U&N)0JDhm}>Z@E)kqtUjBk?AleCtX2fY2GPZsm%i zG;qj10~)4WvlVWnf^wDXXod4Ah%z9#@+%yrOL9=8Tqi5s6b0R^T#FTMx`JjZ*9wKJ zQczI2&QrMg3aV4C^$HhJ(0$6aN#Pz+(4)%r358pxpeL2pZ`%9Z0^=_6A?90yCu8K!WY97;Nl^`vXA!i`ptN4av;EPePD z6i}{33da$(q?@8#Z&tWs1x;73GZn5vK~>5%sBrTXG+(*aDO|mRBFgnXg=t)6|Px9>y_&!g?m#$ZOZjsh1;Q^kCf}tHU0@r zXr&M;^}}F9{OmS2bkiwx5^yGLoL34O;gXHNoLwd`8Zd5*2NRg7z%(ae?gA#Gm!v^( z_;D7JorHNDn4%;M>oRAc3|abG158^IhP9Hj(FDzx^krbsh~vl9ab}v}a1bz@pC)`| z1H)Nr0^CL%q0>k%MIm1n0b_2tCZUVEPG^biIHfAM8NC_GjFr4`&FlPe8`ELSqAuyZ; zCorRd;aoU@xe6G!+lsjn7|x3mG`9o8*>M7M7ciV7ConoNoGB+Tzb6Kxmjs40JsyN} zuzc~^Y_9{uqi_k#hrsaITLSYfFg)>=z&PNUv+qR6rvt+SS_vAC3V3`cff)k~=jqZ{ zss>BW-(L`1nScJ*G+0`+0SbQXb>IyDEkCO!KvY%8KXm~n|EyXrQB^_H4oR7pOa$8v zNGX4e;aD0hryDe+lM&S@j9GIRrC{z$!SF7+{F%P~l!U?FTxr#vR+`i|l&DWO^|h#H zlEPsKTT(FXDVV(}m~>{j_?aBKQZQ$xV1}h&u1LWYq+qC9HxU=MC$Yz2#SosEM1%an zdllVjYLaNeuys?t$ql5br4=Q!M!s+)m3fN2M?5%Gf*qub zux%2&C`XW6U9r6+okj|$nv%I?Q$yHlnmR&0xFitW?SdfZ5=&q;NzdWPh{ek%78;42 zUJ@*^B8|5Ht{&x)=~b`FNUPX!OL$gK z%ShLwzRkl8IZOE6pW#6S7FX_RS*%BW*M}QQ78-8LSghTi*!lIxd%C^!^S}BY&oQ2` zvA!)+RZ>#}Wv`_dU2^I0k$EB!0wuf(WNrd^r$IPMilZRBQ&En}7L-a~t=isA1fXay zkwR*X{gM%aP8Or}p&d)5k`Fso$SSLu54{y&%WC*k)8;c|tEQy947-{l(8PO0@&OB<6WYqWh|vL%Svyb+D!`K*Q7M^t0Gi0)7Izz E0yqeAMF0Q* diff --git a/cdeps/win/png.h b/cdeps/win/png.h deleted file mode 100755 index 9e9b46c0..00000000 --- a/cdeps/win/png.h +++ /dev/null @@ -1,2309 +0,0 @@ - -/* png.h - header file for PNG reference library - * - * libpng version 1.5.2 - March 31, 2011 - * Copyright (c) 1998-2011 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This code is released under the libpng license (See LICENSE, below) - * - * Authors and maintainers: - * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat - * libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger - * libpng versions 0.97, January 1998, through 1.5.2 - March 31, 2011: Glenn - * See also "Contributing Authors", below. - * - * Note about libpng version numbers: - * - * Due to various miscommunications, unforeseen code incompatibilities - * and occasional factors outside the authors' control, version numbering - * on the library has not always been consistent and straightforward. - * The following table summarizes matters since version 0.89c, which was - * the first widely used release: - * - * source png.h png.h shared-lib - * version string int version - * ------- ------ ----- ---------- - * 0.89c "1.0 beta 3" 0.89 89 1.0.89 - * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90] - * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95] - * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96] - * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97] - * 0.97c 0.97 97 2.0.97 - * 0.98 0.98 98 2.0.98 - * 0.99 0.99 98 2.0.99 - * 0.99a-m 0.99 99 2.0.99 - * 1.00 1.00 100 2.1.0 [100 should be 10000] - * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000] - * 1.0.1 png.h string is 10001 2.1.0 - * 1.0.1a-e identical to the 10002 from here on, the shared library - * 1.0.2 source version) 10002 is 2.V where V is the source code - * 1.0.2a-b 10003 version, except as noted. - * 1.0.3 10003 - * 1.0.3a-d 10004 - * 1.0.4 10004 - * 1.0.4a-f 10005 - * 1.0.5 (+ 2 patches) 10005 - * 1.0.5a-d 10006 - * 1.0.5e-r 10100 (not source compatible) - * 1.0.5s-v 10006 (not binary compatible) - * 1.0.6 (+ 3 patches) 10006 (still binary incompatible) - * 1.0.6d-f 10007 (still binary incompatible) - * 1.0.6g 10007 - * 1.0.6h 10007 10.6h (testing xy.z so-numbering) - * 1.0.6i 10007 10.6i - * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0) - * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible) - * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible) - * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) - * 1.0.7 1 10007 (still compatible) - * 1.0.8beta1-4 1 10008 2.1.0.8beta1-4 - * 1.0.8rc1 1 10008 2.1.0.8rc1 - * 1.0.8 1 10008 2.1.0.8 - * 1.0.9beta1-6 1 10009 2.1.0.9beta1-6 - * 1.0.9rc1 1 10009 2.1.0.9rc1 - * 1.0.9beta7-10 1 10009 2.1.0.9beta7-10 - * 1.0.9rc2 1 10009 2.1.0.9rc2 - * 1.0.9 1 10009 2.1.0.9 - * 1.0.10beta1 1 10010 2.1.0.10beta1 - * 1.0.10rc1 1 10010 2.1.0.10rc1 - * 1.0.10 1 10010 2.1.0.10 - * 1.0.11beta1-3 1 10011 2.1.0.11beta1-3 - * 1.0.11rc1 1 10011 2.1.0.11rc1 - * 1.0.11 1 10011 2.1.0.11 - * 1.0.12beta1-2 2 10012 2.1.0.12beta1-2 - * 1.0.12rc1 2 10012 2.1.0.12rc1 - * 1.0.12 2 10012 2.1.0.12 - * 1.1.0a-f - 10100 2.1.1.0a-f (branch abandoned) - * 1.2.0beta1-2 2 10200 2.1.2.0beta1-2 - * 1.2.0beta3-5 3 10200 3.1.2.0beta3-5 - * 1.2.0rc1 3 10200 3.1.2.0rc1 - * 1.2.0 3 10200 3.1.2.0 - * 1.2.1beta1-4 3 10201 3.1.2.1beta1-4 - * 1.2.1rc1-2 3 10201 3.1.2.1rc1-2 - * 1.2.1 3 10201 3.1.2.1 - * 1.2.2beta1-6 12 10202 12.so.0.1.2.2beta1-6 - * 1.0.13beta1 10 10013 10.so.0.1.0.13beta1 - * 1.0.13rc1 10 10013 10.so.0.1.0.13rc1 - * 1.2.2rc1 12 10202 12.so.0.1.2.2rc1 - * 1.0.13 10 10013 10.so.0.1.0.13 - * 1.2.2 12 10202 12.so.0.1.2.2 - * 1.2.3rc1-6 12 10203 12.so.0.1.2.3rc1-6 - * 1.2.3 12 10203 12.so.0.1.2.3 - * 1.2.4beta1-3 13 10204 12.so.0.1.2.4beta1-3 - * 1.0.14rc1 13 10014 10.so.0.1.0.14rc1 - * 1.2.4rc1 13 10204 12.so.0.1.2.4rc1 - * 1.0.14 10 10014 10.so.0.1.0.14 - * 1.2.4 13 10204 12.so.0.1.2.4 - * 1.2.5beta1-2 13 10205 12.so.0.1.2.5beta1-2 - * 1.0.15rc1-3 10 10015 10.so.0.1.0.15rc1-3 - * 1.2.5rc1-3 13 10205 12.so.0.1.2.5rc1-3 - * 1.0.15 10 10015 10.so.0.1.0.15 - * 1.2.5 13 10205 12.so.0.1.2.5 - * 1.2.6beta1-4 13 10206 12.so.0.1.2.6beta1-4 - * 1.0.16 10 10016 10.so.0.1.0.16 - * 1.2.6 13 10206 12.so.0.1.2.6 - * 1.2.7beta1-2 13 10207 12.so.0.1.2.7beta1-2 - * 1.0.17rc1 10 10017 12.so.0.1.0.17rc1 - * 1.2.7rc1 13 10207 12.so.0.1.2.7rc1 - * 1.0.17 10 10017 12.so.0.1.0.17 - * 1.2.7 13 10207 12.so.0.1.2.7 - * 1.2.8beta1-5 13 10208 12.so.0.1.2.8beta1-5 - * 1.0.18rc1-5 10 10018 12.so.0.1.0.18rc1-5 - * 1.2.8rc1-5 13 10208 12.so.0.1.2.8rc1-5 - * 1.0.18 10 10018 12.so.0.1.0.18 - * 1.2.8 13 10208 12.so.0.1.2.8 - * 1.2.9beta1-3 13 10209 12.so.0.1.2.9beta1-3 - * 1.2.9beta4-11 13 10209 12.so.0.9[.0] - * 1.2.9rc1 13 10209 12.so.0.9[.0] - * 1.2.9 13 10209 12.so.0.9[.0] - * 1.2.10beta1-7 13 10210 12.so.0.10[.0] - * 1.2.10rc1-2 13 10210 12.so.0.10[.0] - * 1.2.10 13 10210 12.so.0.10[.0] - * 1.4.0beta1-5 14 10400 14.so.0.0[.0] - * 1.2.11beta1-4 13 10211 12.so.0.11[.0] - * 1.4.0beta7-8 14 10400 14.so.0.0[.0] - * 1.2.11 13 10211 12.so.0.11[.0] - * 1.2.12 13 10212 12.so.0.12[.0] - * 1.4.0beta9-14 14 10400 14.so.0.0[.0] - * 1.2.13 13 10213 12.so.0.13[.0] - * 1.4.0beta15-36 14 10400 14.so.0.0[.0] - * 1.4.0beta37-87 14 10400 14.so.14.0[.0] - * 1.4.0rc01 14 10400 14.so.14.0[.0] - * 1.4.0beta88-109 14 10400 14.so.14.0[.0] - * 1.4.0rc02-08 14 10400 14.so.14.0[.0] - * 1.4.0 14 10400 14.so.14.0[.0] - * 1.4.1beta01-03 14 10401 14.so.14.1[.0] - * 1.4.1rc01 14 10401 14.so.14.1[.0] - * 1.4.1beta04-12 14 10401 14.so.14.1[.0] - * 1.4.1 14 10401 14.so.14.1[.0] - * 1.4.2 14 10402 14.so.14.2[.0] - * 1.4.3 14 10403 14.so.14.3[.0] - * 1.4.4 14 10404 14.so.14.4[.0] - * 1.5.0beta01-58 15 10500 15.so.15.0[.0] - * 1.5.0rc01-07 15 10500 15.so.15.0[.0] - * 1.5.0 15 10500 15.so.15.0[.0] - * 1.5.1beta01-11 15 10501 15.so.15.1[.0] - * 1.5.1rc01-02 15 10501 15.so.15.1[.0] - * 1.5.1 15 10501 15.so.15.1[.0] - * 1.5.2beta01-03 15 10502 15.so.15.2[.0] - * 1.5.2rc01-03 15 10502 15.so.15.2[.0] - * 1.5.2 15 10502 15.so.15.2[.0] - * - * Henceforth the source version will match the shared-library major - * and minor numbers; the shared-library major version number will be - * used for changes in backward compatibility, as it is intended. The - * PNG_LIBPNG_VER macro, which is not used within libpng but is available - * for applications, is an unsigned integer of the form xyyzz corresponding - * to the source version x.y.z (leading zeros in y and z). Beta versions - * were given the previous public release number plus a letter, until - * version 1.0.6j; from then on they were given the upcoming public - * release number plus "betaNN" or "rcN". - * - * Binary incompatibility exists only when applications make direct access - * to the info_ptr or png_ptr members through png.h, and the compiled - * application is loaded with a different version of the library. - * - * DLLNUM will change each time there are forward or backward changes - * in binary compatibility (e.g., when a new feature is added). - * - * See libpng-manual.txt or libpng.3 for more information. The PNG - * specification is available as a W3C Recommendation and as an ISO - * Specification, -# endif - - /* Need the time information for converting tIME chunks, it - * defines struct tm: - */ -# ifdef PNG_CONVERT_tIME_SUPPORTED - /* "time.h" functions are not supported on all operating systems */ -# include -# endif -# endif - -/* Machine specific configuration. */ -# include "pngconf.h" -#endif - -/* - * Added at libpng-1.2.8 - * - * Ref MSDN: Private as priority over Special - * VS_FF_PRIVATEBUILD File *was not* built using standard release - * procedures. If this value is given, the StringFileInfo block must - * contain a PrivateBuild string. - * - * VS_FF_SPECIALBUILD File *was* built by the original company using - * standard release procedures but is a variation of the standard - * file of the same version number. If this value is given, the - * StringFileInfo block must contain a SpecialBuild string. - */ - -#ifdef PNG_USER_PRIVATEBUILD /* From pnglibconf.h */ -# define PNG_LIBPNG_BUILD_TYPE \ - (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_PRIVATE) -#else -# ifdef PNG_LIBPNG_SPECIALBUILD -# define PNG_LIBPNG_BUILD_TYPE \ - (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_SPECIAL) -# else -# define PNG_LIBPNG_BUILD_TYPE (PNG_LIBPNG_BUILD_BASE_TYPE) -# endif -#endif - -#ifndef PNG_VERSION_INFO_ONLY - -/* Inhibit C++ name-mangling for libpng functions but not for system calls. */ -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/* Version information for C files, stored in png.c. This had better match - * the version above. - */ -#define png_libpng_ver png_get_header_ver(NULL) - -/* This file is arranged in several sections: - * - * 1. Any configuration options that can be specified by for the application - * code when it is built. (Build time configuration is in pnglibconf.h) - * 2. Type definitions (base types are defined in pngconf.h), structure - * definitions. - * 3. Exported library functions. - * - * The library source code has additional files (principally pngpriv.h) that - * allow configuration of the library. - */ -/* Section 1: run time configuration - * See pnglibconf.h for build time configuration - * - * Run time configuration allows the application to choose between - * implementations of certain arithmetic APIs. The default is set - * at build time and recorded in pnglibconf.h, but it is safe to - * override these (and only these) settings. Note that this won't - * change what the library does, only application code, and the - * settings can (and probably should) be made on a per-file basis - * by setting the #defines before including png.h - * - * Use macros to read integers from PNG data or use the exported - * functions? - * PNG_USE_READ_MACROS: use the macros (see below) Note that - * the macros evaluate their argument multiple times. - * PNG_NO_USE_READ_MACROS: call the relevant library function. - * - * Use the alternative algorithm for compositing alpha samples that - * does not use division? - * PNG_READ_COMPOSITE_NODIV_SUPPORTED: use the 'no division' - * algorithm. - * PNG_NO_READ_COMPOSITE_NODIV: use the 'division' algorithm. - * - * How to handle benign errors if PNG_ALLOW_BENIGN_ERRORS is - * false? - * PNG_ALLOW_BENIGN_ERRORS: map calls to the benign error - * APIs to png_warning. - * Otherwise the calls are mapped to png_error. - */ - -/* Section 2: type definitions, including structures and compile time - * constants. - * See pngconf.h for base types that vary by machine/system - */ - -/* This triggers a compiler error in png.c, if png.c and png.h - * do not agree upon the version number. - */ -typedef char* png_libpng_version_1_5_2; - -/* Three color definitions. The order of the red, green, and blue, (and the - * exact size) is not important, although the size of the fields need to - * be png_byte or png_uint_16 (as defined below). - */ -typedef struct png_color_struct -{ - png_byte red; - png_byte green; - png_byte blue; -} png_color; -typedef png_color FAR * png_colorp; -typedef PNG_CONST png_color FAR * png_const_colorp; -typedef png_color FAR * FAR * png_colorpp; - -typedef struct png_color_16_struct -{ - png_byte index; /* used for palette files */ - png_uint_16 red; /* for use in red green blue files */ - png_uint_16 green; - png_uint_16 blue; - png_uint_16 gray; /* for use in grayscale files */ -} png_color_16; -typedef png_color_16 FAR * png_color_16p; -typedef PNG_CONST png_color_16 FAR * png_const_color_16p; -typedef png_color_16 FAR * FAR * png_color_16pp; - -typedef struct png_color_8_struct -{ - png_byte red; /* for use in red green blue files */ - png_byte green; - png_byte blue; - png_byte gray; /* for use in grayscale files */ - png_byte alpha; /* for alpha channel files */ -} png_color_8; -typedef png_color_8 FAR * png_color_8p; -typedef PNG_CONST png_color_8 FAR * png_const_color_8p; -typedef png_color_8 FAR * FAR * png_color_8pp; - -/* - * The following two structures are used for the in-core representation - * of sPLT chunks. - */ -typedef struct png_sPLT_entry_struct -{ - png_uint_16 red; - png_uint_16 green; - png_uint_16 blue; - png_uint_16 alpha; - png_uint_16 frequency; -} png_sPLT_entry; -typedef png_sPLT_entry FAR * png_sPLT_entryp; -typedef PNG_CONST png_sPLT_entry FAR * png_const_sPLT_entryp; -typedef png_sPLT_entry FAR * FAR * png_sPLT_entrypp; - -/* When the depth of the sPLT palette is 8 bits, the color and alpha samples - * occupy the LSB of their respective members, and the MSB of each member - * is zero-filled. The frequency member always occupies the full 16 bits. - */ - -typedef struct png_sPLT_struct -{ - png_charp name; /* palette name */ - png_byte depth; /* depth of palette samples */ - png_sPLT_entryp entries; /* palette entries */ - png_int_32 nentries; /* number of palette entries */ -} png_sPLT_t; -typedef png_sPLT_t FAR * png_sPLT_tp; -typedef PNG_CONST png_sPLT_t FAR * png_const_sPLT_tp; -typedef png_sPLT_t FAR * FAR * png_sPLT_tpp; - -#ifdef PNG_TEXT_SUPPORTED -/* png_text holds the contents of a text/ztxt/itxt chunk in a PNG file, - * and whether that contents is compressed or not. The "key" field - * points to a regular zero-terminated C string. The "text", "lang", and - * "lang_key" fields can be regular C strings, empty strings, or NULL pointers. - * However, the * structure returned by png_get_text() will always contain - * regular zero-terminated C strings (possibly empty), never NULL pointers, - * so they can be safely used in printf() and other string-handling functions. - */ -typedef struct png_text_struct -{ - int compression; /* compression value: - -1: tEXt, none - 0: zTXt, deflate - 1: iTXt, none - 2: iTXt, deflate */ - png_charp key; /* keyword, 1-79 character description of "text" */ - png_charp text; /* comment, may be an empty string (ie "") - or a NULL pointer */ - png_size_t text_length; /* length of the text string */ - png_size_t itxt_length; /* length of the itxt string */ - png_charp lang; /* language code, 0-79 characters - or a NULL pointer */ - png_charp lang_key; /* keyword translated UTF-8 string, 0 or more - chars or a NULL pointer */ -} png_text; -typedef png_text FAR * png_textp; -typedef PNG_CONST png_text FAR * png_const_textp; -typedef png_text FAR * FAR * png_textpp; -#endif - -/* Supported compression types for text in PNG files (tEXt, and zTXt). - * The values of the PNG_TEXT_COMPRESSION_ defines should NOT be changed. */ -#define PNG_TEXT_COMPRESSION_NONE_WR -3 -#define PNG_TEXT_COMPRESSION_zTXt_WR -2 -#define PNG_TEXT_COMPRESSION_NONE -1 -#define PNG_TEXT_COMPRESSION_zTXt 0 -#define PNG_ITXT_COMPRESSION_NONE 1 -#define PNG_ITXT_COMPRESSION_zTXt 2 -#define PNG_TEXT_COMPRESSION_LAST 3 /* Not a valid value */ - -/* png_time is a way to hold the time in an machine independent way. - * Two conversions are provided, both from time_t and struct tm. There - * is no portable way to convert to either of these structures, as far - * as I know. If you know of a portable way, send it to me. As a side - * note - PNG has always been Year 2000 compliant! - */ -typedef struct png_time_struct -{ - png_uint_16 year; /* full year, as in, 1995 */ - png_byte month; /* month of year, 1 - 12 */ - png_byte day; /* day of month, 1 - 31 */ - png_byte hour; /* hour of day, 0 - 23 */ - png_byte minute; /* minute of hour, 0 - 59 */ - png_byte second; /* second of minute, 0 - 60 (for leap seconds) */ -} png_time; -typedef png_time FAR * png_timep; -typedef PNG_CONST png_time FAR * png_const_timep; -typedef png_time FAR * FAR * png_timepp; - -#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) || \ - defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED) -/* png_unknown_chunk is a structure to hold queued chunks for which there is - * no specific support. The idea is that we can use this to queue - * up private chunks for output even though the library doesn't actually - * know about their semantics. - */ -typedef struct png_unknown_chunk_t -{ - png_byte name[5]; - png_byte *data; - png_size_t size; - - /* libpng-using applications should NOT directly modify this byte. */ - png_byte location; /* mode of operation at read time */ -} -png_unknown_chunk; -typedef png_unknown_chunk FAR * png_unknown_chunkp; -typedef PNG_CONST png_unknown_chunk FAR * png_const_unknown_chunkp; -typedef png_unknown_chunk FAR * FAR * png_unknown_chunkpp; -#endif - -typedef struct png_info_def png_info; -typedef png_info FAR * png_infop; -typedef PNG_CONST png_info FAR * png_const_infop; -typedef png_info FAR * FAR * png_infopp; - -/* Maximum positive integer used in PNG is (2^31)-1 */ -#define PNG_UINT_31_MAX ((png_uint_32)0x7fffffffL) -#define PNG_UINT_32_MAX ((png_uint_32)(-1)) -#define PNG_SIZE_MAX ((png_size_t)(-1)) - -/* These are constants for fixed point values encoded in the - * PNG specification manner (x100000) - */ -#define PNG_FP_1 100000 -#define PNG_FP_HALF 50000 - -/* These describe the color_type field in png_info. */ -/* color type masks */ -#define PNG_COLOR_MASK_PALETTE 1 -#define PNG_COLOR_MASK_COLOR 2 -#define PNG_COLOR_MASK_ALPHA 4 - -/* color types. Note that not all combinations are legal */ -#define PNG_COLOR_TYPE_GRAY 0 -#define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE) -#define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR) -#define PNG_COLOR_TYPE_RGB_ALPHA (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA) -#define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA) -/* aliases */ -#define PNG_COLOR_TYPE_RGBA PNG_COLOR_TYPE_RGB_ALPHA -#define PNG_COLOR_TYPE_GA PNG_COLOR_TYPE_GRAY_ALPHA - -/* This is for compression type. PNG 1.0-1.2 only define the single type. */ -#define PNG_COMPRESSION_TYPE_BASE 0 /* Deflate method 8, 32K window */ -#define PNG_COMPRESSION_TYPE_DEFAULT PNG_COMPRESSION_TYPE_BASE - -/* This is for filter type. PNG 1.0-1.2 only define the single type. */ -#define PNG_FILTER_TYPE_BASE 0 /* Single row per-byte filtering */ -#define PNG_INTRAPIXEL_DIFFERENCING 64 /* Used only in MNG datastreams */ -#define PNG_FILTER_TYPE_DEFAULT PNG_FILTER_TYPE_BASE - -/* These are for the interlacing type. These values should NOT be changed. */ -#define PNG_INTERLACE_NONE 0 /* Non-interlaced image */ -#define PNG_INTERLACE_ADAM7 1 /* Adam7 interlacing */ -#define PNG_INTERLACE_LAST 2 /* Not a valid value */ - -/* These are for the oFFs chunk. These values should NOT be changed. */ -#define PNG_OFFSET_PIXEL 0 /* Offset in pixels */ -#define PNG_OFFSET_MICROMETER 1 /* Offset in micrometers (1/10^6 meter) */ -#define PNG_OFFSET_LAST 2 /* Not a valid value */ - -/* These are for the pCAL chunk. These values should NOT be changed. */ -#define PNG_EQUATION_LINEAR 0 /* Linear transformation */ -#define PNG_EQUATION_BASE_E 1 /* Exponential base e transform */ -#define PNG_EQUATION_ARBITRARY 2 /* Arbitrary base exponential transform */ -#define PNG_EQUATION_HYPERBOLIC 3 /* Hyperbolic sine transformation */ -#define PNG_EQUATION_LAST 4 /* Not a valid value */ - -/* These are for the sCAL chunk. These values should NOT be changed. */ -#define PNG_SCALE_UNKNOWN 0 /* unknown unit (image scale) */ -#define PNG_SCALE_METER 1 /* meters per pixel */ -#define PNG_SCALE_RADIAN 2 /* radians per pixel */ -#define PNG_SCALE_LAST 3 /* Not a valid value */ - -/* These are for the pHYs chunk. These values should NOT be changed. */ -#define PNG_RESOLUTION_UNKNOWN 0 /* pixels/unknown unit (aspect ratio) */ -#define PNG_RESOLUTION_METER 1 /* pixels/meter */ -#define PNG_RESOLUTION_LAST 2 /* Not a valid value */ - -/* These are for the sRGB chunk. These values should NOT be changed. */ -#define PNG_sRGB_INTENT_PERCEPTUAL 0 -#define PNG_sRGB_INTENT_RELATIVE 1 -#define PNG_sRGB_INTENT_SATURATION 2 -#define PNG_sRGB_INTENT_ABSOLUTE 3 -#define PNG_sRGB_INTENT_LAST 4 /* Not a valid value */ - -/* This is for text chunks */ -#define PNG_KEYWORD_MAX_LENGTH 79 - -/* Maximum number of entries in PLTE/sPLT/tRNS arrays */ -#define PNG_MAX_PALETTE_LENGTH 256 - -/* These determine if an ancillary chunk's data has been successfully read - * from the PNG header, or if the application has filled in the corresponding - * data in the info_struct to be written into the output file. The values - * of the PNG_INFO_ defines should NOT be changed. - */ -#define PNG_INFO_gAMA 0x0001 -#define PNG_INFO_sBIT 0x0002 -#define PNG_INFO_cHRM 0x0004 -#define PNG_INFO_PLTE 0x0008 -#define PNG_INFO_tRNS 0x0010 -#define PNG_INFO_bKGD 0x0020 -#define PNG_INFO_hIST 0x0040 -#define PNG_INFO_pHYs 0x0080 -#define PNG_INFO_oFFs 0x0100 -#define PNG_INFO_tIME 0x0200 -#define PNG_INFO_pCAL 0x0400 -#define PNG_INFO_sRGB 0x0800 /* GR-P, 0.96a */ -#define PNG_INFO_iCCP 0x1000 /* ESR, 1.0.6 */ -#define PNG_INFO_sPLT 0x2000 /* ESR, 1.0.6 */ -#define PNG_INFO_sCAL 0x4000 /* ESR, 1.0.6 */ -#define PNG_INFO_IDAT 0x8000L /* ESR, 1.0.6 */ - -/* This is used for the transformation routines, as some of them - * change these values for the row. It also should enable using - * the routines for other purposes. - */ -typedef struct png_row_info_struct -{ - png_uint_32 width; /* width of row */ - png_size_t rowbytes; /* number of bytes in row */ - png_byte color_type; /* color type of row */ - png_byte bit_depth; /* bit depth of row */ - png_byte channels; /* number of channels (1, 2, 3, or 4) */ - png_byte pixel_depth; /* bits per pixel (depth * channels) */ -} png_row_info; - -typedef png_row_info FAR * png_row_infop; -typedef png_row_info FAR * FAR * png_row_infopp; - -/* These are the function types for the I/O functions and for the functions - * that allow the user to override the default I/O functions with his or her - * own. The png_error_ptr type should match that of user-supplied warning - * and error functions, while the png_rw_ptr type should match that of the - * user read/write data functions. Note that the 'write' function must not - * modify the buffer it is passed. The 'read' function, on the other hand, is - * expected to return the read data in the buffer. - */ -typedef struct png_struct_def png_struct; -typedef PNG_CONST png_struct FAR * png_const_structp; -typedef png_struct FAR * png_structp; - -typedef PNG_CALLBACK(void, *png_error_ptr, (png_structp, png_const_charp)); -typedef PNG_CALLBACK(void, *png_rw_ptr, (png_structp, png_bytep, png_size_t)); -typedef PNG_CALLBACK(void, *png_flush_ptr, (png_structp)); -typedef PNG_CALLBACK(void, *png_read_status_ptr, (png_structp, png_uint_32, - int)); -typedef PNG_CALLBACK(void, *png_write_status_ptr, (png_structp, png_uint_32, - int)); - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop)); -typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop)); - -/* The following callback receives png_uint_32 row_number, int pass for the - * png_bytep data of the row. When transforming an interlaced image the - * row number is the row number within the sub-image of the interlace pass, so - * the value will increase to the height of the sub-image (not the full image) - * then reset to 0 for the next pass. - * - * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to - * find the output pixel (x,y) given an interlaced sub-image pixel - * (row,col,pass). (See below for these macros.) - */ -typedef PNG_CALLBACK(void, *png_progressive_row_ptr, (png_structp, png_bytep, - png_uint_32, int)); -#endif - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) -typedef PNG_CALLBACK(void, *png_user_transform_ptr, (png_structp, png_row_infop, - png_bytep)); -#endif - -#ifdef PNG_USER_CHUNKS_SUPPORTED -typedef PNG_CALLBACK(int, *png_user_chunk_ptr, (png_structp, - png_unknown_chunkp)); -#endif -#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED -typedef PNG_CALLBACK(void, *png_unknown_chunk_ptr, (png_structp)); -#endif - -#ifdef PNG_SETJMP_SUPPORTED -/* This must match the function definition in , and the - * application must include this before png.h to obtain the definition - * of jmp_buf. The function is required to be PNG_NORETURN. (Note that - * PNG_PTR_NORETURN is used here because current versions of the Microsoft - * C compiler do not support the PNG_NORETURN attribute on a pointer.) - * - * If you get a type warning from the compiler when linking against this line - * then your compiler has 'longjmp' that does not match the requirements of the - * compiler that built libpng. You will have to write a wrapper function for - * your compiler's longjmp and call png_set_longjmp_fn directly (not via the - * png_jmpbuf macro.) - * - * If you get a warning here while building the library you will need to make - * changes to ensure that pnglibconf.h records the calling convention used by - * your compiler. This may be very difficult - try using a different compiler - * to build the library! - */ -typedef PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), - PNG_PTR_NORETURN); -#endif - -/* Transform masks for the high-level interface */ -#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */ -#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */ -#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */ -#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */ -#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */ -#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */ -#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */ -#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */ -#define PNG_TRANSFORM_BGR 0x0080 /* read and write */ -#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */ -#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */ -#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */ -#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* write only */ -/* Added to libpng-1.2.34 */ -#define PNG_TRANSFORM_STRIP_FILLER_BEFORE PNG_TRANSFORM_STRIP_FILLER -#define PNG_TRANSFORM_STRIP_FILLER_AFTER 0x1000 /* write only */ -/* Added to libpng-1.4.0 */ -#define PNG_TRANSFORM_GRAY_TO_RGB 0x2000 /* read only */ - -/* Flags for MNG supported features */ -#define PNG_FLAG_MNG_EMPTY_PLTE 0x01 -#define PNG_FLAG_MNG_FILTER_64 0x04 -#define PNG_ALL_MNG_FEATURES 0x05 - -/* NOTE: prior to 1.5 these functions had no 'API' style declaration, - * this allowed the zlib default functions to be used on Windows - * platforms. In 1.5 the zlib default malloc (which just calls malloc and - * ignores the first argument) should be completely compatible with the - * following. - */ -typedef PNG_CALLBACK(png_voidp, *png_malloc_ptr, (png_structp, - png_alloc_size_t)); -typedef PNG_CALLBACK(void, *png_free_ptr, (png_structp, png_voidp)); - -typedef png_struct FAR * FAR * png_structpp; - -/* Section 3: exported functions - * Here are the function definitions most commonly used. This is not - * the place to find out how to use libpng. See libpng-manual.txt for the - * full explanation, see example.c for the summary. This just provides - * a simple one line description of the use of each function. - * - * The PNG_EXPORT() and PNG_EXPORTA() macros used below are defined in - * pngconf.h and in the *.dfn files in the scripts directory. - * - * PNG_EXPORT(ordinal, type, name, (args)); - * - * ordinal: ordinal that is used while building - * *.def files. The ordinal value is only - * relevant when preprocessing png.h with - * the *.dfn files for building symbol table - * entries, and are removed by pngconf.h. - * type: return type of the function - * name: function name - * args: function arguments, with types - * - * When we wish to append attributes to a function prototype we use - * the PNG_EXPORTA() macro instead. - * - * PNG_EXPORTA(ordinal, type, name, (args), attributes); - * - * ordinal, type, name, and args: same as in PNG_EXPORT(). - * attributes: function attributes - */ - -/* Returns the version number of the library */ -PNG_EXPORT(1, png_uint_32, png_access_version_number, (void)); - -/* Tell lib we have already handled the first magic bytes. - * Handling more than 8 bytes from the beginning of the file is an error. - */ -PNG_EXPORT(2, void, png_set_sig_bytes, (png_structp png_ptr, int num_bytes)); - -/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a - * PNG file. Returns zero if the supplied bytes match the 8-byte PNG - * signature, and non-zero otherwise. Having num_to_check == 0 or - * start > 7 will always fail (ie return non-zero). - */ -PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, png_size_t start, - png_size_t num_to_check)); - -/* Simple signature checking function. This is the same as calling - * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). - */ -#define png_check_sig(sig, n) !png_sig_cmp((sig), 0, (n)) - -/* Allocate and initialize png_ptr struct for reading, and any other memory. */ -PNG_EXPORTA(4, png_structp, png_create_read_struct, - (png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn), - PNG_ALLOCATED); - -/* Allocate and initialize png_ptr struct for writing, and any other memory */ -PNG_EXPORTA(5, png_structp, png_create_write_struct, - (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, - png_error_ptr warn_fn), - PNG_ALLOCATED); - -PNG_EXPORT(6, png_size_t, png_get_compression_buffer_size, - (png_const_structp png_ptr)); - -PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structp png_ptr, - png_size_t size)); - -/* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp - * match up. - */ -#ifdef PNG_SETJMP_SUPPORTED -/* This function returns the jmp_buf built in to *png_ptr. It must be - * supplied with an appropriate 'longjmp' function to use on that jmp_buf - * unless the default error function is overridden in which case NULL is - * acceptable. The size of the jmp_buf is checked against the actual size - * allocated by the library - the call will return NULL on a mismatch - * indicating an ABI mismatch. - */ -PNG_EXPORT(8, jmp_buf*, png_set_longjmp_fn, (png_structp png_ptr, - png_longjmp_ptr longjmp_fn, size_t jmp_buf_size)); -# define png_jmpbuf(png_ptr) \ - (*png_set_longjmp_fn((png_ptr), longjmp, sizeof (jmp_buf))) -#else -# define png_jmpbuf(png_ptr) \ - (LIBPNG_WAS_COMPILED_WITH__PNG_NO_SETJMP) -#endif -/* This function should be used by libpng applications in place of - * longjmp(png_ptr->jmpbuf, val). If longjmp_fn() has been set, it - * will use it; otherwise it will call PNG_ABORT(). This function was - * added in libpng-1.5.0. - */ -PNG_EXPORTA(9, void, png_longjmp, (png_structp png_ptr, int val), - PNG_NORETURN); - -#ifdef PNG_READ_SUPPORTED -/* Reset the compression stream */ -PNG_EXPORT(10, int, png_reset_zstream, (png_structp png_ptr)); -#endif - -/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ -#ifdef PNG_USER_MEM_SUPPORTED -PNG_EXPORTA(11, png_structp, png_create_read_struct_2, - (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, - png_error_ptr warn_fn, - png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), - PNG_ALLOCATED); -PNG_EXPORTA(12, png_structp, png_create_write_struct_2, - (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, - png_error_ptr warn_fn, - png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), - PNG_ALLOCATED); -#endif - -/* Write the PNG file signature. */ -PNG_EXPORT(13, void, png_write_sig, (png_structp png_ptr)); - -/* Write a PNG chunk - size, type, (optional) data, CRC. */ -PNG_EXPORT(14, void, png_write_chunk, (png_structp png_ptr, png_const_bytep - chunk_name, png_const_bytep data, png_size_t length)); - -/* Write the start of a PNG chunk - length and chunk name. */ -PNG_EXPORT(15, void, png_write_chunk_start, (png_structp png_ptr, - png_const_bytep chunk_name, png_uint_32 length)); - -/* Write the data of a PNG chunk started with png_write_chunk_start(). */ -PNG_EXPORT(16, void, png_write_chunk_data, (png_structp png_ptr, - png_const_bytep data, png_size_t length)); - -/* Finish a chunk started with png_write_chunk_start() (includes CRC). */ -PNG_EXPORT(17, void, png_write_chunk_end, (png_structp png_ptr)); - -/* Allocate and initialize the info structure */ -PNG_EXPORTA(18, png_infop, png_create_info_struct, (png_structp png_ptr), - PNG_ALLOCATED); - -PNG_EXPORT(19, void, png_info_init_3, (png_infopp info_ptr, - png_size_t png_info_struct_size)); - -/* Writes all the PNG information before the image. */ -PNG_EXPORT(20, void, png_write_info_before_PLTE, - (png_structp png_ptr, png_infop info_ptr)); -PNG_EXPORT(21, void, png_write_info, - (png_structp png_ptr, png_infop info_ptr)); - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read the information before the actual image data. */ -PNG_EXPORT(22, void, png_read_info, - (png_structp png_ptr, png_infop info_ptr)); -#endif - -#ifdef PNG_TIME_RFC1123_SUPPORTED -PNG_EXPORT(23, png_const_charp, png_convert_to_rfc1123, - (png_structp png_ptr, - png_const_timep ptime)); -#endif - -#ifdef PNG_CONVERT_tIME_SUPPORTED -/* Convert from a struct tm to png_time */ -PNG_EXPORT(24, void, png_convert_from_struct_tm, (png_timep ptime, - PNG_CONST struct tm FAR * ttime)); - -/* Convert from time_t to png_time. Uses gmtime() */ -PNG_EXPORT(25, void, png_convert_from_time_t, - (png_timep ptime, time_t ttime)); -#endif /* PNG_CONVERT_tIME_SUPPORTED */ - -#ifdef PNG_READ_EXPAND_SUPPORTED -/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */ -PNG_EXPORT(26, void, png_set_expand, (png_structp png_ptr)); -PNG_EXPORT(27, void, png_set_expand_gray_1_2_4_to_8, (png_structp png_ptr)); -PNG_EXPORT(28, void, png_set_palette_to_rgb, (png_structp png_ptr)); -PNG_EXPORT(29, void, png_set_tRNS_to_alpha, (png_structp png_ptr)); -#endif - -#ifdef PNG_READ_EXPAND_16_SUPPORTED -/* Expand to 16 bit channels, forces conversion of palette to RGB and expansion - * of a tRNS chunk if present. - */ -PNG_EXPORT(221, void, png_set_expand_16, (png_structp png_ptr)); -#endif - -#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) -/* Use blue, green, red order for pixels. */ -PNG_EXPORT(30, void, png_set_bgr, (png_structp png_ptr)); -#endif - -#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED -/* Expand the grayscale to 24-bit RGB if necessary. */ -PNG_EXPORT(31, void, png_set_gray_to_rgb, (png_structp png_ptr)); -#endif - -#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED -/* Reduce RGB to grayscale. */ -PNG_FP_EXPORT(32, void, png_set_rgb_to_gray, (png_structp png_ptr, - int error_action, double red, double green)); -PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed, (png_structp png_ptr, - int error_action, png_fixed_point red, png_fixed_point green)); - -PNG_EXPORT(34, png_byte, png_get_rgb_to_gray_status, (png_const_structp - png_ptr)); -#endif - -PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth, - png_colorp palette)); - -#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED -PNG_EXPORT(36, void, png_set_strip_alpha, (png_structp png_ptr)); -#endif - -#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ - defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) -PNG_EXPORT(37, void, png_set_swap_alpha, (png_structp png_ptr)); -#endif - -#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ - defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) -PNG_EXPORT(38, void, png_set_invert_alpha, (png_structp png_ptr)); -#endif - -#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) -/* Add a filler byte to 8-bit Gray or 24-bit RGB images. */ -PNG_EXPORT(39, void, png_set_filler, (png_structp png_ptr, png_uint_32 filler, - int flags)); -/* The values of the PNG_FILLER_ defines should NOT be changed */ -# define PNG_FILLER_BEFORE 0 -# define PNG_FILLER_AFTER 1 -/* Add an alpha byte to 8-bit Gray or 24-bit RGB images. */ -PNG_EXPORT(40, void, png_set_add_alpha, - (png_structp png_ptr, png_uint_32 filler, - int flags)); -#endif /* PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED */ - -#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) -/* Swap bytes in 16-bit depth files. */ -PNG_EXPORT(41, void, png_set_swap, (png_structp png_ptr)); -#endif - -#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) -/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */ -PNG_EXPORT(42, void, png_set_packing, (png_structp png_ptr)); -#endif - -#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ - defined(PNG_WRITE_PACKSWAP_SUPPORTED) -/* Swap packing order of pixels in bytes. */ -PNG_EXPORT(43, void, png_set_packswap, (png_structp png_ptr)); -#endif - -#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) -/* Converts files to legal bit depths. */ -PNG_EXPORT(44, void, png_set_shift, (png_structp png_ptr, png_const_color_8p - true_bits)); -#endif - -#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ - defined(PNG_WRITE_INTERLACING_SUPPORTED) -/* Have the code handle the interlacing. Returns the number of passes. - * MUST be called before png_read_update_info or png_start_read_image, - * otherwise it will not have the desired effect. Note that it is still - * necessary to call png_read_row or png_read_rows png_get_image_height - * times for each pass. -*/ -PNG_EXPORT(45, int, png_set_interlace_handling, (png_structp png_ptr)); -#endif - -#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) -/* Invert monochrome files */ -PNG_EXPORT(46, void, png_set_invert_mono, (png_structp png_ptr)); -#endif - -#ifdef PNG_READ_BACKGROUND_SUPPORTED -/* Handle alpha and tRNS by replacing with a background color. */ -PNG_FP_EXPORT(47, void, png_set_background, (png_structp png_ptr, - png_const_color_16p background_color, int background_gamma_code, - int need_expand, double background_gamma)); -PNG_FIXED_EXPORT(215, void, png_set_background_fixed, (png_structp png_ptr, - png_const_color_16p background_color, int background_gamma_code, - int need_expand, png_fixed_point background_gamma)); -#endif -#ifdef PNG_READ_BACKGROUND_SUPPORTED -# define PNG_BACKGROUND_GAMMA_UNKNOWN 0 -# define PNG_BACKGROUND_GAMMA_SCREEN 1 -# define PNG_BACKGROUND_GAMMA_FILE 2 -# define PNG_BACKGROUND_GAMMA_UNIQUE 3 -#endif - -#ifdef PNG_READ_16_TO_8_SUPPORTED -/* Strip the second byte of information from a 16-bit depth file. */ -PNG_EXPORT(48, void, png_set_strip_16, (png_structp png_ptr)); -#endif - -#ifdef PNG_READ_QUANTIZE_SUPPORTED -/* Turn on quantizing, and reduce the palette to the number of colors - * available. - */ -PNG_EXPORT(49, void, png_set_quantize, - (png_structp png_ptr, png_colorp palette, - int num_palette, int maximum_colors, png_const_uint_16p histogram, - int full_quantize)); -#endif - -#ifdef PNG_READ_GAMMA_SUPPORTED -/* The threshold on gamma processing is configurable but hard-wired into the - * library. The following is the floating point variant. - */ -#define PNG_GAMMA_THRESHOLD (PNG_GAMMA_THRESHOLD_FIXED*.00001) - -/* Handle gamma correction. Screen_gamma=(display_exponent) */ -PNG_FP_EXPORT(50, void, png_set_gamma, - (png_structp png_ptr, double screen_gamma, - double default_file_gamma)); -PNG_FIXED_EXPORT(208, void, png_set_gamma_fixed, (png_structp png_ptr, - png_fixed_point screen_gamma, png_fixed_point default_file_gamma)); -#endif - -#ifdef PNG_WRITE_FLUSH_SUPPORTED -/* Set how many lines between output flushes - 0 for no flushing */ -PNG_EXPORT(51, void, png_set_flush, (png_structp png_ptr, int nrows)); -/* Flush the current PNG output buffer */ -PNG_EXPORT(52, void, png_write_flush, (png_structp png_ptr)); -#endif - -/* Optional update palette with requested transformations */ -PNG_EXPORT(53, void, png_start_read_image, (png_structp png_ptr)); - -/* Optional call to update the users info structure */ -PNG_EXPORT(54, void, png_read_update_info, - (png_structp png_ptr, png_infop info_ptr)); - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read one or more rows of image data. */ -PNG_EXPORT(55, void, png_read_rows, (png_structp png_ptr, png_bytepp row, - png_bytepp display_row, png_uint_32 num_rows)); -#endif - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read a row of data. */ -PNG_EXPORT(56, void, png_read_row, (png_structp png_ptr, png_bytep row, - png_bytep display_row)); -#endif - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read the whole image into memory at once. */ -PNG_EXPORT(57, void, png_read_image, (png_structp png_ptr, png_bytepp image)); -#endif - -/* Write a row of image data */ -PNG_EXPORT(58, void, png_write_row, - (png_structp png_ptr, png_const_bytep row)); - -/* Write a few rows of image data: (*row) is not written; however, the type - * is declared as writeable to maintain compatibility with previous versions - * of libpng and to allow the 'display_row' array from read_rows to be passed - * unchanged to write_rows. - */ -PNG_EXPORT(59, void, png_write_rows, (png_structp png_ptr, png_bytepp row, - png_uint_32 num_rows)); - -/* Write the image data */ -PNG_EXPORT(60, void, png_write_image, - (png_structp png_ptr, png_bytepp image)); - -/* Write the end of the PNG file. */ -PNG_EXPORT(61, void, png_write_end, - (png_structp png_ptr, png_infop info_ptr)); - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read the end of the PNG file. */ -PNG_EXPORT(62, void, png_read_end, (png_structp png_ptr, png_infop info_ptr)); -#endif - -/* Free any memory associated with the png_info_struct */ -PNG_EXPORT(63, void, png_destroy_info_struct, (png_structp png_ptr, - png_infopp info_ptr_ptr)); - -/* Free any memory associated with the png_struct and the png_info_structs */ -PNG_EXPORT(64, void, png_destroy_read_struct, (png_structpp png_ptr_ptr, - png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); - -/* Free any memory associated with the png_struct and the png_info_structs */ -PNG_EXPORT(65, void, png_destroy_write_struct, (png_structpp png_ptr_ptr, - png_infopp info_ptr_ptr)); - -/* Set the libpng method of handling chunk CRC errors */ -PNG_EXPORT(66, void, png_set_crc_action, - (png_structp png_ptr, int crit_action, int ancil_action)); - -/* Values for png_set_crc_action() say how to handle CRC errors in - * ancillary and critical chunks, and whether to use the data contained - * therein. Note that it is impossible to "discard" data in a critical - * chunk. For versions prior to 0.90, the action was always error/quit, - * whereas in version 0.90 and later, the action for CRC errors in ancillary - * chunks is warn/discard. These values should NOT be changed. - * - * value action:critical action:ancillary - */ -#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */ -#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */ -#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */ -#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */ -#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */ -#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */ - -/* These functions give the user control over the scan-line filtering in - * libpng and the compression methods used by zlib. These functions are - * mainly useful for testing, as the defaults should work with most users. - * Those users who are tight on memory or want faster performance at the - * expense of compression can modify them. See the compression library - * header file (zlib.h) for an explination of the compression functions. - */ - -/* Set the filtering method(s) used by libpng. Currently, the only valid - * value for "method" is 0. - */ -PNG_EXPORT(67, void, png_set_filter, - (png_structp png_ptr, int method, int filters)); - -/* Flags for png_set_filter() to say which filters to use. The flags - * are chosen so that they don't conflict with real filter types - * below, in case they are supplied instead of the #defined constants. - * These values should NOT be changed. - */ -#define PNG_NO_FILTERS 0x00 -#define PNG_FILTER_NONE 0x08 -#define PNG_FILTER_SUB 0x10 -#define PNG_FILTER_UP 0x20 -#define PNG_FILTER_AVG 0x40 -#define PNG_FILTER_PAETH 0x80 -#define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \ - PNG_FILTER_AVG | PNG_FILTER_PAETH) - -/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now. - * These defines should NOT be changed. - */ -#define PNG_FILTER_VALUE_NONE 0 -#define PNG_FILTER_VALUE_SUB 1 -#define PNG_FILTER_VALUE_UP 2 -#define PNG_FILTER_VALUE_AVG 3 -#define PNG_FILTER_VALUE_PAETH 4 -#define PNG_FILTER_VALUE_LAST 5 - -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* EXPERIMENTAL */ -/* The "heuristic_method" is given by one of the PNG_FILTER_HEURISTIC_ - * defines, either the default (minimum-sum-of-absolute-differences), or - * the experimental method (weighted-minimum-sum-of-absolute-differences). - * - * Weights are factors >= 1.0, indicating how important it is to keep the - * filter type consistent between rows. Larger numbers mean the current - * filter is that many times as likely to be the same as the "num_weights" - * previous filters. This is cumulative for each previous row with a weight. - * There needs to be "num_weights" values in "filter_weights", or it can be - * NULL if the weights aren't being specified. Weights have no influence on - * the selection of the first row filter. Well chosen weights can (in theory) - * improve the compression for a given image. - * - * Costs are factors >= 1.0 indicating the relative decoding costs of a - * filter type. Higher costs indicate more decoding expense, and are - * therefore less likely to be selected over a filter with lower computational - * costs. There needs to be a value in "filter_costs" for each valid filter - * type (given by PNG_FILTER_VALUE_LAST), or it can be NULL if you aren't - * setting the costs. Costs try to improve the speed of decompression without - * unduly increasing the compressed image size. - * - * A negative weight or cost indicates the default value is to be used, and - * values in the range [0.0, 1.0) indicate the value is to remain unchanged. - * The default values for both weights and costs are currently 1.0, but may - * change if good general weighting/cost heuristics can be found. If both - * the weights and costs are set to 1.0, this degenerates the WEIGHTED method - * to the UNWEIGHTED method, but with added encoding time/computation. - */ -PNG_FP_EXPORT(68, void, png_set_filter_heuristics, (png_structp png_ptr, - int heuristic_method, int num_weights, png_const_doublep filter_weights, - png_const_doublep filter_costs)); -PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed, - (png_structp png_ptr, - int heuristic_method, int num_weights, png_const_fixed_point_p - filter_weights, png_const_fixed_point_p filter_costs)); -#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ - -/* Heuristic used for row filter selection. These defines should NOT be - * changed. - */ -#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */ -#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */ -#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ -#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ - -/* Set the library compression level. Currently, valid values range from - * 0 - 9, corresponding directly to the zlib compression levels 0 - 9 - * (0 - no compression, 9 - "maximal" compression). Note that tests have - * shown that zlib compression levels 3-6 usually perform as well as level 9 - * for PNG images, and do considerably fewer caclulations. In the future, - * these values may not correspond directly to the zlib compression levels. - */ -PNG_EXPORT(69, void, png_set_compression_level, - (png_structp png_ptr, int level)); - -PNG_EXPORT(70, void, png_set_compression_mem_level, (png_structp png_ptr, - int mem_level)); - -PNG_EXPORT(71, void, png_set_compression_strategy, (png_structp png_ptr, - int strategy)); - -PNG_EXPORT(72, void, png_set_compression_window_bits, (png_structp png_ptr, - int window_bits)); - -PNG_EXPORT(73, void, png_set_compression_method, (png_structp png_ptr, - int method)); - -/* These next functions are called for input/output, memory, and error - * handling. They are in the file pngrio.c, pngwio.c, and pngerror.c, - * and call standard C I/O routines such as fread(), fwrite(), and - * fprintf(). These functions can be made to use other I/O routines - * at run time for those applications that need to handle I/O in a - * different manner by calling png_set_???_fn(). See libpng-manual.txt for - * more information. - */ - -#ifdef PNG_STDIO_SUPPORTED -/* Initialize the input/output for the PNG file to the default functions. */ -PNG_EXPORT(74, void, png_init_io, (png_structp png_ptr, png_FILE_p fp)); -#endif - -/* Replace the (error and abort), and warning functions with user - * supplied functions. If no messages are to be printed you must still - * write and use replacement functions. The replacement error_fn should - * still do a longjmp to the last setjmp location if you are using this - * method of error handling. If error_fn or warning_fn is NULL, the - * default function will be used. - */ - -PNG_EXPORT(75, void, png_set_error_fn, - (png_structp png_ptr, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warning_fn)); - -/* Return the user pointer associated with the error functions */ -PNG_EXPORT(76, png_voidp, png_get_error_ptr, (png_const_structp png_ptr)); - -/* Replace the default data output functions with a user supplied one(s). - * If buffered output is not used, then output_flush_fn can be set to NULL. - * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time - * output_flush_fn will be ignored (and thus can be NULL). - * It is probably a mistake to use NULL for output_flush_fn if - * write_data_fn is not also NULL unless you have built libpng with - * PNG_WRITE_FLUSH_SUPPORTED undefined, because in this case libpng's - * default flush function, which uses the standard *FILE structure, will - * be used. - */ -PNG_EXPORT(77, void, png_set_write_fn, (png_structp png_ptr, png_voidp io_ptr, - png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)); - -/* Replace the default data input function with a user supplied one. */ -PNG_EXPORT(78, void, png_set_read_fn, (png_structp png_ptr, png_voidp io_ptr, - png_rw_ptr read_data_fn)); - -/* Return the user pointer associated with the I/O functions */ -PNG_EXPORT(79, png_voidp, png_get_io_ptr, (png_structp png_ptr)); - -PNG_EXPORT(80, void, png_set_read_status_fn, (png_structp png_ptr, - png_read_status_ptr read_row_fn)); - -PNG_EXPORT(81, void, png_set_write_status_fn, (png_structp png_ptr, - png_write_status_ptr write_row_fn)); - -#ifdef PNG_USER_MEM_SUPPORTED -/* Replace the default memory allocation functions with user supplied one(s). */ -PNG_EXPORT(82, void, png_set_mem_fn, (png_structp png_ptr, png_voidp mem_ptr, - png_malloc_ptr malloc_fn, png_free_ptr free_fn)); -/* Return the user pointer associated with the memory functions */ -PNG_EXPORT(83, png_voidp, png_get_mem_ptr, (png_const_structp png_ptr)); -#endif - -#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED -PNG_EXPORT(84, void, png_set_read_user_transform_fn, (png_structp png_ptr, - png_user_transform_ptr read_user_transform_fn)); -#endif - -#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED -PNG_EXPORT(85, void, png_set_write_user_transform_fn, (png_structp png_ptr, - png_user_transform_ptr write_user_transform_fn)); -#endif - -#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED -PNG_EXPORT(86, void, png_set_user_transform_info, (png_structp png_ptr, - png_voidp user_transform_ptr, int user_transform_depth, - int user_transform_channels)); -/* Return the user pointer associated with the user transform functions */ -PNG_EXPORT(87, png_voidp, png_get_user_transform_ptr, - (png_const_structp png_ptr)); -#endif - -#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED -/* Return information about the row currently being processed. Note that these - * APIs do not fail but will return unexpected results if called outside a user - * transform callback. Also note that when transforming an interlaced image the - * row number is the row number within the sub-image of the interlace pass, so - * the value will increase to the height of the sub-image (not the full image) - * then reset to 0 for the next pass. - * - * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to - * find the output pixel (x,y) given an interlaced sub-image pixel - * (row,col,pass). (See below for these macros.) - */ -PNG_EXPORT(217, png_uint_32, png_get_current_row_number, (png_const_structp)); -PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structp)); -#endif - -#ifdef PNG_USER_CHUNKS_SUPPORTED -PNG_EXPORT(88, void, png_set_read_user_chunk_fn, (png_structp png_ptr, - png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); -PNG_EXPORT(89, png_voidp, png_get_user_chunk_ptr, (png_const_structp png_ptr)); -#endif - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -/* Sets the function callbacks for the push reader, and a pointer to a - * user-defined structure available to the callback functions. - */ -PNG_EXPORT(90, void, png_set_progressive_read_fn, (png_structp png_ptr, - png_voidp progressive_ptr, png_progressive_info_ptr info_fn, - png_progressive_row_ptr row_fn, png_progressive_end_ptr end_fn)); - -/* Returns the user pointer associated with the push read functions */ -PNG_EXPORT(91, png_voidp, png_get_progressive_ptr, (png_const_structp png_ptr)); - -/* Function to be called when data becomes available */ -PNG_EXPORT(92, void, png_process_data, - (png_structp png_ptr, png_infop info_ptr, - png_bytep buffer, png_size_t buffer_size)); - -/* A function which may be called *only* within png_process_data to stop the - * processing of any more data. The function returns the number of bytes - * remaining, excluding any that libpng has cached internally. A subsequent - * call to png_process_data must supply these bytes again. If the argument - * 'save' is set to true the routine will first save all the pending data and - * will always return 0. - */ -PNG_EXPORT(219, png_size_t, png_process_data_pause, (png_structp, int save)); - -/* A function which may be called *only* outside (after) a call to - * png_process_data. It returns the number of bytes of data to skip in the - * input. Normally it will return 0, but if it returns a non-zero value the - * application must skip than number of bytes of input data and pass the - * following data to the next call to png_process_data. - */ -PNG_EXPORT(220, png_uint_32, png_process_data_skip, (png_structp)); - -/* Function that combines rows. 'new_row' is a flag that should come from - * the callback and be non-NULL if anything needs to be done; the library - * stores its own version of the new data internally and ignores the passed - * in value. - */ -PNG_EXPORT(93, void, png_progressive_combine_row, (png_structp png_ptr, - png_bytep old_row, png_const_bytep new_row)); -#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ - -PNG_EXPORTA(94, png_voidp, png_malloc, - (png_structp png_ptr, png_alloc_size_t size), - PNG_ALLOCATED); -/* Added at libpng version 1.4.0 */ -PNG_EXPORTA(95, png_voidp, png_calloc, - (png_structp png_ptr, png_alloc_size_t size), - PNG_ALLOCATED); - -/* Added at libpng version 1.2.4 */ -PNG_EXPORTA(96, png_voidp, png_malloc_warn, (png_structp png_ptr, - png_alloc_size_t size), PNG_ALLOCATED); - -/* Frees a pointer allocated by png_malloc() */ -PNG_EXPORT(97, void, png_free, (png_structp png_ptr, png_voidp ptr)); - -/* Free data that was allocated internally */ -PNG_EXPORT(98, void, png_free_data, - (png_structp png_ptr, png_infop info_ptr, png_uint_32 free_me, int num)); - -/* Reassign responsibility for freeing existing data, whether allocated - * by libpng or by the application */ -PNG_EXPORT(99, void, png_data_freer, - (png_structp png_ptr, png_infop info_ptr, int freer, png_uint_32 mask)); - -/* Assignments for png_data_freer */ -#define PNG_DESTROY_WILL_FREE_DATA 1 -#define PNG_SET_WILL_FREE_DATA 1 -#define PNG_USER_WILL_FREE_DATA 2 -/* Flags for png_ptr->free_me and info_ptr->free_me */ -#define PNG_FREE_HIST 0x0008 -#define PNG_FREE_ICCP 0x0010 -#define PNG_FREE_SPLT 0x0020 -#define PNG_FREE_ROWS 0x0040 -#define PNG_FREE_PCAL 0x0080 -#define PNG_FREE_SCAL 0x0100 -#define PNG_FREE_UNKN 0x0200 -#define PNG_FREE_LIST 0x0400 -#define PNG_FREE_PLTE 0x1000 -#define PNG_FREE_TRNS 0x2000 -#define PNG_FREE_TEXT 0x4000 -#define PNG_FREE_ALL 0x7fff -#define PNG_FREE_MUL 0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ - -#ifdef PNG_USER_MEM_SUPPORTED -PNG_EXPORTA(100, png_voidp, png_malloc_default, (png_structp png_ptr, - png_alloc_size_t size), PNG_ALLOCATED); -PNG_EXPORT(101, void, png_free_default, (png_structp png_ptr, png_voidp ptr)); -#endif - -#ifdef PNG_ERROR_TEXT_SUPPORTED -/* Fatal error in PNG image of libpng - can't continue */ -PNG_EXPORTA(102, void, png_error, - (png_structp png_ptr, png_const_charp error_message), - PNG_NORETURN); - -/* The same, but the chunk name is prepended to the error string. */ -PNG_EXPORTA(103, void, png_chunk_error, (png_structp png_ptr, - png_const_charp error_message), PNG_NORETURN); - -#else -/* Fatal error in PNG image of libpng - can't continue */ -PNG_EXPORTA(104, void, png_err, (png_structp png_ptr), PNG_NORETURN); -#endif - -/* Non-fatal error in libpng. Can continue, but may have a problem. */ -PNG_EXPORT(105, void, png_warning, (png_structp png_ptr, - png_const_charp warning_message)); - -/* Non-fatal error in libpng, chunk name is prepended to message. */ -PNG_EXPORT(106, void, png_chunk_warning, (png_structp png_ptr, - png_const_charp warning_message)); - -#ifdef PNG_BENIGN_ERRORS_SUPPORTED -/* Benign error in libpng. Can continue, but may have a problem. - * User can choose whether to handle as a fatal error or as a warning. */ -# undef png_benign_error -PNG_EXPORT(107, void, png_benign_error, (png_structp png_ptr, - png_const_charp warning_message)); - -/* Same, chunk name is prepended to message. */ -# undef png_chunk_benign_error -PNG_EXPORT(108, void, png_chunk_benign_error, (png_structp png_ptr, - png_const_charp warning_message)); - -PNG_EXPORT(109, void, png_set_benign_errors, - (png_structp png_ptr, int allowed)); -#else -# ifdef PNG_ALLOW_BENIGN_ERRORS -# define png_benign_error png_warning -# define png_chunk_benign_error png_chunk_warning -# else -# define png_benign_error png_error -# define png_chunk_benign_error png_chunk_error -# endif -#endif - -/* The png_set_ functions are for storing values in the png_info_struct. - * Similarly, the png_get_ calls are used to read values from the - * png_info_struct, either storing the parameters in the passed variables, or - * setting pointers into the png_info_struct where the data is stored. The - * png_get_ functions return a non-zero value if the data was available - * in info_ptr, or return zero and do not change any of the parameters if the - * data was not available. - * - * These functions should be used instead of directly accessing png_info - * to avoid problems with future changes in the size and internal layout of - * png_info_struct. - */ -/* Returns "flag" if chunk data is valid in info_ptr. */ -PNG_EXPORT(110, png_uint_32, png_get_valid, - (png_const_structp png_ptr, png_const_infop info_ptr, - png_uint_32 flag)); - -/* Returns number of bytes needed to hold a transformed row. */ -PNG_EXPORT(111, png_size_t, png_get_rowbytes, (png_const_structp png_ptr, - png_const_infop info_ptr)); - -#ifdef PNG_INFO_IMAGE_SUPPORTED -/* Returns row_pointers, which is an array of pointers to scanlines that was - * returned from png_read_png(). - */ -PNG_EXPORT(112, png_bytepp, png_get_rows, - (png_const_structp png_ptr, png_const_infop info_ptr)); -/* Set row_pointers, which is an array of pointers to scanlines for use - * by png_write_png(). - */ -PNG_EXPORT(113, void, png_set_rows, (png_structp png_ptr, - png_infop info_ptr, png_bytepp row_pointers)); -#endif - -/* Returns number of color channels in image. */ -PNG_EXPORT(114, png_byte, png_get_channels, - (png_const_structp png_ptr, png_const_infop info_ptr)); - -#ifdef PNG_EASY_ACCESS_SUPPORTED -/* Returns image width in pixels. */ -PNG_EXPORT(115, png_uint_32, png_get_image_width, (png_const_structp png_ptr, - png_const_infop info_ptr)); - -/* Returns image height in pixels. */ -PNG_EXPORT(116, png_uint_32, png_get_image_height, (png_const_structp png_ptr, - png_const_infop info_ptr)); - -/* Returns image bit_depth. */ -PNG_EXPORT(117, png_byte, png_get_bit_depth, - (png_const_structp png_ptr, png_const_infop info_ptr)); - -/* Returns image color_type. */ -PNG_EXPORT(118, png_byte, png_get_color_type, (png_const_structp png_ptr, - png_const_infop info_ptr)); - -/* Returns image filter_type. */ -PNG_EXPORT(119, png_byte, png_get_filter_type, (png_const_structp png_ptr, - png_const_infop info_ptr)); - -/* Returns image interlace_type. */ -PNG_EXPORT(120, png_byte, png_get_interlace_type, (png_const_structp png_ptr, - png_const_infop info_ptr)); - -/* Returns image compression_type. */ -PNG_EXPORT(121, png_byte, png_get_compression_type, (png_const_structp png_ptr, - png_const_infop info_ptr)); - -/* Returns image resolution in pixels per meter, from pHYs chunk data. */ -PNG_EXPORT(122, png_uint_32, png_get_pixels_per_meter, - (png_const_structp png_ptr, png_const_infop info_ptr)); -PNG_EXPORT(123, png_uint_32, png_get_x_pixels_per_meter, - (png_const_structp png_ptr, png_const_infop info_ptr)); -PNG_EXPORT(124, png_uint_32, png_get_y_pixels_per_meter, - (png_const_structp png_ptr, png_const_infop info_ptr)); - -/* Returns pixel aspect ratio, computed from pHYs chunk data. */ -PNG_FP_EXPORT(125, float, png_get_pixel_aspect_ratio, - (png_const_structp png_ptr, png_const_infop info_ptr)); -PNG_FIXED_EXPORT(210, png_fixed_point, png_get_pixel_aspect_ratio_fixed, - (png_const_structp png_ptr, png_const_infop info_ptr)); - -/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ -PNG_EXPORT(126, png_int_32, png_get_x_offset_pixels, - (png_const_structp png_ptr, png_const_infop info_ptr)); -PNG_EXPORT(127, png_int_32, png_get_y_offset_pixels, - (png_const_structp png_ptr, png_const_infop info_ptr)); -PNG_EXPORT(128, png_int_32, png_get_x_offset_microns, - (png_const_structp png_ptr, png_const_infop info_ptr)); -PNG_EXPORT(129, png_int_32, png_get_y_offset_microns, - (png_const_structp png_ptr, png_const_infop info_ptr)); - -#endif /* PNG_EASY_ACCESS_SUPPORTED */ - -/* Returns pointer to signature string read from PNG header */ -PNG_EXPORT(130, png_const_bytep, png_get_signature, - (png_const_structp png_ptr, png_infop info_ptr)); - -#ifdef PNG_bKGD_SUPPORTED -PNG_EXPORT(131, png_uint_32, png_get_bKGD, - (png_const_structp png_ptr, png_infop info_ptr, - png_color_16p *background)); -#endif - -#ifdef PNG_bKGD_SUPPORTED -PNG_EXPORT(132, void, png_set_bKGD, (png_structp png_ptr, png_infop info_ptr, - png_const_color_16p background)); -#endif - -#ifdef PNG_cHRM_SUPPORTED -PNG_FP_EXPORT(133, png_uint_32, png_get_cHRM, (png_const_structp png_ptr, - png_const_infop info_ptr, double *white_x, double *white_y, double *red_x, - double *red_y, double *green_x, double *green_y, double *blue_x, - double *blue_y)); -#ifdef PNG_FIXED_POINT_SUPPORTED /* Otherwise not implemented */ -PNG_FIXED_EXPORT(134, png_uint_32, png_get_cHRM_fixed, - (png_const_structp png_ptr, - png_const_infop info_ptr, png_fixed_point *int_white_x, - png_fixed_point *int_white_y, png_fixed_point *int_red_x, - png_fixed_point *int_red_y, png_fixed_point *int_green_x, - png_fixed_point *int_green_y, png_fixed_point *int_blue_x, - png_fixed_point *int_blue_y)); -#endif -#endif - -#ifdef PNG_cHRM_SUPPORTED -PNG_FP_EXPORT(135, void, png_set_cHRM, - (png_structp png_ptr, png_infop info_ptr, - double white_x, double white_y, double red_x, double red_y, double green_x, - double green_y, double blue_x, double blue_y)); -PNG_FIXED_EXPORT(136, void, png_set_cHRM_fixed, (png_structp png_ptr, - png_infop info_ptr, png_fixed_point int_white_x, - png_fixed_point int_white_y, png_fixed_point int_red_x, - png_fixed_point int_red_y, png_fixed_point int_green_x, - png_fixed_point int_green_y, png_fixed_point int_blue_x, - png_fixed_point int_blue_y)); -#endif - -#ifdef PNG_gAMA_SUPPORTED -PNG_FP_EXPORT(137, png_uint_32, png_get_gAMA, - (png_const_structp png_ptr, png_const_infop info_ptr, - double *file_gamma)); -PNG_FIXED_EXPORT(138, png_uint_32, png_get_gAMA_fixed, - (png_const_structp png_ptr, png_const_infop info_ptr, - png_fixed_point *int_file_gamma)); -#endif - -#ifdef PNG_gAMA_SUPPORTED -PNG_FP_EXPORT(139, void, png_set_gAMA, (png_structp png_ptr, - png_infop info_ptr, double file_gamma)); -PNG_FIXED_EXPORT(140, void, png_set_gAMA_fixed, (png_structp png_ptr, - png_infop info_ptr, png_fixed_point int_file_gamma)); -#endif - -#ifdef PNG_hIST_SUPPORTED -PNG_EXPORT(141, png_uint_32, png_get_hIST, - (png_const_structp png_ptr, png_const_infop info_ptr, - png_uint_16p *hist)); -#endif - -#ifdef PNG_hIST_SUPPORTED -PNG_EXPORT(142, void, png_set_hIST, (png_structp png_ptr, - png_infop info_ptr, png_const_uint_16p hist)); -#endif - -PNG_EXPORT(143, png_uint_32, png_get_IHDR, - (png_structp png_ptr, png_infop info_ptr, - png_uint_32 *width, png_uint_32 *height, int *bit_depth, int *color_type, - int *interlace_method, int *compression_method, int *filter_method)); - -PNG_EXPORT(144, void, png_set_IHDR, - (png_structp png_ptr, png_infop info_ptr, - png_uint_32 width, png_uint_32 height, int bit_depth, int color_type, - int interlace_method, int compression_method, int filter_method)); - -#ifdef PNG_oFFs_SUPPORTED -PNG_EXPORT(145, png_uint_32, png_get_oFFs, - (png_const_structp png_ptr, png_const_infop info_ptr, - png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type)); -#endif - -#ifdef PNG_oFFs_SUPPORTED -PNG_EXPORT(146, void, png_set_oFFs, - (png_structp png_ptr, png_infop info_ptr, - png_int_32 offset_x, png_int_32 offset_y, int unit_type)); -#endif - -#ifdef PNG_pCAL_SUPPORTED -PNG_EXPORT(147, png_uint_32, png_get_pCAL, - (png_const_structp png_ptr, png_const_infop info_ptr, - png_charp *purpose, png_int_32 *X0, png_int_32 *X1, int *type, - int *nparams, - png_charp *units, png_charpp *params)); -#endif - -#ifdef PNG_pCAL_SUPPORTED -PNG_EXPORT(148, void, png_set_pCAL, (png_structp png_ptr, - png_infop info_ptr, - png_const_charp purpose, png_int_32 X0, png_int_32 X1, int type, - int nparams, png_const_charp units, png_charpp params)); -#endif - -#ifdef PNG_pHYs_SUPPORTED -PNG_EXPORT(149, png_uint_32, png_get_pHYs, - (png_const_structp png_ptr, png_const_infop info_ptr, - png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); -#endif - -#ifdef PNG_pHYs_SUPPORTED -PNG_EXPORT(150, void, png_set_pHYs, - (png_structp png_ptr, png_infop info_ptr, - png_uint_32 res_x, png_uint_32 res_y, int unit_type)); -#endif - -PNG_EXPORT(151, png_uint_32, png_get_PLTE, - (png_const_structp png_ptr, png_const_infop info_ptr, - png_colorp *palette, int *num_palette)); - -PNG_EXPORT(152, void, png_set_PLTE, - (png_structp png_ptr, png_infop info_ptr, - png_const_colorp palette, int num_palette)); - -#ifdef PNG_sBIT_SUPPORTED -PNG_EXPORT(153, png_uint_32, png_get_sBIT, - (png_const_structp png_ptr, png_infop info_ptr, - png_color_8p *sig_bit)); -#endif - -#ifdef PNG_sBIT_SUPPORTED -PNG_EXPORT(154, void, png_set_sBIT, - (png_structp png_ptr, png_infop info_ptr, png_const_color_8p sig_bit)); -#endif - -#ifdef PNG_sRGB_SUPPORTED -PNG_EXPORT(155, png_uint_32, png_get_sRGB, (png_const_structp png_ptr, - png_const_infop info_ptr, int *file_srgb_intent)); -#endif - -#ifdef PNG_sRGB_SUPPORTED -PNG_EXPORT(156, void, png_set_sRGB, - (png_structp png_ptr, png_infop info_ptr, int srgb_intent)); -PNG_EXPORT(157, void, png_set_sRGB_gAMA_and_cHRM, (png_structp png_ptr, - png_infop info_ptr, int srgb_intent)); -#endif - -#ifdef PNG_iCCP_SUPPORTED -PNG_EXPORT(158, png_uint_32, png_get_iCCP, - (png_const_structp png_ptr, png_const_infop info_ptr, - png_charpp name, int *compression_type, png_bytepp profile, - png_uint_32 *proflen)); -#endif - -#ifdef PNG_iCCP_SUPPORTED -PNG_EXPORT(159, void, png_set_iCCP, - (png_structp png_ptr, png_infop info_ptr, - png_const_charp name, int compression_type, png_const_bytep profile, - png_uint_32 proflen)); -#endif - -#ifdef PNG_sPLT_SUPPORTED -PNG_EXPORT(160, png_uint_32, png_get_sPLT, - (png_const_structp png_ptr, png_const_infop info_ptr, - png_sPLT_tpp entries)); -#endif - -#ifdef PNG_sPLT_SUPPORTED -PNG_EXPORT(161, void, png_set_sPLT, - (png_structp png_ptr, png_infop info_ptr, - png_const_sPLT_tp entries, int nentries)); -#endif - -#ifdef PNG_TEXT_SUPPORTED -/* png_get_text also returns the number of text chunks in *num_text */ -PNG_EXPORT(162, png_uint_32, png_get_text, - (png_const_structp png_ptr, png_const_infop info_ptr, - png_textp *text_ptr, int *num_text)); -#endif - -/* Note while png_set_text() will accept a structure whose text, - * language, and translated keywords are NULL pointers, the structure - * returned by png_get_text will always contain regular - * zero-terminated C strings. They might be empty strings but - * they will never be NULL pointers. - */ - -#ifdef PNG_TEXT_SUPPORTED -PNG_EXPORT(163, void, png_set_text, - (png_structp png_ptr, png_infop info_ptr, - png_const_textp text_ptr, int num_text)); -#endif - -#ifdef PNG_tIME_SUPPORTED -PNG_EXPORT(164, png_uint_32, png_get_tIME, - (png_const_structp png_ptr, png_infop info_ptr, png_timep *mod_time)); -#endif - -#ifdef PNG_tIME_SUPPORTED -PNG_EXPORT(165, void, png_set_tIME, - (png_structp png_ptr, png_infop info_ptr, png_const_timep mod_time)); -#endif - -#ifdef PNG_tRNS_SUPPORTED -PNG_EXPORT(166, png_uint_32, png_get_tRNS, - (png_const_structp png_ptr, png_infop info_ptr, - png_bytep *trans_alpha, int *num_trans, png_color_16p *trans_color)); -#endif - -#ifdef PNG_tRNS_SUPPORTED -PNG_EXPORT(167, void, png_set_tRNS, - (png_structp png_ptr, png_infop info_ptr, - png_const_bytep trans_alpha, int num_trans, - png_const_color_16p trans_color)); -#endif - -#ifdef PNG_sCAL_SUPPORTED -PNG_FP_EXPORT(168, png_uint_32, png_get_sCAL, - (png_const_structp png_ptr, png_const_infop info_ptr, - int *unit, double *width, double *height)); -#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED -/* NOTE: this API is currently implemented using floating point arithmetic, - * consequently it can only be used on systems with floating point support. - * In any case the range of values supported by png_fixed_point is small and it - * is highly recommended that png_get_sCAL_s be used instead. - */ -PNG_FIXED_EXPORT(214, png_uint_32, png_get_sCAL_fixed, - (png_structp png_ptr, png_const_infop info_ptr, int *unit, - png_fixed_point *width, - png_fixed_point *height)); -#endif -PNG_EXPORT(169, png_uint_32, png_get_sCAL_s, - (png_const_structp png_ptr, png_const_infop info_ptr, - int *unit, png_charpp swidth, png_charpp sheight)); - -PNG_FP_EXPORT(170, void, png_set_sCAL, - (png_structp png_ptr, png_infop info_ptr, - int unit, double width, double height)); -PNG_FIXED_EXPORT(213, void, png_set_sCAL_fixed, (png_structp png_ptr, - png_infop info_ptr, int unit, png_fixed_point width, - png_fixed_point height)); -PNG_EXPORT(171, void, png_set_sCAL_s, - (png_structp png_ptr, png_infop info_ptr, - int unit, png_const_charp swidth, png_const_charp sheight)); -#endif /* PNG_sCAL_SUPPORTED */ - -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED -/* Provide a list of chunks and how they are to be handled, if the built-in - handling or default unknown chunk handling is not desired. Any chunks not - listed will be handled in the default manner. The IHDR and IEND chunks - must not be listed. - keep = 0: follow default behaviour - = 1: do not keep - = 2: keep only if safe-to-copy - = 3: keep even if unsafe-to-copy -*/ -PNG_EXPORT(172, void, png_set_keep_unknown_chunks, - (png_structp png_ptr, int keep, - png_const_bytep chunk_list, int num_chunks)); -PNG_EXPORT(173, int, png_handle_as_unknown, (png_structp png_ptr, - png_const_bytep chunk_name)); -#endif -#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED -PNG_EXPORT(174, void, png_set_unknown_chunks, (png_structp png_ptr, - png_infop info_ptr, png_const_unknown_chunkp unknowns, - int num_unknowns)); -PNG_EXPORT(175, void, png_set_unknown_chunk_location, - (png_structp png_ptr, png_infop info_ptr, int chunk, int location)); -PNG_EXPORT(176, int, png_get_unknown_chunks, (png_const_structp png_ptr, - png_const_infop info_ptr, png_unknown_chunkpp entries)); -#endif - -/* Png_free_data() will turn off the "valid" flag for anything it frees. - * If you need to turn it off for a chunk that your application has freed, - * you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); - */ -PNG_EXPORT(177, void, png_set_invalid, - (png_structp png_ptr, png_infop info_ptr, int mask)); - -#ifdef PNG_INFO_IMAGE_SUPPORTED -/* The "params" pointer is currently not used and is for future expansion. */ -PNG_EXPORT(178, void, png_read_png, (png_structp png_ptr, png_infop info_ptr, - int transforms, png_voidp params)); -PNG_EXPORT(179, void, png_write_png, (png_structp png_ptr, png_infop info_ptr, - int transforms, png_voidp params)); -#endif - -PNG_EXPORT(180, png_const_charp, png_get_copyright, - (png_const_structp png_ptr)); -PNG_EXPORT(181, png_const_charp, png_get_header_ver, - (png_const_structp png_ptr)); -PNG_EXPORT(182, png_const_charp, png_get_header_version, - (png_const_structp png_ptr)); -PNG_EXPORT(183, png_const_charp, png_get_libpng_ver, - (png_const_structp png_ptr)); - -#ifdef PNG_MNG_FEATURES_SUPPORTED -PNG_EXPORT(184, png_uint_32, png_permit_mng_features, (png_structp png_ptr, - png_uint_32 mng_features_permitted)); -#endif - -/* For use in png_set_keep_unknown, added to version 1.2.6 */ -#define PNG_HANDLE_CHUNK_AS_DEFAULT 0 -#define PNG_HANDLE_CHUNK_NEVER 1 -#define PNG_HANDLE_CHUNK_IF_SAFE 2 -#define PNG_HANDLE_CHUNK_ALWAYS 3 - -/* Strip the prepended error numbers ("#nnn ") from error and warning - * messages before passing them to the error or warning handler. - */ -#ifdef PNG_ERROR_NUMBERS_SUPPORTED -PNG_EXPORT(185, void, png_set_strip_error_numbers, - (png_structp png_ptr, - png_uint_32 strip_mode)); -#endif - -/* Added in libpng-1.2.6 */ -#ifdef PNG_SET_USER_LIMITS_SUPPORTED -PNG_EXPORT(186, void, png_set_user_limits, (png_structp png_ptr, - png_uint_32 user_width_max, png_uint_32 user_height_max)); -PNG_EXPORT(187, png_uint_32, png_get_user_width_max, - (png_const_structp png_ptr)); -PNG_EXPORT(188, png_uint_32, png_get_user_height_max, - (png_const_structp png_ptr)); -/* Added in libpng-1.4.0 */ -PNG_EXPORT(189, void, png_set_chunk_cache_max, (png_structp png_ptr, - png_uint_32 user_chunk_cache_max)); -PNG_EXPORT(190, png_uint_32, png_get_chunk_cache_max, - (png_const_structp png_ptr)); -/* Added in libpng-1.4.1 */ -PNG_EXPORT(191, void, png_set_chunk_malloc_max, (png_structp png_ptr, - png_alloc_size_t user_chunk_cache_max)); -PNG_EXPORT(192, png_alloc_size_t, png_get_chunk_malloc_max, - (png_const_structp png_ptr)); -#endif - -#if defined(PNG_INCH_CONVERSIONS_SUPPORTED) -PNG_EXPORT(193, png_uint_32, png_get_pixels_per_inch, - (png_const_structp png_ptr, png_const_infop info_ptr)); - -PNG_EXPORT(194, png_uint_32, png_get_x_pixels_per_inch, - (png_const_structp png_ptr, png_const_infop info_ptr)); - -PNG_EXPORT(195, png_uint_32, png_get_y_pixels_per_inch, - (png_const_structp png_ptr, png_const_infop info_ptr)); - -PNG_FP_EXPORT(196, float, png_get_x_offset_inches, - (png_const_structp png_ptr, png_const_infop info_ptr)); -#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ -PNG_FIXED_EXPORT(211, png_fixed_point, png_get_x_offset_inches_fixed, - (png_structp png_ptr, png_const_infop info_ptr)); -#endif - -PNG_FP_EXPORT(197, float, png_get_y_offset_inches, (png_const_structp png_ptr, - png_const_infop info_ptr)); -#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ -PNG_FIXED_EXPORT(212, png_fixed_point, png_get_y_offset_inches_fixed, - (png_structp png_ptr, png_const_infop info_ptr)); -#endif - -# ifdef PNG_pHYs_SUPPORTED -PNG_EXPORT(198, png_uint_32, png_get_pHYs_dpi, (png_const_structp png_ptr, - png_const_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, - int *unit_type)); -# endif /* PNG_pHYs_SUPPORTED */ -#endif /* PNG_INCH_CONVERSIONS_SUPPORTED */ - -/* Added in libpng-1.4.0 */ -#ifdef PNG_IO_STATE_SUPPORTED -PNG_EXPORT(199, png_uint_32, png_get_io_state, (png_structp png_ptr)); - -PNG_EXPORTA(200, png_const_bytep, png_get_io_chunk_name, - (png_structp png_ptr), PNG_DEPRECATED); -PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type, - (png_const_structp png_ptr)); - -/* The flags returned by png_get_io_state() are the following: */ -# define PNG_IO_NONE 0x0000 /* no I/O at this moment */ -# define PNG_IO_READING 0x0001 /* currently reading */ -# define PNG_IO_WRITING 0x0002 /* currently writing */ -# define PNG_IO_SIGNATURE 0x0010 /* currently at the file signature */ -# define PNG_IO_CHUNK_HDR 0x0020 /* currently at the chunk header */ -# define PNG_IO_CHUNK_DATA 0x0040 /* currently at the chunk data */ -# define PNG_IO_CHUNK_CRC 0x0080 /* currently at the chunk crc */ -# define PNG_IO_MASK_OP 0x000f /* current operation: reading/writing */ -# define PNG_IO_MASK_LOC 0x00f0 /* current location: sig/hdr/data/crc */ -#endif /* ?PNG_IO_STATE_SUPPORTED */ - -/* Interlace support. The following macros are always defined so that if - * libpng interlace handling is turned off the macros may be used to handle - * interlaced images within the application. - */ -#define PNG_INTERLACE_ADAM7_PASSES 7 - -/* Two macros to return the first row and first column of the original, - * full, image which appears in a given pass. 'pass' is in the range 0 - * to 6 and the result is in the range 0 to 7. - */ -#define PNG_PASS_START_ROW(pass) (((1U&~(pass))<<(3-((pass)>>1)))&7) -#define PNG_PASS_START_COL(pass) (((1U& (pass))<<(3-(((pass)+1)>>1)))&7) - -/* Two macros to help evaluate the number of rows or columns in each - * pass. This is expressed as a shift - effectively log2 of the number or - * rows or columns in each 8x8 tile of the original image. - */ -#define PNG_PASS_ROW_SHIFT(pass) ((pass)>2?(8-(pass))>>1:3) -#define PNG_PASS_COL_SHIFT(pass) ((pass)>1?(7-(pass))>>1:3) - -/* Hence two macros to determine the number of rows or columns in a given - * pass of an image given its height or width. In fact these macros may - * return non-zero even though the sub-image is empty, because the other - * dimension may be empty for a small image. - */ -#define PNG_PASS_ROWS(height, pass) (((height)+(((1<>PNG_PASS_ROW_SHIFT(pass)) -#define PNG_PASS_COLS(width, pass) (((width)+(((1<>PNG_PASS_COL_SHIFT(pass)) - -/* For the reader row callbacks (both progressive and sequential) it is - * necessary to find the row in the output image given a row in an interlaced - * image, so two more macros: - */ -#define PNG_ROW_FROM_PASS_ROW(yIn, pass) \ - (((yIn)<>(((7-(off))-(pass))<<2)) & 0xFU) | \ - ((0x01145AF0U>>(((7-(off))-(pass))<<2)) & 0xF0U)) - -#define PNG_ROW_IN_INTERLACE_PASS(y, pass) \ - ((PNG_PASS_MASK(pass,0) >> ((y)&7)) & 1) -#define PNG_COL_IN_INTERLACE_PASS(x, pass) \ - ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1) - -#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED -/* With these routines we avoid an integer divide, which will be slower on - * most machines. However, it does take more operations than the corresponding - * divide method, so it may be slower on a few RISC systems. There are two - * shifts (by 8 or 16 bits) and an addition, versus a single integer divide. - * - * Note that the rounding factors are NOT supposed to be the same! 128 and - * 32768 are correct for the NODIV code; 127 and 32767 are correct for the - * standard method. - * - * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ] - */ - - /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ - -# define png_composite(composite, fg, alpha, bg) \ - { png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) \ - * (png_uint_16)(alpha) \ - + (png_uint_16)(bg)*(png_uint_16)(255 \ - - (png_uint_16)(alpha)) + (png_uint_16)128); \ - (composite) = (png_byte)((temp + (temp >> 8)) >> 8); } - -# define png_composite_16(composite, fg, alpha, bg) \ - { png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) \ - * (png_uint_32)(alpha) \ - + (png_uint_32)(bg)*(png_uint_32)(65535L \ - - (png_uint_32)(alpha)) + (png_uint_32)32768L); \ - (composite) = (png_uint_16)((temp + (temp >> 16)) >> 16); } - -#else /* Standard method using integer division */ - -# define png_composite(composite, fg, alpha, bg) \ - (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) + \ - (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ - (png_uint_16)127) / 255) - -# define png_composite_16(composite, fg, alpha, bg) \ - (composite) = (png_uint_16)(((png_uint_32)(fg) * (png_uint_32)(alpha) + \ - (png_uint_32)(bg)*(png_uint_32)(65535L - (png_uint_32)(alpha)) + \ - (png_uint_32)32767) / (png_uint_32)65535L) -#endif /* PNG_READ_COMPOSITE_NODIV_SUPPORTED */ - -#ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED -PNG_EXPORT(201, png_uint_32, png_get_uint_32, (png_const_bytep buf)); -PNG_EXPORT(202, png_uint_16, png_get_uint_16, (png_const_bytep buf)); -PNG_EXPORT(203, png_int_32, png_get_int_32, (png_const_bytep buf)); -#endif - -PNG_EXPORT(204, png_uint_32, png_get_uint_31, (png_structp png_ptr, - png_const_bytep buf)); -/* No png_get_int_16 -- may be added if there's a real need for it. */ - -/* Place a 32-bit number into a buffer in PNG byte order (big-endian). */ -#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED -PNG_EXPORT(205, void, png_save_uint_32, (png_bytep buf, png_uint_32 i)); -#endif -#ifdef PNG_SAVE_INT_32_SUPPORTED -PNG_EXPORT(206, void, png_save_int_32, (png_bytep buf, png_int_32 i)); -#endif - -/* Place a 16-bit number into a buffer in PNG byte order. - * The parameter is declared unsigned int, not png_uint_16, - * just to avoid potential problems on pre-ANSI C compilers. - */ -#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED -PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i)); -/* No png_save_int_16 -- may be added if there's a real need for it. */ -#endif - -#ifdef PNG_USE_READ_MACROS -/* Inline macros to do direct reads of bytes from the input buffer. - * The png_get_int_32() routine assumes we are using two's complement - * format for negative values, which is almost certainly true. - */ -# define png_get_uint_32(buf) \ - (((png_uint_32)(*(buf)) << 24) + \ - ((png_uint_32)(*((buf) + 1)) << 16) + \ - ((png_uint_32)(*((buf) + 2)) << 8) + \ - ((png_uint_32)(*((buf) + 3)))) - - /* From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the - * function) incorrectly returned a value of type png_uint_32. - */ -# define png_get_uint_16(buf) \ - ((png_uint_16) \ - (((unsigned int)(*(buf)) << 8) + \ - ((unsigned int)(*((buf) + 1))))) - -# define png_get_int_32(buf) \ - ((png_int_32)((*(buf) & 0x80) \ - ? -((png_int_32)((png_get_uint_32(buf) ^ 0xffffffffL) + 1)) \ - : (png_int_32)png_get_uint_32(buf))) -#endif - -/* Maintainer: Put new public prototypes here ^, in libpng.3, and project - * defs - */ - -/* The last ordinal number (this is the *last* one already used; the next - * one to use is one more than this.) Maintainer, remember to add an entry to - * scripts/symbols.def as well. - */ -#ifdef PNG_EXPORT_LAST_ORDINAL - PNG_EXPORT_LAST_ORDINAL(221); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* PNG_VERSION_INFO_ONLY */ -/* Do not put anything past this line */ -#endif /* PNG_H */ diff --git a/cdeps/win/pngconf.h b/cdeps/win/pngconf.h deleted file mode 100755 index 084de8ef..00000000 --- a/cdeps/win/pngconf.h +++ /dev/null @@ -1,649 +0,0 @@ - -/* pngconf.h - machine configurable file for libpng - * - * libpng version 1.5.2 - March 31, 2011 - * - * Copyright (c) 1998-2011 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This code is released under the libpng license. - * For conditions of distribution and use, see the disclaimer - * and license in png.h - * - */ - -/* Any machine specific code is near the front of this file, so if you - * are configuring libpng for a machine, you may want to read the section - * starting here down to where it starts to typedef png_color, png_text, - * and png_info. - */ - -#ifndef PNGCONF_H -#define PNGCONF_H - -#ifndef PNG_BUILDING_SYMBOL_TABLE -/* PNG_NO_LIMITS_H may be used to turn off the use of the standard C - * definition file for machine specific limits, this may impact the - * correctness of the definitons below (see uses of INT_MAX). - */ -# ifndef PNG_NO_LIMITS_H -# include -# endif - -/* For the memory copy APIs (i.e. the standard definitions of these), - * because this file defines png_memcpy and so on the base APIs must - * be defined here. - */ -# ifdef BSD -# include -# else -# include -# endif - -/* For png_FILE_p - this provides the standard definition of a - * FILE - */ -# ifdef PNG_STDIO_SUPPORTED -# include -# endif -#endif - -/* This controls optimization of the reading of 16 and 32 bit values - * from PNG files. It can be set on a per-app-file basis - it - * just changes whether a macro is used to the function is called. - * The library builder sets the default, if read functions are not - * built into the library the macro implementation is forced on. - */ -#ifndef PNG_READ_INT_FUNCTIONS_SUPPORTED -# define PNG_USE_READ_MACROS -#endif -#if !defined(PNG_NO_USE_READ_MACROS) && !defined(PNG_USE_READ_MACROS) -# if PNG_DEFAULT_READ_MACROS -# define PNG_USE_READ_MACROS -# endif -#endif - -/* COMPILER SPECIFIC OPTIONS. - * - * These options are provided so that a variety of difficult compilers - * can be used. Some are fixed at build time (e.g. PNG_API_RULE - * below) but still have compiler specific implementations, others - * may be changed on a per-file basis when compiling against libpng. - */ - -/* The PNGARG macro protects us against machines that don't have function - * prototypes (ie K&R style headers). If your compiler does not handle - * function prototypes, define this macro and use the included ansi2knr. - * I've always been able to use _NO_PROTO as the indicator, but you may - * need to drag the empty declaration out in front of here, or change the - * ifdef to suit your own needs. - */ -#ifndef PNGARG - -# ifdef OF /* zlib prototype munger */ -# define PNGARG(arglist) OF(arglist) -# else - -# ifdef _NO_PROTO -# define PNGARG(arglist) () -# else -# define PNGARG(arglist) arglist -# endif /* _NO_PROTO */ - -# endif /* OF */ - -#endif /* PNGARG */ - -/* Function calling conventions. - * ============================= - * Normally it is not necessary to specify to the compiler how to call - * a function - it just does it - however on x86 systems derived from - * Microsoft and Borland C compilers ('IBM PC', 'DOS', 'Windows' systems - * and some others) there are multiple ways to call a function and the - * default can be changed on the compiler command line. For this reason - * libpng specifies the calling convention of every exported function and - * every function called via a user supplied function pointer. This is - * done in this file by defining the following macros: - * - * PNGAPI Calling convention for exported functions. - * PNGCBAPI Calling convention for user provided (callback) functions. - * PNGCAPI Calling convention used by the ANSI-C library (required - * for longjmp callbacks and sometimes used internally to - * specify the calling convention for zlib). - * - * These macros should never be overridden. If it is necessary to - * change calling convention in a private build this can be done - * by setting PNG_API_RULE (which defaults to 0) to one of the values - * below to select the correct 'API' variants. - * - * PNG_API_RULE=0 Use PNGCAPI - the 'C' calling convention - throughout. - * This is correct in every known environment. - * PNG_API_RULE=1 Use the operating system convention for PNGAPI and - * the 'C' calling convention (from PNGCAPI) for - * callbacks (PNGCBAPI). This is no longer required - * in any known environment - if it has to be used - * please post an explanation of the problem to the - * libpng mailing list. - * - * These cases only differ if the operating system does not use the C - * calling convention, at present this just means the above cases - * (x86 DOS/Windows sytems) and, even then, this does not apply to - * Cygwin running on those systems. - * - * Note that the value must be defined in pnglibconf.h so that what - * the application uses to call the library matches the conventions - * set when building the library. - */ - -/* Symbol export - * ============= - * When building a shared library it is almost always necessary to tell - * the compiler which symbols to export. The png.h macro 'PNG_EXPORT' - * is used to mark the symbols. On some systems these symbols can be - * extracted at link time and need no special processing by the compiler, - * on other systems the symbols are flagged by the compiler and just - * the declaration requires a special tag applied (unfortunately) in a - * compiler dependent way. Some systems can do either. - * - * A small number of older systems also require a symbol from a DLL to - * be flagged to the program that calls it. This is a problem because - * we do not know in the header file included by application code that - * the symbol will come from a shared library, as opposed to a statically - * linked one. For this reason the application must tell us by setting - * the magic flag PNG_USE_DLL to turn on the special processing before - * it includes png.h. - * - * Four additional macros are used to make this happen: - * - * PNG_IMPEXP The magic (if any) to cause a symbol to be exported from - * the build or imported if PNG_USE_DLL is set - compiler - * and system specific. - * - * PNG_EXPORT_TYPE(type) A macro that pre or appends PNG_IMPEXP to - * 'type', compiler specific. - * - * PNG_DLL_EXPORT Set to the magic to use during a libpng build to - * make a symbol exported from the DLL. - * - * PNG_DLL_IMPORT Set to the magic to force the libpng symbols to come - * from a DLL - used to define PNG_IMPEXP when - * PNG_USE_DLL is set. - */ - -/* System specific discovery. - * ========================== - * This code is used at build time to find PNG_IMPEXP, the API settings - * and PNG_EXPORT_TYPE(), it may also set a macro to indicate the DLL - * import processing is possible. On Windows/x86 systems it also sets - * compiler-specific macros to the values required to change the calling - * conventions of the various functions. - */ -#if ( defined(_Windows) || defined(_WINDOWS) || defined(WIN32) ||\ - defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) ) &&\ - ( defined(_X86_) || defined(_X64_) || defined(_M_IX86) ||\ - defined(_M_X64) || defined(_M_IA64) ) - /* Windows system (DOS doesn't support DLLs) running on x86/x64. Includes - * builds under Cygwin or MinGW. Also includes Watcom builds but these need - * special treatment because they are not compatible with GCC or Visual C - * because of different calling conventions. - */ -# if PNG_API_RULE == 2 - /* If this line results in an error, either because __watcall is not - * understood or because of a redefine just below you cannot use *this* - * build of the library with the compiler you are using. *This* build was - * build using Watcom and applications must also be built using Watcom! - */ -# define PNGCAPI __watcall -# endif - -# if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800)) -# define PNGCAPI __cdecl -# if PNG_API_RULE == 1 -# define PNGAPI __stdcall -# endif -# else - /* An older compiler, or one not detected (erroneously) above, - * if necessary override on the command line to get the correct - * variants for the compiler. - */ -# ifndef PNGCAPI -# define PNGCAPI _cdecl -# endif -# if PNG_API_RULE == 1 && !defined(PNGAPI) -# define PNGAPI _stdcall -# endif -# endif /* compiler/api */ - /* NOTE: PNGCBAPI always defaults to PNGCAPI. */ - -# if defined(PNGAPI) && !defined(PNG_USER_PRIVATEBUILD) - ERROR: PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed -# endif - -# if (defined(_MSC_VER) && _MSC_VER < 800) ||\ - (defined(__BORLANDC__) && __BORLANDC__ < 0x500) - /* older Borland and MSC - * compilers used '__export' and required this to be after - * the type. - */ -# ifndef PNG_EXPORT_TYPE -# define PNG_EXPORT_TYPE(type) type PNG_IMPEXP -# endif -# define PNG_DLL_EXPORT __export -# else /* newer compiler */ -# define PNG_DLL_EXPORT __declspec(dllexport) -# ifndef PNG_DLL_IMPORT -# define PNG_DLL_IMPORT __declspec(dllimport) -# endif -# endif /* compiler */ - -#else /* !Windows/x86 */ -# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) -# define PNGAPI _System -# else /* !Windows/x86 && !OS/2 */ - /* Use the defaults, or define PNG*API on the command line (but - * this will have to be done for every compile!) - */ -# endif /* other system, !OS/2 */ -#endif /* !Windows/x86 */ - -/* Now do all the defaulting . */ -#ifndef PNGCAPI -# define PNGCAPI -#endif -#ifndef PNGCBAPI -# define PNGCBAPI PNGCAPI -#endif -#ifndef PNGAPI -# define PNGAPI PNGCAPI -#endif - -/* The default for PNG_IMPEXP depends on whether the library is - * being built or used. - */ -#ifndef PNG_IMPEXP -# ifdef PNGLIB_BUILD - /* Building the library */ -# if (defined(DLL_EXPORT)/*from libtool*/ ||\ - defined(_WINDLL) || defined(_DLL) || defined(__DLL__) ||\ - defined(_USRDLL) ||\ - defined(PNG_BUILD_DLL)) && defined(PNG_DLL_EXPORT) - /* Building a DLL. */ -# define PNG_IMPEXP PNG_DLL_EXPORT -# endif /* DLL */ -# else - /* Using the library */ -# if defined(PNG_USE_DLL) && defined(PNG_DLL_IMPORT) - /* This forces use of a DLL, disallowing static linking */ -# define PNG_IMPEXP PNG_DLL_IMPORT -# endif -# endif - -# ifndef PNG_IMPEXP -# define PNG_IMPEXP -# endif -#endif - -/* In 1.5.2 the definition of PNG_FUNCTION has been changed to always treat - * 'attributes' as a storage class - the attributes go at the start of the - * function definition, and attributes are always appended regardless of the - * compiler. This considerably simplifies these macros but may cause problems - * if any compilers both need function attributes and fail to handle them as - * a storage class (this is unlikely.) - */ -#ifndef PNG_FUNCTION -# define PNG_FUNCTION(type, name, args, attributes) attributes type name args -#endif - -#ifndef PNG_EXPORT_TYPE -# define PNG_EXPORT_TYPE(type) PNG_IMPEXP type -#endif - - /* The ordinal value is only relevant when preprocessing png.h for symbol - * table entries, so we discard it here. See the .dfn files in the - * scripts directory. - */ -#ifndef PNG_EXPORTA - -# define PNG_EXPORTA(ordinal, type, name, args, attributes)\ - PNG_FUNCTION(PNG_EXPORT_TYPE(type),(PNGAPI name),PNGARG(args), \ - extern attributes) -#endif - -/* ANSI-C (C90) does not permit a macro to be invoked with an empty argument, - * so make something non-empty to satisfy the requirement: - */ -#define PNG_EMPTY /*empty list*/ - -#define PNG_EXPORT(ordinal, type, name, args)\ - PNG_EXPORTA(ordinal, type, name, args, PNG_EMPTY) - -/* Use PNG_REMOVED to comment out a removed interface. */ -#ifndef PNG_REMOVED -# define PNG_REMOVED(ordinal, type, name, args, attributes) -#endif - -#ifndef PNG_CALLBACK -# define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) PNGARG(args) -#endif - -/* Support for compiler specific function attributes. These are used - * so that where compiler support is available incorrect use of API - * functions in png.h will generate compiler warnings. - * - * Added at libpng-1.2.41. - */ - -#ifndef PNG_NO_PEDANTIC_WARNINGS -# ifndef PNG_PEDANTIC_WARNINGS_SUPPORTED -# define PNG_PEDANTIC_WARNINGS_SUPPORTED -# endif -#endif - -#ifdef PNG_PEDANTIC_WARNINGS_SUPPORTED - /* Support for compiler specific function attributes. These are used - * so that where compiler support is available incorrect use of API - * functions in png.h will generate compiler warnings. Added at libpng - * version 1.2.41. - */ -# if defined(__GNUC__) -# ifndef PNG_USE_RESULT -# define PNG_USE_RESULT __attribute__((__warn_unused_result__)) -# endif -# ifndef PNG_NORETURN -# define PNG_NORETURN __attribute__((__noreturn__)) -# endif -# ifndef PNG_PTR_NORETURN - /* It's not enough to have the compiler be the correct compiler at - * this point - it's necessary for the library (which defines - * the type of the library longjmp) to also be the GNU library. - * This is because many systems use the GNU compiler with a - * non-GNU libc implementation. Min/GW headers are also compatible - * with GCC as well as uclibc, so it seems best to exclude known - * problem libcs here rather than just including known libcs. - * - * NOTE: this relies on the only use of PNG_PTR_NORETURN being with - * the system longjmp. If the same type is used elsewhere then this - * will need to be changed. - */ -# if !defined(__CYGWIN__) -# define PNG_PTR_NORETURN __attribute__((__noreturn__)) -# endif -# endif -# ifndef PNG_ALLOCATED -# define PNG_ALLOCATED __attribute__((__malloc__)) -# endif - - /* This specifically protects structure members that should only be - * accessed from within the library, therefore should be empty during - * a library build. - */ -# ifndef PNGLIB_BUILD -# ifndef PNG_DEPRECATED -# define PNG_DEPRECATED __attribute__((__deprecated__)) -# endif -# ifndef PNG_DEPSTRUCT -# define PNG_DEPSTRUCT __attribute__((__deprecated__)) -# endif -# ifndef PNG_PRIVATE -# if 0 /* Doesn't work so we use deprecated instead*/ -# define PNG_PRIVATE \ - __attribute__((warning("This function is not exported by libpng."))) -# else -# define PNG_PRIVATE \ - __attribute__((__deprecated__)) -# endif -# endif -# endif /* PNGLIB_BUILD */ -# endif /* __GNUC__ */ - -# if defined(_MSC_VER) && (_MSC_VER >= 1300) -# ifndef PNG_USE_RESULT -# define PNG_USE_RESULT /* not supported */ -# endif -# ifndef PNG_NORETURN -# define PNG_NORETURN __declspec(noreturn) -# endif -# ifndef PNG_PTR_NORETURN -# define PNG_PTR_NORETURN /* not supported */ -# endif -# ifndef PNG_ALLOCATED -# define PNG_ALLOCATED __declspec(restrict) -# endif - - /* This specifically protects structure members that should only be - * accessed from within the library, therefore should be empty during - * a library build. - */ -# ifndef PNGLIB_BUILD -# ifndef PNG_DEPRECATED -# define PNG_DEPRECATED __declspec(deprecated) -# endif -# ifndef PNG_DEPSTRUCT -# define PNG_DEPSTRUCT __declspec(deprecated) -# endif -# ifndef PNG_PRIVATE -# define PNG_PRIVATE __declspec(deprecated) -# endif -# endif /* PNGLIB_BUILD */ -# endif /* _MSC_VER */ -#endif /* PNG_PEDANTIC_WARNINGS */ - -#ifndef PNG_DEPRECATED -# define PNG_DEPRECATED /* Use of this function is deprecated */ -#endif -#ifndef PNG_USE_RESULT -# define PNG_USE_RESULT /* The result of this function must be checked */ -#endif -#ifndef PNG_NORETURN -# define PNG_NORETURN /* This function does not return */ -#endif -#ifndef PNG_PTR_NORETURN -# define PNG_PTR_NORETURN /* This function does not return */ -#endif -#ifndef PNG_ALLOCATED -# define PNG_ALLOCATED /* The result of the function is new memory */ -#endif -#ifndef PNG_DEPSTRUCT -# define PNG_DEPSTRUCT /* Access to this struct member is deprecated */ -#endif -#ifndef PNG_PRIVATE -# define PNG_PRIVATE /* This is a private libpng function */ -#endif -#ifndef PNG_FP_EXPORT /* A floating point API. */ -# ifdef PNG_FLOATING_POINT_SUPPORTED -# define PNG_FP_EXPORT(ordinal, type, name, args)\ - PNG_EXPORT(ordinal, type, name, args) -# else /* No floating point APIs */ -# define PNG_FP_EXPORT(ordinal, type, name, args) -# endif -#endif -#ifndef PNG_FIXED_EXPORT /* A fixed point API. */ -# ifdef PNG_FIXED_POINT_SUPPORTED -# define PNG_FIXED_EXPORT(ordinal, type, name, args)\ - PNG_EXPORT(ordinal, type, name, args) -# else /* No fixed point APIs */ -# define PNG_FIXED_EXPORT(ordinal, type, name, args) -# endif -#endif - -/* The following uses const char * instead of char * for error - * and warning message functions, so some compilers won't complain. - * If you do not want to use const, define PNG_NO_CONST here. - * - * This should not change how the APIs are called, so it can be done - * on a per-file basis in the application. - */ -#ifndef PNG_CONST -# ifndef PNG_NO_CONST -# define PNG_CONST const -# else -# define PNG_CONST -# endif -#endif - -/* Some typedefs to get us started. These should be safe on most of the - * common platforms. The typedefs should be at least as large as the - * numbers suggest (a png_uint_32 must be at least 32 bits long), but they - * don't have to be exactly that size. Some compilers dislike passing - * unsigned shorts as function parameters, so you may be better off using - * unsigned int for png_uint_16. - */ - -#if defined(INT_MAX) && (INT_MAX > 0x7ffffffeL) -typedef unsigned int png_uint_32; -typedef int png_int_32; -#else -typedef unsigned long png_uint_32; -typedef long png_int_32; -#endif -typedef unsigned short png_uint_16; -typedef short png_int_16; -typedef unsigned char png_byte; - -#ifdef PNG_NO_SIZE_T -typedef unsigned int png_size_t; -#else -typedef size_t png_size_t; -#endif -#define png_sizeof(x) (sizeof (x)) - -/* The following is needed for medium model support. It cannot be in the - * pngpriv.h header. Needs modification for other compilers besides - * MSC. Model independent support declares all arrays and pointers to be - * large using the far keyword. The zlib version used must also support - * model independent data. As of version zlib 1.0.4, the necessary changes - * have been made in zlib. The USE_FAR_KEYWORD define triggers other - * changes that are needed. (Tim Wegner) - */ - -/* Separate compiler dependencies (problem here is that zlib.h always - * defines FAR. (SJT) - */ -#ifdef __BORLANDC__ -# if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__) -# define LDATA 1 -# else -# define LDATA 0 -# endif - /* GRR: why is Cygwin in here? Cygwin is not Borland C... */ -# if !defined(__WIN32__) && !defined(__FLAT__) && !defined(__CYGWIN__) -# define PNG_MAX_MALLOC_64K /* only used in build */ -# if (LDATA != 1) -# ifndef FAR -# define FAR __far -# endif -# define USE_FAR_KEYWORD -# endif /* LDATA != 1 */ - /* Possibly useful for moving data out of default segment. - * Uncomment it if you want. Could also define FARDATA as - * const if your compiler supports it. (SJT) -# define FARDATA FAR - */ -# endif /* __WIN32__, __FLAT__, __CYGWIN__ */ -#endif /* __BORLANDC__ */ - - -/* Suggest testing for specific compiler first before testing for - * FAR. The Watcom compiler defines both __MEDIUM__ and M_I86MM, - * making reliance oncertain keywords suspect. (SJT) - */ - -/* MSC Medium model */ -#ifdef FAR -# ifdef M_I86MM -# define USE_FAR_KEYWORD -# define FARDATA FAR -# include -# endif -#endif - -/* SJT: default case */ -#ifndef FAR -# define FAR -#endif - -/* At this point FAR is always defined */ -#ifndef FARDATA -# define FARDATA -#endif - -/* Typedef for floating-point numbers that are converted - * to fixed-point with a multiple of 100,000, e.g., gamma - */ -typedef png_int_32 png_fixed_point; - -/* Add typedefs for pointers */ -typedef void FAR * png_voidp; -typedef PNG_CONST void FAR * png_const_voidp; -typedef png_byte FAR * png_bytep; -typedef PNG_CONST png_byte FAR * png_const_bytep; -typedef png_uint_32 FAR * png_uint_32p; -typedef PNG_CONST png_uint_32 FAR * png_const_uint_32p; -typedef png_int_32 FAR * png_int_32p; -typedef PNG_CONST png_int_32 FAR * png_const_int_32p; -typedef png_uint_16 FAR * png_uint_16p; -typedef PNG_CONST png_uint_16 FAR * png_const_uint_16p; -typedef png_int_16 FAR * png_int_16p; -typedef PNG_CONST png_int_16 FAR * png_const_int_16p; -typedef char FAR * png_charp; -typedef PNG_CONST char FAR * png_const_charp; -typedef png_fixed_point FAR * png_fixed_point_p; -typedef PNG_CONST png_fixed_point FAR * png_const_fixed_point_p; -typedef png_size_t FAR * png_size_tp; -typedef PNG_CONST png_size_t FAR * png_const_size_tp; - -#ifdef PNG_STDIO_SUPPORTED -typedef FILE * png_FILE_p; -#endif - -#ifdef PNG_FLOATING_POINT_SUPPORTED -typedef double FAR * png_doublep; -typedef PNG_CONST double FAR * png_const_doublep; -#endif - -/* Pointers to pointers; i.e. arrays */ -typedef png_byte FAR * FAR * png_bytepp; -typedef png_uint_32 FAR * FAR * png_uint_32pp; -typedef png_int_32 FAR * FAR * png_int_32pp; -typedef png_uint_16 FAR * FAR * png_uint_16pp; -typedef png_int_16 FAR * FAR * png_int_16pp; -typedef PNG_CONST char FAR * FAR * png_const_charpp; -typedef char FAR * FAR * png_charpp; -typedef png_fixed_point FAR * FAR * png_fixed_point_pp; -#ifdef PNG_FLOATING_POINT_SUPPORTED -typedef double FAR * FAR * png_doublepp; -#endif - -/* Pointers to pointers to pointers; i.e., pointer to array */ -typedef char FAR * FAR * FAR * png_charppp; - -/* png_alloc_size_t is guaranteed to be no smaller than png_size_t, - * and no smaller than png_uint_32. Casts from png_size_t or png_uint_32 - * to png_alloc_size_t are not necessary; in fact, it is recommended - * not to use them at all so that the compiler can complain when something - * turns out to be problematic. - * Casts in the other direction (from png_alloc_size_t to png_size_t or - * png_uint_32) should be explicitly applied; however, we do not expect - * to encounter practical situations that require such conversions. - */ -#if defined(__TURBOC__) && !defined(__FLAT__) - typedef unsigned long png_alloc_size_t; -#else -# if defined(_MSC_VER) && defined(MAXSEG_64K) - typedef unsigned long png_alloc_size_t; -# else - /* This is an attempt to detect an old Windows system where (int) is - * actually 16 bits, in that case png_malloc must have an argument with a - * bigger size to accomodate the requirements of the library. - */ -# if (defined(_Windows) || defined(_WINDOWS) || defined(_WINDOWS_)) && \ - (!defined(INT_MAX) || INT_MAX <= 0x7ffffffeL) - typedef DWORD png_alloc_size_t; -# else - typedef png_size_t png_alloc_size_t; -# endif -# endif -#endif - -#endif /* PNGCONF_H */ diff --git a/cdeps/win/pnglibconf.h b/cdeps/win/pnglibconf.h deleted file mode 100755 index e36ee348..00000000 --- a/cdeps/win/pnglibconf.h +++ /dev/null @@ -1,181 +0,0 @@ - -/* libpng STANDARD API DEFINITION */ - -/* pnglibconf.h - library build configuration */ - -/* libpng version 1.5.0 - last changed on February 11, 2011 */ - -/* Copyright (c) 1998-2011 Glenn Randers-Pehrson */ - -/* This code is released under the libpng license. */ -/* For conditions of distribution and use, see the disclaimer */ -/* and license in png.h */ - -/* pnglibconf.h */ -/* Derived from: scripts/pnglibconf.dfa */ -/* If you edit this file by hand you must obey the rules expressed in */ -/* pnglibconf.dfa with respect to the dependencies between the following */ -/* symbols. It is much better to generate a new file using */ -/* scripts/libpngconf.mak */ - -#ifndef PNGLCONF_H -#define PNGLCONF_H -/* settings */ -#define PNG_API_RULE 0 -#define PNG_CALLOC_SUPPORTED -#define PNG_COST_SHIFT 3 -#define PNG_DEFAULT_READ_MACROS 1 -#define PNG_GAMMA_THRESHOLD_FIXED 5000 -#define PNG_MAX_GAMMA_8 11 -#define PNG_QUANTIZE_BLUE_BITS 5 -#define PNG_QUANTIZE_GREEN_BITS 5 -#define PNG_QUANTIZE_RED_BITS 5 -#define PNG_sCAL_PRECISION 5 -#define PNG_USER_CHUNK_CACHE_MAX 0 -#define PNG_USER_CHUNK_MALLOC_MAX 0 -#define PNG_USER_HEIGHT_MAX 1000000L -#define PNG_USER_WIDTH_MAX 1000000L -#define PNG_WEIGHT_SHIFT 8 -#define PNG_ZBUF_SIZE 8192 -/* end of settings */ -/* options */ -#define PNG_16BIT_SUPPORTED -#define PNG_ALIGN_MEMORY_SUPPORTED -#define PNG_BENIGN_ERRORS_SUPPORTED -#define PNG_bKGD_SUPPORTED -#define PNG_CHECK_cHRM_SUPPORTED -#define PNG_cHRM_SUPPORTED -#define PNG_CONSOLE_IO_SUPPORTED -#define PNG_CONVERT_tIME_SUPPORTED -#define PNG_EASY_ACCESS_SUPPORTED -#define PNG_ERROR_TEXT_SUPPORTED -#define PNG_FIXED_POINT_SUPPORTED -#define PNG_FLOATING_ARITHMETIC_SUPPORTED -#define PNG_FLOATING_POINT_SUPPORTED -#define PNG_gAMA_SUPPORTED -#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED -#define PNG_hIST_SUPPORTED -#define PNG_iCCP_SUPPORTED -#define PNG_INCH_CONVERSIONS_SUPPORTED -#define PNG_INFO_IMAGE_SUPPORTED -#define PNG_IO_STATE_SUPPORTED -#define PNG_iTXt_SUPPORTED -#define PNG_MNG_FEATURES_SUPPORTED -#define PNG_oFFs_SUPPORTED -#define PNG_pCAL_SUPPORTED -#define PNG_pHYs_SUPPORTED -#define PNG_POINTER_INDEXING_SUPPORTED -#define PNG_PROGRESSIVE_READ_SUPPORTED -#define PNG_READ_16BIT_SUPPORTED -#define PNG_READ_16_TO_8_SUPPORTED -#define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED -#define PNG_READ_BACKGROUND_SUPPORTED -#define PNG_READ_BGR_SUPPORTED -#define PNG_READ_bKGD_SUPPORTED -#define PNG_READ_cHRM_SUPPORTED -#define PNG_READ_COMPOSITE_NODIV_SUPPORTED -#define PNG_READ_EXPAND_16_SUPPORTED -#define PNG_READ_EXPAND_SUPPORTED -#define PNG_READ_FILLER_SUPPORTED -#define PNG_READ_gAMA_SUPPORTED -#define PNG_READ_GAMMA_SUPPORTED -#define PNG_READ_GRAY_TO_RGB_SUPPORTED -#define PNG_READ_hIST_SUPPORTED -#define PNG_READ_iCCP_SUPPORTED -#define PNG_READ_INTERLACING_SUPPORTED -#define PNG_READ_INT_FUNCTIONS_SUPPORTED -#define PNG_READ_INVERT_ALPHA_SUPPORTED -#define PNG_READ_INVERT_SUPPORTED -#define PNG_READ_iTXt_SUPPORTED -#define PNG_READ_oFFs_SUPPORTED -#define PNG_READ_OPT_PLTE_SUPPORTED -#define PNG_READ_PACK_SUPPORTED -#define PNG_READ_PACKSWAP_SUPPORTED -#define PNG_READ_pCAL_SUPPORTED -#define PNG_READ_pHYs_SUPPORTED -#define PNG_READ_QUANTIZE_SUPPORTED -#define PNG_READ_RGB_TO_GRAY_SUPPORTED -#define PNG_READ_sBIT_SUPPORTED -#define PNG_READ_sCAL_SUPPORTED -#define PNG_READ_SHIFT_SUPPORTED -#define PNG_READ_sPLT_SUPPORTED -#define PNG_READ_sRGB_SUPPORTED -#define PNG_READ_STRIP_ALPHA_SUPPORTED -#define PNG_READ_SUPPORTED -#define PNG_READ_SWAP_ALPHA_SUPPORTED -#define PNG_READ_SWAP_SUPPORTED -#define PNG_READ_tEXt_SUPPORTED -#define PNG_READ_TEXT_SUPPORTED -#define PNG_READ_tIME_SUPPORTED -#define PNG_READ_TRANSFORMS_SUPPORTED -#define PNG_READ_tRNS_SUPPORTED -#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED -#define PNG_READ_USER_CHUNKS_SUPPORTED -#define PNG_READ_USER_TRANSFORM_SUPPORTED -#define PNG_READ_zTXt_SUPPORTED -#define PNG_SAVE_INT_32_SUPPORTED -#define PNG_sBIT_SUPPORTED -#define PNG_sCAL_SUPPORTED -#define PNG_SEQUENTIAL_READ_SUPPORTED -#define PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED -#define PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED -#define PNG_SETJMP_SUPPORTED -#define PNG_SET_USER_LIMITS_SUPPORTED -#define PNG_sPLT_SUPPORTED -#define PNG_sRGB_SUPPORTED -#define PNG_STDIO_SUPPORTED -#define PNG_tEXt_SUPPORTED -#define PNG_TEXT_SUPPORTED -#define PNG_TIME_RFC1123_SUPPORTED -#define PNG_tIME_SUPPORTED -#define PNG_tRNS_SUPPORTED -#define PNG_UNKNOWN_CHUNKS_SUPPORTED -#define PNG_USER_CHUNKS_SUPPORTED -#define PNG_USER_LIMITS_SUPPORTED -#define PNG_USER_MEM_SUPPORTED -#define PNG_USER_TRANSFORM_INFO_SUPPORTED -#define PNG_USER_TRANSFORM_PTR_SUPPORTED -#define PNG_WARNINGS_SUPPORTED -#define PNG_WRITE_16BIT_SUPPORTED -#define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED -#define PNG_WRITE_BGR_SUPPORTED -#define PNG_WRITE_bKGD_SUPPORTED -#define PNG_WRITE_cHRM_SUPPORTED -#define PNG_WRITE_FILLER_SUPPORTED -#define PNG_WRITE_FILTER_SUPPORTED -#define PNG_WRITE_FLUSH_SUPPORTED -#define PNG_WRITE_gAMA_SUPPORTED -#define PNG_WRITE_hIST_SUPPORTED -#define PNG_WRITE_iCCP_SUPPORTED -#define PNG_WRITE_INTERLACING_SUPPORTED -#define PNG_WRITE_INT_FUNCTIONS_SUPPORTED -#define PNG_WRITE_INVERT_ALPHA_SUPPORTED -#define PNG_WRITE_INVERT_SUPPORTED -#define PNG_WRITE_iTXt_SUPPORTED -#define PNG_WRITE_oFFs_SUPPORTED -#define PNG_WRITE_PACK_SUPPORTED -#define PNG_WRITE_PACKSWAP_SUPPORTED -#define PNG_WRITE_pCAL_SUPPORTED -#define PNG_WRITE_pHYs_SUPPORTED -#define PNG_WRITE_sBIT_SUPPORTED -#define PNG_WRITE_sCAL_SUPPORTED -#define PNG_WRITE_SHIFT_SUPPORTED -#define PNG_WRITE_sPLT_SUPPORTED -#define PNG_WRITE_sRGB_SUPPORTED -#define PNG_WRITE_SUPPORTED -#define PNG_WRITE_SWAP_ALPHA_SUPPORTED -#define PNG_WRITE_SWAP_SUPPORTED -#define PNG_WRITE_tEXt_SUPPORTED -#define PNG_WRITE_TEXT_SUPPORTED -#define PNG_WRITE_tIME_SUPPORTED -#define PNG_WRITE_TRANSFORMS_SUPPORTED -#define PNG_WRITE_tRNS_SUPPORTED -#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED -#define PNG_WRITE_USER_TRANSFORM_SUPPORTED -#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED -#define PNG_WRITE_zTXt_SUPPORTED -#define PNG_zTXt_SUPPORTED -/*#undef PNG_ERROR_NUMBERS_SUPPORTED*/ -/*#undef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED*/ -/* end of options */ -#endif /* PNGLCONF_H */ diff --git a/cdeps/win/zconf.h b/cdeps/win/zconf.h deleted file mode 100755 index 02ce56c4..00000000 --- a/cdeps/win/zconf.h +++ /dev/null @@ -1,428 +0,0 @@ -/* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2010 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#ifndef ZCONF_H -#define ZCONF_H - -/* - * If you *really* need a unique prefix for all types and library functions, - * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. - * Even better than compiling with -DZ_PREFIX would be to use configure to set - * this permanently in zconf.h using "./configure --zprefix". - */ -#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ - -/* all linked symbols */ -# define _dist_code z__dist_code -# define _length_code z__length_code -# define _tr_align z__tr_align -# define _tr_flush_block z__tr_flush_block -# define _tr_init z__tr_init -# define _tr_stored_block z__tr_stored_block -# define _tr_tally z__tr_tally -# define adler32 z_adler32 -# define adler32_combine z_adler32_combine -# define adler32_combine64 z_adler32_combine64 -# define compress z_compress -# define compress2 z_compress2 -# define compressBound z_compressBound -# define crc32 z_crc32 -# define crc32_combine z_crc32_combine -# define crc32_combine64 z_crc32_combine64 -# define deflate z_deflate -# define deflateBound z_deflateBound -# define deflateCopy z_deflateCopy -# define deflateEnd z_deflateEnd -# define deflateInit2_ z_deflateInit2_ -# define deflateInit_ z_deflateInit_ -# define deflateParams z_deflateParams -# define deflatePrime z_deflatePrime -# define deflateReset z_deflateReset -# define deflateSetDictionary z_deflateSetDictionary -# define deflateSetHeader z_deflateSetHeader -# define deflateTune z_deflateTune -# define deflate_copyright z_deflate_copyright -# define get_crc_table z_get_crc_table -# define gz_error z_gz_error -# define gz_intmax z_gz_intmax -# define gz_strwinerror z_gz_strwinerror -# define gzbuffer z_gzbuffer -# define gzclearerr z_gzclearerr -# define gzclose z_gzclose -# define gzclose_r z_gzclose_r -# define gzclose_w z_gzclose_w -# define gzdirect z_gzdirect -# define gzdopen z_gzdopen -# define gzeof z_gzeof -# define gzerror z_gzerror -# define gzflush z_gzflush -# define gzgetc z_gzgetc -# define gzgets z_gzgets -# define gzoffset z_gzoffset -# define gzoffset64 z_gzoffset64 -# define gzopen z_gzopen -# define gzopen64 z_gzopen64 -# define gzprintf z_gzprintf -# define gzputc z_gzputc -# define gzputs z_gzputs -# define gzread z_gzread -# define gzrewind z_gzrewind -# define gzseek z_gzseek -# define gzseek64 z_gzseek64 -# define gzsetparams z_gzsetparams -# define gztell z_gztell -# define gztell64 z_gztell64 -# define gzungetc z_gzungetc -# define gzwrite z_gzwrite -# define inflate z_inflate -# define inflateBack z_inflateBack -# define inflateBackEnd z_inflateBackEnd -# define inflateBackInit_ z_inflateBackInit_ -# define inflateCopy z_inflateCopy -# define inflateEnd z_inflateEnd -# define inflateGetHeader z_inflateGetHeader -# define inflateInit2_ z_inflateInit2_ -# define inflateInit_ z_inflateInit_ -# define inflateMark z_inflateMark -# define inflatePrime z_inflatePrime -# define inflateReset z_inflateReset -# define inflateReset2 z_inflateReset2 -# define inflateSetDictionary z_inflateSetDictionary -# define inflateSync z_inflateSync -# define inflateSyncPoint z_inflateSyncPoint -# define inflateUndermine z_inflateUndermine -# define inflate_copyright z_inflate_copyright -# define inflate_fast z_inflate_fast -# define inflate_table z_inflate_table -# define uncompress z_uncompress -# define zError z_zError -# define zcalloc z_zcalloc -# define zcfree z_zcfree -# define zlibCompileFlags z_zlibCompileFlags -# define zlibVersion z_zlibVersion - -/* all zlib typedefs in zlib.h and zconf.h */ -# define Byte z_Byte -# define Bytef z_Bytef -# define alloc_func z_alloc_func -# define charf z_charf -# define free_func z_free_func -# define gzFile z_gzFile -# define gz_header z_gz_header -# define gz_headerp z_gz_headerp -# define in_func z_in_func -# define intf z_intf -# define out_func z_out_func -# define uInt z_uInt -# define uIntf z_uIntf -# define uLong z_uLong -# define uLongf z_uLongf -# define voidp z_voidp -# define voidpc z_voidpc -# define voidpf z_voidpf - -/* all zlib structs in zlib.h and zconf.h */ -# define gz_header_s z_gz_header_s -# define internal_state z_internal_state - -#endif - -#if defined(__MSDOS__) && !defined(MSDOS) -# define MSDOS -#endif -#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) -# define OS2 -#endif -#if defined(_WINDOWS) && !defined(WINDOWS) -# define WINDOWS -#endif -#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) -# ifndef WIN32 -# define WIN32 -# endif -#endif -#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) -# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) -# ifndef SYS16BIT -# define SYS16BIT -# endif -# endif -#endif - -/* - * Compile with -DMAXSEG_64K if the alloc function cannot allocate more - * than 64k bytes at a time (needed on systems with 16-bit int). - */ -#ifdef SYS16BIT -# define MAXSEG_64K -#endif -#ifdef MSDOS -# define UNALIGNED_OK -#endif - -#ifdef __STDC_VERSION__ -# ifndef STDC -# define STDC -# endif -# if __STDC_VERSION__ >= 199901L -# ifndef STDC99 -# define STDC99 -# endif -# endif -#endif -#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) -# define STDC -#endif -#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) -# define STDC -#endif -#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) -# define STDC -#endif -#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) -# define STDC -#endif - -#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ -# define STDC -#endif - -#ifndef STDC -# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ -# define const /* note: need a more gentle solution here */ -# endif -#endif - -/* Some Mac compilers merge all .h files incorrectly: */ -#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) -# define NO_DUMMY_DECL -#endif - -/* Maximum value for memLevel in deflateInit2 */ -#ifndef MAX_MEM_LEVEL -# ifdef MAXSEG_64K -# define MAX_MEM_LEVEL 8 -# else -# define MAX_MEM_LEVEL 9 -# endif -#endif - -/* Maximum value for windowBits in deflateInit2 and inflateInit2. - * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files - * created by gzip. (Files created by minigzip can still be extracted by - * gzip.) - */ -#ifndef MAX_WBITS -# define MAX_WBITS 15 /* 32K LZ77 window */ -#endif - -/* The memory requirements for deflate are (in bytes): - (1 << (windowBits+2)) + (1 << (memLevel+9)) - that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) - plus a few kilobytes for small objects. For example, if you want to reduce - the default memory requirements from 256K to 128K, compile with - make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" - Of course this will generally degrade compression (there's no free lunch). - - The memory requirements for inflate are (in bytes) 1 << windowBits - that is, 32K for windowBits=15 (default value) plus a few kilobytes - for small objects. -*/ - - /* Type declarations */ - -#ifndef OF /* function prototypes */ -# ifdef STDC -# define OF(args) args -# else -# define OF(args) () -# endif -#endif - -/* The following definitions for FAR are needed only for MSDOS mixed - * model programming (small or medium model with some far allocations). - * This was tested only with MSC; for other MSDOS compilers you may have - * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, - * just define FAR to be empty. - */ -#ifdef SYS16BIT -# if defined(M_I86SM) || defined(M_I86MM) - /* MSC small or medium model */ -# define SMALL_MEDIUM -# ifdef _MSC_VER -# define FAR _far -# else -# define FAR far -# endif -# endif -# if (defined(__SMALL__) || defined(__MEDIUM__)) - /* Turbo C small or medium model */ -# define SMALL_MEDIUM -# ifdef __BORLANDC__ -# define FAR _far -# else -# define FAR far -# endif -# endif -#endif - -#if defined(WINDOWS) || defined(WIN32) - /* If building or using zlib as a DLL, define ZLIB_DLL. - * This is not mandatory, but it offers a little performance increase. - */ -# ifdef ZLIB_DLL -# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) -# ifdef ZLIB_INTERNAL -# define ZEXTERN extern __declspec(dllexport) -# else -# define ZEXTERN extern __declspec(dllimport) -# endif -# endif -# endif /* ZLIB_DLL */ - /* If building or using zlib with the WINAPI/WINAPIV calling convention, - * define ZLIB_WINAPI. - * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. - */ -# ifdef ZLIB_WINAPI -# ifdef FAR -# undef FAR -# endif -# include - /* No need for _export, use ZLIB.DEF instead. */ - /* For complete Windows compatibility, use WINAPI, not __stdcall. */ -# define ZEXPORT WINAPI -# ifdef WIN32 -# define ZEXPORTVA WINAPIV -# else -# define ZEXPORTVA FAR CDECL -# endif -# endif -#endif - -#if defined (__BEOS__) -# ifdef ZLIB_DLL -# ifdef ZLIB_INTERNAL -# define ZEXPORT __declspec(dllexport) -# define ZEXPORTVA __declspec(dllexport) -# else -# define ZEXPORT __declspec(dllimport) -# define ZEXPORTVA __declspec(dllimport) -# endif -# endif -#endif - -#ifndef ZEXTERN -# define ZEXTERN extern -#endif -#ifndef ZEXPORT -# define ZEXPORT -#endif -#ifndef ZEXPORTVA -# define ZEXPORTVA -#endif - -#ifndef FAR -# define FAR -#endif - -#if !defined(__MACTYPES__) -typedef unsigned char Byte; /* 8 bits */ -#endif -typedef unsigned int uInt; /* 16 bits or more */ -typedef unsigned long uLong; /* 32 bits or more */ - -#ifdef SMALL_MEDIUM - /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ -# define Bytef Byte FAR -#else - typedef Byte FAR Bytef; -#endif -typedef char FAR charf; -typedef int FAR intf; -typedef uInt FAR uIntf; -typedef uLong FAR uLongf; - -#ifdef STDC - typedef void const *voidpc; - typedef void FAR *voidpf; - typedef void *voidp; -#else - typedef Byte const *voidpc; - typedef Byte FAR *voidpf; - typedef Byte *voidp; -#endif - -#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ -# define Z_HAVE_UNISTD_H -#endif - -#ifdef STDC -# include /* for off_t */ -#endif - -/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and - * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even - * though the former does not conform to the LFS document), but considering - * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as - * equivalently requesting no 64-bit operations - */ -#if -_LARGEFILE64_SOURCE - -1 == 1 -# undef _LARGEFILE64_SOURCE -#endif - -#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) -# include /* for SEEK_* and off_t */ -# ifdef VMS -# include /* for off_t */ -# endif -# ifndef z_off_t -# define z_off_t off_t -# endif -#endif - -#ifndef SEEK_SET -# define SEEK_SET 0 /* Seek from beginning of file. */ -# define SEEK_CUR 1 /* Seek from current position. */ -# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ -#endif - -#ifndef z_off_t -# define z_off_t long -#endif - -#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 -# define z_off64_t off64_t -#else -# define z_off64_t z_off_t -#endif - -#if defined(__OS400__) -# define NO_vsnprintf -#endif - -#if defined(__MVS__) -# define NO_vsnprintf -#endif - -/* MVS linker does not support external names larger than 8 bytes */ -#if defined(__MVS__) - #pragma map(deflateInit_,"DEIN") - #pragma map(deflateInit2_,"DEIN2") - #pragma map(deflateEnd,"DEEND") - #pragma map(deflateBound,"DEBND") - #pragma map(inflateInit_,"ININ") - #pragma map(inflateInit2_,"ININ2") - #pragma map(inflateEnd,"INEND") - #pragma map(inflateSync,"INSY") - #pragma map(inflateSetDictionary,"INSEDI") - #pragma map(compressBound,"CMBND") - #pragma map(inflate_table,"INTABL") - #pragma map(inflate_fast,"INFA") - #pragma map(inflate_copyright,"INCOPY") -#endif - -#endif /* ZCONF_H */ diff --git a/cdeps/win/zlib.h b/cdeps/win/zlib.h deleted file mode 100755 index bfbba83e..00000000 --- a/cdeps/win/zlib.h +++ /dev/null @@ -1,1613 +0,0 @@ -/* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.5, April 19th, 2010 - - Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jean-loup Gailly Mark Adler - jloup@gzip.org madler@alumni.caltech.edu - - - The data format used by the zlib library is described by RFCs (Request for - Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt - (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). -*/ - -#ifndef ZLIB_H -#define ZLIB_H - -#include "zconf.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define ZLIB_VERSION "1.2.5" -#define ZLIB_VERNUM 0x1250 -#define ZLIB_VER_MAJOR 1 -#define ZLIB_VER_MINOR 2 -#define ZLIB_VER_REVISION 5 -#define ZLIB_VER_SUBREVISION 0 - -/* - The 'zlib' compression library provides in-memory compression and - decompression functions, including integrity checks of the uncompressed data. - This version of the library supports only one compression method (deflation) - but other algorithms will be added later and will have the same stream - interface. - - Compression can be done in a single step if the buffers are large enough, - or can be done by repeated calls of the compression function. In the latter - case, the application must provide more input and/or consume the output - (providing more output space) before each call. - - The compressed data format used by default by the in-memory functions is - the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped - around a deflate stream, which is itself documented in RFC 1951. - - The library also supports reading and writing files in gzip (.gz) format - with an interface similar to that of stdio using the functions that start - with "gz". The gzip format is different from the zlib format. gzip is a - gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. - - This library can optionally read and write gzip streams in memory as well. - - The zlib format was designed to be compact and fast for use in memory - and on communications channels. The gzip format was designed for single- - file compression on file systems, has a larger header than zlib to maintain - directory information, and uses a different, slower check method than zlib. - - The library does not install any signal handler. The decoder checks - the consistency of the compressed data, so the library should never crash - even in case of corrupted input. -*/ - -typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); -typedef void (*free_func) OF((voidpf opaque, voidpf address)); - -struct internal_state; - -typedef struct z_stream_s { - Bytef *next_in; /* next input byte */ - uInt avail_in; /* number of bytes available at next_in */ - uLong total_in; /* total nb of input bytes read so far */ - - Bytef *next_out; /* next output byte should be put there */ - uInt avail_out; /* remaining free space at next_out */ - uLong total_out; /* total nb of bytes output so far */ - - char *msg; /* last error message, NULL if no error */ - struct internal_state FAR *state; /* not visible by applications */ - - alloc_func zalloc; /* used to allocate the internal state */ - free_func zfree; /* used to free the internal state */ - voidpf opaque; /* private data object passed to zalloc and zfree */ - - int data_type; /* best guess about the data type: binary or text */ - uLong adler; /* adler32 value of the uncompressed data */ - uLong reserved; /* reserved for future use */ -} z_stream; - -typedef z_stream FAR *z_streamp; - -/* - gzip header information passed to and from zlib routines. See RFC 1952 - for more details on the meanings of these fields. -*/ -typedef struct gz_header_s { - int text; /* true if compressed data believed to be text */ - uLong time; /* modification time */ - int xflags; /* extra flags (not used when writing a gzip file) */ - int os; /* operating system */ - Bytef *extra; /* pointer to extra field or Z_NULL if none */ - uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ - uInt extra_max; /* space at extra (only when reading header) */ - Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ - uInt name_max; /* space at name (only when reading header) */ - Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ - uInt comm_max; /* space at comment (only when reading header) */ - int hcrc; /* true if there was or will be a header crc */ - int done; /* true when done reading gzip header (not used - when writing a gzip file) */ -} gz_header; - -typedef gz_header FAR *gz_headerp; - -/* - The application must update next_in and avail_in when avail_in has dropped - to zero. It must update next_out and avail_out when avail_out has dropped - to zero. The application must initialize zalloc, zfree and opaque before - calling the init function. All other fields are set by the compression - library and must not be updated by the application. - - The opaque value provided by the application will be passed as the first - parameter for calls of zalloc and zfree. This can be useful for custom - memory management. The compression library attaches no meaning to the - opaque value. - - zalloc must return Z_NULL if there is not enough memory for the object. - If zlib is used in a multi-threaded application, zalloc and zfree must be - thread safe. - - On 16-bit systems, the functions zalloc and zfree must be able to allocate - exactly 65536 bytes, but will not be required to allocate more than this if - the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers - returned by zalloc for objects of exactly 65536 bytes *must* have their - offset normalized to zero. The default allocation function provided by this - library ensures this (see zutil.c). To reduce memory requirements and avoid - any allocation of 64K objects, at the expense of compression ratio, compile - the library with -DMAX_WBITS=14 (see zconf.h). - - The fields total_in and total_out can be used for statistics or progress - reports. After compression, total_in holds the total size of the - uncompressed data and may be saved for use in the decompressor (particularly - if the decompressor wants to decompress everything in a single step). -*/ - - /* constants */ - -#define Z_NO_FLUSH 0 -#define Z_PARTIAL_FLUSH 1 -#define Z_SYNC_FLUSH 2 -#define Z_FULL_FLUSH 3 -#define Z_FINISH 4 -#define Z_BLOCK 5 -#define Z_TREES 6 -/* Allowed flush values; see deflate() and inflate() below for details */ - -#define Z_OK 0 -#define Z_STREAM_END 1 -#define Z_NEED_DICT 2 -#define Z_ERRNO (-1) -#define Z_STREAM_ERROR (-2) -#define Z_DATA_ERROR (-3) -#define Z_MEM_ERROR (-4) -#define Z_BUF_ERROR (-5) -#define Z_VERSION_ERROR (-6) -/* Return codes for the compression/decompression functions. Negative values - * are errors, positive values are used for special but normal events. - */ - -#define Z_NO_COMPRESSION 0 -#define Z_BEST_SPEED 1 -#define Z_BEST_COMPRESSION 9 -#define Z_DEFAULT_COMPRESSION (-1) -/* compression levels */ - -#define Z_FILTERED 1 -#define Z_HUFFMAN_ONLY 2 -#define Z_RLE 3 -#define Z_FIXED 4 -#define Z_DEFAULT_STRATEGY 0 -/* compression strategy; see deflateInit2() below for details */ - -#define Z_BINARY 0 -#define Z_TEXT 1 -#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ -#define Z_UNKNOWN 2 -/* Possible values of the data_type field (though see inflate()) */ - -#define Z_DEFLATED 8 -/* The deflate compression method (the only one supported in this version) */ - -#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ - -#define zlib_version zlibVersion() -/* for compatibility with versions < 1.0.2 */ - - - /* basic functions */ - -ZEXTERN const char * ZEXPORT zlibVersion OF((void)); -/* The application can compare zlibVersion and ZLIB_VERSION for consistency. - If the first character differs, the library code actually used is not - compatible with the zlib.h header file used by the application. This check - is automatically made by deflateInit and inflateInit. - */ - -/* -ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); - - Initializes the internal stream state for compression. The fields - zalloc, zfree and opaque must be initialized before by the caller. If - zalloc and zfree are set to Z_NULL, deflateInit updates them to use default - allocation functions. - - The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: - 1 gives best speed, 9 gives best compression, 0 gives no compression at all - (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION - requests a default compromise between speed and compression (currently - equivalent to level 6). - - deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if level is not a valid compression level, or - Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible - with the version assumed by the caller (ZLIB_VERSION). msg is set to null - if there is no error message. deflateInit does not perform any compression: - this will be done by deflate(). -*/ - - -ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); -/* - deflate compresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may introduce - some output latency (reading input without producing any output) except when - forced to flush. - - The detailed semantics are as follows. deflate performs one or both of the - following actions: - - - Compress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in and avail_in are updated and - processing will resume at this point for the next call of deflate(). - - - Provide more output starting at next_out and update next_out and avail_out - accordingly. This action is forced if the parameter flush is non zero. - Forcing flush frequently degrades the compression ratio, so this parameter - should be set only when necessary (in interactive applications). Some - output may be provided even if flush is not set. - - Before the call of deflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming more - output, and updating avail_in or avail_out accordingly; avail_out should - never be zero before the call. The application can consume the compressed - output when it wants, for example when the output buffer is full (avail_out - == 0), or after each call of deflate(). If deflate returns Z_OK and with - zero avail_out, it must be called again after making room in the output - buffer because there might be more output pending. - - Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to - decide how much data to accumulate before producing output, in order to - maximize compression. - - If the parameter flush is set to Z_SYNC_FLUSH, all pending output is - flushed to the output buffer and the output is aligned on a byte boundary, so - that the decompressor can get all input data available so far. (In - particular avail_in is zero after the call if enough output space has been - provided before the call.) Flushing may degrade compression for some - compression algorithms and so it should be used only when necessary. This - completes the current deflate block and follows it with an empty stored block - that is three bits plus filler bits to the next byte, followed by four bytes - (00 00 ff ff). - - If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the - output buffer, but the output is not aligned to a byte boundary. All of the - input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. - This completes the current deflate block and follows it with an empty fixed - codes block that is 10 bits long. This assures that enough bytes are output - in order for the decompressor to finish the block before the empty fixed code - block. - - If flush is set to Z_BLOCK, a deflate block is completed and emitted, as - for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to - seven bits of the current block are held to be written as the next byte after - the next deflate block is completed. In this case, the decompressor may not - be provided enough bits at this point in order to complete decompression of - the data provided so far to the compressor. It may need to wait for the next - block to be emitted. This is for advanced applications that need to control - the emission of deflate blocks. - - If flush is set to Z_FULL_FLUSH, all output is flushed as with - Z_SYNC_FLUSH, and the compression state is reset so that decompression can - restart from this point if previous compressed data has been damaged or if - random access is desired. Using Z_FULL_FLUSH too often can seriously degrade - compression. - - If deflate returns with avail_out == 0, this function must be called again - with the same value of the flush parameter and more output space (updated - avail_out), until the flush is complete (deflate returns with non-zero - avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that - avail_out is greater than six to avoid repeated flush markers due to - avail_out == 0 on return. - - If the parameter flush is set to Z_FINISH, pending input is processed, - pending output is flushed and deflate returns with Z_STREAM_END if there was - enough output space; if deflate returns with Z_OK, this function must be - called again with Z_FINISH and more output space (updated avail_out) but no - more input data, until it returns with Z_STREAM_END or an error. After - deflate has returned Z_STREAM_END, the only possible operations on the stream - are deflateReset or deflateEnd. - - Z_FINISH can be used immediately after deflateInit if all the compression - is to be done in a single step. In this case, avail_out must be at least the - value returned by deflateBound (see below). If deflate does not return - Z_STREAM_END, then it must be called again as described above. - - deflate() sets strm->adler to the adler32 checksum of all input read - so far (that is, total_in bytes). - - deflate() may update strm->data_type if it can make a good guess about - the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered - binary. This field is only for information purposes and does not affect the - compression algorithm in any manner. - - deflate() returns Z_OK if some progress has been made (more input - processed or more output produced), Z_STREAM_END if all input has been - consumed and all output has been produced (only when flush is set to - Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example - if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible - (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not - fatal, and deflate() can be called again with more input and more output - space to continue compressing. -*/ - - -ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any pending - output. - - deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the - stream state was inconsistent, Z_DATA_ERROR if the stream was freed - prematurely (some input or output was discarded). In the error case, msg - may be set but then points to a static string (which must not be - deallocated). -*/ - - -/* -ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); - - Initializes the internal stream state for decompression. The fields - next_in, avail_in, zalloc, zfree and opaque must be initialized before by - the caller. If next_in is not Z_NULL and avail_in is large enough (the - exact value depends on the compression method), inflateInit determines the - compression method from the zlib header and allocates all data structures - accordingly; otherwise the allocation will be deferred to the first call of - inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to - use default allocation functions. - - inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_VERSION_ERROR if the zlib library version is incompatible with the - version assumed by the caller, or Z_STREAM_ERROR if the parameters are - invalid, such as a null pointer to the structure. msg is set to null if - there is no error message. inflateInit does not perform any decompression - apart from possibly reading the zlib header if present: actual decompression - will be done by inflate(). (So next_in and avail_in may be modified, but - next_out and avail_out are unused and unchanged.) The current implementation - of inflateInit() does not process any header information -- that is deferred - until inflate() is called. -*/ - - -ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); -/* - inflate decompresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may introduce - some output latency (reading input without producing any output) except when - forced to flush. - - The detailed semantics are as follows. inflate performs one or both of the - following actions: - - - Decompress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in is updated and processing will - resume at this point for the next call of inflate(). - - - Provide more output starting at next_out and update next_out and avail_out - accordingly. inflate() provides as much output as possible, until there is - no more input data or no more space in the output buffer (see below about - the flush parameter). - - Before the call of inflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming more - output, and updating the next_* and avail_* values accordingly. The - application can consume the uncompressed output when it wants, for example - when the output buffer is full (avail_out == 0), or after each call of - inflate(). If inflate returns Z_OK and with zero avail_out, it must be - called again after making room in the output buffer because there might be - more output pending. - - The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, - Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much - output as possible to the output buffer. Z_BLOCK requests that inflate() - stop if and when it gets to the next deflate block boundary. When decoding - the zlib or gzip format, this will cause inflate() to return immediately - after the header and before the first block. When doing a raw inflate, - inflate() will go ahead and process the first block, and will return when it - gets to the end of that block, or when it runs out of data. - - The Z_BLOCK option assists in appending to or combining deflate streams. - Also to assist in this, on return inflate() will set strm->data_type to the - number of unused bits in the last byte taken from strm->next_in, plus 64 if - inflate() is currently decoding the last block in the deflate stream, plus - 128 if inflate() returned immediately after decoding an end-of-block code or - decoding the complete header up to just before the first byte of the deflate - stream. The end-of-block will not be indicated until all of the uncompressed - data from that block has been written to strm->next_out. The number of - unused bits may in general be greater than seven, except when bit 7 of - data_type is set, in which case the number of unused bits will be less than - eight. data_type is set as noted here every time inflate() returns for all - flush options, and so can be used to determine the amount of currently - consumed input in bits. - - The Z_TREES option behaves as Z_BLOCK does, but it also returns when the - end of each deflate block header is reached, before any actual data in that - block is decoded. This allows the caller to determine the length of the - deflate block header for later use in random access within a deflate block. - 256 is added to the value of strm->data_type when inflate() returns - immediately after reaching the end of the deflate block header. - - inflate() should normally be called until it returns Z_STREAM_END or an - error. However if all decompression is to be performed in a single step (a - single call of inflate), the parameter flush should be set to Z_FINISH. In - this case all pending input is processed and all pending output is flushed; - avail_out must be large enough to hold all the uncompressed data. (The size - of the uncompressed data may have been saved by the compressor for this - purpose.) The next operation on this stream must be inflateEnd to deallocate - the decompression state. The use of Z_FINISH is never required, but can be - used to inform inflate that a faster approach may be used for the single - inflate() call. - - In this implementation, inflate() always flushes as much output as - possible to the output buffer, and always uses the faster approach on the - first call. So the only effect of the flush parameter in this implementation - is on the return value of inflate(), as noted below, or when it returns early - because Z_BLOCK or Z_TREES is used. - - If a preset dictionary is needed after this call (see inflateSetDictionary - below), inflate sets strm->adler to the adler32 checksum of the dictionary - chosen by the compressor and returns Z_NEED_DICT; otherwise it sets - strm->adler to the adler32 checksum of all output produced so far (that is, - total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described - below. At the end of the stream, inflate() checks that its computed adler32 - checksum is equal to that saved by the compressor and returns Z_STREAM_END - only if the checksum is correct. - - inflate() can decompress and check either zlib-wrapped or gzip-wrapped - deflate data. The header type is detected automatically, if requested when - initializing with inflateInit2(). Any information contained in the gzip - header is not retained, so applications that need that information should - instead use raw inflate, see inflateInit2() below, or inflateBack() and - perform their own processing of the gzip header and trailer. - - inflate() returns Z_OK if some progress has been made (more input processed - or more output produced), Z_STREAM_END if the end of the compressed data has - been reached and all uncompressed output has been produced, Z_NEED_DICT if a - preset dictionary is needed at this point, Z_DATA_ERROR if the input data was - corrupted (input stream not conforming to the zlib format or incorrect check - value), Z_STREAM_ERROR if the stream structure was inconsistent (for example - next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory, - Z_BUF_ERROR if no progress is possible or if there was not enough room in the - output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and - inflate() can be called again with more input and more output space to - continue decompressing. If Z_DATA_ERROR is returned, the application may - then call inflateSync() to look for a good compression block if a partial - recovery of the data is desired. -*/ - - -ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any pending - output. - - inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state - was inconsistent. In the error case, msg may be set but then points to a - static string (which must not be deallocated). -*/ - - - /* Advanced functions */ - -/* - The following functions are needed only in some special applications. -*/ - -/* -ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, - int level, - int method, - int windowBits, - int memLevel, - int strategy)); - - This is another version of deflateInit with more compression options. The - fields next_in, zalloc, zfree and opaque must be initialized before by the - caller. - - The method parameter is the compression method. It must be Z_DEFLATED in - this version of the library. - - The windowBits parameter is the base two logarithm of the window size - (the size of the history buffer). It should be in the range 8..15 for this - version of the library. Larger values of this parameter result in better - compression at the expense of memory usage. The default value is 15 if - deflateInit is used instead. - - windowBits can also be -8..-15 for raw deflate. In this case, -windowBits - determines the window size. deflate() will then generate raw deflate data - with no zlib header or trailer, and will not compute an adler32 check value. - - windowBits can also be greater than 15 for optional gzip encoding. Add - 16 to windowBits to write a simple gzip header and trailer around the - compressed data instead of a zlib wrapper. The gzip header will have no - file name, no extra data, no comment, no modification time (set to zero), no - header crc, and the operating system will be set to 255 (unknown). If a - gzip stream is being written, strm->adler is a crc32 instead of an adler32. - - The memLevel parameter specifies how much memory should be allocated - for the internal compression state. memLevel=1 uses minimum memory but is - slow and reduces compression ratio; memLevel=9 uses maximum memory for - optimal speed. The default value is 8. See zconf.h for total memory usage - as a function of windowBits and memLevel. - - The strategy parameter is used to tune the compression algorithm. Use the - value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a - filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no - string match), or Z_RLE to limit match distances to one (run-length - encoding). Filtered data consists mostly of small values with a somewhat - random distribution. In this case, the compression algorithm is tuned to - compress them better. The effect of Z_FILTERED is to force more Huffman - coding and less string matching; it is somewhat intermediate between - Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as - fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The - strategy parameter only affects the compression ratio but not the - correctness of the compressed output even if it is not set appropriately. - Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler - decoder for special applications. - - deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid - method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is - incompatible with the version assumed by the caller (ZLIB_VERSION). msg is - set to null if there is no error message. deflateInit2 does not perform any - compression: this will be done by deflate(). -*/ - -ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); -/* - Initializes the compression dictionary from the given byte sequence - without producing any compressed output. This function must be called - immediately after deflateInit, deflateInit2 or deflateReset, before any call - of deflate. The compressor and decompressor must use exactly the same - dictionary (see inflateSetDictionary). - - The dictionary should consist of strings (byte sequences) that are likely - to be encountered later in the data to be compressed, with the most commonly - used strings preferably put towards the end of the dictionary. Using a - dictionary is most useful when the data to be compressed is short and can be - predicted with good accuracy; the data can then be compressed better than - with the default empty dictionary. - - Depending on the size of the compression data structures selected by - deflateInit or deflateInit2, a part of the dictionary may in effect be - discarded, for example if the dictionary is larger than the window size - provided in deflateInit or deflateInit2. Thus the strings most likely to be - useful should be put at the end of the dictionary, not at the front. In - addition, the current implementation of deflate will use at most the window - size minus 262 bytes of the provided dictionary. - - Upon return of this function, strm->adler is set to the adler32 value - of the dictionary; the decompressor may later use this value to determine - which dictionary has been used by the compressor. (The adler32 value - applies to the whole dictionary even if only a subset of the dictionary is - actually used by the compressor.) If a raw deflate was requested, then the - adler32 value is not computed and strm->adler is not set. - - deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a - parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is - inconsistent (for example if deflate has already been called for this stream - or if the compression method is bsort). deflateSetDictionary does not - perform any compression: this will be done by deflate(). -*/ - -ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, - z_streamp source)); -/* - Sets the destination stream as a complete copy of the source stream. - - This function can be useful when several compression strategies will be - tried, for example when there are several ways of pre-processing the input - data with a filter. The streams that will be discarded should then be freed - by calling deflateEnd. Note that deflateCopy duplicates the internal - compression state which can be quite large, so this strategy is slow and can - consume lots of memory. - - deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if the source stream state was inconsistent - (such as zalloc being Z_NULL). msg is left unchanged in both source and - destination. -*/ - -ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); -/* - This function is equivalent to deflateEnd followed by deflateInit, - but does not free and reallocate all the internal compression state. The - stream will keep the same compression level and any other attributes that - may have been set by deflateInit2. - - deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being Z_NULL). -*/ - -ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, - int level, - int strategy)); -/* - Dynamically update the compression level and compression strategy. The - interpretation of level and strategy is as in deflateInit2. This can be - used to switch between compression and straight copy of the input data, or - to switch to a different kind of input data requiring a different strategy. - If the compression level is changed, the input available so far is - compressed with the old level (and may be flushed); the new level will take - effect only at the next call of deflate(). - - Before the call of deflateParams, the stream state must be set as for - a call of deflate(), since the currently available input may have to be - compressed and flushed. In particular, strm->avail_out must be non-zero. - - deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source - stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if - strm->avail_out was zero. -*/ - -ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, - int good_length, - int max_lazy, - int nice_length, - int max_chain)); -/* - Fine tune deflate's internal compression parameters. This should only be - used by someone who understands the algorithm used by zlib's deflate for - searching for the best matching string, and even then only by the most - fanatic optimizer trying to squeeze out the last compressed bit for their - specific input data. Read the deflate.c source code for the meaning of the - max_lazy, good_length, nice_length, and max_chain parameters. - - deflateTune() can be called after deflateInit() or deflateInit2(), and - returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. - */ - -ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, - uLong sourceLen)); -/* - deflateBound() returns an upper bound on the compressed size after - deflation of sourceLen bytes. It must be called after deflateInit() or - deflateInit2(), and after deflateSetHeader(), if used. This would be used - to allocate an output buffer for deflation in a single pass, and so would be - called before deflate(). -*/ - -ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, - int bits, - int value)); -/* - deflatePrime() inserts bits in the deflate output stream. The intent - is that this function is used to start off the deflate output with the bits - leftover from a previous deflate stream when appending to it. As such, this - function can only be used for raw deflate, and must be used before the first - deflate() call after a deflateInit2() or deflateReset(). bits must be less - than or equal to 16, and that many of the least significant bits of value - will be inserted in the output. - - deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, - gz_headerp head)); -/* - deflateSetHeader() provides gzip header information for when a gzip - stream is requested by deflateInit2(). deflateSetHeader() may be called - after deflateInit2() or deflateReset() and before the first call of - deflate(). The text, time, os, extra field, name, and comment information - in the provided gz_header structure are written to the gzip header (xflag is - ignored -- the extra flags are set according to the compression level). The - caller must assure that, if not Z_NULL, name and comment are terminated with - a zero byte, and that if extra is not Z_NULL, that extra_len bytes are - available there. If hcrc is true, a gzip header crc is included. Note that - the current versions of the command-line version of gzip (up through version - 1.3.x) do not support header crc's, and will report that it is a "multi-part - gzip file" and give up. - - If deflateSetHeader is not used, the default gzip header has text false, - the time set to zero, and os set to 255, with no extra, name, or comment - fields. The gzip header is returned to the default state by deflateReset(). - - deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -/* -ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, - int windowBits)); - - This is another version of inflateInit with an extra parameter. The - fields next_in, avail_in, zalloc, zfree and opaque must be initialized - before by the caller. - - The windowBits parameter is the base two logarithm of the maximum window - size (the size of the history buffer). It should be in the range 8..15 for - this version of the library. The default value is 15 if inflateInit is used - instead. windowBits must be greater than or equal to the windowBits value - provided to deflateInit2() while compressing, or it must be equal to 15 if - deflateInit2() was not used. If a compressed stream with a larger window - size is given as input, inflate() will return with the error code - Z_DATA_ERROR instead of trying to allocate a larger window. - - windowBits can also be zero to request that inflate use the window size in - the zlib header of the compressed stream. - - windowBits can also be -8..-15 for raw inflate. In this case, -windowBits - determines the window size. inflate() will then process raw deflate data, - not looking for a zlib or gzip header, not generating a check value, and not - looking for any check values for comparison at the end of the stream. This - is for use with other formats that use the deflate compressed data format - such as zip. Those formats provide their own check values. If a custom - format is developed using the raw deflate format for compressed data, it is - recommended that a check value such as an adler32 or a crc32 be applied to - the uncompressed data as is done in the zlib, gzip, and zip formats. For - most applications, the zlib format should be used as is. Note that comments - above on the use in deflateInit2() applies to the magnitude of windowBits. - - windowBits can also be greater than 15 for optional gzip decoding. Add - 32 to windowBits to enable zlib and gzip decoding with automatic header - detection, or add 16 to decode only the gzip format (the zlib format will - return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a - crc32 instead of an adler32. - - inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_VERSION_ERROR if the zlib library version is incompatible with the - version assumed by the caller, or Z_STREAM_ERROR if the parameters are - invalid, such as a null pointer to the structure. msg is set to null if - there is no error message. inflateInit2 does not perform any decompression - apart from possibly reading the zlib header if present: actual decompression - will be done by inflate(). (So next_in and avail_in may be modified, but - next_out and avail_out are unused and unchanged.) The current implementation - of inflateInit2() does not process any header information -- that is - deferred until inflate() is called. -*/ - -ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); -/* - Initializes the decompression dictionary from the given uncompressed byte - sequence. This function must be called immediately after a call of inflate, - if that call returned Z_NEED_DICT. The dictionary chosen by the compressor - can be determined from the adler32 value returned by that call of inflate. - The compressor and decompressor must use exactly the same dictionary (see - deflateSetDictionary). For raw inflate, this function can be called - immediately after inflateInit2() or inflateReset() and before any call of - inflate() to set the dictionary. The application must insure that the - dictionary that was used for compression is provided. - - inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a - parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is - inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the - expected one (incorrect adler32 value). inflateSetDictionary does not - perform any decompression: this will be done by subsequent calls of - inflate(). -*/ - -ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); -/* - Skips invalid compressed data until a full flush point (see above the - description of deflate with Z_FULL_FLUSH) can be found, or until all - available input is skipped. No output is provided. - - inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR - if no more input was provided, Z_DATA_ERROR if no flush point has been - found, or Z_STREAM_ERROR if the stream structure was inconsistent. In the - success case, the application may save the current current value of total_in - which indicates where valid compressed data was found. In the error case, - the application may repeatedly call inflateSync, providing more input each - time, until success or end of the input data. -*/ - -ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, - z_streamp source)); -/* - Sets the destination stream as a complete copy of the source stream. - - This function can be useful when randomly accessing a large stream. The - first pass through the stream can periodically record the inflate state, - allowing restarting inflate at those points when randomly accessing the - stream. - - inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if the source stream state was inconsistent - (such as zalloc being Z_NULL). msg is left unchanged in both source and - destination. -*/ - -ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); -/* - This function is equivalent to inflateEnd followed by inflateInit, - but does not free and reallocate all the internal decompression state. The - stream will keep attributes that may have been set by inflateInit2. - - inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being Z_NULL). -*/ - -ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, - int windowBits)); -/* - This function is the same as inflateReset, but it also permits changing - the wrap and window size requests. The windowBits parameter is interpreted - the same as it is for inflateInit2. - - inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being Z_NULL), or if - the windowBits parameter is invalid. -*/ - -ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, - int bits, - int value)); -/* - This function inserts bits in the inflate input stream. The intent is - that this function is used to start inflating at a bit position in the - middle of a byte. The provided bits will be used before any bytes are used - from next_in. This function should only be used with raw inflate, and - should be used before the first inflate() call after inflateInit2() or - inflateReset(). bits must be less than or equal to 16, and that many of the - least significant bits of value will be inserted in the input. - - If bits is negative, then the input stream bit buffer is emptied. Then - inflatePrime() can be called again to put bits in the buffer. This is used - to clear out bits leftover after feeding inflate a block description prior - to feeding inflate codes. - - inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); -/* - This function returns two values, one in the lower 16 bits of the return - value, and the other in the remaining upper bits, obtained by shifting the - return value down 16 bits. If the upper value is -1 and the lower value is - zero, then inflate() is currently decoding information outside of a block. - If the upper value is -1 and the lower value is non-zero, then inflate is in - the middle of a stored block, with the lower value equaling the number of - bytes from the input remaining to copy. If the upper value is not -1, then - it is the number of bits back from the current bit position in the input of - the code (literal or length/distance pair) currently being processed. In - that case the lower value is the number of bytes already emitted for that - code. - - A code is being processed if inflate is waiting for more input to complete - decoding of the code, or if it has completed decoding but is waiting for - more output space to write the literal or match data. - - inflateMark() is used to mark locations in the input data for random - access, which may be at bit positions, and to note those cases where the - output of a code may span boundaries of random access blocks. The current - location in the input stream can be determined from avail_in and data_type - as noted in the description for the Z_BLOCK flush parameter for inflate. - - inflateMark returns the value noted above or -1 << 16 if the provided - source stream state was inconsistent. -*/ - -ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, - gz_headerp head)); -/* - inflateGetHeader() requests that gzip header information be stored in the - provided gz_header structure. inflateGetHeader() may be called after - inflateInit2() or inflateReset(), and before the first call of inflate(). - As inflate() processes the gzip stream, head->done is zero until the header - is completed, at which time head->done is set to one. If a zlib stream is - being decoded, then head->done is set to -1 to indicate that there will be - no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be - used to force inflate() to return immediately after header processing is - complete and before any actual data is decompressed. - - The text, time, xflags, and os fields are filled in with the gzip header - contents. hcrc is set to true if there is a header CRC. (The header CRC - was valid if done is set to one.) If extra is not Z_NULL, then extra_max - contains the maximum number of bytes to write to extra. Once done is true, - extra_len contains the actual extra field length, and extra contains the - extra field, or that field truncated if extra_max is less than extra_len. - If name is not Z_NULL, then up to name_max characters are written there, - terminated with a zero unless the length is greater than name_max. If - comment is not Z_NULL, then up to comm_max characters are written there, - terminated with a zero unless the length is greater than comm_max. When any - of extra, name, or comment are not Z_NULL and the respective field is not - present in the header, then that field is set to Z_NULL to signal its - absence. This allows the use of deflateSetHeader() with the returned - structure to duplicate the header. However if those fields are set to - allocated memory, then the application will need to save those pointers - elsewhere so that they can be eventually freed. - - If inflateGetHeader is not used, then the header information is simply - discarded. The header is always checked for validity, including the header - CRC if present. inflateReset() will reset the process to discard the header - information. The application would need to call inflateGetHeader() again to - retrieve the header from the next gzip stream. - - inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -/* -ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, - unsigned char FAR *window)); - - Initialize the internal stream state for decompression using inflateBack() - calls. The fields zalloc, zfree and opaque in strm must be initialized - before the call. If zalloc and zfree are Z_NULL, then the default library- - derived memory allocation routines are used. windowBits is the base two - logarithm of the window size, in the range 8..15. window is a caller - supplied buffer of that size. Except for special applications where it is - assured that deflate was used with small window sizes, windowBits must be 15 - and a 32K byte window must be supplied to be able to decompress general - deflate streams. - - See inflateBack() for the usage of these routines. - - inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of - the paramaters are invalid, Z_MEM_ERROR if the internal state could not be - allocated, or Z_VERSION_ERROR if the version of the library does not match - the version of the header file. -*/ - -typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); -typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); - -ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, - in_func in, void FAR *in_desc, - out_func out, void FAR *out_desc)); -/* - inflateBack() does a raw inflate with a single call using a call-back - interface for input and output. This is more efficient than inflate() for - file i/o applications in that it avoids copying between the output and the - sliding window by simply making the window itself the output buffer. This - function trusts the application to not change the output buffer passed by - the output function, at least until inflateBack() returns. - - inflateBackInit() must be called first to allocate the internal state - and to initialize the state with the user-provided window buffer. - inflateBack() may then be used multiple times to inflate a complete, raw - deflate stream with each call. inflateBackEnd() is then called to free the - allocated state. - - A raw deflate stream is one with no zlib or gzip header or trailer. - This routine would normally be used in a utility that reads zip or gzip - files and writes out uncompressed files. The utility would decode the - header and process the trailer on its own, hence this routine expects only - the raw deflate stream to decompress. This is different from the normal - behavior of inflate(), which expects either a zlib or gzip header and - trailer around the deflate stream. - - inflateBack() uses two subroutines supplied by the caller that are then - called by inflateBack() for input and output. inflateBack() calls those - routines until it reads a complete deflate stream and writes out all of the - uncompressed data, or until it encounters an error. The function's - parameters and return types are defined above in the in_func and out_func - typedefs. inflateBack() will call in(in_desc, &buf) which should return the - number of bytes of provided input, and a pointer to that input in buf. If - there is no input available, in() must return zero--buf is ignored in that - case--and inflateBack() will return a buffer error. inflateBack() will call - out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() - should return zero on success, or non-zero on failure. If out() returns - non-zero, inflateBack() will return with an error. Neither in() nor out() - are permitted to change the contents of the window provided to - inflateBackInit(), which is also the buffer that out() uses to write from. - The length written by out() will be at most the window size. Any non-zero - amount of input may be provided by in(). - - For convenience, inflateBack() can be provided input on the first call by - setting strm->next_in and strm->avail_in. If that input is exhausted, then - in() will be called. Therefore strm->next_in must be initialized before - calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called - immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in - must also be initialized, and then if strm->avail_in is not zero, input will - initially be taken from strm->next_in[0 .. strm->avail_in - 1]. - - The in_desc and out_desc parameters of inflateBack() is passed as the - first parameter of in() and out() respectively when they are called. These - descriptors can be optionally used to pass any information that the caller- - supplied in() and out() functions need to do their job. - - On return, inflateBack() will set strm->next_in and strm->avail_in to - pass back any unused input that was provided by the last in() call. The - return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR - if in() or out() returned an error, Z_DATA_ERROR if there was a format error - in the deflate stream (in which case strm->msg is set to indicate the nature - of the error), or Z_STREAM_ERROR if the stream was not properly initialized. - In the case of Z_BUF_ERROR, an input or output error can be distinguished - using strm->next_in which will be Z_NULL only if in() returned an error. If - strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning - non-zero. (in() will always be called before out(), so strm->next_in is - assured to be defined if out() returns non-zero.) Note that inflateBack() - cannot return Z_OK. -*/ - -ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); -/* - All memory allocated by inflateBackInit() is freed. - - inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream - state was inconsistent. -*/ - -ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); -/* Return flags indicating compile-time options. - - Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: - 1.0: size of uInt - 3.2: size of uLong - 5.4: size of voidpf (pointer) - 7.6: size of z_off_t - - Compiler, assembler, and debug options: - 8: DEBUG - 9: ASMV or ASMINF -- use ASM code - 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention - 11: 0 (reserved) - - One-time table building (smaller code, but not thread-safe if true): - 12: BUILDFIXED -- build static block decoding tables when needed - 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed - 14,15: 0 (reserved) - - Library content (indicates missing functionality): - 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking - deflate code when not needed) - 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect - and decode gzip streams (to avoid linking crc code) - 18-19: 0 (reserved) - - Operation variations (changes in library functionality): - 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate - 21: FASTEST -- deflate algorithm with only one, lowest compression level - 22,23: 0 (reserved) - - The sprintf variant used by gzprintf (zero is best): - 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format - 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! - 26: 0 = returns value, 1 = void -- 1 means inferred string length returned - - Remainder: - 27-31: 0 (reserved) - */ - - - /* utility functions */ - -/* - The following utility functions are implemented on top of the basic - stream-oriented functions. To simplify the interface, some default options - are assumed (compression level and memory usage, standard memory allocation - functions). The source code of these utility functions can be modified if - you need special options. -*/ - -ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); -/* - Compresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total size - of the destination buffer, which must be at least the value returned by - compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed buffer. - - compress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer. -*/ - -ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen, - int level)); -/* - Compresses the source buffer into the destination buffer. The level - parameter has the same meaning as in deflateInit. sourceLen is the byte - length of the source buffer. Upon entry, destLen is the total size of the - destination buffer, which must be at least the value returned by - compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed buffer. - - compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_BUF_ERROR if there was not enough room in the output buffer, - Z_STREAM_ERROR if the level parameter is invalid. -*/ - -ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); -/* - compressBound() returns an upper bound on the compressed size after - compress() or compress2() on sourceLen bytes. It would be used before a - compress() or compress2() call to allocate the destination buffer. -*/ - -ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); -/* - Decompresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total size - of the destination buffer, which must be large enough to hold the entire - uncompressed data. (The size of the uncompressed data must have been saved - previously by the compressor and transmitted to the decompressor by some - mechanism outside the scope of this compression library.) Upon exit, destLen - is the actual size of the uncompressed buffer. - - uncompress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. -*/ - - - /* gzip file access functions */ - -/* - This library supports reading and writing files in gzip (.gz) format with - an interface similar to that of stdio, using the functions that start with - "gz". The gzip format is different from the zlib format. gzip is a gzip - wrapper, documented in RFC 1952, wrapped around a deflate stream. -*/ - -typedef voidp gzFile; /* opaque gzip file descriptor */ - -/* -ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); - - Opens a gzip (.gz) file for reading or writing. The mode parameter is as - in fopen ("rb" or "wb") but can also include a compression level ("wb9") or - a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only - compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' - for fixed code compression as in "wb9F". (See the description of - deflateInit2 for more information about the strategy parameter.) Also "a" - can be used instead of "w" to request that the gzip stream that will be - written be appended to the file. "+" will result in an error, since reading - and writing to the same gzip file is not supported. - - gzopen can be used to read a file which is not in gzip format; in this - case gzread will directly read from the file without decompression. - - gzopen returns NULL if the file could not be opened, if there was - insufficient memory to allocate the gzFile state, or if an invalid mode was - specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). - errno can be checked to determine if the reason gzopen failed was that the - file could not be opened. -*/ - -ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); -/* - gzdopen associates a gzFile with the file descriptor fd. File descriptors - are obtained from calls like open, dup, creat, pipe or fileno (if the file - has been previously opened with fopen). The mode parameter is as in gzopen. - - The next call of gzclose on the returned gzFile will also close the file - descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor - fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, - mode);. The duplicated descriptor should be saved to avoid a leak, since - gzdopen does not close fd if it fails. - - gzdopen returns NULL if there was insufficient memory to allocate the - gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not - provided, or '+' was provided), or if fd is -1. The file descriptor is not - used until the next gz* read, write, seek, or close operation, so gzdopen - will not detect if fd is invalid (unless fd is -1). -*/ - -ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); -/* - Set the internal buffer size used by this library's functions. The - default buffer size is 8192 bytes. This function must be called after - gzopen() or gzdopen(), and before any other calls that read or write the - file. The buffer memory allocation is always deferred to the first read or - write. Two buffers are allocated, either both of the specified size when - writing, or one of the specified size and the other twice that size when - reading. A larger buffer size of, for example, 64K or 128K bytes will - noticeably increase the speed of decompression (reading). - - The new buffer size also affects the maximum length for gzprintf(). - - gzbuffer() returns 0 on success, or -1 on failure, such as being called - too late. -*/ - -ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); -/* - Dynamically update the compression level or strategy. See the description - of deflateInit2 for the meaning of these parameters. - - gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not - opened for writing. -*/ - -ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); -/* - Reads the given number of uncompressed bytes from the compressed file. If - the input file was not in gzip format, gzread copies the given number of - bytes into the buffer. - - After reaching the end of a gzip stream in the input, gzread will continue - to read, looking for another gzip stream, or failing that, reading the rest - of the input file directly without decompression. The entire input file - will be read if gzread is called until it returns less than the requested - len. - - gzread returns the number of uncompressed bytes actually read, less than - len for end of file, or -1 for error. -*/ - -ZEXTERN int ZEXPORT gzwrite OF((gzFile file, - voidpc buf, unsigned len)); -/* - Writes the given number of uncompressed bytes into the compressed file. - gzwrite returns the number of uncompressed bytes written or 0 in case of - error. -*/ - -ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); -/* - Converts, formats, and writes the arguments to the compressed file under - control of the format string, as in fprintf. gzprintf returns the number of - uncompressed bytes actually written, or 0 in case of error. The number of - uncompressed bytes written is limited to 8191, or one less than the buffer - size given to gzbuffer(). The caller should assure that this limit is not - exceeded. If it is exceeded, then gzprintf() will return an error (0) with - nothing written. In this case, there may also be a buffer overflow with - unpredictable consequences, which is possible only if zlib was compiled with - the insecure functions sprintf() or vsprintf() because the secure snprintf() - or vsnprintf() functions were not available. This can be determined using - zlibCompileFlags(). -*/ - -ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); -/* - Writes the given null-terminated string to the compressed file, excluding - the terminating null character. - - gzputs returns the number of characters written, or -1 in case of error. -*/ - -ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); -/* - Reads bytes from the compressed file until len-1 characters are read, or a - newline character is read and transferred to buf, or an end-of-file - condition is encountered. If any characters are read or if len == 1, the - string is terminated with a null character. If no characters are read due - to an end-of-file or len < 1, then the buffer is left untouched. - - gzgets returns buf which is a null-terminated string, or it returns NULL - for end-of-file or in case of error. If there was an error, the contents at - buf are indeterminate. -*/ - -ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); -/* - Writes c, converted to an unsigned char, into the compressed file. gzputc - returns the value that was written, or -1 in case of error. -*/ - -ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); -/* - Reads one byte from the compressed file. gzgetc returns this byte or -1 - in case of end of file or error. -*/ - -ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); -/* - Push one character back onto the stream to be read as the first character - on the next read. At least one character of push-back is allowed. - gzungetc() returns the character pushed, or -1 on failure. gzungetc() will - fail if c is -1, and may fail if a character has been pushed but not read - yet. If gzungetc is used immediately after gzopen or gzdopen, at least the - output buffer size of pushed characters is allowed. (See gzbuffer above.) - The pushed character will be discarded if the stream is repositioned with - gzseek() or gzrewind(). -*/ - -ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); -/* - Flushes all pending output into the compressed file. The parameter flush - is as in the deflate() function. The return value is the zlib error number - (see function gzerror below). gzflush is only permitted when writing. - - If the flush parameter is Z_FINISH, the remaining data is written and the - gzip stream is completed in the output. If gzwrite() is called again, a new - gzip stream will be started in the output. gzread() is able to read such - concatented gzip streams. - - gzflush should be called only when strictly necessary because it will - degrade compression if called too often. -*/ - -/* -ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, - z_off_t offset, int whence)); - - Sets the starting position for the next gzread or gzwrite on the given - compressed file. The offset represents a number of bytes in the - uncompressed data stream. The whence parameter is defined as in lseek(2); - the value SEEK_END is not supported. - - If the file is opened for reading, this function is emulated but can be - extremely slow. If the file is opened for writing, only forward seeks are - supported; gzseek then compresses a sequence of zeroes up to the new - starting position. - - gzseek returns the resulting offset location as measured in bytes from - the beginning of the uncompressed stream, or -1 in case of error, in - particular if the file is opened for writing and the new starting position - would be before the current position. -*/ - -ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); -/* - Rewinds the given file. This function is supported only for reading. - - gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) -*/ - -/* -ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); - - Returns the starting position for the next gzread or gzwrite on the given - compressed file. This position represents a number of bytes in the - uncompressed data stream, and is zero when starting, even if appending or - reading a gzip stream from the middle of a file using gzdopen(). - - gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) -*/ - -/* -ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); - - Returns the current offset in the file being read or written. This offset - includes the count of bytes that precede the gzip stream, for example when - appending or when using gzdopen() for reading. When reading, the offset - does not include as yet unused buffered input. This information can be used - for a progress indicator. On error, gzoffset() returns -1. -*/ - -ZEXTERN int ZEXPORT gzeof OF((gzFile file)); -/* - Returns true (1) if the end-of-file indicator has been set while reading, - false (0) otherwise. Note that the end-of-file indicator is set only if the - read tried to go past the end of the input, but came up short. Therefore, - just like feof(), gzeof() may return false even if there is no more data to - read, in the event that the last read request was for the exact number of - bytes remaining in the input file. This will happen if the input file size - is an exact multiple of the buffer size. - - If gzeof() returns true, then the read functions will return no more data, - unless the end-of-file indicator is reset by gzclearerr() and the input file - has grown since the previous end of file was detected. -*/ - -ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); -/* - Returns true (1) if file is being copied directly while reading, or false - (0) if file is a gzip stream being decompressed. This state can change from - false to true while reading the input file if the end of a gzip stream is - reached, but is followed by data that is not another gzip stream. - - If the input file is empty, gzdirect() will return true, since the input - does not contain a gzip stream. - - If gzdirect() is used immediately after gzopen() or gzdopen() it will - cause buffers to be allocated to allow reading the file to determine if it - is a gzip file. Therefore if gzbuffer() is used, it should be called before - gzdirect(). -*/ - -ZEXTERN int ZEXPORT gzclose OF((gzFile file)); -/* - Flushes all pending output if necessary, closes the compressed file and - deallocates the (de)compression state. Note that once file is closed, you - cannot call gzerror with file, since its structures have been deallocated. - gzclose must not be called more than once on the same file, just as free - must not be called more than once on the same allocation. - - gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a - file operation error, or Z_OK on success. -*/ - -ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); -ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); -/* - Same as gzclose(), but gzclose_r() is only for use when reading, and - gzclose_w() is only for use when writing or appending. The advantage to - using these instead of gzclose() is that they avoid linking in zlib - compression or decompression code that is not used when only reading or only - writing respectively. If gzclose() is used, then both compression and - decompression code will be included the application when linking to a static - zlib library. -*/ - -ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); -/* - Returns the error message for the last error which occurred on the given - compressed file. errnum is set to zlib error number. If an error occurred - in the file system and not in the compression library, errnum is set to - Z_ERRNO and the application may consult errno to get the exact error code. - - The application must not modify the returned string. Future calls to - this function may invalidate the previously returned string. If file is - closed, then the string previously returned by gzerror will no longer be - available. - - gzerror() should be used to distinguish errors from end-of-file for those - functions above that do not distinguish those cases in their return values. -*/ - -ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); -/* - Clears the error and end-of-file flags for file. This is analogous to the - clearerr() function in stdio. This is useful for continuing to read a gzip - file that is being written concurrently. -*/ - - - /* checksum functions */ - -/* - These functions are not related to compression but are exported - anyway because they might be useful in applications using the compression - library. -*/ - -ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); -/* - Update a running Adler-32 checksum with the bytes buf[0..len-1] and - return the updated checksum. If buf is Z_NULL, this function returns the - required initial value for the checksum. - - An Adler-32 checksum is almost as reliable as a CRC32 but can be computed - much faster. - - Usage example: - - uLong adler = adler32(0L, Z_NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - adler = adler32(adler, buffer, length); - } - if (adler != original_adler) error(); -*/ - -/* -ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, - z_off_t len2)); - - Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 - and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for - each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of - seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. -*/ - -ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); -/* - Update a running CRC-32 with the bytes buf[0..len-1] and return the - updated CRC-32. If buf is Z_NULL, this function returns the required - initial value for the for the crc. Pre- and post-conditioning (one's - complement) is performed within this function so it shouldn't be done by the - application. - - Usage example: - - uLong crc = crc32(0L, Z_NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - crc = crc32(crc, buffer, length); - } - if (crc != original_crc) error(); -*/ - -/* -ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); - - Combine two CRC-32 check values into one. For two sequences of bytes, - seq1 and seq2 with lengths len1 and len2, CRC-32 check values were - calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 - check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and - len2. -*/ - - - /* various hacks, don't look :) */ - -/* deflateInit and inflateInit are macros to allow checking the zlib version - * and the compiler's view of z_stream: - */ -ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, - int windowBits, int memLevel, - int strategy, const char *version, - int stream_size)); -ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, - unsigned char FAR *window, - const char *version, - int stream_size)); -#define deflateInit(strm, level) \ - deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) -#define inflateInit(strm) \ - inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) -#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ - deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ - (strategy), ZLIB_VERSION, sizeof(z_stream)) -#define inflateInit2(strm, windowBits) \ - inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) -#define inflateBackInit(strm, windowBits, window) \ - inflateBackInit_((strm), (windowBits), (window), \ - ZLIB_VERSION, sizeof(z_stream)) - -/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or - * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if - * both are true, the application gets the *64 functions, and the regular - * functions are changed to 64 bits) -- in case these are set on systems - * without large file support, _LFS64_LARGEFILE must also be true - */ -#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 - ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); - ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); - ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); - ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); - ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); -#endif - -#if !defined(ZLIB_INTERNAL) && _FILE_OFFSET_BITS-0 == 64 && _LFS64_LARGEFILE-0 -# define gzopen gzopen64 -# define gzseek gzseek64 -# define gztell gztell64 -# define gzoffset gzoffset64 -# define adler32_combine adler32_combine64 -# define crc32_combine crc32_combine64 -# ifdef _LARGEFILE64_SOURCE - ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); - ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); - ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); - ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); -# endif -#else - ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); - ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); - ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); - ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); -#endif - -/* hack for buggy compilers */ -#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) - struct internal_state {int dummy;}; -#endif - -/* undocumented functions */ -ZEXTERN const char * ZEXPORT zError OF((int)); -ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); -ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); -ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); - -#ifdef __cplusplus -} -#endif - -#endif /* ZLIB_H */ diff --git a/examples/bitmap/bitmapTobytes/main.go b/examples/bitmap/bitmapTobytes/main.go deleted file mode 100644 index cc012b9c..00000000 --- a/examples/bitmap/bitmapTobytes/main.go +++ /dev/null @@ -1,34 +0,0 @@ -package main - -import ( - "bytes" - "log" - - "image/jpeg" - "io/ioutil" - - "github.com/go-vgo/robotgo" - "golang.org/x/image/bmp" -) - -func main() { - bitMap := robotgo.CaptureScreen() - defer robotgo.FreeBitmap(bitMap) - - bs := robotgo.ToBitmapBytes(bitMap) - img, err := bmp.Decode(bytes.NewReader(bs)) - if err != nil { - log.Println("bmp.Decode err is: ", err) - return - } - - b := new(bytes.Buffer) - err = jpeg.Encode(b, img, &jpeg.Options{Quality: 20}) - if err != nil { - log.Println("jpeg.Encode err is: ", err) - return - } - - log.Println("bytes: ", b.Bytes()) - ioutil.WriteFile("out.jpg", b.Bytes(), 0666) -} diff --git a/examples/bitmap/cbitmap/main.go b/examples/bitmap/cbitmap/main.go deleted file mode 100644 index c9c9560b..00000000 --- a/examples/bitmap/cbitmap/main.go +++ /dev/null @@ -1,53 +0,0 @@ -package main - -import ( - "github.com/go-vgo/robotgo" -) - -func main() { - bmp, free := loadBitmaps("start.png", "chest.png", "eat.png") - defer free() - - for { - clickBitmap(bmp["start.png"], false) - clickBitmap(bmp["chest.png"], true) - clickBitmap(bmp["eat.png"], false) - } -} - -func loadBitmaps(files ...string) (bitmaps map[string]robotgo.Bitmap, free func()) { - freeFuncs := make([]func(), 0) - bitmaps = make(map[string]robotgo.Bitmap) - for _, f := range files { - bitmap, freeFunc := readBitmap(f) - bitmaps[f] = bitmap - freeFuncs = append(freeFuncs, freeFunc) - } - - free = func() { - for key := range freeFuncs { - freeFuncs[key]() - } - } - return bitmaps, free -} - -func readBitmap(file string) (bitmap robotgo.Bitmap, free func()) { - cBitmap := robotgo.OpenBitmap(file) - bitmap = robotgo.ToBitmap(cBitmap) - free = func() { - robotgo.FreeBitmap(cBitmap) - } - return bitmap, free -} - -func clickBitmap(bmp robotgo.Bitmap, doubleClick bool) bool { - fx, fy := robotgo.FindBitmap(robotgo.ToCBitmap(bmp)) - if fx != -1 && fy != -1 { - robotgo.MoveMouse(fx, fy) - robotgo.MouseClick("left", doubleClick) - return true - } - - return false -} diff --git a/examples/bitmap/imgToBitmap/main.go b/examples/bitmap/imgToBitmap/main.go deleted file mode 100644 index 17a3df6e..00000000 --- a/examples/bitmap/imgToBitmap/main.go +++ /dev/null @@ -1,52 +0,0 @@ -//go:build go1.16 -// +build go1.16 - -package main - -import ( - _ "embed" - "fmt" - - "github.com/go-vgo/robotgo" - "github.com/vcaesar/imgo" -) - -//go:embed test_007.jpeg -var testPng []byte - -func main() { - bit1 := robotgo.CaptureScreen(300, 300, 100, 100) - defer robotgo.FreeBitmap(bit1) - robotgo.SaveBitmap(bit1, "test_003.jpeg") - - m1 := robotgo.ToImage(bit1) - fmt.Println("m1: ", m1.Bounds()) - imgo.SaveToPNG("test_01.png", m1) - - r1 := robotgo.ToRGBA(bit1) - fmt.Println("r1: ", r1.Pix) - - bit2 := robotgo.ToCBitmap(robotgo.ImgToBitmap(m1)) - robotgo.SaveBitmap(bit2, "test_002.jpeg") - - test() -} - -func test() { - bitmap := robotgo.CaptureScreen(10, 10, 10, 10) - defer robotgo.FreeBitmap(bitmap) - - img := robotgo.ToImage(bitmap) - robotgo.SavePng(img, "test_1.png") - - img1, _ := robotgo.ByteToImg(testPng) - robotgo.SaveJpeg(img1, "test_7.jpeg") - - bit2 := robotgo.ToCBitmap(robotgo.ImgToBitmap(img)) - fx, fy := robotgo.FindBitmap(bit2) - fmt.Println("FindBitmap------ ", fx, fy) - - arr := robotgo.FindAllBitmap(bit2) - fmt.Println("Find every bitmap: ", arr) - robotgo.SaveBitmap(bitmap, "test.png") -} diff --git a/examples/bitmap/imgToBitmap/test_007.jpeg b/examples/bitmap/imgToBitmap/test_007.jpeg deleted file mode 100644 index 0823de1f5b7facd6c0729da2614871a3b9112d93..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3261 zcmbW&c{tQ-8wc>;m|={qtXW2u;mDFA!`RC~RT!_LOa$|k_YeS$|=P~^0*ARI0#AulB=E{A}_&!|YtomWs&QWB9;)kG<3$X`%W z1i@f1HdZ!%c6NS6F}RrG{~Y>zfRh=p0c^k^ae#pn1m*0K^FTE5N@4VgN%J znV`%t7S@vh0|*RefPfhpA&}#j5yy7`gp-j=OyLp}_q7{PabF%qd~!ZBLZ`BY7xQ^T z;=)b8doUKhQ~UyglD|ovk(N}XbdvKcTVRL_m<`^WexF(RB$VbPH~%F4CHn6`_x>-@ zKcIg+^l^X<3_2bdm=n+j)=$~jHP$D;Pe)`k_Cw5l#(ht_+^^#D?|fzJfziFeJG9wZ zUVmtKC9iFlpdjHrz&wC@-w#zqc9U-A#1Omkdf;n)VL`kgahwg_(xt;@HZtI`l4P1A zUSd!4#6I%l@@cW7j}3vjP=%;o5*oz@^7id(Q(-JXrCue?3mYi>^k`}u7VX2&` zx=OYGd|gj?!C|pw(lYc{5uxb$hCN4hTELx&)C3OIquk-SOXJp+-=+$pjL+;GDy++M znJU}zg!n0}x4fsl@71Gu1l_*@TLYGI(OV*Ex@DS2`Qe`=v)i53`S>46a45F1%`S{Y zG$@a^eVA2K@+M&>7eW)aN8W}AIgAdi6rom0cB}KXvF&B6Z%R+RZM=g<9AKP0{2f~h z3$wjf+FK+RqIe@+28EY>uJ#SgU~X5lz5ix8&ze#;Y!exAxJ*eUpkGZoQ1>|c);U{q zi`$%|)LE#Ht1z)$c0q64SAGefo2U^3!n<54V_j=#(IY*piShH2kGZcS=gRqF{5w+m*TAO~ zBaW-*gEe-EM)HuV25CrK8<5Z#`LHo)cfc-_u@o|HE40H zmE4=NvcKLf;qz#D`9->=ts0rO;%55nh*LkTZRGI4YkE{}}OR<4$e<+@ZN;{j-&nwcXPe1=h7AWE_LbPgt)<9Ess1vb=@y;rzo{4Hjf(}nC!^7mD% zRkyknCQ@CEL?=4KR?F!ML+DnRrGLlS?lTVY-}>NVz22QwY%s00(8SBBD}HzTb@#2N zN#0cx96so--TY^+g>%%eSBpMFyFs~t5WoejAMOU@T{z1ex z)d3ePo)*Yr$j zX*JRa=QOS47Gvt)?rUCz;WAnFQ6;Ch3#%9m6>j|cR7M*&34N*ho>xK zDE8@w^9J!3P4?9*(B22bwzcZ)ego6mbya$ouAOE`pNC+{aLdv}E~=f2#&XLVA2L2> z%LYH8DQ!W(SYKAFNE9ETc&qu)MDr{f9-(;(_JnkO^9Ff(dctyU-rljud6)Foi~vm? z`h9=cCfq(>qaUH`3*UBr7as!;fG@=@2l(7npL}j#YuJQ^b2P{6O&Nx5=~AM@37OpP zCWT)nJ+oqOZ5gbey=ud~94bNw99`Y5wE{-nKI})OFeE2pYsY#^COkdlxE;`Et6bGw zL1e7jDDv){JF$PfY$5%#E(CDHo1wG{whLKeiv+WjJxrAM{~#tjH1qOjuaqgr*M2%} zX}TGqWmj4-(TaOvOD-ra3iW8WP&+y6>RR%qNncTrPk>PH?Y@>CPz*u@ZC z>Q_=04I(arQN?E2X@8UxFe%Xv2kbQ)TdgdI`CZb_xMmq4yP{duyZqWqUqycTksikk z5u;(RK3*Lgzfj}uT`%@wIJMN#9DsnYC7u?}l4N9{=iMZ|{=#1y{)_m z!>lWcenrjG0YB|SzBIC@_74iKB?%yr%o2YC%&^)UsfBlvCkbUFp<=m1QUVA2-H z14V!K*i)F%qShPn7{$m fwK^I-_4DptSMkiDMe{n#y#%j1EWyC&0)6aXG&3FM diff --git a/examples/bitmap/main.go b/examples/bitmap/main.go deleted file mode 100644 index b9ae1ca4..00000000 --- a/examples/bitmap/main.go +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// https://github.com/go-vgo/robotgo/blob/master/LICENSE -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -package main - -import ( - "fmt" - "log" - - "github.com/go-vgo/robotgo" - "github.com/vcaesar/imgo" - // "go-vgo/robotgo" -) - -func toBitmap(bmp robotgo.CBitmap) { - bitmap := robotgo.ToMMBitmapRef(bmp) - img := robotgo.ToImage(bitmap) - fmt.Println("img: ", img) - imgo.SaveToPNG("test_IMG.png", img) - - gbit := robotgo.ToBitmap(bitmap) - fmt.Println("go bitmap", gbit, gbit.Width) - - cbit := robotgo.ToCBitmap(gbit) - // defer robotgo.FreeBitmap(cbit) - log.Println("cbit == bitmap: ", cbit == bitmap) - robotgo.SaveBitmap(cbit, "tocbitmap.png") -} - -// find color -func findColor(bmp robotgo.CBitmap) { - bitmap := robotgo.ToMMBitmapRef(bmp) - - // find the color in bitmap - color := robotgo.GetColor(bitmap, 1, 2) - fmt.Println("color...", color) - cx, cy := robotgo.FindColor(robotgo.CHex(color), bitmap, 1.0) - fmt.Println("pos...", cx, cy) - cx, cy = robotgo.FindColor(robotgo.CHex(color)) - fmt.Println("pos...", cx, cy) - - cx, cy = robotgo.FindColor(0xAADCDC, bitmap) - fmt.Println("pos...", cx, cy) - cx, cy = robotgo.FindColor(0xAADCDC, nil, 0.1) - fmt.Println("pos...", cx, cy) - - cx, cy = robotgo.FindColorCS(0xAADCDC, 388, 179, 300, 300) - fmt.Println("pos...", cx, cy) - - cnt := robotgo.CountColor(0xAADCDC, bitmap) - fmt.Println("count...", cnt) - cnt1 := robotgo.CountColorCS(0xAADCDC, 10, 20, 30, 40) - fmt.Println("count...", cnt1) - - arr := robotgo.FindAllColor(0xAADCDC) - fmt.Println("find all color: ", arr) - for i := 0; i < len(arr); i++ { - fmt.Println("pos is: ", arr[i].X, arr[i].Y) - } -} - -func bitmapString(bmp robotgo.CBitmap) { - bitmap := robotgo.ToMMBitmapRef(bmp) - - // creates bitmap from string by bitmap - bitstr := robotgo.TostringBitmap(bitmap) - fmt.Println("bitstr...", bitstr) - - // sbitmap := robotgo.BitmapFromstring(bitstr, 2) - // fmt.Println("...", sbitmap) - - // sbitmap := robotgo.BitmapStr(bitstr) - sbitmap := robotgo.BitmapFromStr(bitstr) - fmt.Println("bitmap str...", sbitmap) - robotgo.SaveBitmap(sbitmap, "teststr.png") -} - -func bitmapTool(bmp robotgo.CBitmap) { - bitmap := robotgo.ToMMBitmapRef(bmp) - - // bitmap := robotgo.CaptureScreen(10, 20, 30, 40) - abool := robotgo.PointInBounds(bitmap, 1, 2) - fmt.Println("point in bounds...", abool) - - // returns new bitmap object created from a portion of another - bitpos := robotgo.GetPortion(bitmap, 10, 10, 11, 10) - fmt.Println(bitpos) - - // saves image to absolute filepath in the given format - robotgo.SaveBitmap(bitmap, "test.png") - robotgo.SaveBitmap(bitmap, "test31.tif", 1) -} - -func decode() { - img, name, err := robotgo.DecodeImg("test.png") - if err != nil { - log.Println("decode image ", err) - } - fmt.Println("decode test.png", img, name) - - byt, _ := robotgo.OpenImg("test.png") - imgo.SaveByte("test2.png", byt) - - w, h := robotgo.GetImgSize("test.png") - fmt.Println("image width and hight ", w, h) - w, h, _ = imgo.GetSize("test.png") - fmt.Println("image width and hight ", w, h) - - // convert image - robotgo.Convert("test.png", "test.tif") -} - -func bitmapTest(bmp robotgo.CBitmap) { - bitmap := robotgo.ToMMBitmapRef(bmp) - - bit := robotgo.CaptureScreen(1, 2, 40, 40) - defer robotgo.FreeBitmap(bit) - fmt.Println("CaptureScreen...", bit) - - // searches for needle in bitmap - fx, fy := robotgo.FindBitmap(bit, bitmap) - fmt.Println("FindBitmap------", fx, fy) - - // fx, fy := robotgo.FindBit(bitmap) - // fmt.Println("FindBitmap------", fx, fy) - - fx, fy = robotgo.FindBitmap(bit) - fmt.Println("FindBitmap------", fx, fy) - - fx, fy = robotgo.FindBitmap(bit, nil, 0.2) - fmt.Println("find bitmap: ", fx, fy) - - fx, fy = robotgo.FindBitmap(bit, bitmap, 0.3) - fmt.Println("find bitmap: ", fx, fy) -} - -func findBitmap(bmp robotgo.CBitmap) { - fx, fy := robotgo.FindBitmap(robotgo.ToMMBitmapRef(bmp)) - fmt.Println("findBitmap: ", fx, fy) - - fx, fy = robotgo.FindCBitmap(bmp) - fmt.Println("findCBitmap: ", fx, fy) - fx, fy = robotgo.FindCBitmap(bmp, nil, 0.1) - fmt.Println("findCBitmap: ", fx, fy) - - // open image bitmap - openbit := robotgo.OpenBitmap("test.tif") - fmt.Println("openBitmap...", openbit) - - fx, fy = robotgo.FindBitmap(openbit) - fmt.Println("FindBitmap------", fx, fy) - - fx, fy = robotgo.FindPic("test.tif") - fmt.Println("FindPic------", fx, fy) - - arr := robotgo.FindAllBitmap(openbit) - fmt.Println("find all bitmap: ", arr) - for i := 0; i < len(arr); i++ { - fmt.Println("pos is: ", arr[i].X, arr[i].Y) - } -} - -func bitmap() { - //////////////////////////////////////////////////////////////////////////////// - // Bitmap - //////////////////////////////////////////////////////////////////////////////// - - // gets all of the screen - abitMap := robotgo.CaptureScreen() - fmt.Println("abitMap...", abitMap) - - // gets part of the screen - bitmap := robotgo.CaptureScreen(100, 200, 30, 30) - defer robotgo.FreeBitmap(bitmap) - fmt.Println("CaptureScreen...", bitmap) - - cbit := robotgo.CBitmap(bitmap) - toBitmap(cbit) - - findColor(cbit) - - count := robotgo.CountBitmap(abitMap, bitmap) - fmt.Println("count...", count) - - bitmapTest(cbit) - findBitmap(cbit) - - bitmapString(cbit) - bitmapTool(cbit) - - decode() - - // free the bitmap - robotgo.FreeBitmap(abitMap) - // robotgo.FreeBitmap(bitmap) -} - -func main() { - bitmap() -} diff --git a/examples/gohook/event/main.go b/examples/gohook/event/main.go deleted file mode 100644 index 7c627f01..00000000 --- a/examples/gohook/event/main.go +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// https://github.com/go-vgo/robotgo/blob/master/LICENSE -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -package main - -import ( - "fmt" - - "github.com/go-vgo/robotgo" - // "go-vgo/robotgo" -) - -func addEvent() { - fmt.Println("--- Please press ctrl + shift + q ---") - ok := robotgo.AddEvents("q", "ctrl", "shift") - if ok { - fmt.Println("add events...") - } - - fmt.Println("--- Please press w---") - ok = robotgo.AddEvents("w") - if ok { - fmt.Println("add events") - } - - // start hook - s := robotgo.Start() - // end hook - defer robotgo.End() - - for ev := range s { - fmt.Println("hook: ", ev) - } -} - -func addMouse() { - fmt.Println("--- Please press left mouse button ---") - ok := robotgo.AddMouse("left") - if ok { - fmt.Println("add mouse...") - } - - fmt.Println("--- Please press left mouse button and move mosue to 100,100 ---") - ok = robotgo.AddMouse("left", 100, 100) - if ok { - fmt.Println("add mouse and move to 100,100 ...") - } - - fmt.Println("--- Please move mosue to 100,100 ---") - ok = robotgo.AddMousePos(100, 100) - if ok { - fmt.Println(" move mouse to 100,100 ...") - } -} - -func add() { - fmt.Println("--- Please press v---") - eve := robotgo.AddEvent("v") - - if eve { - fmt.Println("--- You press v---", "v") - } - - fmt.Println("--- Please press k---") - keve := robotgo.AddEvent("k") - if keve { - fmt.Println("--- You press k---", "k") - } - - fmt.Println("--- Please press f1---") - feve := robotgo.AddEvent("f1") - if feve { - fmt.Println("You press...", "f1") - } -} - -func event() { - //////////////////////////////////////////////////////////////////////////////// - // Global event listener - //////////////////////////////////////////////////////////////////////////////// - - add() - - fmt.Println("--- Please press left mouse button---") - mleft := robotgo.AddEvent("mleft") - if mleft { - fmt.Println("--- You press left mouse button---", "mleft") - } - - mright := robotgo.AddEvent("mright") - if mright { - fmt.Println("--- You press right mouse button---", "mright") - } - - // stop AddEvent - // robotgo.StopEvent() -} - -func main() { - fmt.Println("test begin...") - - addEvent() - - addMouse() - - event() -} diff --git a/examples/gohook/hook/main.go b/examples/gohook/hook/main.go deleted file mode 100644 index eddc31ca..00000000 --- a/examples/gohook/hook/main.go +++ /dev/null @@ -1,42 +0,0 @@ -package main - -import ( - "fmt" - - hook "github.com/robotn/gohook" -) - -// hook listen and return values using detailed examples -func add() { - s := hook.Start() - defer hook.End() - - ct := false - for { - i := <-s - - if i.Kind == hook.KeyHold && i.Rawcode == 59 { - ct = true - } - - if ct && i.Rawcode == 12 { - break - } - } -} - -// base hook example -func base() { - evChan := hook.Start() - defer hook.End() - - for ev := range evChan { - fmt.Println("hook: ", ev) - } -} - -func main() { - base() - - add() -} diff --git a/examples/gohook/main.go b/examples/gohook/main.go deleted file mode 100644 index ab6c5a5c..00000000 --- a/examples/gohook/main.go +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2016 The cauefcr Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// https://github.com/cauefcr/robotgo/blob/master/LICENSE -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -package main - -import ( - "fmt" - - "github.com/go-vgo/robotgo" - hook "github.com/robotn/gohook" -) - -func addEvent() { - fmt.Println("--- Please press ctrl + shift + q to stop hook ---") - robotgo.EventHook(hook.KeyDown, []string{"q", "ctrl", "shift"}, func(e hook.Event) { - fmt.Println("ctrl-shift-q") - robotgo.EventEnd() - }) - - fmt.Println("--- Please press w---") - robotgo.EventHook(hook.KeyDown, []string{"w"}, func(e hook.Event) { - fmt.Println("w") - }) - - s := robotgo.EventStart() - <-robotgo.EventProcess(s) -} - -func addMouse() { - fmt.Println("--- Please press left mouse button to see it's position and the right mouse button to exit ---") - robotgo.EventHook(hook.MouseDown, []string{}, func(e hook.Event) { - if e.Button == hook.MouseMap["left"] { - fmt.Printf("mouse left @ %v - %v\n", e.X, e.Y) - } else if e.Button == hook.MouseMap["right"] { - robotgo.EventEnd() - } - }) - - s := robotgo.EventStart() - <-robotgo.EventProcess(s) -} - -func lowLevel() { - //////////////////////////////////////////////////////////////////////////////// - // Global event listener - //////////////////////////////////////////////////////////////////////////////// - fmt.Println("Press q to stop event gathering") - evChan := robotgo.EventStart() - for e := range evChan { - fmt.Println(e) - if e.Keychar == 'q' { - robotgo.EventEnd() - // break - } - } -} - -func main() { - fmt.Println("test begin...") - addEvent() - - addMouse() - - lowLevel() -} diff --git a/hook.go b/hook.go deleted file mode 100644 index e7ff9302..00000000 --- a/hook.go +++ /dev/null @@ -1,195 +0,0 @@ -// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// https://github.com/go-vgo/robotgo/blob/master/LICENSE -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -package robotgo - -import ( - "strconv" - - hook "github.com/robotn/gohook" -) - -/* - ___________ ____ _______ .__ __. .___________. -| ____\ \ / / | ____|| \ | | | | -| |__ \ \/ / | |__ | \| | `---| |----` -| __| \ / | __| | . ` | | | -| |____ \ / | |____ | |\ | | | -|_______| \__/ |_______||__| \__| |__| -*/ - -// EventStart start global event hook -// return event channel -func EventStart() chan hook.Event { - return hook.Start() -} - -// EventEnd removes global event hook -func EventEnd() { - hook.End() -} - -// Deprecated: use the EventStart(), -// -// Start start global event hook -// return event channel -func Start() chan hook.Event { - return hook.Start() -} - -// Deprecated: use the EventEnd(), -// -// End removes global event hook -func End() { - hook.End() -} - -// StopEvent stop event listener, use by AddEvent() -func StopEvent() { - hook.StopEvent() -} - -// EventProcess return go hook process -func EventProcess(events chan hook.Event) chan bool { - return hook.Process(events) -} - -// EventHook register gohook event -func EventHook(when uint8, keysPressed []string, callback func(hook.Event)) { - hook.Register(when, keysPressed, callback) -} - -// AddEvent add event listener, -// -// parameters for the string type, -// the keyboard corresponding key parameters, -// -// mouse arguments: mleft, center, mright, wheelDown, wheelUp, -// wheelLeft, wheelRight. -// -// Use "robotgo.AddEvents()" or "gohook" add asynchronous event listener -func AddEvent(key string) bool { - var ( - // cs *C.char - mArr = []string{"mleft", "center", "mright", "wheelDown", - "wheelUp", "wheelLeft", "wheelRight"} - mouseBool bool - ) - - for i := 0; i < len(mArr); i++ { - if key == mArr[i] { - mouseBool = true - } - } - - if len(key) > 1 && !mouseBool { - key = strconv.Itoa(int(Keycode[key])) - } - - geve := hook.AddEvent(key) - // defer C.free(unsafe.Pointer(cs)) - return geve == 0 -} - -// AddEvents add global event hook -// -// robotgo.AddEvents("q") -// robotgo.AddEvents("q", "ctrl") -// robotgo.AddEvents("q", "ctrl", "shift") -func AddEvents(key string, arr ...string) bool { - s := hook.Start() - // defer hook.End() - - ct := false - k := 0 - for { - e := <-s - - l := len(arr) - if l > 0 { - for i := 0; i < l; i++ { - ukey := Keycode[arr[i]] - - if e.Kind == hook.KeyHold && e.Keycode == ukey { - k++ - } - - if k == l { - ct = true - } - - if e.Kind == hook.KeyUp && e.Keycode == ukey { - if k > 0 { - k-- - } - // time.Sleep(10 * time.Microsecond) - ct = false - } - } - } else { - ct = true - } - - if ct && e.Kind == hook.KeyUp && e.Keycode == Keycode[key] { - hook.End() - // k = 0 - break - } - } - - return true -} - -// AddMouse add mouse event hook -// -// mouse arguments: left, center, right, wheelDown, wheelUp, -// wheelLeft, wheelRight. -// -// robotgo.AddMouse("left") -// robotgo.AddMouse("left", 100, 100) -func AddMouse(btn string, x ...int16) bool { - s := hook.Start() - ukey := MouseMap[btn] - - ct := false - for { - e := <-s - - if len(x) > 1 { - if e.Kind == hook.MouseMove && e.X == x[0] && e.Y == x[1] { - ct = true - } - } else { - ct = true - } - - if ct && e.Kind == hook.MouseDown && e.Button == ukey { - hook.End() - break - } - } - - return true -} - -// AddMousePos add listen mouse event pos hook -func AddMousePos(x, y int16) bool { - s := hook.Start() - - for { - e := <-s - if e.Kind == hook.MouseMove && e.X == x && e.Y == y { - hook.End() - break - } - } - - return true -} From 28fd0b9af6afcaa5588f5c923e1c1c06b71b2211 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 2 Jan 2022 18:15:15 -0400 Subject: [PATCH 156/327] Add capture multi screen support and update return, and remove unused files --- .circleci/config.yml | 10 +- .github/workflows/go.yml | 4 - base/bitmap_free_c.h | 41 ++++++ bitmap/bitmap_class.h | 24 ---- bitmap/bitmap_find.h | 55 -------- bitmap/bitmap_find_c.h | 270 --------------------------------------- bitmap/goBitmap.h | 203 ----------------------------- go.mod | 4 +- go.sum | 2 - robotgo.go | 72 ++++++++--- robotgo_test.go | 31 ----- screen/goScreen.h | 20 +-- screen/screen_c.h | 2 +- screen/screengrab.h | 5 +- screen/screengrab_c.h | 16 ++- 15 files changed, 123 insertions(+), 636 deletions(-) create mode 100644 base/bitmap_free_c.h delete mode 100644 bitmap/bitmap_class.h delete mode 100644 bitmap/bitmap_find.h delete mode 100644 bitmap/bitmap_find_c.h delete mode 100644 bitmap/goBitmap.h diff --git a/.circleci/config.yml b/.circleci/config.yml index 5b6b8de2..2c56bc4d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -11,11 +11,13 @@ jobs: - checkout # specify any bash command here prefixed with `run: ` - run: apt update - - run: apt -y install gcc libc6-dev - libx11-dev xorg-dev libxtst-dev libpng++-dev - xcb libxcb-xkb-dev x11-xkb-utils libx11-xcb-dev libxkbcommon-x11-dev - libxkbcommon-dev + - run: + apt -y install gcc libc6-dev + libx11-dev xorg-dev libxtst-dev xsel xclip + # libpng++-dev + # xcb libxcb-xkb-dev x11-xkb-utils libx11-xcb-dev libxkbcommon-x11-dev + # libxkbcommon-dev - run: apt -y install xvfb # # override: diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 0f509b14..f64bda72 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -22,10 +22,6 @@ jobs: - name: Get dependencies run: | go get -v -t -d ./... - # if [ -f Gopkg.toml ]; then - # curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh - # dep ensure - # fi - name: Build run: go build -v . diff --git a/base/bitmap_free_c.h b/base/bitmap_free_c.h new file mode 100644 index 00000000..e4c751f3 --- /dev/null +++ b/base/bitmap_free_c.h @@ -0,0 +1,41 @@ +#include "MMBitmap.h" +#include +#include + +MMBitmapRef createMMBitmap_c( + uint8_t *buffer, + size_t width, + size_t height, + size_t bytewidth, + uint8_t bitsPerPixel, + uint8_t bytesPerPixel +){ + MMBitmapRef bitmap = malloc(sizeof(MMBitmap)); + if (bitmap == NULL) { return NULL; } + + bitmap->imageBuffer = buffer; + bitmap->width = width; + bitmap->height = height; + bitmap->bytewidth = bytewidth; + bitmap->bitsPerPixel = bitsPerPixel; + bitmap->bytesPerPixel = bytesPerPixel; + + return bitmap; +} + +void destroyMMBitmap(MMBitmapRef bitmap) { + assert(bitmap != NULL); + + if (bitmap->imageBuffer != NULL) { + free(bitmap->imageBuffer); + bitmap->imageBuffer = NULL; + } + + free(bitmap); +} + +void destroyMMBitmapBuffer(char * bitmapBuffer, void * hint) { + if (bitmapBuffer != NULL) { + free(bitmapBuffer); + } +} diff --git a/bitmap/bitmap_class.h b/bitmap/bitmap_class.h deleted file mode 100644 index 1f7f9c0c..00000000 --- a/bitmap/bitmap_class.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once -// #ifndef BITMAP_CLASS_H -// #define BITMAP_CLASS_H - -#include "../base/MMBitmap.h" - -/* This file defines the class "Bitmap" for dealing with raw bitmaps. */ -struct _BitmapObject { - MMBitmapRef bitmap; - MMPoint point; /* For iterator */ -}; - -typedef struct _BitmapObject BitmapObject; - -// extern PyTypeObject Bitmap_Type; - -/* Returns a newly-initialized BitmapObject from the given MMBitmap. - * The reference to |bitmap| is "stolen"; i.e., only the pointer is copied, and - * the reponsibility for free()'ing the buffer is given to the |BitmapObject|. - * - * Remember to call PyType_Ready() before using this for the first time! */ -BitmapObject BitmapObject_FromMMBitmap(MMBitmapRef bitmap); - -// #endif /* PY_BITMAP_CLASS_H */ \ No newline at end of file diff --git a/bitmap/bitmap_find.h b/bitmap/bitmap_find.h deleted file mode 100644 index 763fa234..00000000 --- a/bitmap/bitmap_find.h +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once -#ifndef BITMAP_H -#define BITMAP_H - -// #include "../base/types.h" -#include "../base/MMBitmap.h" -#include "../base/MMPointArray_c.h" - -/* Convenience wrapper around findBitmapInRect(), where |rect| is the bounds - * of |haystack|. */ -#define findBitmapInBitmap(needle, haystack, pointPtr, tol) \ - findBitmapInRect(needle, haystack, pointPtr, MMBitmapGetBounds(haystack), tol) - -/* Returns 0 and sets |point| to the origin of |needle| in |haystack| if - * |needle| was found in |haystack| inside of |rect|, or returns -1 if not. - * - * |tolerance| should be in the range 0.0f - 1.0f, denoting how closely the - * colors in the bitmaps need to match, with 0 being exact and 1 being any. - */ -int findBitmapInRect(MMBitmapRef needle, MMBitmapRef haystack, - MMPoint *point, MMRect rect, float tolerance); - -/* Convenience wrapper around findAllBitmapInRect(), where |rect| is the bounds - * of |haystack|. */ -#define findAllBitmapInBitmap(needle, haystack, tolerance) \ - findAllBitmapInRect(needle, haystack, \ - MMBitmapGetBounds(haystack), tolerance) - -/* Returns MMPointArray of all occurrences of |needle| in |haystack| inside of - * |rect|. Note that an is returned regardless of whether |needle| was found; - * check array->count to see if it actually was. - * - * |tolerance| should be in the range 0.0f - 1.0f, denoting how closely the - * colors in the bitmaps need to match, with 0 being exact and 1 being any. - * - * Responsibility for freeing the MMPointArray with destroyMMPointArray() is - * given to the caller. - */ -MMPointArrayRef findAllBitmapInRect(MMBitmapRef needle, MMBitmapRef haystack, - MMRect rect, float tolerance); - -// #define MMRGBHexAtPoint(image, x, y) \ -// hexFromMMRGB(MMRGBColorAtPoint(image, x, y)) - -/* Convenience wrapper around countOfBitmapInRect(), where |rect| is the bounds - * of |haystack|. */ -#define countOfBitmapInBitmap(needle, haystack, tolerance) \ - countOfBitmapInRect(needle, haystack, MMBitmapGetBounds(haystack), tolerance) - -/* Returns the number of occurences of |needle| in |haystack| inside - * of |rect|. */ -size_t countOfBitmapInRect(MMBitmapRef needle, MMBitmapRef haystack, - MMRect rect, float tolerance); - -#endif /* BITMAP_H */ diff --git a/bitmap/bitmap_find_c.h b/bitmap/bitmap_find_c.h deleted file mode 100644 index 1df90f63..00000000 --- a/bitmap/bitmap_find_c.h +++ /dev/null @@ -1,270 +0,0 @@ -#include "bitmap_find.h" -#include "../base/UTHashTable_c.h" -#include - -/* Node to be used in hash table. */ -struct shiftNode { - UTHashNode_HEAD /* Make structure hashable */ - MMRGBHex color; /* Key */ - MMPoint offset; /* Value */ -}; - -/* --- Hash table helper functions --- */ - -/* Adds hex-color/offset pair to jump table. */ -static void addNodeToTable(UTHashTable *table, MMRGBHex color, MMPoint offset); - -/* Returns node associated with color in jump table, or NULL if it - * doesn't exist. */ -static struct shiftNode *nodeForColor(UTHashTable *table, MMRGBHex color); - -/* Returns nonzero (true) if table has key, or zero (false) if not. */ -#define tableHasKey(table, color) (nodeForColor(table, color) != NULL) - -/* --- Boyer-Moore helper functions --- */ - -/* Calculates the first table for use in a Boyer-Moore search algorithm. - * Table is in the form [colors: shift_values], where colors are those in - * |needle|, and the shift values are each color's distance from the rightmost - * offset. All other colors are assumed to have a shift value equal to the - * length of needle. - */ -static void initBadShiftTable(UTHashTable *jumpTable, MMBitmapRef needle); - -/* Frees memory occupied by calling initBadShiftTable(). - * Currently this is just an alias for destroyHashTable(). */ -#define destroyBadShiftTable(jumpTable) destroyHashTable(jumpTable) - -/* Returns true if |needle| is found in |haystack| at |offset|. */ -static int needleAtOffset(MMBitmapRef needle, MMBitmapRef haystack, - MMPoint offset, float tolerance); -/* --- --- */ - -/* An modification of the Boyer-Moore-Horspool Algorithm, only applied to - * bitmaps and colors instead of strings and characters. - * - * TODO: The Boyer-Moore algorithm (with the second jump table) would probably - * be more efficient, but this was simpler (for now). - * - * The jump table (|badShiftTable|) is passed as a parameter to avoid being - * recalculated each time. It should be a pointer to a UTHashTable init'd with - * initBadShiftTable(). - * - * Returns 0 and sets |point| to the starting point of |needle| in |haystack| - * if |needle| was found in |haystack|, or returns -1 if not. */ -static int findBitmapInRectAt(MMBitmapRef needle, - MMBitmapRef haystack, - MMPoint *point, - MMRect rect, - float tolerance, - MMPoint startPoint, - UTHashTable *badShiftTable) -{ - const size_t scanHeight = rect.size.height - needle->height; - const size_t scanWidth = rect.size.width - needle->width; - MMPoint pointOffset = startPoint; - /* const MMPoint lastPoint = MMPointMake(needle->width - 1, needle->height - 1); */ - - /* Sanity check */ - if (needle->height > haystack->height || needle->width > haystack->width || - !MMBitmapRectInBounds(haystack, rect)) { - return -1; - } - - assert(point != NULL); - assert(needle != NULL); - assert(needle->height > 0 && needle->width > 0); - assert(haystack != NULL); - assert(haystack->height > 0 && haystack->width > 0); - assert(badShiftTable != NULL); - - /* Search |haystack|, while |needle| can still be within it. */ - while (pointOffset.y <= scanHeight) { - /* struct shiftNode *node = NULL; - MMRGBHex lastColor; */ - - while (pointOffset.x <= scanWidth) { - /* Check offset in |haystack| for |needle|. */ - if (needleAtOffset(needle, haystack, pointOffset, tolerance)) { - // ++pointOffset.x; - // ++pointOffset.y; - *point = pointOffset; - return 0; - } - - /* Otherwise, calculate next x offset to check. */ - /* - * Note that here we are getting the skip value based on the last - * color of |needle|, no matter where we didn't match. The - * alternative of pretending that the mismatched color was the previous - * color is slower in the normal case. - */ - /* lastColor = MMRGBHexAtPoint(haystack, pointOffset.x + lastPoint.x, - pointOffset.y + lastPoint.y); */ - - /* TODO: This fails on certain edge cases (issue#7). */ - /* When a color is encountered that does not occur in |needle|, we can - * safely skip ahead for the whole length of |needle|. - * Otherwise, use the value stored in the jump table. */ - /* node = nodeForColor(badShiftTable, lastColor); - pointOffset.x += (node == NULL) ? needle->width : (node->offset).x; */ - - /* For now, be naive. */ - ++pointOffset.x; - } - - pointOffset.x = rect.origin.x; - - /* lastColor = MMRGBHexAtPoint(haystack, pointOffset.x + lastPoint.x, - pointOffset.y + lastPoint.y); - node = nodeForColor(badShiftTable, lastColor); - pointOffset.y += node == NULL ? lastPoint.y : (node->offset).y; */ - - /* TODO: The above commented out code fails at certain edge cases, e.g.: - * Needle: [B, b - * b, b, - * B, b] - * Haystack: [w, w, w, w, w - * w, w, w, w, b - * w, w, w, b, b - * w, w, w, w, b] - * The previous algorithm noticed that the first 3 x 3 block had nothing - * in common with the image, and thus, after scanning the first row, - * skipped three blocks downward to scan the next (which didn't exist, - * so the loop ended). However, the needle was hidden IN-BETWEEN this - * jump -- skipping was appropriate for scanning the column but not - * the row. - * - * I need to figure out a more optimal solution; temporarily I am just - * scanning every single y coordinate, only skipping on x's. This - * always works, but is probably not optimal. - */ - ++pointOffset.y; - } - - return -1; -} - -int findBitmapInRect(MMBitmapRef needle, - MMBitmapRef haystack, - MMPoint *point, - MMRect rect, - float tolerance) -{ - UTHashTable badShiftTable; - int ret; - - initBadShiftTable(&badShiftTable, needle); - ret = findBitmapInRectAt(needle, haystack, point, rect, - tolerance, MMPointZero, &badShiftTable); - destroyBadShiftTable(&badShiftTable); - return ret; -} - -MMPointArrayRef findAllBitmapInRect(MMBitmapRef needle, MMBitmapRef haystack, - MMRect rect, float tolerance) -{ - MMPointArrayRef pointArray = createMMPointArray(0); - MMPoint point = MMPointZero; - UTHashTable badShiftTable; - - initBadShiftTable(&badShiftTable, needle); - while (findBitmapInRectAt(needle, haystack, &point, rect, - tolerance, point, &badShiftTable) == 0) { - const size_t scanWidth = (haystack->width - needle->width) + 1; - MMPointArrayAppendPoint(pointArray, point); - ITER_NEXT_POINT(point, scanWidth, 0); - } - destroyBadShiftTable(&badShiftTable); - - return pointArray; -} - -size_t countOfBitmapInRect(MMBitmapRef needle, MMBitmapRef haystack, - MMRect rect, float tolerance) -{ - size_t count = 0; - MMPoint point = MMPointZero; - UTHashTable badShiftTable; - - initBadShiftTable(&badShiftTable, needle); - while (findBitmapInRectAt(needle, haystack, &point, rect, - tolerance, point, &badShiftTable) == 0) { - const size_t scanWidth = (haystack->width - needle->width) + 1; - ++count; - ITER_NEXT_POINT(point, scanWidth, 0); - } - destroyBadShiftTable(&badShiftTable); - - return count; -} - -/* --- Boyer-Moore helper functions --- */ - -static void initBadShiftTable(UTHashTable *jumpTable, MMBitmapRef needle) -{ - const MMPoint lastPoint = MMPointMake(needle->width - 1, needle->height - 1); - const size_t maxColors = needle->width * needle->height; - MMPoint scan; - - /* Allocate max size initially to avoid a million calls to malloc(). */ - initHashTable(jumpTable, maxColors, sizeof(struct shiftNode)); - - /* Populate jumpTable with analysis of |needle|. */ - for (scan.y = lastPoint.y; ; --scan.y) { - for (scan.x = lastPoint.x; ; --scan.x) { - MMRGBHex color = MMRGBHexAtPoint(needle, scan.x, scan.y); - if (!tableHasKey(jumpTable, color)) { - addNodeToTable(jumpTable, color, - MMPointMake(needle->width - scan.x, - needle->height - scan.y)); - } - - if (scan.x == 0) break; /* Avoid infinite loop from unsigned type. */ - } - if (scan.y == 0) break; - } -} - -static int needleAtOffset(MMBitmapRef needle, MMBitmapRef haystack, - MMPoint offset, float tolerance) -{ - const MMPoint lastPoint = MMPointMake(needle->width - 1, needle->height - 1); - MMPoint scan; - - /* Note that |needle| is searched backwards, in accordance with the - * Boyer-Moore search algorithm. */ - for (scan.y = lastPoint.y; ; --scan.y) { - for (scan.x = lastPoint.x; ; --scan.x) { - MMRGBHex ncolor = MMRGBHexAtPoint(needle, scan.x, scan.y); - MMRGBHex hcolor = MMRGBHexAtPoint(haystack, offset.x + scan.x, - offset.y + scan.y); - if (!MMRGBHexSimilarToColor(ncolor, hcolor, tolerance)) return 0; - if (scan.x == 0) break; /* Avoid infinite loop from unsigned type. */ - } - if (scan.y == 0) break; - } - - return 1; -} - -/* --- Hash table helper functions --- */ - -static void addNodeToTable(UTHashTable *table, - MMRGBHex hexColor, - MMPoint offset) -{ - struct shiftNode *node = getNewNode(table); - node->color = hexColor; - node->offset = offset; - UTHASHTABLE_ADD_INT(table, color, node, struct shiftNode); -} - -static struct shiftNode *nodeForColor(UTHashTable *table, - MMRGBHex color) -{ - struct shiftNode *uttable = table->uttable; - struct shiftNode *node; - HASH_FIND_INT(uttable, &color, node); - return node; -} diff --git a/bitmap/goBitmap.h b/bitmap/goBitmap.h deleted file mode 100644 index 0a205c39..00000000 --- a/bitmap/goBitmap.h +++ /dev/null @@ -1,203 +0,0 @@ -// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// https://github.com/go-vgo/robotgo/blob/master/LICENSE -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#include "bitmap_class.h" -#include "bitmap_find_c.h" -#include "../base/color_find_c.h" -// #include "../screen/screen_c.h" -#include "../base/file_io_c.h" -#include "../base/pasteboard_c.h" -#include "../base/str_io_c.h" -#include -#include - -/* Returns false and sets error if |bitmap| is NULL. */ -bool bitmap_ready(MMBitmapRef bitmap){ - if (bitmap == NULL || bitmap->imageBuffer == NULL) { - return false; - } - return true; -} - -// void bitmap_dealloc(MMBitmapRef bitmap){ -// if (bitmap != NULL) { -// destroyMMBitmap(bitmap); -// bitmap = NULL; -// } -// } - -bool bitmap_copy_to_pboard(MMBitmapRef bitmap){ - MMPasteError err; - - if (!bitmap_ready(bitmap)) return false; - if ((err = copyMMBitmapToPasteboard(bitmap)) != kMMPasteNoError) { - return false; - } - - return true; -} - -MMBitmapRef bitmap_deepcopy(MMBitmapRef bitmap){ - return bitmap == NULL ? NULL : copyMMBitmap(bitmap); -} - -MMPoint find_bitmap(MMBitmapRef bitmap, MMBitmapRef sbit, float tolerance){ - MMPoint point = {-1, -1}; - // printf("tolenrance=%f\n", tolerance); - if (!bitmap_ready(sbit) || !bitmap_ready(bitmap)) { - printf("bitmap is not ready yet!\n"); - return point; - } - - MMRect rect = MMBitmapGetBounds(sbit); - // printf("x=%d, y=%d, width=%d, height=%d\n", rect.origin.x, - // rect.origin.y, rect.size.width, rect.size.height); - - if (findBitmapInRect(bitmap, sbit, &point, rect, tolerance) == 0) { - return point; - } - - return point; -} - -MMPointArrayRef find_every_bitmap(MMBitmapRef bitmap, MMBitmapRef sbit, float tolerance, MMPoint *list){ - if (!bitmap_ready(bitmap) || !bitmap_ready(sbit)) { return NULL; } - - MMPoint point; - MMPointArrayRef pointArray; - MMRect rect = MMBitmapGetBounds(sbit); - - if (findBitmapInRect(bitmap, sbit, &point, rect, tolerance) == 0) { - // return NULL; - } - - pointArray = findAllBitmapInRect(bitmap, sbit, rect, tolerance); - return pointArray; -} - -int count_of_bitmap(MMBitmapRef bitmap, MMBitmapRef sbit, float tolerance){ - if (!bitmap_ready(bitmap) || !bitmap_ready(sbit)) { return 0; } - - MMRect rect = MMBitmapGetBounds(bitmap); - return countOfBitmapInRect(bitmap, sbit, rect, tolerance); -} - -bool point_in_bounds(MMBitmapRef bitmap, MMPoint point){ - if (!bitmap_ready(bitmap)) { - return NULL; - } - - if (MMBitmapPointInBounds(bitmap, point)) { - return true; - } - - return false; -} - -MMBitmapRef bitmap_open(char *path, uint16_t ttype){ - // MMImageType type; - MMBitmapRef bitmap; - MMIOError err; - - bitmap = newMMBitmapFromFile(path, ttype, &err); - // printf("....%zd\n", bitmap->width); - return bitmap; -} - -MMBitmapRef bitmap_from_string(const char *str){ - size_t len = strlen(str); - - MMBitmapRef bitmap; - MMBMPStringError err; - - if ((bitmap = createMMBitmapFromString((unsigned char*)str, len, &err)) - == NULL) { - return NULL; - } - - return bitmap; -} - -char *bitmap_save(MMBitmapRef bitmap, char *path, uint16_t type){ - if (saveMMBitmapToFile(bitmap, path, (MMImageType) type) != 0) { - return "Could not save image to file."; - } - // destroyMMBitmap(bitmap); - return ""; -} - -char *tostring_bitmap(MMBitmapRef bitmap){ - char *buf = NULL; - MMBMPStringError err; - - buf = (char *)createStringFromMMBitmap(bitmap, &err); - return buf; -} - -// char out size 200 is enough -bool bitmap_str(MMBitmapRef bitmap, char *out){ - if (!bitmap_ready(bitmap)) { return false; } - sprintf(out, "", - (unsigned long)bitmap->width, - (unsigned long)bitmap->height, - bitmap->bitsPerPixel, - bitmap->bytesPerPixel); - - return true; -} - -MMBitmapRef get_portion(MMBitmapRef bit_map, MMRect rect){ - // MMRect rect; - MMBitmapRef portion = NULL; - - portion = copyMMBitmapFromPortion(bit_map, rect); - return portion; -} - -MMRGBHex bitmap_get_color(MMBitmapRef bitmap, size_t x, size_t y){ - if (!bitmap_ready(bitmap)) { return 0; } - - MMPoint point; - point = MMPointMake(x, y); - - if (!MMBitmapPointInBounds(bitmap, point)) { - return 0; - } - - return MMRGBHexAtPoint(bitmap, point.x, point.y); -} - -MMPoint bitmap_find_color(MMBitmapRef bitmap, MMRGBHex color, float tolerance){ - MMRect rect = MMBitmapGetBounds(bitmap); - MMPoint point = {-1, -1}; - - if (findColorInRect(bitmap, color, &point, rect, tolerance) == 0) { - return point; - } - - return point; -} - -MMPointArrayRef bitmap_find_every_color(MMBitmapRef bitmap, MMRGBHex color, float tolerance, MMPoint *list){ - if (!bitmap_ready(bitmap)) { return NULL; } - MMRect rect = MMBitmapGetBounds(bitmap); - MMPointArrayRef pointArray; - - pointArray = findAllColorInRect(bitmap, color, rect, tolerance); - return pointArray; -} - -int bitmap_count_of_color(MMBitmapRef bitmap, MMRGBHex color, float tolerance){ - if (!bitmap_ready(bitmap)) return 0; - MMRect rect = MMBitmapGetBounds(bitmap); - - return countOfColorsInRect(bitmap, color, rect, tolerance); -} diff --git a/go.mod b/go.mod index c84c38f1..d2f60ef8 100644 --- a/go.mod +++ b/go.mod @@ -5,14 +5,14 @@ go 1.17 require ( github.com/lxn/win v0.0.0-20210218163916-a377121e959e github.com/otiai10/gosseract v2.2.1+incompatible - github.com/robotn/gohook v0.31.3 + // github.com/robotn/gohook v0.31.3 github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 github.com/vcaesar/gops v0.21.3 github.com/vcaesar/imgo v0.30.0 github.com/vcaesar/keycode v0.10.0 github.com/vcaesar/tt v0.20.0 - golang.org/x/image v0.0.0-20211028202545-6944b10bf410 + golang.org/x/image v0.0.0-20211028202545-6944b10bf410 // indirect golang.org/x/net v0.0.0-20201110031124-69a78807bb2b // indirect ) diff --git a/go.sum b/go.sum index c5017780..4bed75b4 100644 --- a/go.sum +++ b/go.sum @@ -17,8 +17,6 @@ github.com/otiai10/mint v1.3.0 h1:Ady6MKVezQwHBkGzLFbrsywyp09Ah7rkmfjV3Bcr5uc= github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/robotn/gohook v0.31.3 h1:kGX8iukJ9ensVRwRKnTtdojAMQOpa6KFnXDi4OA4RaI= -github.com/robotn/gohook v0.31.3/go.mod h1:wyGik0yb4iwCfJjDprtNkTyxkgQWuKoVPQ3hkz6+6js= github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 h1:2lhSR8N3T6I30q096DT7/5AKEIcf1vvnnWAmS0wfnNY= github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934/go.mod h1:SxQhJskUJ4rleVU44YvnrdvxQr0tKy5SRSigBrCgyyQ= github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 h1:2uX8QRLkkxn2EpAQ6I3KhA79BkdRZfvugJUzJadiJwk= diff --git a/robotgo.go b/robotgo.go index 21027f59..f62390a8 100644 --- a/robotgo.go +++ b/robotgo.go @@ -18,6 +18,7 @@ See Requirements: https://github.com/go-vgo/robotgo#requirements Installation: + With Go module support (Go 1.11+), just import: import "github.com/go-vgo/robotgo" @@ -68,7 +69,7 @@ import ( const ( // Version get the robotgo version - Version = "v0.100.0.1189, MT. Baker!" + Version = "v1.00.0.1189, MT. Baker!" ) // GetVersion get the robotgo version @@ -81,6 +82,9 @@ var ( MouseSleep = 0 // KeySleep set the key default millisecond sleep time KeySleep = 0 + + // DisplayID set the screen display id + DisplayID = -1 ) type ( @@ -199,17 +203,18 @@ func RgbToHex(r, g, b uint8) C.uint32_t { } // GetPxColor get the pixel color return C.MMRGBHex -func GetPxColor(x, y int) C.MMRGBHex { +func GetPxColor(x, y int, displayId ...int) C.MMRGBHex { cx := C.int32_t(x) cy := C.int32_t(y) - color := C.get_px_color(cx, cy) + display := displayIdx(displayId...) + color := C.get_px_color(cx, cy, C.int32_t(display)) return color } // GetPixelColor get the pixel color return string -func GetPixelColor(x, y int) string { - return PadHex(GetPxColor(x, y)) +func GetPixelColor(x, y int, displayId ...int) string { + return PadHex(GetPxColor(x, y, displayId...)) } // GetMouseColor get the mouse pos's color @@ -218,6 +223,18 @@ func GetMouseColor() string { return GetPixelColor(x, y) } +func displayIdx(id ...int) int { + display := -1 + if DisplayID != -1 { + display = DisplayID + } + if len(id) > 0 { + display = id[0] + } + + return display +} + // SysScale get the sys scale func SysScale() float64 { s := C.sys_scale() @@ -244,7 +261,7 @@ func GetScreenSize() (int, int) { // GetScreenRect get the screen rect (x, y, w, h) func GetScreenRect(displayId ...int) Rect { - display := 0 + display := -1 if len(displayId) > 0 { display = displayId[0] } @@ -274,8 +291,16 @@ func GetScaleSize() (int, int) { // use `defer robotgo.FreeBitmap(bitmap)` to free the bitmap // // robotgo.CaptureScreen(x, y, w, h int) -func CaptureScreen(args ...int) C.MMBitmapRef { +func CaptureScreen(args ...int) CBitmap { var x, y, w, h C.int32_t + displayId := -1 + if DisplayID != -1 { + displayId = DisplayID + } + + if len(args) > 4 { + displayId = args[4] + } if len(args) > 3 { x = C.int32_t(args[0]) @@ -284,16 +309,15 @@ func CaptureScreen(args ...int) C.MMBitmapRef { h = C.int32_t(args[3]) } else { // Get the main screen rect. - rect := GetScreenRect() - + rect := GetScreenRect(displayId) x = C.int32_t(rect.X) y = C.int32_t(rect.Y) w = C.int32_t(rect.W) h = C.int32_t(rect.H) } - bit := C.capture_screen(x, y, w, h) - return bit + bit := C.capture_screen(x, y, w, h, C.int32_t(displayId)) + return CBitmap(bit) } // GoCaptureScreen capture the screen and return bitmap(go struct) @@ -313,13 +337,13 @@ func CaptureImg(args ...int) image.Image { } // FreeBitmap free and dealloc the C bitmap -func FreeBitmap(bitmap C.MMBitmapRef) { +func FreeBitmap(bitmap CBitmap) { // C.destroyMMBitmap(bitmap) - C.bitmap_dealloc(bitmap) + C.bitmap_dealloc(C.MMBitmapRef(bitmap)) } // ToBitmap trans C.MMBitmapRef to Bitmap -func ToBitmap(bit C.MMBitmapRef) Bitmap { +func ToBitmap(bit CBitmap) Bitmap { bitmap := Bitmap{ ImgBuf: (*uint8)(bit.imageBuffer), Width: int(bit.width), @@ -332,13 +356,27 @@ func ToBitmap(bit C.MMBitmapRef) Bitmap { return bitmap } +// ToCBitmap trans Bitmap to C.MMBitmapRef +func ToCBitmap(bit Bitmap) CBitmap { + cbitmap := C.createMMBitmap_c( + (*C.uint8_t)(bit.ImgBuf), + C.size_t(bit.Width), + C.size_t(bit.Height), + C.size_t(bit.Bytewidth), + C.uint8_t(bit.BitsPixel), + C.uint8_t(bit.BytesPerPixel), + ) + + return CBitmap(cbitmap) +} + // ToImage convert C.MMBitmapRef to standard image.Image -func ToImage(bit C.MMBitmapRef) image.Image { +func ToImage(bit CBitmap) image.Image { return ToRGBA(bit) } // ToRGBA convert C.MMBitmapRef to standard image.RGBA -func ToRGBA(bit C.MMBitmapRef) *image.RGBA { +func ToRGBA(bit CBitmap) *image.RGBA { bmp1 := ToBitmap(bit) return ToRGBAGo(bmp1) } @@ -536,7 +574,7 @@ func MoveSmooth(x, y int, args ...interface{}) bool { cy := C.int32_t(y) var ( - mouseDelay = 5 + mouseDelay = 1 low C.double high C.double ) diff --git a/robotgo_test.go b/robotgo_test.go index 0a11e8e6..142e8aca 100644 --- a/robotgo_test.go +++ b/robotgo_test.go @@ -14,7 +14,6 @@ package robotgo import ( - "fmt" "testing" "github.com/vcaesar/tt" @@ -152,36 +151,6 @@ func TestKeyCode(t *testing.T) { tt.Equal(t, "=", s) } -func TestBitmap(t *testing.T) { - bit := CaptureScreen() - tt.NotNil(t, bit) - e := SaveBitmap(bit, "robot_test.png") - tt.Empty(t, e) - - bit0 := CaptureScreen(10, 10, 20, 20) - x, y := FindBitmap(bit0) - fmt.Println("Find bitmap: ", x, y) - - arr := FindAllBitmap(bit0) - fmt.Println("Find all bitmap:", arr) - tt.Equal(t, 1, len(arr)) - - c1 := CHex(0xAADCDC) - x, y = FindColor(c1) - fmt.Println("Find color: ", x, y) - arr = FindAllColor(c1) - fmt.Println("Find all color: ", arr) - - img := ToImage(bit) - err := SavePng(img, "robot_img.png") - tt.Nil(t, err) - - bit1 := OpenBitmap("robot_test.png") - b := tt.TypeOf(bit, bit1) - tt.True(t, b) - tt.NotNil(t, bit1) -} - func TestPs(t *testing.T) { id, err := Pids() tt.Not(t, "[]", id) diff --git a/screen/goScreen.h b/screen/goScreen.h index a983b358..ce6b117c 100644 --- a/screen/goScreen.h +++ b/screen/goScreen.h @@ -45,7 +45,7 @@ uint32_t color_rgb_to_hex(uint8_t r, uint8_t g, uint8_t b){ return RGB_TO_HEX(r, g, b); } -MMRGBHex get_px_color(int32_t x, int32_t y){ +MMRGBHex get_px_color(int32_t x, int32_t y, int32_t display_id) { MMBitmapRef bitmap; MMRGBHex color; @@ -53,7 +53,7 @@ MMRGBHex get_px_color(int32_t x, int32_t y){ return color; } - bitmap = copyMMBitmapFromDisplayInRect(MMRectInt32Make(x, y, 1, 1)); + bitmap = copyMMBitmapFromDisplayInRect(MMRectInt32Make(x, y, 1, 1), display_id); // bitmap = MMRectMake(x, y, 1, 1); color = MMRGBHexAtPoint(bitmap, 0, 0); @@ -62,8 +62,8 @@ MMRGBHex get_px_color(int32_t x, int32_t y){ return color; } -char* get_pixel_color(int32_t x, int32_t y){ - MMRGBHex color = get_px_color(x, y); +char* get_pixel_color(int32_t x, int32_t y, int32_t display_id) { + MMRGBHex color = get_px_color(x, y, display_id); char* s = pad_hex(color); return s; @@ -104,16 +104,8 @@ void bitmap_dealloc(MMBitmapRef bitmap){ } // capture_screen capture screen -MMBitmapRef capture_screen(int32_t x, int32_t y, int32_t w, int32_t h){ - // if () { - // x = 0; - // y = 0; - // // Get screen size. - // MMSize displaySize = getMainDisplaySize(); - // w = displaySize.width; - // h = displaySize.height; - // } - MMBitmapRef bitmap = copyMMBitmapFromDisplayInRect(MMRectInt32Make(x, y, w, h)); +MMBitmapRef capture_screen(int32_t x, int32_t y, int32_t w, int32_t h, int32_t display_id) { + MMBitmapRef bitmap = copyMMBitmapFromDisplayInRect(MMRectInt32Make(x, y, w, h), display_id); // printf("%s\n", bitmap); return bitmap; } diff --git a/screen/screen_c.h b/screen/screen_c.h index bc33e977..9845ff07 100644 --- a/screen/screen_c.h +++ b/screen/screen_c.h @@ -38,7 +38,7 @@ MMSizeInt32 getMainDisplaySize(void){ MMRectInt32 getScreenRect(int32_t display_id) { #if defined(IS_MACOSX) CGDirectDisplayID displayID = (CGDirectDisplayID) display_id; - if (display_id == 0) { + if (display_id == -1) { displayID = CGMainDisplayID(); } CGRect displayRect = CGDisplayBounds(displayID); diff --git a/screen/screengrab.h b/screen/screengrab.h index b40badd5..728925af 100644 --- a/screen/screengrab.h +++ b/screen/screengrab.h @@ -3,7 +3,8 @@ #define SCREENGRAB_H #include "../base/types.h" -#include "../base/MMBitmap_c.h" +// #include "../base/MMBitmap_c.h" +#include "../base/bitmap_free_c.h" #ifdef __cplusplus extern "C" @@ -12,7 +13,7 @@ extern "C" /* Returns a raw bitmap of screengrab of the display (to be destroyed()'d by * caller), or NULL on error. */ -MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect); +MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id); #ifdef __cplusplus } diff --git a/screen/screengrab_c.h b/screen/screengrab_c.h index 214d6bfb..ebc9b680 100644 --- a/screen/screengrab_c.h +++ b/screen/screengrab_c.h @@ -17,22 +17,24 @@ #include #endif -MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect){ +MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id){ #if defined(IS_MACOSX) MMBitmapRef bitmap = NULL; uint8_t *buffer = NULL; size_t bufferSize = 0; - CGDirectDisplayID displayID = CGMainDisplayID(); + CGDirectDisplayID displayID = (CGDirectDisplayID) display_id; + + if (displayID == -1) { + displayID = CGMainDisplayID(); + } CGImageRef image = CGDisplayCreateImageForRect(displayID, CGRectMake(rect.origin.x, rect.origin.y, rect.size.w, rect.size.h)); - if (!image) { return NULL; } CFDataRef imageData = CGDataProviderCopyData(CGImageGetDataProvider(image)); - if (!imageData) { return NULL; } bufferSize = CFDataGetLength(imageData); @@ -40,7 +42,7 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect){ CFDataGetBytes(imageData, CFRangeMake(0, bufferSize), buffer); - bitmap = createMMBitmap(buffer, + bitmap = createMMBitmap_c(buffer, CGImageGetWidth(image),CGImageGetHeight(image), CGImageGetBytesPerRow(image), CGImageGetBitsPerPixel(image), CGImageGetBitsPerPixel(image) / 8); @@ -60,7 +62,7 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect){ XCloseDisplay(display); if (image == NULL) { return NULL; } - bitmap = createMMBitmap((uint8_t *)image->data, + bitmap = createMMBitmap_c((uint8_t *)image->data, rect.size.w, rect.size.h, (size_t)image->bytes_per_line, (uint8_t)image->bits_per_pixel, (uint8_t)image->bits_per_pixel / 8); image->data = NULL; /* Steal ownership of bitmap data so we don't have to @@ -109,7 +111,7 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect){ return NULL; } - bitmap = createMMBitmap(NULL, rect.size.w, rect.size.h, 4 * rect.size.w, + bitmap = createMMBitmap_c(NULL, rect.size.w, rect.size.h, 4 * rect.size.w, (uint8_t)bi.bmiHeader.biBitCount, 4); /* Copy the data to our pixel buffer. */ From cc2d0198ea2734e6e527f04913b74f09d06fbc02 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 2 Jan 2022 18:24:22 -0400 Subject: [PATCH 157/327] Fixed CI build and test --- base/snprintf.h | 46 ++ base/snprintf_c.h | 1019 +++++++++++++++++++++++++++++++++++++++++++++ test/main.go | 74 ---- window/alert_c.h | 1 + 4 files changed, 1066 insertions(+), 74 deletions(-) create mode 100644 base/snprintf.h create mode 100644 base/snprintf_c.h delete mode 100644 test/main.go diff --git a/base/snprintf.h b/base/snprintf.h new file mode 100644 index 00000000..60046e56 --- /dev/null +++ b/base/snprintf.h @@ -0,0 +1,46 @@ +#ifndef _PORTABLE_SNPRINTF_H_ +#define _PORTABLE_SNPRINTF_H_ + +#define PORTABLE_SNPRINTF_VERSION_MAJOR 2 +#define PORTABLE_SNPRINTF_VERSION_MINOR 2 + +#include "os.h" +#if defined(IS_MACOSX) + #define HAVE_SNPRINTF +#else + #define HAVE_SNPRINTF + #define PREFER_PORTABLE_SNPRINTF +#endif + +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +#ifdef HAVE_SNPRINTF +#include +#else +extern int snprintf(char *, size_t, const char *, /*args*/ ...); +extern int vsnprintf(char *, size_t, const char *, va_list); +#endif + +#if defined(HAVE_SNPRINTF) && defined(PREFER_PORTABLE_SNPRINTF) +extern int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args*/ ...); +extern int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap); +#define snprintf portable_snprintf +#define vsnprintf portable_vsnprintf +#endif + +extern int asprintf (char **ptr, const char *fmt, /*args*/ ...); +extern int vasprintf (char **ptr, const char *fmt, va_list ap); +extern int asnprintf (char **ptr, size_t str_m, const char *fmt, /*args*/ ...); +extern int vasnprintf(char **ptr, size_t str_m, const char *fmt, va_list ap); + +#endif + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/base/snprintf_c.h b/base/snprintf_c.h new file mode 100644 index 00000000..22ae3677 --- /dev/null +++ b/base/snprintf_c.h @@ -0,0 +1,1019 @@ +/* + * snprintf.c - a portable implementation of snprintf + * + * AUTHOR + * Mark Martinec , April 1999. + * + * Copyright 1999, Mark Martinec. All rights reserved. + * + * TERMS AND CONDITIONS + * This program is free software; you can redistribute it and/or modify + * it under the terms of the "Frontier Artistic License" which comes + * with this Kit. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the Frontier Artistic License for more details. + * + * You should have received a copy of the Frontier Artistic License + * with this Kit in the file named LICENSE.txt . + * If not, I'll be glad to provide one. + * + * FEATURES + * - careful adherence to specs regarding flags, field width and precision; + * - good performance for large string handling (large format, large + * argument or large paddings). Performance is similar to system's sprintf + * and in several cases significantly better (make sure you compile with + * optimizations turned on, tell the compiler the code is strict ANSI + * if necessary to give it more freedom for optimizations); + * - return value semantics per ISO/IEC 9899:1999 ("ISO C99"); + * - written in standard ISO/ANSI C - requires an ANSI C compiler. + * + * SUPPORTED CONVERSION SPECIFIERS AND DATA TYPES + * + * This snprintf only supports the following conversion specifiers: + * s, c, d, u, o, x, X, p (and synonyms: i, D, U, O - see below) + * with flags: '-', '+', ' ', '0' and '#'. + * An asterisk is supported for field width as well as precision. + * + * Length modifiers 'h' (short int), 'l' (long int), + * and 'll' (long long int) are supported. + * NOTE: + * If macro SNPRINTF_LONGLONG_SUPPORT is not defined (default) the + * length modifier 'll' is recognized but treated the same as 'l', + * which may cause argument value truncation! Defining + * SNPRINTF_LONGLONG_SUPPORT requires that your system's sprintf also + * handles length modifier 'll'. long long int is a language extension + * which may not be portable. + * + * Conversion of numeric data (conversion specifiers d, u, o, x, X, p) + * with length modifiers (none or h, l, ll) is left to the system routine + * sprintf, but all handling of flags, field width and precision as well as + * c and s conversions is done very carefully by this portable routine. + * If a string precision (truncation) is specified (e.g. %.8s) it is + * guaranteed the string beyond the specified precision will not be referenced. + * + * Length modifiers h, l and ll are ignored for c and s conversions (data + * types wint_t and wchar_t are not supported). + * + * The following common synonyms for conversion characters are supported: + * - i is a synonym for d + * - D is a synonym for ld, explicit length modifiers are ignored + * - U is a synonym for lu, explicit length modifiers are ignored + * - O is a synonym for lo, explicit length modifiers are ignored + * The D, O and U conversion characters are nonstandard, they are supported + * for backward compatibility only, and should not be used for new code. + * + * The following is specifically NOT supported: + * - flag ' (thousands' grouping character) is recognized but ignored + * - numeric conversion specifiers: f, e, E, g, G and synonym F, + * as well as the new a and A conversion specifiers + * - length modifier 'L' (long double) and 'q' (quad - use 'll' instead) + * - wide character/string conversions: lc, ls, and nonstandard + * synonyms C and S + * - writeback of converted string length: conversion character n + * - the n$ specification for direct reference to n-th argument + * - locales + * + * It is permitted for str_m to be zero, and it is permitted to specify NULL + * pointer for resulting string argument if str_m is zero (as per ISO C99). + * + * The return value is the number of characters which would be generated + * for the given input, excluding the trailing null. If this value + * is greater or equal to str_m, not all characters from the result + * have been stored in str, output bytes beyond the (str_m-1) -th character + * are discarded. If str_m is greater than zero it is guaranteed + * the resulting string will be null-terminated. + * + * NOTE that this matches the ISO C99, OpenBSD, and GNU C library 2.1, + * but is different from some older and vendor implementations, + * and is also different from XPG, XSH5, SUSv2 specifications. + * For historical discussion on changes in the semantics and standards + * of snprintf see printf(3) man page in the Linux programmers manual. + * + * Routines asprintf and vasprintf return a pointer (in the ptr argument) + * to a buffer sufficiently large to hold the resulting string. This pointer + * should be passed to free(3) to release the allocated storage when it is + * no longer needed. If sufficient space cannot be allocated, these functions + * will return -1 and set ptr to be a NULL pointer. These two routines are a + * GNU C library extensions (glibc). + * + * Routines asnprintf and vasnprintf are similar to asprintf and vasprintf, + * yet, like snprintf and vsnprintf counterparts, will write at most str_m-1 + * characters into the allocated output string, the last character in the + * allocated buffer then gets the terminating null. If the formatted string + * length (the return value) is greater than or equal to the str_m argument, + * the resulting string was truncated and some of the formatted characters + * were discarded. These routines present a handy way to limit the amount + * of allocated memory to some sane value. + * + * AVAILABILITY + * http://www.ijs.si/software/snprintf/ + * + * REVISION HISTORY + * 1999-04 V0.9 Mark Martinec + * - initial version, some modifications after comparing printf + * man pages for Digital Unix 4.0, Solaris 2.6 and HPUX 10, + * and checking how Perl handles sprintf (differently!); + * 1999-04-09 V1.0 Mark Martinec + * - added main test program, fixed remaining inconsistencies, + * added optional (long long int) support; + * 1999-04-12 V1.1 Mark Martinec + * - support the 'p' conversion (pointer to void); + * - if a string precision is specified + * make sure the string beyond the specified precision + * will not be referenced (e.g. by strlen); + * 1999-04-13 V1.2 Mark Martinec + * - support synonyms %D=%ld, %U=%lu, %O=%lo; + * - speed up the case of long format string with few conversions; + * 1999-06-30 V1.3 Mark Martinec + * - fixed runaway loop (eventually crashing when str_l wraps + * beyond 2^31) while copying format string without + * conversion specifiers to a buffer that is too short + * (thanks to Edwin Young for + * spotting the problem); + * - added macros PORTABLE_SNPRINTF_VERSION_(MAJOR|MINOR) + * to snprintf.h + * 2000-02-14 V2.0 (never released) Mark Martinec + * - relaxed license terms: The Artistic License now applies. + * You may still apply the GNU GENERAL PUBLIC LICENSE + * as was distributed with previous versions, if you prefer; + * - changed REVISION HISTORY dates to use ISO 8601 date format; + * - added vsnprintf (patch also independently proposed by + * Caolan McNamara 2000-05-04, and Keith M Willenson 2000-06-01) + * 2000-06-27 V2.1 Mark Martinec + * - removed POSIX check for str_m<1; value 0 for str_m is + * allowed by ISO C99 (and GNU C library 2.1) - (pointed out + * on 2000-05-04 by Caolan McNamara, caolan@ csn dot ul dot ie). + * Besides relaxed license this change in standards adherence + * is the main reason to bump up the major version number; + * - added nonstandard routines asnprintf, vasnprintf, asprintf, + * vasprintf that dynamically allocate storage for the + * resulting string; these routines are not compiled by default, + * see comments where NEED_V?ASN?PRINTF macros are defined; + * - autoconf contributed by Caolan McNamara + * 2000-10-06 V2.2 Mark Martinec + * - BUG FIX: the %c conversion used a temporary variable + * that was no longer in scope when referenced, + * possibly causing incorrect resulting character; + * - BUG FIX: make precision and minimal field width unsigned + * to handle huge values (2^31 <= n < 2^32) correctly; + * also be more careful in the use of signed/unsigned/size_t + * internal variables - probably more careful than many + * vendor implementations, but there may still be a case + * where huge values of str_m, precision or minimal field + * could cause incorrect behaviour; + * - use separate variables for signed/unsigned arguments, + * and for short/int, long, and long long argument lengths + * to avoid possible incompatibilities on certain + * computer architectures. Also use separate variable + * arg_sign to hold sign of a numeric argument, + * to make code more transparent; + * - some fiddling with zero padding and "0x" to make it + * Linux compatible; + * - systematically use macros fast_memcpy and fast_memset + * instead of case-by-case hand optimization; determine some + * breakeven string lengths for different architectures; + * - terminology change: 'format' -> 'conversion specifier', + * 'C9x' -> 'ISO/IEC 9899:1999 ("ISO C99")', + * 'alternative form' -> 'alternate form', + * 'data type modifier' -> 'length modifier'; + * - several comments rephrased and new ones added; + * - make compiler not complain about 'credits' defined but + * not used; + */ + + +/* Define HAVE_SNPRINTF if your system already has snprintf and vsnprintf. + * + * If HAVE_SNPRINTF is defined this module will not produce code for + * snprintf and vsnprintf, unless PREFER_PORTABLE_SNPRINTF is defined as well, + * causing this portable version of snprintf to be called portable_snprintf + * (and portable_vsnprintf). + */ +/* #define HAVE_SNPRINTF */ + +/* Define PREFER_PORTABLE_SNPRINTF if your system does have snprintf and + * vsnprintf but you would prefer to use the portable routine(s) instead. + * In this case the portable routine is declared as portable_snprintf + * (and portable_vsnprintf) and a macro 'snprintf' (and 'vsnprintf') + * is defined to expand to 'portable_v?snprintf' - see file snprintf.h . + * Defining this macro is only useful if HAVE_SNPRINTF is also defined, + * but does does no harm if defined nevertheless. + */ +/* #define PREFER_PORTABLE_SNPRINTF */ + +/* Define SNPRINTF_LONGLONG_SUPPORT if you want to support + * data type (long long int) and length modifier 'll' (e.g. %lld). + * If undefined, 'll' is recognized but treated as a single 'l'. + * + * If the system's sprintf does not handle 'll' + * the SNPRINTF_LONGLONG_SUPPORT must not be defined! + * + * This is off by default as (long long int) is a language extension. + */ +/* #define SNPRINTF_LONGLONG_SUPPORT */ + +/* Define NEED_SNPRINTF_ONLY if you only need snprintf, and not vsnprintf. + * If NEED_SNPRINTF_ONLY is defined, the snprintf will be defined directly, + * otherwise both snprintf and vsnprintf routines will be defined + * and snprintf will be a simple wrapper around vsnprintf, at the expense + * of an extra procedure call. + */ +/* #define NEED_SNPRINTF_ONLY */ + +/* Define NEED_V?ASN?PRINTF macros if you need library extension + * routines asprintf, vasprintf, asnprintf, vasnprintf respectively, + * and your system library does not provide them. They are all small + * wrapper routines around portable_vsnprintf. Defining any of the four + * NEED_V?ASN?PRINTF macros automatically turns off NEED_SNPRINTF_ONLY + * and turns on PREFER_PORTABLE_SNPRINTF. + * + * Watch for name conflicts with the system library if these routines + * are already present there. + * + * NOTE: vasprintf and vasnprintf routines need va_copy() from stdarg.h, as + * specified by C99, to be able to traverse the same list of arguments twice. + * I don't know of any other standard and portable way of achieving the same. + * With some versions of gcc you may use __va_copy(). You might even get away + * with "ap2 = ap", in this case you must not call va_end(ap2) ! + * #define va_copy(ap2,ap) ap2 = ap + */ +/* #define NEED_ASPRINTF */ +/* #define NEED_ASNPRINTF */ +/* #define NEED_VASPRINTF */ +/* #define NEED_VASNPRINTF */ + + +/* Define the following macros if desired: + * SOLARIS_COMPATIBLE, SOLARIS_BUG_COMPATIBLE, + * HPUX_COMPATIBLE, HPUX_BUG_COMPATIBLE, LINUX_COMPATIBLE, + * DIGITAL_UNIX_COMPATIBLE, DIGITAL_UNIX_BUG_COMPATIBLE, + * PERL_COMPATIBLE, PERL_BUG_COMPATIBLE, + * + * - For portable applications it is best not to rely on peculiarities + * of a given implementation so it may be best not to define any + * of the macros that select compatibility and to avoid features + * that vary among the systems. + * + * - Selecting compatibility with more than one operating system + * is not strictly forbidden but is not recommended. + * + * - 'x'_BUG_COMPATIBLE implies 'x'_COMPATIBLE . + * + * - 'x'_COMPATIBLE refers to (and enables) a behaviour that is + * documented in a sprintf man page on a given operating system + * and actually adhered to by the system's sprintf (but not on + * most other operating systems). It may also refer to and enable + * a behaviour that is declared 'undefined' or 'implementation specific' + * in the man page but a given implementation behaves predictably + * in a certain way. + * + * - 'x'_BUG_COMPATIBLE refers to (and enables) a behaviour of system's sprintf + * that contradicts the sprintf man page on the same operating system. + * + * - I do not claim that the 'x'_COMPATIBLE and 'x'_BUG_COMPATIBLE + * conditionals take into account all idiosyncrasies of a particular + * implementation, there may be other incompatibilities. + */ + + + +/* ============================================= */ +/* NO USER SERVICABLE PARTS FOLLOWING THIS POINT */ +/* ============================================= */ + +#define PORTABLE_SNPRINTF_VERSION_MAJOR 2 +#define PORTABLE_SNPRINTF_VERSION_MINOR 2 + +#if defined(NEED_ASPRINTF) || defined(NEED_ASNPRINTF) || defined(NEED_VASPRINTF) || defined(NEED_VASNPRINTF) +# if defined(NEED_SNPRINTF_ONLY) +# undef NEED_SNPRINTF_ONLY +# endif +# if !defined(PREFER_PORTABLE_SNPRINTF) +# define PREFER_PORTABLE_SNPRINTF +# endif +#endif + +#if defined(SOLARIS_BUG_COMPATIBLE) && !defined(SOLARIS_COMPATIBLE) +#define SOLARIS_COMPATIBLE +#endif + +#if defined(HPUX_BUG_COMPATIBLE) && !defined(HPUX_COMPATIBLE) +#define HPUX_COMPATIBLE +#endif + +#if defined(DIGITAL_UNIX_BUG_COMPATIBLE) && !defined(DIGITAL_UNIX_COMPATIBLE) +#define DIGITAL_UNIX_COMPATIBLE +#endif + +#if defined(PERL_BUG_COMPATIBLE) && !defined(PERL_COMPATIBLE) +#define PERL_COMPATIBLE +#endif + +#if defined(LINUX_BUG_COMPATIBLE) && !defined(LINUX_COMPATIBLE) +#define LINUX_COMPATIBLE +#endif + +#include "snprintf.h" +#include +#include +#include +#include +#include +#include +#include + +#ifdef isdigit +#undef isdigit +#endif +#define isdigit(c) ((c) >= '0' && (c) <= '9') + +/* For copying strings longer or equal to 'breakeven_point' + * it is more efficient to call memcpy() than to do it inline. + * The value depends mostly on the processor architecture, + * but also on the compiler and its optimization capabilities. + * The value is not critical, some small value greater than zero + * will be just fine if you don't care to squeeze every drop + * of performance out of the code. + * + * Small values favor memcpy, large values favor inline code. + */ +#if defined(__alpha__) || defined(__alpha) +# define breakeven_point 2 /* AXP (DEC Alpha) - gcc or cc or egcs */ +#endif +#if defined(__i386__) || defined(__i386) +# define breakeven_point 12 /* Intel Pentium/Linux - gcc 2.96 */ +#endif +#if defined(__hppa) +# define breakeven_point 10 /* HP-PA - gcc */ +#endif +#if defined(__sparc__) || defined(__sparc) +# define breakeven_point 33 /* Sun Sparc 5 - gcc 2.8.1 */ +#endif + +/* some other values of possible interest: */ +/* #define breakeven_point 8 */ /* VAX 4000 - vaxc */ +/* #define breakeven_point 19 */ /* VAX 4000 - gcc 2.7.0 */ + +#ifndef breakeven_point +# define breakeven_point 6 /* some reasonable one-size-fits-all value */ +#endif + +#define fast_memcpy(d,s,n) \ + { register size_t nn = (size_t)(n); \ + if (nn >= breakeven_point) memcpy((d), (s), nn); \ + else if (nn > 0) { /* proc call overhead is worth only for large strings*/\ + register char *dd; register const char *ss; \ + for (ss=(s), dd=(d); nn>0; nn--) *dd++ = *ss++; } } + +#define fast_memset(d,c,n) \ + { register size_t nn = (size_t)(n); \ + if (nn >= breakeven_point) memset((d), (int)(c), nn); \ + else if (nn > 0) { /* proc call overhead is worth only for large strings*/\ + register char *dd; register const int cc=(int)(c); \ + for (dd=(d); nn>0; nn--) *dd++ = cc; } } + +/* prototypes */ + +#if defined(NEED_ASPRINTF) +int asprintf (char **ptr, const char *fmt, /*args*/ ...); +#endif +#if defined(NEED_VASPRINTF) +int vasprintf (char **ptr, const char *fmt, va_list ap); +#endif +#if defined(NEED_ASNPRINTF) +int asnprintf (char **ptr, size_t str_m, const char *fmt, /*args*/ ...); +#endif +#if defined(NEED_VASNPRINTF) +int vasnprintf (char **ptr, size_t str_m, const char *fmt, va_list ap); +#endif + +#if defined(HAVE_SNPRINTF) +/* declare our portable snprintf routine under name portable_snprintf */ +/* declare our portable vsnprintf routine under name portable_vsnprintf */ +#else +/* declare our portable routines under names snprintf and vsnprintf */ +#define portable_snprintf snprintf +#if !defined(NEED_SNPRINTF_ONLY) +#define portable_vsnprintf vsnprintf +#endif +#endif + +#if !defined(HAVE_SNPRINTF) || defined(PREFER_PORTABLE_SNPRINTF) +int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args*/ ...); +#if !defined(NEED_SNPRINTF_ONLY) +int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap); +#endif +#endif + +/* declarations */ + +#if defined(NEED_ASPRINTF) +int asprintf(char **ptr, const char *fmt, /*args*/ ...) { + va_list ap; + size_t str_m; + int str_l; + + *ptr = NULL; + va_start(ap, fmt); /* measure the required size */ + str_l = portable_vsnprintf(NULL, (size_t)0, fmt, ap); + va_end(ap); + assert(str_l >= 0); /* possible integer overflow if str_m > INT_MAX */ + *ptr = (char *) malloc(str_m = (size_t)str_l + 1); + if (*ptr == NULL) { errno = ENOMEM; str_l = -1; } + else { + int str_l2; + va_start(ap, fmt); + str_l2 = portable_vsnprintf(*ptr, str_m, fmt, ap); + va_end(ap); + assert(str_l2 == str_l); + } + return str_l; +} +#endif + +#if defined(NEED_VASPRINTF) +int vasprintf(char **ptr, const char *fmt, va_list ap) { + size_t str_m; + int str_l; + + *ptr = NULL; + { va_list ap2; + va_copy(ap2, ap); /* don't consume the original ap, we'll need it again */ + str_l = portable_vsnprintf(NULL, (size_t)0, fmt, ap2);/*get required size*/ + va_end(ap2); + } + assert(str_l >= 0); /* possible integer overflow if str_m > INT_MAX */ + *ptr = (char *) malloc(str_m = (size_t)str_l + 1); + if (*ptr == NULL) { errno = ENOMEM; str_l = -1; } + else { + int str_l2 = portable_vsnprintf(*ptr, str_m, fmt, ap); + assert(str_l2 == str_l); + } + return str_l; +} +#endif + +#if defined(NEED_ASNPRINTF) +int asnprintf (char **ptr, size_t str_m, const char *fmt, /*args*/ ...) { + va_list ap; + int str_l; + + *ptr = NULL; + va_start(ap, fmt); /* measure the required size */ + str_l = portable_vsnprintf(NULL, (size_t)0, fmt, ap); + va_end(ap); + assert(str_l >= 0); /* possible integer overflow if str_m > INT_MAX */ + if ((size_t)str_l + 1 < str_m) str_m = (size_t)str_l + 1; /* truncate */ + /* if str_m is 0, no buffer is allocated, just set *ptr to NULL */ + if (str_m == 0) { /* not interested in resulting string, just return size */ + } else { + *ptr = (char *) malloc(str_m); + if (*ptr == NULL) { errno = ENOMEM; str_l = -1; } + else { + int str_l2; + va_start(ap, fmt); + str_l2 = portable_vsnprintf(*ptr, str_m, fmt, ap); + va_end(ap); + assert(str_l2 == str_l); + } + } + return str_l; +} +#endif + +#if defined(NEED_VASNPRINTF) +int vasnprintf (char **ptr, size_t str_m, const char *fmt, va_list ap) { + int str_l; + + *ptr = NULL; + { va_list ap2; + va_copy(ap2, ap); /* don't consume the original ap, we'll need it again */ + str_l = portable_vsnprintf(NULL, (size_t)0, fmt, ap2);/*get required size*/ + va_end(ap2); + } + assert(str_l >= 0); /* possible integer overflow if str_m > INT_MAX */ + if ((size_t)str_l + 1 < str_m) str_m = (size_t)str_l + 1; /* truncate */ + /* if str_m is 0, no buffer is allocated, just set *ptr to NULL */ + if (str_m == 0) { /* not interested in resulting string, just return size */ + } else { + *ptr = (char *) malloc(str_m); + if (*ptr == NULL) { errno = ENOMEM; str_l = -1; } + else { + int str_l2 = portable_vsnprintf(*ptr, str_m, fmt, ap); + assert(str_l2 == str_l); + } + } + return str_l; +} +#endif + +/* + * If the system does have snprintf and the portable routine is not + * specifically required, this module produces no code for snprintf/vsnprintf. + */ +#if !defined(HAVE_SNPRINTF) || defined(PREFER_PORTABLE_SNPRINTF) + +#if !defined(NEED_SNPRINTF_ONLY) +int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args*/ ...) { + va_list ap; + int str_l; + + va_start(ap, fmt); + str_l = portable_vsnprintf(str, str_m, fmt, ap); + va_end(ap); + return str_l; +} +#endif + +#if defined(NEED_SNPRINTF_ONLY) +int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args*/ ...) { +#else +int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap) { +#endif + +#if defined(NEED_SNPRINTF_ONLY) + va_list ap; +#endif + size_t str_l = 0; + const char *p = fmt; + +/* In contrast with POSIX, the ISO C99 now says + * that str can be NULL and str_m can be 0. + * This is more useful than the old: if (str_m < 1) return -1; */ + +#if defined(NEED_SNPRINTF_ONLY) + va_start(ap, fmt); +#endif + if (!p) p = ""; + while (*p) { + if (*p != '%') { + /* if (str_l < str_m) str[str_l++] = *p++; -- this would be sufficient */ + /* but the following code achieves better performance for cases + * where format string is long and contains few conversions */ + const char *q = strchr(p+1,'%'); + size_t n = !q ? strlen(p) : (q-p); + if (str_l < str_m) { + size_t avail = str_m-str_l; + fast_memcpy(str+str_l, p, (n>avail?avail:n)); + } + p += n; str_l += n; + } else { + const char *starting_p; + size_t min_field_width = 0, precision = 0; + int zero_padding = 0, precision_specified = 0, justify_left = 0; + int alternate_form = 0, force_sign = 0; + int space_for_positive = 1; /* If both the ' ' and '+' flags appear, + the ' ' flag should be ignored. */ + char length_modifier = '\0'; /* allowed values: \0, h, l, L */ + char tmp[32];/* temporary buffer for simple numeric->string conversion */ + + const char *str_arg; /* string address in case of string argument */ + size_t str_arg_l; /* natural field width of arg without padding + and sign */ + unsigned char uchar_arg; + /* unsigned char argument value - only defined for c conversion. + N.B. standard explicitly states the char argument for + the c conversion is unsigned */ + + size_t number_of_zeros_to_pad = 0; + /* number of zeros to be inserted for numeric conversions + as required by the precision or minimal field width */ + + size_t zero_padding_insertion_ind = 0; + /* index into tmp where zero padding is to be inserted */ + + char fmt_spec = '\0'; + /* current conversion specifier character */ + + starting_p = p; p++; /* skip '%' */ + /* parse flags */ + while (*p == '0' || *p == '-' || *p == '+' || + *p == ' ' || *p == '#' || *p == '\'') { + switch (*p) { + case '0': zero_padding = 1; break; + case '-': justify_left = 1; break; + case '+': force_sign = 1; space_for_positive = 0; break; + case ' ': force_sign = 1; + /* If both the ' ' and '+' flags appear, the ' ' flag should be ignored */ +#ifdef PERL_COMPATIBLE + /* ... but in Perl the last of ' ' and '+' applies */ + space_for_positive = 1; +#endif + break; + case '#': alternate_form = 1; break; + case '\'': break; + } + p++; + } + /* If the '0' and '-' flags both appear, the '0' flag should be ignored. */ + + /* parse field width */ + if (*p == '*') { + int j; + p++; j = va_arg(ap, int); + if (j >= 0) min_field_width = j; + else { min_field_width = -j; justify_left = 1; } + } else if (isdigit((int)(*p))) { + /* size_t could be wider than unsigned int; + make sure we treat argument like common implementations do */ + unsigned int uj = *p++ - '0'; + while (isdigit((int)(*p))) uj = 10*uj + (unsigned int)(*p++ - '0'); + min_field_width = uj; + } + /* parse precision */ + if (*p == '.') { + p++; precision_specified = 1; + if (*p == '*') { + int j = va_arg(ap, int); + p++; + if (j >= 0) precision = j; + else { + precision_specified = 0; precision = 0; + /* NOTE: + * Solaris 2.6 man page claims that in this case the precision + * should be set to 0. Digital Unix 4.0, HPUX 10 and BSD man page + * claim that this case should be treated as unspecified precision, + * which is what we do here. + */ + } + } else if (isdigit((int)(*p))) { + /* size_t could be wider than unsigned int; + make sure we treat argument like common implementations do */ + unsigned int uj = *p++ - '0'; + while (isdigit((int)(*p))) uj = 10*uj + (unsigned int)(*p++ - '0'); + precision = uj; + } + } + /* parse 'h', 'l' and 'll' length modifiers */ + if (*p == 'h' || *p == 'l') { + length_modifier = *p; p++; + if (length_modifier == 'l' && *p == 'l') { /* double l = long long */ +#ifdef SNPRINTF_LONGLONG_SUPPORT + length_modifier = '2'; /* double l encoded as '2' */ +#else + length_modifier = 'l'; /* treat it as a single 'l' */ +#endif + p++; + } + } + fmt_spec = *p; + /* common synonyms: */ + switch (fmt_spec) { + case 'i': fmt_spec = 'd'; break; + case 'D': fmt_spec = 'd'; length_modifier = 'l'; break; + case 'U': fmt_spec = 'u'; length_modifier = 'l'; break; + case 'O': fmt_spec = 'o'; length_modifier = 'l'; break; + default: break; + } + /* get parameter value, do initial processing */ + switch (fmt_spec) { + case '%': /* % behaves similar to 's' regarding flags and field widths */ + case 'c': /* c behaves similar to 's' regarding flags and field widths */ + case 's': + length_modifier = '\0'; /* wint_t and wchar_t not supported */ + /* the result of zero padding flag with non-numeric conversion specifier*/ + /* is undefined. Solaris and HPUX 10 does zero padding in this case, */ + /* Digital Unix and Linux does not. */ +#if !defined(SOLARIS_COMPATIBLE) && !defined(HPUX_COMPATIBLE) + zero_padding = 0; /* turn zero padding off for string conversions */ +#endif + str_arg_l = 1; + switch (fmt_spec) { + case '%': + str_arg = p; break; + case 'c': { + int j = va_arg(ap, int); + uchar_arg = (unsigned char) j; /* standard demands unsigned char */ + str_arg = (const char *) &uchar_arg; + break; + } + case 's': + str_arg = va_arg(ap, const char *); + if (!str_arg) str_arg_l = 0; + /* make sure not to address string beyond the specified precision !!! */ + else if (!precision_specified) str_arg_l = strlen(str_arg); + /* truncate string if necessary as requested by precision */ + else if (precision == 0) str_arg_l = 0; + else { + /* memchr on HP does not like n > 2^31 !!! */ + const char *q = memchr(str_arg, '\0', + precision <= 0x7fffffff ? precision : 0x7fffffff); + str_arg_l = !q ? precision : (q-str_arg); + } + break; + default: break; + } + break; + case 'd': case 'u': case 'o': case 'x': case 'X': case 'p': { + /* NOTE: the u, o, x, X and p conversion specifiers imply + the value is unsigned; d implies a signed value */ + + int arg_sign = 0; + /* 0 if numeric argument is zero (or if pointer is NULL for 'p'), + +1 if greater than zero (or nonzero for unsigned arguments), + -1 if negative (unsigned argument is never negative) */ + + int int_arg = 0; unsigned int uint_arg = 0; + /* only defined for length modifier h, or for no length modifiers */ + + long int long_arg = 0; unsigned long int ulong_arg = 0; + /* only defined for length modifier l */ + + void *ptr_arg = NULL; + /* pointer argument value -only defined for p conversion */ + +#ifdef SNPRINTF_LONGLONG_SUPPORT + long long int long_long_arg = 0; + unsigned long long int ulong_long_arg = 0; + /* only defined for length modifier ll */ +#endif + if (fmt_spec == 'p') { + /* HPUX 10: An l, h, ll or L before any other conversion character + * (other than d, i, u, o, x, or X) is ignored. + * Digital Unix: + * not specified, but seems to behave as HPUX does. + * Solaris: If an h, l, or L appears before any other conversion + * specifier (other than d, i, u, o, x, or X), the behavior + * is undefined. (Actually %hp converts only 16-bits of address + * and %llp treats address as 64-bit data which is incompatible + * with (void *) argument on a 32-bit system). + */ +#ifdef SOLARIS_COMPATIBLE +# ifdef SOLARIS_BUG_COMPATIBLE + /* keep length modifiers even if it represents 'll' */ +# else + if (length_modifier == '2') length_modifier = '\0'; +# endif +#else + length_modifier = '\0'; +#endif + ptr_arg = va_arg(ap, void *); + if (ptr_arg != NULL) arg_sign = 1; + } else if (fmt_spec == 'd') { /* signed */ + switch (length_modifier) { + case '\0': + case 'h': + /* It is non-portable to specify a second argument of char or short + * to va_arg, because arguments seen by the called function + * are not char or short. C converts char and short arguments + * to int before passing them to a function. + */ + int_arg = va_arg(ap, int); + if (int_arg > 0) arg_sign = 1; + else if (int_arg < 0) arg_sign = -1; + break; + case 'l': + long_arg = va_arg(ap, long int); + if (long_arg > 0) arg_sign = 1; + else if (long_arg < 0) arg_sign = -1; + break; +#ifdef SNPRINTF_LONGLONG_SUPPORT + case '2': + long_long_arg = va_arg(ap, long long int); + if (long_long_arg > 0) arg_sign = 1; + else if (long_long_arg < 0) arg_sign = -1; + break; +#endif + } + } else { /* unsigned */ + switch (length_modifier) { + case '\0': + case 'h': + uint_arg = va_arg(ap, unsigned int); + if (uint_arg) arg_sign = 1; + break; + case 'l': + ulong_arg = va_arg(ap, unsigned long int); + if (ulong_arg) arg_sign = 1; + break; +#ifdef SNPRINTF_LONGLONG_SUPPORT + case '2': + ulong_long_arg = va_arg(ap, unsigned long long int); + if (ulong_long_arg) arg_sign = 1; + break; +#endif + } + } + str_arg = tmp; str_arg_l = 0; + /* NOTE: + * For d, i, u, o, x, and X conversions, if precision is specified, + * the '0' flag should be ignored. This is so with Solaris 2.6, + * Digital UNIX 4.0, HPUX 10, Linux, FreeBSD, NetBSD; but not with Perl. + */ +#ifndef PERL_COMPATIBLE + if (precision_specified) zero_padding = 0; +#endif + if (fmt_spec == 'd') { + if (force_sign && arg_sign >= 0) + tmp[str_arg_l++] = space_for_positive ? ' ' : '+'; + /* leave negative numbers for sprintf to handle, + to avoid handling tricky cases like (short int)(-32768) */ +#ifdef LINUX_COMPATIBLE + } else if (fmt_spec == 'p' && force_sign && arg_sign > 0) { + tmp[str_arg_l++] = space_for_positive ? ' ' : '+'; +#endif + } else if (alternate_form) { + if (arg_sign != 0 && (fmt_spec == 'x' || fmt_spec == 'X') ) + { tmp[str_arg_l++] = '0'; tmp[str_arg_l++] = fmt_spec; } + /* alternate form should have no effect for p conversion, but ... */ +#ifdef HPUX_COMPATIBLE + else if (fmt_spec == 'p' + /* HPUX 10: for an alternate form of p conversion, + * a nonzero result is prefixed by 0x. */ +#ifndef HPUX_BUG_COMPATIBLE + /* Actually it uses 0x prefix even for a zero value. */ + && arg_sign != 0 +#endif + ) { tmp[str_arg_l++] = '0'; tmp[str_arg_l++] = 'x'; } +#endif + } + zero_padding_insertion_ind = str_arg_l; + if (!precision_specified) precision = 1; /* default precision is 1 */ + if (precision == 0 && arg_sign == 0 +#if defined(HPUX_BUG_COMPATIBLE) || defined(LINUX_COMPATIBLE) + && fmt_spec != 'p' + /* HPUX 10 man page claims: With conversion character p the result of + * converting a zero value with a precision of zero is a null string. + * Actually HP returns all zeroes, and Linux returns "(nil)". */ +#endif + ) { + /* converted to null string */ + /* When zero value is formatted with an explicit precision 0, + the resulting formatted string is empty (d, i, u, o, x, X, p). */ + } else { + char f[5]; int f_l = 0; + f[f_l++] = '%'; /* construct a simple format string for sprintf */ + if (!length_modifier) { } + else if (length_modifier=='2') { f[f_l++] = 'l'; f[f_l++] = 'l'; } + else f[f_l++] = length_modifier; + f[f_l++] = fmt_spec; f[f_l++] = '\0'; + if (fmt_spec == 'p') str_arg_l += sprintf(tmp+str_arg_l, f, ptr_arg); + else if (fmt_spec == 'd') { /* signed */ + switch (length_modifier) { + case '\0': + case 'h': str_arg_l+=sprintf(tmp+str_arg_l, f, int_arg); break; + case 'l': str_arg_l+=sprintf(tmp+str_arg_l, f, long_arg); break; +#ifdef SNPRINTF_LONGLONG_SUPPORT + case '2': str_arg_l+=sprintf(tmp+str_arg_l,f,long_long_arg); break; +#endif + } + } else { /* unsigned */ + switch (length_modifier) { + case '\0': + case 'h': str_arg_l+=sprintf(tmp+str_arg_l, f, uint_arg); break; + case 'l': str_arg_l+=sprintf(tmp+str_arg_l, f, ulong_arg); break; +#ifdef SNPRINTF_LONGLONG_SUPPORT + case '2': str_arg_l+=sprintf(tmp+str_arg_l,f,ulong_long_arg);break; +#endif + } + } + /* include the optional minus sign and possible "0x" + in the region before the zero padding insertion point */ + if (zero_padding_insertion_ind < str_arg_l && + tmp[zero_padding_insertion_ind] == '-') { + zero_padding_insertion_ind++; + } + if (zero_padding_insertion_ind+1 < str_arg_l && + tmp[zero_padding_insertion_ind] == '0' && + (tmp[zero_padding_insertion_ind+1] == 'x' || + tmp[zero_padding_insertion_ind+1] == 'X') ) { + zero_padding_insertion_ind += 2; + } + } + { size_t num_of_digits = str_arg_l - zero_padding_insertion_ind; + if (alternate_form && fmt_spec == 'o' +#ifdef HPUX_COMPATIBLE /* ("%#.o",0) -> "" */ + && (str_arg_l > 0) +#endif +#ifdef DIGITAL_UNIX_BUG_COMPATIBLE /* ("%#o",0) -> "00" */ +#else + /* unless zero is already the first character */ + && !(zero_padding_insertion_ind < str_arg_l + && tmp[zero_padding_insertion_ind] == '0') +#endif + ) { /* assure leading zero for alternate-form octal numbers */ + if (!precision_specified || precision < num_of_digits+1) { + /* precision is increased to force the first character to be zero, + except if a zero value is formatted with an explicit precision + of zero */ + precision = num_of_digits+1; precision_specified = 1; + } + } + /* zero padding to specified precision? */ + if (num_of_digits < precision) + number_of_zeros_to_pad = precision - num_of_digits; + } + /* zero padding to specified minimal field width? */ + if (!justify_left && zero_padding) { + int n = min_field_width - (str_arg_l+number_of_zeros_to_pad); + if (n > 0) number_of_zeros_to_pad += n; + } + break; + } + default: /* unrecognized conversion specifier, keep format string as-is*/ + zero_padding = 0; /* turn zero padding off for non-numeric convers. */ +#ifndef DIGITAL_UNIX_COMPATIBLE + justify_left = 1; min_field_width = 0; /* reset flags */ +#endif +#if defined(PERL_COMPATIBLE) || defined(LINUX_COMPATIBLE) + /* keep the entire format string unchanged */ + str_arg = starting_p; str_arg_l = p - starting_p; + /* well, not exactly so for Linux, which does something inbetween, + * and I don't feel an urge to imitate it: "%+++++hy" -> "%+y" */ +#else + /* discard the unrecognized conversion, just keep * + * the unrecognized conversion character */ + str_arg = p; str_arg_l = 0; +#endif + if (*p) str_arg_l++; /* include invalid conversion specifier unchanged + if not at end-of-string */ + break; + } + if (*p) p++; /* step over the just processed conversion specifier */ + /* insert padding to the left as requested by min_field_width; + this does not include the zero padding in case of numerical conversions*/ + if (!justify_left) { /* left padding with blank or zero */ + int n = min_field_width - (str_arg_l+number_of_zeros_to_pad); + if (n > 0) { + if (str_l < str_m) { + size_t avail = str_m-str_l; + fast_memset(str+str_l, (zero_padding?'0':' '), (n>avail?avail:n)); + } + str_l += n; + } + } + /* zero padding as requested by the precision or by the minimal field width + * for numeric conversions required? */ + if (number_of_zeros_to_pad <= 0) { + /* will not copy first part of numeric right now, * + * force it to be copied later in its entirety */ + zero_padding_insertion_ind = 0; + } else { + /* insert first part of numerics (sign or '0x') before zero padding */ + int n = zero_padding_insertion_ind; + if (n > 0) { + if (str_l < str_m) { + size_t avail = str_m-str_l; + fast_memcpy(str+str_l, str_arg, (n>avail?avail:n)); + } + str_l += n; + } + /* insert zero padding as requested by the precision or min field width */ + n = number_of_zeros_to_pad; + if (n > 0) { + if (str_l < str_m) { + size_t avail = str_m-str_l; + fast_memset(str+str_l, '0', (n>avail?avail:n)); + } + str_l += n; + } + } + /* insert formatted string + * (or as-is conversion specifier for unknown conversions) */ + { int n = str_arg_l - zero_padding_insertion_ind; + if (n > 0) { + if (str_l < str_m) { + size_t avail = str_m-str_l; + fast_memcpy(str+str_l, str_arg+zero_padding_insertion_ind, + (n>avail?avail:n)); + } + str_l += n; + } + } + /* insert right padding */ + if (justify_left) { /* right blank padding to the field width */ + int n = min_field_width - (str_arg_l+number_of_zeros_to_pad); + if (n > 0) { + if (str_l < str_m) { + size_t avail = str_m-str_l; + fast_memset(str+str_l, ' ', (n>avail?avail:n)); + } + str_l += n; + } + } + } + } +#if defined(NEED_SNPRINTF_ONLY) + va_end(ap); +#endif + if (str_m > 0) { /* make sure the string is null-terminated + even at the expense of overwriting the last character + (shouldn't happen, but just in case) */ + str[str_l <= str_m-1 ? str_l : str_m-1] = '\0'; + } + /* Return the number of characters formatted (excluding trailing null + * character), that is, the number of characters that would have been + * written to the buffer if it were large enough. + * + * The value of str_l should be returned, but str_l is of unsigned type + * size_t, and snprintf is int, possibly leading to an undetected + * integer overflow, resulting in a negative return value, which is illegal. + * Both XSH5 and ISO C99 (at least the draft) are silent on this issue. + * Should errno be set to EOVERFLOW and EOF returned in this case??? + */ + return (int) str_l; +} +#endif diff --git a/test/main.go b/test/main.go deleted file mode 100644 index 2ede969d..00000000 --- a/test/main.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// https://github.com/go-vgo/robotgo/blob/master/LICENSE -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -package main - -import ( - "fmt" - "reflect" - - "github.com/go-vgo/robotgo" -) - -func aRobotgo() { - abool := robotgo.ShowAlert("test", "robotgo") - if abool { - fmt.Println("ok@@@", "ok") - } - - x, y := robotgo.GetMousePos() - fmt.Println("pos:", x, y) - - robotgo.Move(x, y) - robotgo.Move(100, 200) - - robotgo.Toggle("left") - robotgo.Toggle("left", "up") - - for i := 0; i < 1080; i += 1000 { - fmt.Println(i) - robotgo.Move(800, i) - } - - fmt.Println(robotgo.GetPixelColor(x, y)) - - color := robotgo.GetPixelColor(100, 200) - fmt.Println("color@@@", color) - - robotgo.TypeStr("Hello World") - // robotgo.KeyTap("a", "control") - robotgo.KeyTap("f1", "control") - // robotgo.KeyTap("enter") - // robotgo.KeyToggle("enter", "down") - robotgo.TypeStr("en") - - abitmap := robotgo.CaptureScreen() - fmt.Println("all...", abitmap) - - bitmap := robotgo.CaptureScreen(10, 20, 30, 40) - fmt.Println("...", bitmap) - - fx, fy := robotgo.FindBitmap(bitmap) - fmt.Println("FindBitmap------", fx, fy) - - robotgo.SaveBitmap(bitmap, "test.png", 1) - - var bitmapTest robotgo.Bitmap - bitTest := robotgo.OpenBitmap("test.png") - bitmapTest = robotgo.ToBitmap(bitTest) - fmt.Println("...type", reflect.TypeOf(bitTest), reflect.TypeOf(bitmapTest)) - - // robotgo.MouseClick() - robotgo.Scroll(0, 10) -} - -func main() { - aRobotgo() -} diff --git a/window/alert_c.h b/window/alert_c.h index 46a2048d..b6761c42 100644 --- a/window/alert_c.h +++ b/window/alert_c.h @@ -73,6 +73,7 @@ int showAlert(const char *title, const char *msg, const char *defaultButton, if (defaultButton == NULL) defaultButton = "OK"; + // snprintf.h if (cancelButton == NULL) { asprintf(&buttonList, "%s:2", defaultButton); } else { From ca337b850512c38e0831aac62d83ed1f55334e83 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 2 Jan 2022 18:32:07 -0400 Subject: [PATCH 158/327] Update examples --- cmd/color-pos/main.go | 34 ---------------------------------- examples/scale/main.go | 6 ++++-- examples/screen/main.go | 2 +- 3 files changed, 5 insertions(+), 37 deletions(-) delete mode 100644 cmd/color-pos/main.go diff --git a/cmd/color-pos/main.go b/cmd/color-pos/main.go deleted file mode 100644 index 64e4dcb1..00000000 --- a/cmd/color-pos/main.go +++ /dev/null @@ -1,34 +0,0 @@ -package main - -import ( - "fmt" - - "github.com/go-vgo/robotgo" -) - -func colorPicker() { - // click the left mouse button to get the value - m := robotgo.AddEvent("mleft") - if m { - x, y := robotgo.GetMousePos() - fmt.Println("mouse pos: ", x, y) - - clo := robotgo.GetPixelColor(x, y) - fmt.Println("color: #", clo) - - // clipboard - s1 := fmt.Sprint(x, ", ", y) + ": " + "#" + clo - err := robotgo.WriteAll(s1) - if err != nil { - fmt.Println("clipboard err: ", err) - } - } -} - -func main() { - fmt.Println("color picker: ") - fmt.Println("click the left mouse button to get the value.") - for { - colorPicker() - } -} diff --git a/examples/scale/main.go b/examples/scale/main.go index cf822ffc..71e7371d 100644 --- a/examples/scale/main.go +++ b/examples/scale/main.go @@ -14,7 +14,8 @@ func main() { fmt.Println("get scale screen size: ", width, height) bitmap := robotgo.CaptureScreen(0, 0, width, height) - robotgo.SaveBitmap(bitmap, "test.png") + // robotgo.SaveBitmap(bitmap, "test.png") + robotgo.Save(robotgo.ToImage(bitmap), "test.png") sx := robotgo.ScaleX() s := robotgo.Scale() @@ -27,7 +28,8 @@ func main() { rx, ry, rw, rh := sx, sy, robotx, roboty // bit1 := robotgo.CaptureScreen(10, 20, robotw, roboth) bit1 := robotgo.CaptureScreen(rx, ry, rw, rh) - robotgo.SaveBitmap(bit1, "test2.png") + // robotgo.SaveBitmap(bit1, "test2.png") + robotgo.Save(robotgo.ToImage(bit1), "test2.png") clo := robotgo.GetPixelColor(robotx, roboty) fmt.Println("GetPixelColor...", clo) diff --git a/examples/screen/main.go b/examples/screen/main.go index 53fdb009..2b8dee15 100644 --- a/examples/screen/main.go +++ b/examples/screen/main.go @@ -27,7 +27,7 @@ func bitmap() { fmt.Println("GoCaptureScreen...", gbitMap.Width) // fmt.Println("...", gbitmap.Width, gbitmap.BytesPerPixel) - robotgo.SaveCapture("saveCapture.png", 10, 20, 100, 100) + // robotgo.SaveCapture("saveCapture.png", 10, 20, 100, 100) } func color() { From 627f5c9d3bdee1df6ddd32b3d61586468c25fc93 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 2 Jan 2022 18:53:07 -0400 Subject: [PATCH 159/327] remove unused files --- event/goEvent.h | 252 ------------------------------------------------ event/pub.h | 95 ------------------ 2 files changed, 347 deletions(-) delete mode 100644 event/goEvent.h delete mode 100644 event/pub.h diff --git a/event/goEvent.h b/event/goEvent.h deleted file mode 100644 index b3467fb8..00000000 --- a/event/goEvent.h +++ /dev/null @@ -1,252 +0,0 @@ -// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// https://github.com/go-vgo/robotgo/blob/master/LICENSE -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#ifdef HAVE_CONFIG_H - #include -#endif - -#include "pub.h" - - -void dispatch_proc(iohook_event * const event) { - char buffer[256] = { 0 }; - size_t length = snprintf(buffer, sizeof(buffer), - "id=%i,when=%" PRIu64 ",mask=0x%X", - event->type, event->time, event->mask); - - switch (event->type) { - case EVENT_KEY_PRESSED: - // If the escape key is pressed, naturally terminate the program. - if (event->data.keyboard.keycode == VC_ESCAPE) { - // int status = hook_stop(); - // switch (status) { - // // System level errors. - // case IOHOOK_ERROR_OUT_OF_MEMORY: - // loggerProc(LOG_LEVEL_ERROR, "Failed to allocate memory. (%#X)", status); - // break; - - // case IOHOOK_ERROR_X_RECORD_GET_CONTEXT: - // // NOTE This is the only platform specific error that occurs on hook_stop(). - // loggerProc(LOG_LEVEL_ERROR, "Failed to get XRecord context. (%#X)", status); - // break; - - // // Default error. - // case IOHOOK_FAILURE: - // default: - // loggerProc(LOG_LEVEL_ERROR, "An unknown hook error occurred. (%#X)", status); - // break; - // } - } - case EVENT_KEY_RELEASED: - snprintf(buffer + length, sizeof(buffer) - length, - ",keycode=%u,rawcode=0x%X", - event->data.keyboard.keycode, event->data.keyboard.rawcode); - int akeyCode = (uint16_t) event->data.keyboard.keycode; - - if (event->data.keyboard.keycode == VC_ESCAPE - && atoi(cevent) == 11) { - int stopEvent = stop_event(); - // printf("stop_event%d\n", stopEvent); - cstatus = 0; - } - - // printf("atoi(str)---%d\n", atoi(cevent)); - if (akeyCode == atoi(cevent)) { - int stopEvent = stop_event(); - // printf("%d\n", stopEvent); - cstatus = 0; - } - break; - - case EVENT_KEY_TYPED: - snprintf(buffer + length, sizeof(buffer) - length, - ",keychar=%lc,rawcode=%u", - (uint16_t) event->data.keyboard.keychar, - event->data.keyboard.rawcode); - - #ifdef WE_REALLY_WANT_A_POINTER - char *buf = malloc (6); - #else - char buf[6]; - #endif - - sprintf(buf, "%lc", (uint16_t) event->data.keyboard.keychar); - - #ifdef WE_REALLY_WANT_A_POINTER - free (buf); - #endif - - if (strcmp(buf, cevent) == 0) { - int stopEvent = stop_event(); - // printf("%d\n", stopEvent); - cstatus = 0; - } - // return (char*) event->data.keyboard.keychar; - break; - - case EVENT_MOUSE_PRESSED: - case EVENT_MOUSE_RELEASED: - case EVENT_MOUSE_CLICKED: - case EVENT_MOUSE_MOVED: - case EVENT_MOUSE_DRAGGED: - snprintf(buffer + length, sizeof(buffer) - length, - ",x=%i,y=%i,button=%i,clicks=%i", - event->data.mouse.x, event->data.mouse.y, - event->data.mouse.button, event->data.mouse.clicks); - - int abutton = event->data.mouse.button; - int aclicks = event->data.mouse.clicks; - int amouse = -1; - - if (strcmp(cevent, "mleft") == 0) { - amouse = 1; - } - if (strcmp(cevent, "mright") == 0) { - amouse = 2; - } - if (strcmp(cevent, "wheelDown") == 0) { - amouse = 4; - } - if (strcmp(cevent, "wheelUp") == 0) { - amouse = 5; - } - if (strcmp(cevent, "wheelLeft") == 0) { - amouse = 6; - } - if (strcmp(cevent, "wheelRight") == 0) { - amouse = 7; - } - if (abutton == amouse && aclicks == 1) { - int stopEvent = stop_event(); - cstatus = 0; - } - - break; - - case EVENT_MOUSE_WHEEL: - snprintf(buffer + length, sizeof(buffer) - length, - ",type=%i,amount=%i,rotation=%i", - event->data.wheel.type, event->data.wheel.amount, - event->data.wheel.rotation); - break; - - default: - break; - } - - // fprintf(stdout, "----%s\n", buffer); -} - -int add_event(char *key_event) { - // (uint16_t *) - cevent = key_event; - // Set the logger callback for library output. - hookSetlogger(&loggerProc); - - // Set the event callback for IOhook events. - hook_set_dispatch_proc(&dispatch_proc); - // Start the hook and block. - // NOTE If EVENT_HOOK_ENABLED was delivered, the status will always succeed. - int status = hook_run(); - - switch (status) { - case IOHOOK_SUCCESS: - // Everything is ok. - break; - - // System level errors. - case IOHOOK_ERROR_OUT_OF_MEMORY: - loggerProc(LOG_LEVEL_ERROR, "Failed to allocate memory. (%#X)", status); - break; - - - // X11 specific errors. - case IOHOOK_ERROR_X_OPEN_DISPLAY: - loggerProc(LOG_LEVEL_ERROR, "Failed to open X11 display. (%#X)", status); - break; - - case IOHOOK_ERROR_X_RECORD_NOT_FOUND: - loggerProc(LOG_LEVEL_ERROR, "Unable to locate XRecord extension. (%#X)", status); - break; - - case IOHOOK_ERROR_X_RECORD_ALLOC_RANGE: - loggerProc(LOG_LEVEL_ERROR, "Unable to allocate XRecord range. (%#X)", status); - break; - - case IOHOOK_ERROR_X_RECORD_CREATE_CONTEXT: - loggerProc(LOG_LEVEL_ERROR, "Unable to allocate XRecord context. (%#X)", status); - break; - - case IOHOOK_ERROR_X_RECORD_ENABLE_CONTEXT: - loggerProc(LOG_LEVEL_ERROR, "Failed to enable XRecord context. (%#X)", status); - break; - - - // Windows specific errors. - case IOHOOK_ERROR_SET_WINDOWS_HOOK_EX: - loggerProc(LOG_LEVEL_ERROR, "Failed to register low level windows hook. (%#X)", status); - break; - - - // Darwin specific errors. - case IOHOOK_ERROR_AXAPI_DISABLED: - loggerProc(LOG_LEVEL_ERROR, "Failed to enable access for assistive devices. (%#X)", status); - break; - - case IOHOOK_ERROR_CREATE_EVENT_PORT: - loggerProc(LOG_LEVEL_ERROR, "Failed to create apple event port. (%#X)", status); - break; - - case IOHOOK_ERROR_CREATE_RUN_LOOP_SOURCE: - loggerProc(LOG_LEVEL_ERROR, "Failed to create apple run loop source. (%#X)", status); - break; - - case IOHOOK_ERROR_GET_RUNLOOP: - loggerProc(LOG_LEVEL_ERROR, "Failed to acquire apple run loop. (%#X)", status); - break; - - case IOHOOK_ERROR_CREATE_OBSERVER: - loggerProc(LOG_LEVEL_ERROR, "Failed to create apple run loop observer. (%#X)", status); - break; - - // Default error. - case IOHOOK_FAILURE: - default: - loggerProc(LOG_LEVEL_ERROR, "An unknown hook error occurred. (%#X)", status); - break; - } - - // return status; - // printf("%d\n", status); - return cstatus; -} - -int stop_event(){ - int status = hook_stop(); - switch (status) { - // System level errors. - case IOHOOK_ERROR_OUT_OF_MEMORY: - loggerProc(LOG_LEVEL_ERROR, "Failed to allocate memory. (%#X)", status); - break; - - case IOHOOK_ERROR_X_RECORD_GET_CONTEXT: - // NOTE This is the only platform specific error that occurs on hook_stop(). - loggerProc(LOG_LEVEL_ERROR, "Failed to get XRecord context. (%#X)", status); - break; - - // Default error. - case IOHOOK_FAILURE: - default: - // loggerProc(LOG_LEVEL_ERROR, "An unknown hook error occurred. (%#X)", status); - break; - } - - return status; -} \ No newline at end of file diff --git a/event/pub.h b/event/pub.h deleted file mode 100644 index e93b7a91..00000000 --- a/event/pub.h +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// https://github.com/go-vgo/robotgo/blob/master/LICENSE -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#include "../base/os.h" - -#if defined(IS_MACOSX) - #include "../cdeps/hook/darwin/input_c.h" - #include "../cdeps/hook/darwin/hook_c.h" - #include "../cdeps/hook/darwin/event_c.h" - #include "../cdeps/hook/darwin/properties_c.h" -#elif defined(USE_X11) - //#define USE_XKBCOMMON 0 - #include "../cdeps/hook/x11/input_c.h" - #include "../cdeps/hook/x11/hook_c.h" - #include "../cdeps/hook/x11/event_c.h" - #include "../cdeps/hook/x11/properties_c.h" -#elif defined(IS_WINDOWS) - #include "../cdeps/hook/windows/input_c.h" - #include "../cdeps/hook/windows/hook_c.h" - #include "../cdeps/hook/windows/event_c.h" - #include "../cdeps/hook/windows/properties_c.h" -#endif - -#include -#include -#include -#include -#include -#include "../cdeps/hook/iohook.h" - - -int vccode[100]; -int codesz; - -char *cevent; -int rrevent; -// uint16_t *cevent; -int cstatus = 1; - - -int stop_event(); -int add_event(char *key_event); -// int allEvent(char *key_event); -int allEvent(char *key_event, int vcode[], int size); - -// NOTE: The following callback executes on the same thread that hook_run() is called -// from. - -struct _MEvent { - uint8_t id; - size_t mask; - uint16_t keychar; - // char *keychar; - size_t x; - uint8_t y; - uint8_t bytesPerPixel; -}; - -typedef struct _MEvent MEvent; -// typedef MMBitmap *MMBitmapRef; - -MEvent mEvent; - - -bool loggerProc(unsigned int level, const char *format, ...) { - bool status = false; - - va_list args; - switch (level) { - #ifdef USE_DEBUG - case LOG_LEVEL_DEBUG: - case LOG_LEVEL_INFO: - va_start(args, format); - status = vfprintf(stdout, format, args) >= 0; - va_end(args); - break; - #endif - - case LOG_LEVEL_WARN: - case LOG_LEVEL_ERROR: - va_start(args, format); - status = vfprintf(stderr, format, args) >= 0; - va_end(args); - break; - } - - return status; -} \ No newline at end of file From 337cd3f73a238d24ec25c29c7866f82e91c959a4 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 3 Jan 2022 19:49:54 -0400 Subject: [PATCH 160/327] add sys scale option displayID support --- base/MMBitmap.h | 38 +++++++++++++++++++------------------- base/deadbeef_rand_c.h | 9 +++------ robotgo.go | 15 ++++++++------- robotgo_mac_unix.go | 4 ++-- robotgo_win.go | 9 +++++++-- window/alert_c.h | 18 +++++------------- window/win_sys.h | 42 ++++++++++++++++++++++-------------------- 7 files changed, 66 insertions(+), 69 deletions(-) diff --git a/base/MMBitmap.h b/base/MMBitmap.h index 31b66cf3..9e73feb6 100644 --- a/base/MMBitmap.h +++ b/base/MMBitmap.h @@ -33,7 +33,7 @@ typedef MMBitmap *MMBitmapRef; /* Creates new MMBitmap with the given values. * Follows the Create Rule (caller is responsible for destroy()'ing object). */ -MMBitmapRef createMMBitmap(uint8_t *buffer, size_t width, size_t height, +MMBitmapRef createMMBitmap_c(uint8_t *buffer, size_t width, size_t height, size_t bytewidth, uint8_t bitsPerPixel, uint8_t bytesPerPixel); @@ -43,12 +43,12 @@ void destroyMMBitmap(MMBitmapRef bitmap); /* Releases memory occupied by MMBitmap. Acts via CallBack method*/ void destroyMMBitmapBuffer(char * bitmapBuffer, void * hint); -/* Returns copy of MMBitmap, to be destroy()'d by caller. */ -MMBitmapRef copyMMBitmap(MMBitmapRef bitmap); +// /* Returns copy of MMBitmap, to be destroy()'d by caller. */ +// MMBitmapRef copyMMBitmap(MMBitmapRef bitmap); -/* Returns copy of one MMBitmap juxtaposed in another (to be destroy()'d - * by the caller.), or NULL on error. */ -MMBitmapRef copyMMBitmapFromPortion(MMBitmapRef source, MMRect rect); +// /* Returns copy of one MMBitmap juxtaposed in another (to be destroy()'d +// * by the caller.), or NULL on error. */ +// MMBitmapRef copyMMBitmapFromPortion(MMBitmapRef source, MMRect rect); #define MMBitmapPointInBounds(image, p) ((p).x < (image)->width && \ (p).y < (image)->height) @@ -72,19 +72,19 @@ MMBitmapRef copyMMBitmapFromPortion(MMBitmapRef source, MMRect rect); #define MMRGBHexAtPoint(image, x, y) \ hexFromMMRGB(MMRGBColorAtPoint(image, x, y)) -/* Increment either point.x or point.y depending on the position of point.x. - * That is, if x + 1 is >= width, increment y and start x at the beginning. - * Otherwise, increment x. - * - * This is used as a convenience macro to scan rows when calling functions such - * as findColorInRectAt() and findBitmapInBitmapAt(). */ -#define ITER_NEXT_POINT(pixel, width, start_x) \ -do { \ - if (++(pixel).x >= (width)) { \ - (pixel).x = start_x; \ - ++(point).y; \ - } \ -} while (0); +// /* Increment either point.x or point.y depending on the position of point.x. +// * That is, if x + 1 is >= width, increment y and start x at the beginning. +// * Otherwise, increment x. +// * +// * This is used as a convenience macro to scan rows when calling functions such +// * as findColorInRectAt() and findBitmapInBitmapAt(). */ +// #define ITER_NEXT_POINT(pixel, width, start_x) \ +// do { \ +// if (++(pixel).x >= (width)) { \ +// (pixel).x = start_x; \ +// ++(point).y; \ +// } \ +// } while (0); #ifdef __cplusplus } diff --git a/base/deadbeef_rand_c.h b/base/deadbeef_rand_c.h index 1de295f8..d33062f9 100644 --- a/base/deadbeef_rand_c.h +++ b/base/deadbeef_rand_c.h @@ -4,23 +4,20 @@ static uint32_t deadbeef_seed; static uint32_t deadbeef_beef = 0xdeadbeef; -uint32_t deadbeef_rand(void) -{ +uint32_t deadbeef_rand(void) { deadbeef_seed = (deadbeef_seed << 7) ^ ((deadbeef_seed >> 25) + deadbeef_beef); deadbeef_beef = (deadbeef_beef << 7) ^ ((deadbeef_beef >> 25) + 0xdeadbeef); return deadbeef_seed; } -void deadbeef_srand(uint32_t x) -{ +void deadbeef_srand(uint32_t x) { deadbeef_seed = x; deadbeef_beef = 0xdeadbeef; } /* Taken directly from the documentation: * http://inglorion.net/software/cstuff/deadbeef_rand/ */ -uint32_t deadbeef_generate_seed(void) -{ +uint32_t deadbeef_generate_seed(void) { uint32_t t = (uint32_t)time(NULL); uint32_t c = (uint32_t)clock(); return (t << 24) ^ (c << 11) ^ t ^ (size_t) &c; diff --git a/robotgo.go b/robotgo.go index f62390a8..da6a6d9e 100644 --- a/robotgo.go +++ b/robotgo.go @@ -236,14 +236,15 @@ func displayIdx(id ...int) int { } // SysScale get the sys scale -func SysScale() float64 { - s := C.sys_scale() +func SysScale(displayId ...int) float64 { + display := displayIdx(displayId...) + s := C.sys_scale(C.int32_t(display)) return float64(s) } // Scaled get the screen scaled size -func Scaled(x int) int { - f := ScaleF() +func Scaled(x int, displayId ...int) int { + f := ScaleF(displayId...) return Scaled0(x, f) } @@ -271,7 +272,7 @@ func GetScreenRect(displayId ...int) Rect { int(rect.size.w), int(rect.size.h) if runtime.GOOS == "windows" { - f := ScaleF() + f := ScaleF(displayId...) x, y, w, h = Scaled0(x, f), Scaled0(y, f), Scaled0(w, f), Scaled0(h, f) } return Rect{ @@ -281,9 +282,9 @@ func GetScreenRect(displayId ...int) Rect { } // GetScaleSize get the screen scale size -func GetScaleSize() (int, int) { +func GetScaleSize(displayId ...int) (int, int) { x, y := GetScreenSize() - f := ScaleF() + f := ScaleF(displayId...) return int(float64(x) * f), int(float64(y) * f) } diff --git a/robotgo_mac_unix.go b/robotgo_mac_unix.go index 365914ba..72ad4ec5 100644 --- a/robotgo_mac_unix.go +++ b/robotgo_mac_unix.go @@ -14,8 +14,8 @@ package robotgo // ScaleF get the system scale val -func ScaleF() float64 { - f := SysScale() +func ScaleF(displayId ...int) float64 { + f := SysScale(displayId...) if f == 0.0 { f = 1.0 } diff --git a/robotgo_win.go b/robotgo_win.go index 38268648..6d06213e 100644 --- a/robotgo_win.go +++ b/robotgo_win.go @@ -53,8 +53,13 @@ func SetFocus(hwnd win.HWND) win.HWND { } // ScaleF get the system scale val -func ScaleF() float64 { - f := float64(GetMainDPI()) / 96.0 +func ScaleF(displayId ...int) (f float64) { + if len(displayId) > 0 && displayId[0] != -1 { + dpi := GetDPI(win.HWND(displayId[0])) + f = float64(dpi) / 96.0 + } else { + f = float64(GetMainDPI()) / 96.0 + } if f == 0.0 { f = 1.0 } diff --git a/window/alert_c.h b/window/alert_c.h index b6761c42..12f7143c 100644 --- a/window/alert_c.h +++ b/window/alert_c.h @@ -37,8 +37,8 @@ static int xmessage(char *argv[], int *exit_status); kCFStringEncodingUTF8)) #endif -int showAlert(const char *title, const char *msg, const char *defaultButton, - const char *cancelButton) +int showAlert(const char *title, const char *msg, + const char *defaultButton, const char *cancelButton) { #if defined(IS_MACOSX) CFStringRef alertHeader = CFStringCreateWithUTF8String(title); @@ -46,17 +46,9 @@ int showAlert(const char *title, const char *msg, const char *defaultButton, CFStringRef defaultButtonTitle = CFStringCreateWithUTF8String(defaultButton); CFStringRef cancelButtonTitle = CFStringCreateWithUTF8String(cancelButton); CFOptionFlags responseFlags; - SInt32 err = CFUserNotificationDisplayAlert(0.0, - kCFUserNotificationNoteAlertLevel, - NULL, - NULL, - NULL, - alertHeader, - alertMessage, - defaultButtonTitle, - cancelButtonTitle, - NULL, - &responseFlags); + SInt32 err = CFUserNotificationDisplayAlert( + 0.0, kCFUserNotificationNoteAlertLevel, NULL, NULL, NULL, alertHeader, alertMessage, + defaultButtonTitle, cancelButtonTitle, NULL, &responseFlags); if (alertHeader != NULL) CFRelease(alertHeader); if (alertMessage != NULL) CFRelease(alertMessage); diff --git a/window/win_sys.h b/window/win_sys.h index 0e1dd155..e6e2ddbf 100644 --- a/window/win_sys.h +++ b/window/win_sys.h @@ -17,25 +17,13 @@ Bounds get_client(uintptr pid, uintptr isHwnd); -intptr scaleX(){ - #if defined(IS_MACOSX) - return 0; - #elif defined(USE_X11) - return 0; - #elif defined(IS_WINDOWS) - // Get desktop dc - HDC desktopDc = GetDC(NULL); - // Get native resolution - intptr horizontalDPI = GetDeviceCaps(desktopDc, LOGPIXELSX); - // intptr verticalDPI = GetDeviceCaps(desktopDc, LOGPIXELSY); - return horizontalDPI; - #endif -} - -double sys_scale() { +double sys_scale(int32_t display_id) { #if defined(IS_MACOSX) - CGDirectDisplayID displayID = CGMainDisplayID(); + CGDirectDisplayID displayID = (CGDirectDisplayID) display_id; + if (displayID == -1) { + displayID = CGMainDisplayID(); + } CGDisplayModeRef modeRef = CGDisplayCopyDisplayMode(displayID); double pixelWidth = CGDisplayModeGetPixelWidth(modeRef); @@ -44,12 +32,11 @@ double sys_scale() { return pixelWidth / targetWidth; #elif defined(USE_X11) double xres; - Display *dpy; char *displayname = NULL; + Display *dpy = XOpenDisplay(displayname); + int scr = 0; /* Screen number */ - - dpy = XOpenDisplay(displayname); xres = ((((double) DisplayWidth(dpy, scr)) * 25.4) / ((double) DisplayWidthMM(dpy, scr))); @@ -79,6 +66,21 @@ double sys_scale() { #endif } +intptr scaleX(){ + #if defined(IS_MACOSX) + return 0; + #elif defined(USE_X11) + return 0; + #elif defined(IS_WINDOWS) + // Get desktop dc + HDC desktopDc = GetDC(NULL); + // Get native resolution + intptr horizontalDPI = GetDeviceCaps(desktopDc, LOGPIXELSX); + // intptr verticalDPI = GetDeviceCaps(desktopDc, LOGPIXELSY); + return horizontalDPI; + #endif +} + intptr scaleY(){ #if defined(IS_MACOSX) return 0; From f6abdbe21bbf8c2f19b0efc21f019d2092bd268b Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 3 Jan 2022 19:56:42 -0400 Subject: [PATCH 161/327] Fixed windows CI build --- window/win_sys.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/window/win_sys.h b/window/win_sys.h index e6e2ddbf..23abb1f0 100644 --- a/window/win_sys.h +++ b/window/win_sys.h @@ -16,6 +16,7 @@ #endif Bounds get_client(uintptr pid, uintptr isHwnd); +intptr scaleX(); double sys_scale(int32_t display_id) { #if defined(IS_MACOSX) @@ -31,13 +32,11 @@ double sys_scale(int32_t display_id) { return pixelWidth / targetWidth; #elif defined(USE_X11) - double xres; - char *displayname = NULL; Display *dpy = XOpenDisplay(displayname); int scr = 0; /* Screen number */ - xres = ((((double) DisplayWidth(dpy, scr)) * 25.4) / + double xres = ((((double) DisplayWidth(dpy, scr)) * 25.4) / ((double) DisplayWidthMM(dpy, scr))); // https://github.com/glfw/glfw/issues/1019#issuecomment-302772498 From d2f905e308b9153d17b605d1b7d6a967a1475204 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 3 Jan 2022 21:51:52 -0400 Subject: [PATCH 162/327] add PadHexs and ToMMBitmap support --- robotgo.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/robotgo.go b/robotgo.go index da6a6d9e..5a9cd80d 100644 --- a/robotgo.go +++ b/robotgo.go @@ -192,6 +192,11 @@ func PadHex(hex C.MMRGBHex) string { return gcolor } +// PadHexs trans CHex to string +func PadHexs(hex CHex) string { + return PadHex(C.MMRGBHex(hex)) +} + // HexToRgb trans hex to rgb func HexToRgb(hex uint32) *C.uint8_t { return C.color_hex_to_rgb(C.uint32_t(hex)) @@ -343,6 +348,11 @@ func FreeBitmap(bitmap CBitmap) { C.bitmap_dealloc(C.MMBitmapRef(bitmap)) } +// ToMMBitmapRef trans CBitmap to C.MMBitmapRef +func ToMMBitmapRef(bit CBitmap) C.MMBitmapRef { + return C.MMBitmapRef(bit) +} + // ToBitmap trans C.MMBitmapRef to Bitmap func ToBitmap(bit CBitmap) Bitmap { bitmap := Bitmap{ From a93a984215e121e33c3dfa6946865d7c72993398 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 3 Jan 2022 21:56:14 -0400 Subject: [PATCH 163/327] add move mouse windows multi screen support --- mouse/mouse_c.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/mouse/mouse_c.h b/mouse/mouse_c.h index 1b72e747..ce4595e5 100644 --- a/mouse/mouse_c.h +++ b/mouse/mouse_c.h @@ -113,14 +113,15 @@ void moveMouse(MMPointInt32 point){ #define MOUSE_COORD_TO_ABS(coord, width_or_height) ( \ ((65536 * coord) / width_or_height) + (coord < 0 ? -1 : 1)) - point.x = MOUSE_COORD_TO_ABS(point.x, GetSystemMetrics(SM_CXSCREEN)); - point.y = MOUSE_COORD_TO_ABS(point.y, GetSystemMetrics(SM_CYSCREEN)); + MMRectInt32 rect = getScreenRect(); + size_t x = MOUSE_COORD_TO_ABS(point.x - rect.origin.x, rect.size.w); + size_t y = MOUSE_COORD_TO_ABS(point.y - rect.origin.y, rect.size.h); INPUT mouseInput; mouseInput.type = INPUT_MOUSE; - mouseInput.mi.dx = point.x; - mouseInput.mi.dy = point.y; - mouseInput.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE; + mouseInput.mi.dx = x; + mouseInput.mi.dy = y; + mouseInput.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE | MOUSEEVENTF_VIRTUALDESK; mouseInput.mi.time = 0; // System will provide the timestamp mouseInput.mi.dwExtraInfo = 0; mouseInput.mi.mouseData = 0; From cf237175a75c4fe3cd283b9deb5d127d28d27740 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 3 Jan 2022 21:59:37 -0400 Subject: [PATCH 164/327] Fixed windows CI --- mouse/mouse_c.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mouse/mouse_c.h b/mouse/mouse_c.h index ce4595e5..b9c4c45e 100644 --- a/mouse/mouse_c.h +++ b/mouse/mouse_c.h @@ -113,7 +113,7 @@ void moveMouse(MMPointInt32 point){ #define MOUSE_COORD_TO_ABS(coord, width_or_height) ( \ ((65536 * coord) / width_or_height) + (coord < 0 ? -1 : 1)) - MMRectInt32 rect = getScreenRect(); + MMRectInt32 rect = getScreenRect(-1); size_t x = MOUSE_COORD_TO_ABS(point.x - rect.origin.x, rect.size.w); size_t y = MOUSE_COORD_TO_ABS(point.y - rect.origin.y, rect.size.h); From 7685ce8a3b309a0eb249b9de55fd2de5976882c0 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 3 Jan 2022 22:05:39 -0400 Subject: [PATCH 165/327] Update windows int type --- mouse/mouse_c.h | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/mouse/mouse_c.h b/mouse/mouse_c.h index b9c4c45e..d6da85d9 100644 --- a/mouse/mouse_c.h +++ b/mouse/mouse_c.h @@ -93,9 +93,8 @@ void calculateDeltas(CGEventRef *event, MMPointInt32 point){ */ void moveMouse(MMPointInt32 point){ #if defined(IS_MACOSX) - CGEventRef move = CGEventCreateMouseEvent(NULL, kCGEventMouseMoved, - CGPointFromMMPointInt32(point), - kCGMouseButtonLeft); + CGEventRef move = CGEventCreateMouseEvent(NULL, kCGEventMouseMoved, + CGPointFromMMPointInt32(point), kCGMouseButtonLeft); calculateDeltas(&move, point); @@ -103,8 +102,7 @@ void moveMouse(MMPointInt32 point){ CFRelease(move); #elif defined(USE_X11) Display *display = XGetMainDisplay(); - XWarpPointer(display, None, DefaultRootWindow(display), - 0, 0, 0, 0, point.x, point.y); + XWarpPointer(display, None, DefaultRootWindow(display), 0, 0, 0, 0, point.x, point.y); XSync(display, false); #elif defined(IS_WINDOWS) @@ -114,8 +112,8 @@ void moveMouse(MMPointInt32 point){ ((65536 * coord) / width_or_height) + (coord < 0 ? -1 : 1)) MMRectInt32 rect = getScreenRect(-1); - size_t x = MOUSE_COORD_TO_ABS(point.x - rect.origin.x, rect.size.w); - size_t y = MOUSE_COORD_TO_ABS(point.y - rect.origin.y, rect.size.h); + int32_t x = MOUSE_COORD_TO_ABS(point.x - rect.origin.x, rect.size.w); + int32_t y = MOUSE_COORD_TO_ABS(point.y - rect.origin.y, rect.size.h); INPUT mouseInput; mouseInput.type = INPUT_MOUSE; @@ -123,6 +121,7 @@ void moveMouse(MMPointInt32 point){ mouseInput.mi.dy = y; mouseInput.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE | MOUSEEVENTF_VIRTUALDESK; mouseInput.mi.time = 0; // System will provide the timestamp + mouseInput.mi.dwExtraInfo = 0; mouseInput.mi.mouseData = 0; SendInput(1, &mouseInput, sizeof(mouseInput)); @@ -133,8 +132,8 @@ void moveMouse(MMPointInt32 point){ void dragMouse(MMPointInt32 point, const MMMouseButton button){ #if defined(IS_MACOSX) const CGEventType dragType = MMMouseDragToCGEventType(button); - CGEventRef drag = CGEventCreateMouseEvent(NULL, dragType, - CGPointFromMMPoint(point), (CGMouseButton)button); + CGEventRef drag = CGEventCreateMouseEvent(NULL, dragType, + CGPointFromMMPoint(point), (CGMouseButton)button); calculateDeltas(&drag, point); @@ -181,7 +180,7 @@ void toggleMouse(bool down, MMMouseButton button){ const CGPoint currentPos = CGPointFromMMPoint(getMousePos()); const CGEventType mouseType = MMMouseToCGEventType(down, button); CGEventRef event = CGEventCreateMouseEvent(NULL, - mouseType, currentPos, (CGMouseButton)button); + mouseType, currentPos, (CGMouseButton)button); CGEventPost(kCGSessionEventTap, event); CFRelease(event); @@ -191,7 +190,6 @@ void toggleMouse(bool down, MMMouseButton button){ XSync(display, false); #elif defined(IS_WINDOWS) // mouse_event(MMMouseToMEventF(down, button), 0, 0, 0, 0); - INPUT mouseInput; mouseInput.type = INPUT_MOUSE; @@ -224,7 +222,7 @@ void doubleClick(MMMouseButton button){ const CGEventType mouseTypeUP = MMMouseToCGEventType(false, button); CGEventRef event = CGEventCreateMouseEvent( - NULL, mouseTypeDown, currentPos, kCGMouseButtonLeft); + NULL, mouseTypeDown, currentPos, kCGMouseButtonLeft); /* Set event to double click. */ CGEventSetIntegerValueField(event, kCGMouseEventClickState, 2); @@ -275,7 +273,7 @@ void scrollMouse(int scrollMagnitude, MMMouseWheelDirection scrollDirection){ cleanScrollMagnitude = cleanScrollMagnitude * scrollDirection; event = CGEventCreateScrollWheelEvent(NULL, - kCGScrollEventUnitLine, wheel, cleanScrollMagnitude, 0); + kCGScrollEventUnitLine, wheel, cleanScrollMagnitude, 0); CGEventPost(kCGHIDEventTap, event); From ec4d4dd0d8a125f6ac5d7bbfc351c77a1c87d572 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 5 Jan 2022 02:18:26 -0400 Subject: [PATCH 166/327] Update dockerfile and circle --- .circleci/config.yml | 7 ++----- .circleci/images/primary/Dockerfile | 9 +++------ 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2c56bc4d..4dbdc3bc 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -16,17 +16,14 @@ jobs: libx11-dev xorg-dev libxtst-dev xsel xclip # libpng++-dev - # xcb libxcb-xkb-dev x11-xkb-utils libx11-xcb-dev libxkbcommon-x11-dev - # libxkbcommon-dev + # xcb libxcb-xkb-dev x11-xkb-utils libx11-xcb-dev libxkbcommon-x11-dev libxkbcommon-dev - run: apt -y install xvfb # # override: - # './...' is a relative pattern which means all subdirectories # - run: go get -u github.com/go-vgo/robotgo - # - run: go get -u golang.org/x/sys/unix - # - run: go get -u github.com/shirou/gopsutil - run: go get -v -t -d ./... - run: xvfb-run go test -v ./... + # # codecov.io # - run: xvfb-run go test -v -covermode=count -coverprofile=coverage.out # - run: bash <(curl -s https://codecov.io/bash) diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index d9909c23..5b20e3df 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -5,18 +5,15 @@ FROM golang:1.17.5-stretch AS build RUN apt update && apt install -y --no-install-recommends \ # customize dependencies libx11-dev xorg-dev \ - # libgtkglextmm-x11-dev - # libghc6-x11-dev - # libgl1-mesa-swx11-dev - # xorg-dev - libxtst-dev libpng++-dev \ + libxtst-dev \ + # Bitmap + libpng++-dev \ # Event: xcb libxcb-xkb-dev \ x11-xkb-utils libx11-xcb-dev \ libxkbcommon-x11-dev libxkbcommon-dev \ # Clipboard: xsel xclip && \ - # RUN apt install -y xclip # apt remove --purge --auto-remove && \ apt clean && \ From 112fc4c6bb15113060f4be60ac1679c005fccd97 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 6 Jan 2022 20:49:10 -0400 Subject: [PATCH 167/327] Update capture go function --- examples/screen/main.go | 4 ++-- robotgo.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/screen/main.go b/examples/screen/main.go index 2b8dee15..d6d7ff3e 100644 --- a/examples/screen/main.go +++ b/examples/screen/main.go @@ -23,8 +23,8 @@ func bitmap() { gbit := robotgo.ToBitmap(abitMap) fmt.Println("bitmap...", gbit.Width) - gbitMap := robotgo.GoCaptureScreen() - fmt.Println("GoCaptureScreen...", gbitMap.Width) + gbitMap := robotgo.CaptureGo() + fmt.Println("Go CaptureScreen...", gbitMap.Width) // fmt.Println("...", gbitmap.Width, gbitmap.BytesPerPixel) // robotgo.SaveCapture("saveCapture.png", 10, 20, 100, 100) diff --git a/robotgo.go b/robotgo.go index 5a9cd80d..9598d609 100644 --- a/robotgo.go +++ b/robotgo.go @@ -326,8 +326,8 @@ func CaptureScreen(args ...int) CBitmap { return CBitmap(bit) } -// GoCaptureScreen capture the screen and return bitmap(go struct) -func GoCaptureScreen(args ...int) Bitmap { +// CaptureGo capture the screen and return bitmap(go struct) +func CaptureGo(args ...int) Bitmap { bit := CaptureScreen(args...) defer FreeBitmap(bit) From 4705e668bcd328af2e689c23d4ed269fcd56d48d Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 6 Jan 2022 21:10:00 -0400 Subject: [PATCH 168/327] remove unused cgo code --- robotgo.go | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/robotgo.go b/robotgo.go index 9598d609..5613459d 100644 --- a/robotgo.go +++ b/robotgo.go @@ -28,22 +28,21 @@ Otherwise, to install the robotgo package, run the command: package robotgo /* -//#if defined(IS_MACOSX) - #cgo darwin CFLAGS: -x objective-c -Wno-deprecated-declarations - #cgo darwin LDFLAGS: -framework Cocoa -framework OpenGL -framework IOKit - #cgo darwin LDFLAGS: -framework Carbon -framework CoreFoundation -//#elif defined(USE_X11) - #cgo linux CFLAGS: -I/usr/src - #cgo linux LDFLAGS: -L/usr/src -lX11 -lXtst -lm - // #cgo linux LDFLAGS: -lX11-xcb -lxcb -lxcb-xkb -lxkbcommon -lxkbcommon-x11 -//#endif - // #cgo windows LDFLAGS: -lgdi32 -luser32 -lpng -lz - #cgo windows LDFLAGS: -lgdi32 -luser32 +#cgo darwin CFLAGS: -x objective-c -Wno-deprecated-declarations +#cgo darwin LDFLAGS: -framework Cocoa -framework OpenGL -framework IOKit +#cgo darwin LDFLAGS: -framework Carbon -framework CoreFoundation + +#cgo linux CFLAGS: -I/usr/src +#cgo linux LDFLAGS: -L/usr/src -lX11 -lXtst -lm +// #cgo linux LDFLAGS: -lX11-xcb -lxcb -lxcb-xkb -lxkbcommon -lxkbcommon-x11 + +// #cgo windows LDFLAGS: -lgdi32 -luser32 -lpng -lz +#cgo windows LDFLAGS: -lgdi32 -luser32 +// // #include #include "screen/goScreen.h" #include "mouse/goMouse.h" #include "key/goKey.h" -//#include "event/goEvent.h" #include "window/goWindow.h" */ import "C" From 83ebdf3efdc2a746778b498b198e2660754ef3db Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 16 Jan 2022 10:45:18 -0400 Subject: [PATCH 169/327] Update dockerfile and CI --- .circleci/config.yml | 2 +- .circleci/images/primary/Dockerfile | 2 +- appveyor.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 4dbdc3bc..b88fd25f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,7 +5,7 @@ jobs: docker: # using custom image, see .circleci/images/primary/Dockerfile # - image: govgo/robotgoci:1.10.3 - - image: golang:1.17.5 + - image: golang:1.17.6 working_directory: /gopath/src/github.com/go-vgo/robotgo steps: - checkout diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index 5b20e3df..e1bca462 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.17.5-stretch AS build +FROM golang:1.17.6-stretch AS build # FROM govgo/go:1.11.1 RUN apt update && apt install -y --no-install-recommends \ diff --git a/appveyor.yml b/appveyor.yml index 59ababdb..8fe84955 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,7 +34,7 @@ environment: PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% # - COMPILER: MINGW_W64 # ARCHITECTURE: x64 - GOVERSION: 1.17.5 + GOVERSION: 1.17.6 # GOPATH: c:\gopath # scripts that run after cloning repository From ce0972d699aa1ab83f19a375545bc6a7fbe569f5 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 19 Jan 2022 12:43:26 -0400 Subject: [PATCH 170/327] Close window X11 display fixed #438 --- window/pub.h | 4 ++++ window/win_sys.h | 2 ++ window/window.h | 8 +++++--- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/window/pub.h b/window/pub.h index 2cf99d21..a7814913 100644 --- a/window/pub.h +++ b/window/pub.h @@ -135,6 +135,7 @@ typedef struct _Bounds Bounds; // Reinstate old handler XSetErrorHandler(mOld); + XCloseDisplay(rDisplay); } // Definitions @@ -182,6 +183,7 @@ typedef struct _Bounds Bounds; WM_ACTIVE = XInternAtom(rDisplay, "_NET_ACTIVE_WINDOW", True); WM_HINTS = XInternAtom(rDisplay, "_MOTIF_WM_HINTS", True); WM_EXTENTS = XInternAtom(rDisplay, "_NET_FRAME_EXTENTS", True); + XCloseDisplay(rDisplay); } @@ -219,6 +221,7 @@ typedef struct _Bounds Bounds; XFree (result); } + XCloseDisplay(rDisplay); return NULL; } @@ -262,6 +265,7 @@ typedef struct _Bounds Bounds; XFree(desktop); } } + XCloseDisplay(rDisplay); } static Bounds GetFrame(MData win){ diff --git a/window/win_sys.h b/window/win_sys.h index 23abb1f0..0a7cbe61 100644 --- a/window/win_sys.h +++ b/window/win_sys.h @@ -224,6 +224,8 @@ Bounds get_client(uintptr pid, uintptr isHwnd){ bounds.Y = y; bounds.W = attr.width; bounds.H = attr.height; + XCloseDisplay(rDisplay); + return bounds; #elif defined(IS_WINDOWS) diff --git a/window/window.h b/window/window.h index fcf1a6e8..a8cba40f 100644 --- a/window/window.h +++ b/window/window.h @@ -41,7 +41,7 @@ void initWindow(uintptr handle){ } mData.XWin = 0; - + XCloseDisplay(rDisplay); #elif defined(IS_WINDOWS) mData.HWnd = 0; #endif @@ -125,6 +125,7 @@ bool IsValid(){ // Free result and return true XFree(result); + XCloseDisplay(rDisplay); return true; #elif defined(IS_WINDOWS) @@ -412,7 +413,7 @@ void SetActive(const MData win){ XSetInputFocus(rDisplay, win.XWin, RevertToParent, CurrentTime); } - + XCloseDisplay(rDisplay); #elif defined(IS_WINDOWS) if (IsMinimized()) { @@ -502,6 +503,7 @@ MData GetActive(void){ Window window = None; int revert = RevertToNone; XGetInputFocus(rDisplay, &window, &revert); + XCloseDisplay(rDisplay); // Return foreground window result.XWin = window; @@ -590,7 +592,7 @@ void close_window_by_Id(MData m_data){ // Close the window XDestroyWindow(rDisplay, m_data.XWin); - + XCloseDisplay(rDisplay); #elif defined(IS_WINDOWS) PostMessage(m_data.HWnd, WM_CLOSE, 0, 0); From a860bbcff9bd8b4f52ecb6d15cde5f7d12a782c8 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 20 Jan 2022 13:03:35 -0400 Subject: [PATCH 171/327] add get DisplaysNum support --- robotgo.go | 4 ++++ robotgo_mac_win.go | 5 +++++ robotgo_x11.go | 22 ++++++++++++++++++++++ screen/goScreen.h | 27 +++++++++++++++++++++++++++ 4 files changed, 58 insertions(+) diff --git a/robotgo.go b/robotgo.go index 5613459d..79eac1e2 100644 --- a/robotgo.go +++ b/robotgo.go @@ -239,6 +239,10 @@ func displayIdx(id ...int) int { return display } +func getNumDisplays() int { + return int(C.get_num_displays()) +} + // SysScale get the sys scale func SysScale(displayId ...int) float64 { display := displayIdx(displayId...) diff --git a/robotgo_mac_win.go b/robotgo_mac_win.go index b0486c9f..df183eaa 100644 --- a/robotgo_mac_win.go +++ b/robotgo_mac_win.go @@ -50,3 +50,8 @@ func ActivePID(pid int32, args ...int) error { internalActive(pid, hwnd) return nil } + +// DisplaysNum get the count of displays +func DisplaysNum() int { + return getNumDisplays() +} diff --git a/robotgo_x11.go b/robotgo_x11.go index 009c9d4a..87bdde69 100644 --- a/robotgo_x11.go +++ b/robotgo_x11.go @@ -17,6 +17,7 @@ import ( "errors" "log" + "github.com/robotn/xgb/xinerama" "github.com/robotn/xgb/xproto" "github.com/robotn/xgbutil" "github.com/robotn/xgbutil/ewmh" @@ -149,3 +150,24 @@ func GetXidFromPid(xu *xgbutil.XUtil, pid int32) (xproto.Window, error) { return 0, errors.New("failed to find a window with a matching pid.") } + +// DisplaysNum get the count of displays +func DisplaysNum() int { + c, err := xgb.NewConn() + if err != nil { + return 0 + } + defer c.Close() + + err = xinerama.Init(c) + if err != nil { + return 0 + } + + reply, err := xinerama.QueryScreens(c).Reply() + if err != nil { + return 0 + } + + return int(reply.Number) +} diff --git a/screen/goScreen.h b/screen/goScreen.h index ce6b117c..ab6cf706 100644 --- a/screen/goScreen.h +++ b/screen/goScreen.h @@ -96,6 +96,33 @@ char* get_XDisplay_name(){ #endif } +#if defined(IS_WINDOWS) +bool CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { + uint32_t *count = (uint32_t*)dwData; + (*count)++; + return true; +} +#endif + +uint32_t get_num_displays() { +#if defined(IS_MACOSX) + uint32_t count = 0; + if (CGGetActiveDisplayList(0, nil, &count) == kCGErrorSuccess) { + return count; + } + return 0; +#elif defined(USE_X11) + return 0; +#elif defined(IS_WINDOWS) + uint32_t count = 0; + if (EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)&count)) { + return count; + } + return 0; +#endif +} + + void bitmap_dealloc(MMBitmapRef bitmap){ if (bitmap != NULL) { destroyMMBitmap(bitmap); From 30f45205413b5f1e4ea4e70c1694ad353474527e Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 20 Jan 2022 13:11:24 -0400 Subject: [PATCH 172/327] Fixed x11 import --- robotgo_x11.go | 1 + 1 file changed, 1 insertion(+) diff --git a/robotgo_x11.go b/robotgo_x11.go index 87bdde69..301dbad1 100644 --- a/robotgo_x11.go +++ b/robotgo_x11.go @@ -17,6 +17,7 @@ import ( "errors" "log" + "github.com/robotn/xgb" "github.com/robotn/xgb/xinerama" "github.com/robotn/xgb/xproto" "github.com/robotn/xgbutil" From 481fbb72a5e6b6ba48d7bfea721ef22d7422c590 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Fri, 21 Jan 2022 15:58:02 -0400 Subject: [PATCH 173/327] Add more multi screen support, update go mod, remove some code --- base/os.h | 14 +++ base/win32.h | 34 +++++++ examples/screen/main.go | 6 +- go.mod | 11 ++- go.sum | 31 +++--- screen/goScreen.h | 57 +++++------ screen/screengrab_c.h | 24 +++-- window/alert_c.h | 115 +++++++++++----------- window/arr.h | 26 ----- window/goWindow.h | 2 +- window/process.h | 133 ------------------------- window/pub.h | 95 +++++++++--------- window/win32.h | 56 ----------- window/win_sys.h | 24 +---- window/window.h | 212 +++++++++++----------------------------- 15 files changed, 278 insertions(+), 562 deletions(-) create mode 100644 base/win32.h delete mode 100644 window/arr.h delete mode 100644 window/process.h delete mode 100644 window/win32.h diff --git a/base/os.h b/base/os.h index ab469892..5d08c4fe 100644 --- a/base/os.h +++ b/base/os.h @@ -46,4 +46,18 @@ #define ADD_PADDING(width) (BYTE_ALIGN + (((width) - 1) & ~(BYTE_ALIGN - 1))) #endif +#if defined(IS_WINDOWS) + #if defined (_WIN64) + #define RobotGo_64 + #else + #define RobotGo_32 + #endif +#else + #if defined (__x86_64__) + #define RobotGo_64 + #else + #define RobotGo_32 + #endif +#endif + #endif /* OS_H */ diff --git a/base/win32.h b/base/win32.h new file mode 100644 index 00000000..d5b458e8 --- /dev/null +++ b/base/win32.h @@ -0,0 +1,34 @@ +#if defined(IS_WINDOWS) + bool CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { + uint32_t *count = (uint32_t*)dwData; + (*count)++; + return true; + } + + typedef struct{ + HWND hWnd; + DWORD dwPid; + }WNDINFO; + + BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam){ + WNDINFO* pInfo = (WNDINFO*)lParam; + DWORD dwProcessId = 0; + GetWindowThreadProcessId(hWnd, &dwProcessId); + + if (dwProcessId == pInfo->dwPid) { + pInfo->hWnd = hWnd; + return FALSE; + } + return TRUE; + } + + HWND GetHwndByPId(DWORD dwProcessId) { + WNDINFO info = {0}; + info.hWnd = NULL; + info.dwPid = dwProcessId; + EnumWindows(EnumWindowsProc, (LPARAM)&info); + // printf("%d\n", info.hWnd); + return info.hWnd; + } + +#endif \ No newline at end of file diff --git a/examples/screen/main.go b/examples/screen/main.go index d6d7ff3e..118a8b90 100644 --- a/examples/screen/main.go +++ b/examples/screen/main.go @@ -18,9 +18,9 @@ import ( ) func bitmap() { - abitMap := robotgo.CaptureScreen() - fmt.Println("abitMap...", abitMap) - gbit := robotgo.ToBitmap(abitMap) + bit := robotgo.CaptureScreen() + fmt.Println("abitMap...", bit) + gbit := robotgo.ToBitmap(bit) fmt.Println("bitmap...", gbit.Width) gbitMap := robotgo.CaptureGo() diff --git a/go.mod b/go.mod index d2f60ef8..0d96a29d 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( // github.com/robotn/gohook v0.31.3 github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 - github.com/vcaesar/gops v0.21.3 + github.com/vcaesar/gops v0.22.0 github.com/vcaesar/imgo v0.30.0 github.com/vcaesar/keycode v0.10.0 github.com/vcaesar/tt v0.20.0 @@ -17,15 +17,16 @@ require ( ) require ( - github.com/StackExchange/wmi v1.2.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/go-ole/go-ole v1.2.6 // indirect + github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/otiai10/mint v1.3.0 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/shirou/gopsutil v3.21.10+incompatible // indirect + github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect + github.com/shirou/gopsutil/v3 v3.21.12 // indirect github.com/tklauser/go-sysconf v0.3.9 // indirect github.com/tklauser/numcpus v0.3.0 // indirect - golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab // indirect + github.com/yusufpapurcu/wmi v1.2.2 // indirect + golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) diff --git a/go.sum b/go.sum index 4bed75b4..16a189ab 100644 --- a/go.sum +++ b/go.sum @@ -1,13 +1,14 @@ github.com/BurntSushi/freetype-go v0.0.0-20160129220410-b763ddbfe298/go.mod h1:D+QujdIlUNfa0igpNMk6UIvlb6C252URs4yupRUV4lQ= github.com/BurntSushi/graphics-go v0.0.0-20160129215708-b43f31a4a966/go.mod h1:Mid70uvE93zn9wgF92A/r5ixgnvX8Lh68fxp9KQBaI0= -github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= -github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/lxn/win v0.0.0-20210218163916-a377121e959e h1:H+t6A/QJMbhCSEH5rAuRxh+CtW96g0Or0Fxa9IKr4uc= github.com/lxn/win v0.0.0-20210218163916-a377121e959e/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= @@ -17,27 +18,31 @@ github.com/otiai10/mint v1.3.0 h1:Ady6MKVezQwHBkGzLFbrsywyp09Ah7rkmfjV3Bcr5uc= github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 h1:2lhSR8N3T6I30q096DT7/5AKEIcf1vvnnWAmS0wfnNY= github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934/go.mod h1:SxQhJskUJ4rleVU44YvnrdvxQr0tKy5SRSigBrCgyyQ= github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 h1:2uX8QRLkkxn2EpAQ6I3KhA79BkdRZfvugJUzJadiJwk= github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770/go.mod h1:svkDXUDQjUiWzLrA0OZgHc4lbOts3C+uRfP6/yjwYnU= -github.com/shirou/gopsutil v3.21.10+incompatible h1:AL2kpVykjkqeN+MFe1WcwSBVUjGjvdU8/ubvCuXAjrU= -github.com/shirou/gopsutil v3.21.10+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil/v3 v3.21.12 h1:VoGxEW2hpmz0Vt3wUvHIl9fquzYLNpVpgNNB7pGJimA= +github.com/shirou/gopsutil/v3 v3.21.12/go.mod h1:BToYZVTlSVlfazpDDYFnsVZLaoRG+g8ufT6fPQLdJzA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/tklauser/go-sysconf v0.3.9 h1:JeUVdAOWhhxVcU6Eqr/ATFHgXk/mmiItdKeJPev3vTo= github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs= github.com/tklauser/numcpus v0.3.0 h1:ILuRUQBtssgnxw0XXIjKUC56fgnOrFoQQ/4+DeU2biQ= github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8= -github.com/vcaesar/gops v0.21.3 h1:VR7amkxVv9CQfsotkXrmMyT19dVuNTa1PM/oopJeIc0= -github.com/vcaesar/gops v0.21.3/go.mod h1:3e2EnlZTI9/44bqzRwkeZ3s0ZQwK2Cn4QPLx8Ii8Agk= +github.com/vcaesar/gops v0.22.0 h1:aWHWxY3fvUuaJGph+LegYUSEU/874WJT7MInd8OUmP0= +github.com/vcaesar/gops v0.22.0/go.mod h1:GFNGo9xpCfjcfd/Hovi9RSrpd4FdaQt8V92TzpU22w4= github.com/vcaesar/imgo v0.30.0 h1:ODQVX0EFJEh+WkKahCBtE0SqcDCIjl/kjiOplR0Ouh8= github.com/vcaesar/imgo v0.30.0/go.mod h1:8TGnt5hjaMgwDByvMFIzUDSh5uSea4n1tAbSvnhvA6U= github.com/vcaesar/keycode v0.10.0 h1:Qx5QE8ZXHyRyjoA2QOxBp25OKMKB+zxMVqm0FWGV0d4= github.com/vcaesar/keycode v0.10.0/go.mod h1:JNlY7xbKsh+LAGfY2j4M3znVrGEm5W1R8s/Uv6BJcfQ= github.com/vcaesar/tt v0.20.0 h1:9t2Ycb9RNHcP0WgQgIaRKJBB+FrRdejuaL6uWIHuoBA= github.com/vcaesar/tt v0.20.0/go.mod h1:GHPxQYhn+7OgKakRusH7KJ0M5MhywoeLb8Fcffs/Gtg= +github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= +github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= @@ -51,13 +56,17 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab h1:rfJ1bsoJQQIAoAxTxB7bme+vHrNkRw8CqfsYh9w54cw= -golang.org/x/sys v0.0.0-20211123173158-ef496fb156ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= diff --git a/screen/goScreen.h b/screen/goScreen.h index ab6cf706..3a38f87e 100644 --- a/screen/goScreen.h +++ b/screen/goScreen.h @@ -10,18 +10,19 @@ #include "../base/types.h" #include "../base/rgb.h" +#include "../base/win32.h" #include "screengrab_c.h" #include "screen_c.h" #include // #include "../MMBitmap_c.h" -void padHex(MMRGBHex color, char* hex){ +void padHex(MMRGBHex color, char* hex) { // Length needs to be 7 because snprintf includes a terminating null. // Use %06x to pad hex value with leading 0s. snprintf(hex, 7, "%06x", color); } -char* pad_hex(MMRGBHex color){ +char* pad_hex(MMRGBHex color) { char hex[7]; padHex(color, hex); // destroyMMBitmap(bitmap); @@ -34,14 +35,14 @@ char* pad_hex(MMRGBHex color){ static uint8_t rgb[3]; -uint8_t* color_hex_to_rgb(uint32_t h){ +uint8_t* color_hex_to_rgb(uint32_t h) { rgb[0] = RED_FROM_HEX(h); rgb[1] = GREEN_FROM_HEX(h); rgb[2] = BLUE_FROM_HEX(h); return rgb; } -uint32_t color_rgb_to_hex(uint8_t r, uint8_t g, uint8_t b){ +uint32_t color_rgb_to_hex(uint8_t r, uint8_t g, uint8_t b) { return RGB_TO_HEX(r, g, b); } @@ -49,7 +50,7 @@ MMRGBHex get_px_color(int32_t x, int32_t y, int32_t display_id) { MMBitmapRef bitmap; MMRGBHex color; - if (!pointVisibleOnMainDisplay(MMPointInt32Make(x, y))){ + if (!pointVisibleOnMainDisplay(MMPointInt32Make(x, y))) { return color; } @@ -69,13 +70,13 @@ char* get_pixel_color(int32_t x, int32_t y, int32_t display_id) { return s; } -MMSizeInt32 get_screen_size(){ +MMSizeInt32 get_screen_size() { // Get display size. MMSizeInt32 displaySize = getMainDisplaySize(); return displaySize; } -char* set_XDisplay_name(char* name){ +char* set_XDisplay_name(char* name) { #if defined(USE_X11) setXDisplay(name); return "success"; @@ -84,7 +85,7 @@ char* set_XDisplay_name(char* name){ #endif } -char* get_XDisplay_name(){ +char* get_XDisplay_name() { #if defined(USE_X11) const char* display = getXDisplay(); char* sd = (char*)calloc(100, sizeof(char*)); @@ -96,34 +97,26 @@ char* get_XDisplay_name(){ #endif } -#if defined(IS_WINDOWS) -bool CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { - uint32_t *count = (uint32_t*)dwData; - (*count)++; - return true; -} -#endif - uint32_t get_num_displays() { -#if defined(IS_MACOSX) - uint32_t count = 0; - if (CGGetActiveDisplayList(0, nil, &count) == kCGErrorSuccess) { - return count; - } - return 0; -#elif defined(USE_X11) - return 0; -#elif defined(IS_WINDOWS) - uint32_t count = 0; - if (EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)&count)) { - return count; - } - return 0; -#endif + #if defined(IS_MACOSX) + uint32_t count = 0; + if (CGGetActiveDisplayList(0, nil, &count) == kCGErrorSuccess) { + return count; + } + return 0; + #elif defined(USE_X11) + return 0; + #elif defined(IS_WINDOWS) + uint32_t count = 0; + if (EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)&count)) { + return count; + } + return 0; + #endif } -void bitmap_dealloc(MMBitmapRef bitmap){ +void bitmap_dealloc(MMBitmapRef bitmap) { if (bitmap != NULL) { destroyMMBitmap(bitmap); bitmap = NULL; diff --git a/screen/screengrab_c.h b/screen/screengrab_c.h index ebc9b680..32367b50 100644 --- a/screen/screengrab_c.h +++ b/screen/screengrab_c.h @@ -17,15 +17,13 @@ #include #endif -MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id){ +MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id) { #if defined(IS_MACOSX) - MMBitmapRef bitmap = NULL; uint8_t *buffer = NULL; size_t bufferSize = 0; CGDirectDisplayID displayID = (CGDirectDisplayID) display_id; - if (displayID == -1) { displayID = CGMainDisplayID(); } @@ -43,7 +41,7 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id){ CFDataGetBytes(imageData, CFRangeMake(0, bufferSize), buffer); bitmap = createMMBitmap_c(buffer, - CGImageGetWidth(image),CGImageGetHeight(image), + CGImageGetWidth(image), CGImageGetHeight(image), CGImageGetBytesPerRow(image), CGImageGetBitsPerPixel(image), CGImageGetBitsPerPixel(image) / 8); @@ -53,11 +51,16 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id){ return bitmap; #elif defined(USE_X11) MMBitmapRef bitmap; + Display *display; + if display_id == -1 { + display = XOpenDisplay(NULL); + } else { + display = XGetMainDisplay(); + } - Display *display = XOpenDisplay(NULL); XImage *image = XGetImage(display, XDefaultRootWindow(display), (int)rect.origin.x, (int)rect.origin.y, - (unsigned int)rect.size.w,(unsigned int)rect.size.h, + (unsigned int)rect.size.w, (unsigned int)rect.size.h, AllPlanes, ZPixmap); XCloseDisplay(display); if (image == NULL) { return NULL; } @@ -65,8 +68,7 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id){ bitmap = createMMBitmap_c((uint8_t *)image->data, rect.size.w, rect.size.h, (size_t)image->bytes_per_line, (uint8_t)image->bits_per_pixel, (uint8_t)image->bits_per_pixel / 8); - image->data = NULL; /* Steal ownership of bitmap data so we don't have to - * copy it. */ + image->data = NULL; /* Steal ownership of bitmap data so we don't have to copy it. */ XDestroyImage(image); return bitmap; @@ -90,7 +92,11 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id){ bi.bmiHeader.biClrUsed = 0; bi.bmiHeader.biClrImportant = 0; - screen = GetDC(NULL); /* Get entire screen */ + if display_id == -1 { + screen = GetDC(NULL); /* Get entire screen */ + } else { + screen = GetDC((HWND) display_id); + } if (screen == NULL) { return NULL; } /* Get screen data in display device context. */ diff --git a/window/alert_c.h b/window/alert_c.h index 12f7143c..db7455e8 100644 --- a/window/alert_c.h +++ b/window/alert_c.h @@ -14,7 +14,6 @@ #endif #if defined(USE_X11) - enum { TASK_SUCCESS = 0, FORK_FAILED = -1, @@ -38,68 +37,67 @@ static int xmessage(char *argv[], int *exit_status); #endif int showAlert(const char *title, const char *msg, - const char *defaultButton, const char *cancelButton) -{ -#if defined(IS_MACOSX) - CFStringRef alertHeader = CFStringCreateWithUTF8String(title); - CFStringRef alertMessage = CFStringCreateWithUTF8String(msg); - CFStringRef defaultButtonTitle = CFStringCreateWithUTF8String(defaultButton); - CFStringRef cancelButtonTitle = CFStringCreateWithUTF8String(cancelButton); - CFOptionFlags responseFlags; - SInt32 err = CFUserNotificationDisplayAlert( - 0.0, kCFUserNotificationNoteAlertLevel, NULL, NULL, NULL, alertHeader, alertMessage, - defaultButtonTitle, cancelButtonTitle, NULL, &responseFlags); + const char *defaultButton, const char *cancelButton) { + #if defined(IS_MACOSX) + CFStringRef alertHeader = CFStringCreateWithUTF8String(title); + CFStringRef alertMessage = CFStringCreateWithUTF8String(msg); + CFStringRef defaultButtonTitle = CFStringCreateWithUTF8String(defaultButton); + CFStringRef cancelButtonTitle = CFStringCreateWithUTF8String(cancelButton); + CFOptionFlags responseFlags; + SInt32 err = CFUserNotificationDisplayAlert( + 0.0, kCFUserNotificationNoteAlertLevel, NULL, NULL, NULL, alertHeader, alertMessage, + defaultButtonTitle, cancelButtonTitle, NULL, &responseFlags); - if (alertHeader != NULL) CFRelease(alertHeader); - if (alertMessage != NULL) CFRelease(alertMessage); - if (defaultButtonTitle != NULL) CFRelease(defaultButtonTitle); - if (cancelButtonTitle != NULL) CFRelease(cancelButtonTitle); - - if (err != 0) { return -1; } - return (responseFlags == kCFUserNotificationDefaultResponse) ? 0 : 1; -#elif defined(USE_X11) - /* Note that args[0] is set by the xmessage() function. */ - const char *args[10] = {NULL, msg, "-title", title, "-center"}; - int response, ret; - char *buttonList = NULL; /* To be free()'d. */ - - if (defaultButton == NULL) defaultButton = "OK"; - - // snprintf.h - if (cancelButton == NULL) { - asprintf(&buttonList, "%s:2", defaultButton); - } else { - asprintf(&buttonList, "%s:2,%s:3", defaultButton, cancelButton); - } + if (alertHeader != NULL) CFRelease(alertHeader); + if (alertMessage != NULL) CFRelease(alertMessage); + if (defaultButtonTitle != NULL) CFRelease(defaultButtonTitle); + if (cancelButtonTitle != NULL) CFRelease(cancelButtonTitle); + + if (err != 0) { return -1; } + return (responseFlags == kCFUserNotificationDefaultResponse) ? 0 : 1; + #elif defined(USE_X11) + /* Note that args[0] is set by the xmessage() function. */ + const char *args[10] = {NULL, msg, "-title", title, "-center"}; + int response, ret; + char *buttonList = NULL; /* To be free()'d. */ + + if (defaultButton == NULL) defaultButton = "OK"; + + // snprintf.h + if (cancelButton == NULL) { + asprintf(&buttonList, "%s:2", defaultButton); + } else { + asprintf(&buttonList, "%s:2,%s:3", defaultButton, cancelButton); + } - if (buttonList == NULL) { return -1; /* asprintf() failed. */ } - args[5] = "-buttons"; - args[6] = buttonList; - args[7] = "-default"; - args[8] = defaultButton; - args[9] = NULL; - - ret = xmessage((char **)args, &response); - if (buttonList != NULL) { - free(buttonList); - buttonList = NULL; - } + if (buttonList == NULL) { return -1; /* asprintf() failed. */ } + args[5] = "-buttons"; + args[6] = buttonList; + args[7] = "-default"; + args[8] = defaultButton; + args[9] = NULL; + + ret = xmessage((char **)args, &response); + if (buttonList != NULL) { + free(buttonList); + buttonList = NULL; + } - if (ret != TASK_SUCCESS) { - if (ret == EXEC_FAILED) { - fputs("xmessage or equivalent not found.\n", stderr); + if (ret != TASK_SUCCESS) { + if (ret == EXEC_FAILED) { + fputs("xmessage or equivalent not found.\n", stderr); + } + return -1; } - return -1; - } - return (response == 2) ? 0 : 1; -#else - /* TODO: Display custom buttons instead of the pre-defined "OK" - * and "Cancel". */ - int response = MessageBox(NULL, msg, title, - (cancelButton == NULL) ? MB_OK : MB_OKCANCEL); - return (response == IDOK) ? 0 : 1; -#endif + return (response == 2) ? 0 : 1; + #else + /* TODO: Display custom buttons instead of the pre-defined "OK" + * and "Cancel". */ + int response = MessageBox(NULL, msg, title, + (cancelButton == NULL) ? MB_OK : MB_OKCANCEL); + return (response == IDOK) ? 0 : 1; + #endif } #if defined(USE_X11) @@ -171,5 +169,4 @@ static int runTask(const char *taskname, char * const argv[], int *exit_status) return TASK_SUCCESS; /* Success! */ } } - #endif diff --git a/window/arr.h b/window/arr.h deleted file mode 100644 index 26bc8351..00000000 --- a/window/arr.h +++ /dev/null @@ -1,26 +0,0 @@ -// #include -// #include -// #include - -struct Arr{ - int len; - int cnu; - char** pName; - int *pId; -}; - -// int init_Arr(struct Arr *pArray, int len){ -// pArray->pName = (char**)malloc(sizeof(char*)*len); -// pArray->pId = (int*)malloc(sizeof(int)*len); -// if(NULL == pArray->pName){ -// printf("false \n"); -// return 1; -// }else{ -// pArray->len = len; -// pArray->cnu = 0; -// printf("true %d \n", pArray->len); -// return 0; -// } - -// return 0; -// } \ No newline at end of file diff --git a/window/goWindow.h b/window/goWindow.h index ea56f6f0..fd8a7947 100644 --- a/window/goWindow.h +++ b/window/goWindow.h @@ -121,7 +121,7 @@ char* get_title(uintptr pid, uintptr isHwnd){ return title; } -int32 get_PID(void){ +int32_t get_PID(void){ int pid = WGetPID(); return pid; } diff --git a/window/process.h b/window/process.h deleted file mode 100644 index 03249678..00000000 --- a/window/process.h +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// https://github.com/go-vgo/robotgo/blob/master/LICENSE -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// #include -#include -#if defined(IS_MACOSX) - #if defined (__x86_64__) - #define RobotGo_64 - #else - #define RobotGo_32 - #endif - // #include - // #include - // #include - - // Apple process API - #include - #include - #include - - #ifdef MAC_OS_X_VERSION_10_11 - #define kAXValueCGPointType kAXValueTypeCGPoint - #define kAXValueCGSizeType kAXValueTypeCGSize - #endif - - #ifndef EXC_MASK_GUARD - #define EXC_MASK_GUARD 0 - #endif -#elif defined(USE_X11) - #if defined (__x86_64__) - #define RobotGo_64 - #else - #define RobotGo_32 - #endif - - #include - #include - - #ifndef X_HAVE_UTF8_STRING - #error It appears that X_HAVE_UTF8_STRING is not defined - \ - please verify that your version of XLib is supported - #endif -#elif defined(IS_WINDOWS) - #if defined (_WIN64) - #define RobotGo_64 - #else - #define RobotGo_32 - #endif - - #include - #include -#endif - -typedef signed char int8; // Signed 8-Bit integer -typedef signed short int16; // Signed 16-Bit integer -typedef signed int int32; // Signed 32-Bit integer -typedef signed long long int64; // Signed 64-Bit integer - -typedef unsigned char uint8; // Unsigned 8-Bit integer -typedef unsigned short uint16; // Unsigned 16-Bit integer -typedef unsigned int uint32; // Unsigned 32-Bit integer -typedef unsigned long long uint64; // Unsigned 64-Bit integer - -typedef float real32; // 32-Bit float value -typedef double real64; // 64-Bit float value - -#ifdef RobotGo_64 - - typedef int64 intptr; // Signed pointer integer - typedef uint64 uintptr; // Unsigned pointer integer - -#else - - typedef int32 intptr; // Signed pointer integer - typedef uint32 uintptr; // Unsigned pointer integer - -#endif -// - -struct _PData{ - int32 ProcID; // The process ID - - char* Name; // Name of process - char* Path; // Path of process - - bool Is64Bit; // Process is 64-Bit - -#if defined(IS_MACOSX) - - task_t Handle; // The mach task - -#elif defined(USE_X11) - - uint32 Handle; // Unused handle - -#elif defined(IS_WINDOWS) - - HANDLE Handle; // Process handle - -#endif -}; - -struct _PPData{ - int32 ProcID; // The process ID - - char** Name; // Name of process - char** Path; // Path of process - - bool Is64Bit; // Process is 64-Bit - -#if defined(IS_MACOSX) - - task_t Handle; // The mach task - -#elif defined(USE_X11) - - uint32 Handle; // Unused handle - -#elif defined(IS_WINDOWS) - - HANDLE Handle; // Process handle - -#endif -}; - -typedef struct _PData PData; diff --git a/window/pub.h b/window/pub.h index a7814913..a30d52f0 100644 --- a/window/pub.h +++ b/window/pub.h @@ -10,6 +10,14 @@ // #include "../base/os.h" +#ifdef RobotGo_64 + typedef int64 intptr; + typedef uint64 uintptr; +#else + typedef int32_t intptr; + typedef uint32_t uintptr; // Unsigned pointer integer +#endif + struct _MData{ #if defined(IS_MACOSX) CGWindowID CgID; // Handle to a CGWindowID @@ -23,49 +31,41 @@ struct _MData{ }; typedef struct _MData MData; - MData mData; -struct _Bounds{ - int32 X; // Top left X coordinate - int32 Y; // Top left Y coordinate - int32 W; // Total bounds width - int32 H; // Total bounds height +struct _Bounds { + int32_t X; // Top left X coordinate + int32_t Y; // Top left Y coordinate + int32_t W; // bounds width + int32_t H; // bounds height }; - typedef struct _Bounds Bounds; #if defined(IS_MACOSX) - static Boolean(*gAXIsProcessTrustedWithOptions) (CFDictionaryRef); - static CFStringRef* gkAXTrustedCheckOptionPrompt; AXError _AXUIElementGetWindow(AXUIElementRef, CGWindowID* out); - static AXUIElementRef GetUIElement(CGWindowID win){ intptr pid = 0; // double_t pid = 0; // Create array storing window CGWindowID window[1] = { win }; - CFArrayRef wlist = CFArrayCreate(NULL, - (const void**)window, 1, NULL); + CFArrayRef wlist = CFArrayCreate(NULL, (const void**)window, 1, NULL); // Get window info CFArrayRef info = CGWindowListCreateDescriptionFromArray(wlist); CFRelease(wlist); // Check whether the resulting array is populated - if (info != NULL && CFArrayGetCount(info) > 0){ + if (info != NULL && CFArrayGetCount(info) > 0) { // Retrieve description from info array CFDictionaryRef desc = (CFDictionaryRef)CFArrayGetValueAtIndex(info, 0); // Get window PID - CFNumberRef data =(CFNumberRef) - CFDictionaryGetValue(desc, kCGWindowOwnerPID); - - if (data != NULL){ + CFNumberRef data = (CFNumberRef) CFDictionaryGetValue(desc, kCGWindowOwnerPID); + if (data != NULL) { CFNumberGetValue(data, kCFNumberIntType, &pid); } @@ -74,17 +74,15 @@ typedef struct _Bounds Bounds; } // Check if PID was retrieved - if (pid <= 0) {return NULL;} + if (pid <= 0) { return NULL; } // Create an accessibility object using retrieved PID AXUIElementRef application = AXUIElementCreateApplication(pid); - if (application == 0) {return NULL;} CFArrayRef windows = NULL; // Get all windows associated with the app - AXUIElementCopyAttributeValues(application, - kAXWindowsAttribute, 0, 1024, &windows); + AXUIElementCopyAttributeValues(application, kAXWindowsAttribute, 0, 1024, &windows); // Reference to resulting value AXUIElementRef result = NULL; @@ -94,14 +92,11 @@ typedef struct _Bounds Bounds; // Loop all windows in the process for (CFIndex i = 0; i < count; ++i){ // Get the element at the index - AXUIElementRef element = (AXUIElementRef) - CFArrayGetValueAtIndex(windows, i); - + AXUIElementRef element = (AXUIElementRef) CFArrayGetValueAtIndex(windows, i); CGWindowID temp = 0; // Use undocumented API to get WindowID _AXUIElementGetWindow(element, &temp); - // Check results if (temp == win) { // Retain element CFRetain(element); @@ -117,15 +112,11 @@ typedef struct _Bounds Bounds; return result; } #elif defined(USE_X11) - // Error Handling - typedef int (*XErrorHandler) (Display*, XErrorEvent*); static int XHandleError(Display* dp, XErrorEvent* e) { return 0; } - XErrorHandler mOld; - void XDismissErrors (void) { Display *rDisplay = XOpenDisplay(NULL); // Save old handler and dismiss errors @@ -139,12 +130,11 @@ typedef struct _Bounds Bounds; } // Definitions - struct Hints{ unsigned long Flags; unsigned long Funcs; unsigned long Decorations; - signed long Mode; + signed long Mode; unsigned long Stat; }; @@ -186,10 +176,8 @@ typedef struct _Bounds Bounds; XCloseDisplay(rDisplay); } - - // Functions - static void* GetWindowProperty(MData win, Atom atom, uint32* items){ + static void* GetWindowProperty(MData win, Atom atom, uint32* items) { // Property variables Atom type; int format; unsigned long nItems; @@ -200,25 +188,22 @@ typedef struct _Bounds Bounds; // Check the atom if (atom != None) { // Retrieve and validate the specified property - if (!XGetWindowProperty(rDisplay, win.XWin, atom, 0, - BUFSIZ, False, AnyPropertyType, &type, &format, - &nItems, &bAfter, &result) && result && nItems) { + if (!XGetWindowProperty(rDisplay, win.XWin, atom, 0, + BUFSIZ, False, AnyPropertyType, &type, &format, &nItems, &bAfter, &result) + && result && nItems) { // Copy items result if (items != NULL) { *items = (uint32) nItems; } - return result; } } // Reset the items result if valid - if (items != NULL) {*items = 0;} - - // Free the result if it got allocated + if (items != NULL) { *items = 0; } if (result != NULL) { - XFree (result); + XFree(result); } XCloseDisplay(rDisplay); @@ -226,12 +211,10 @@ typedef struct _Bounds Bounds; } ////// - #define STATE_TOPMOST 0 #define STATE_MINIMIZE 1 #define STATE_MAXIMIZE 2 - ////// static void SetDesktopForWindow(MData win){ Display *rDisplay = XOpenDisplay(NULL); @@ -239,7 +222,6 @@ typedef struct _Bounds Bounds; if (WM_DESKTOP != None && WM_CURDESK != None) { // Get desktop property long* desktop = (long*)GetWindowProperty(win, WM_DESKTOP,NULL); - // Check result value if (desktop != NULL) { // Retrieve the screen number @@ -258,9 +240,8 @@ typedef struct _Bounds Bounds; e.data.l[1] = CurrentTime; // Send the message - XSendEvent(rDisplay, - root, False, SubstructureNotifyMask | - SubstructureRedirectMask, (XEvent*) &e); + XSendEvent(rDisplay, root, False, SubstructureNotifyMask | SubstructureRedirectMask, + (XEvent*) &e); XFree(desktop); } @@ -275,8 +256,6 @@ typedef struct _Bounds Bounds; long* result; uint32 nItems = 0; // Get the window extents property result = (long*) GetWindowProperty(win, WM_EXTENTS, &nItems); - - // Verify the results if (result != NULL) { if (nItems == 4) { frame.X = (int32) result[0]; @@ -288,11 +267,25 @@ typedef struct _Bounds Bounds; XFree(result); } } - return frame; } #elif defined(IS_WINDOWS) // + void win_min(HWND hwnd, bool state){ + if (state) { + ShowWindow(hwnd, SW_MINIMIZE); + } else { + ShowWindow(hwnd, SW_RESTORE); + } + } + + void win_max(HWND hwnd, bool state){ + if (state) { + ShowWindow(hwnd, SW_MAXIMIZE); + } else { + ShowWindow(hwnd, SW_RESTORE); + } + } #endif \ No newline at end of file diff --git a/window/win32.h b/window/win32.h deleted file mode 100644 index 8935aefc..00000000 --- a/window/win32.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// https://github.com/go-vgo/robotgo/blob/master/LICENSE -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// #include "../base/os.h" - -#if defined(IS_WINDOWS) - typedef struct{ - HWND hWnd; - DWORD dwPid; - }WNDINFO; - - BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam){ - WNDINFO* pInfo = (WNDINFO*)lParam; - DWORD dwProcessId = 0; - GetWindowThreadProcessId(hWnd, &dwProcessId); - - if (dwProcessId == pInfo->dwPid) { - pInfo->hWnd = hWnd; - return FALSE; - } - return TRUE; - } - - HWND GetHwndByPId(DWORD dwProcessId){ - WNDINFO info = {0}; - info.hWnd = NULL; - info.dwPid = dwProcessId; - EnumWindows(EnumWindowsProc, (LPARAM)&info); - // printf("%d\n", info.hWnd); - return info.hWnd; - } - - // window - void win_min(HWND hwnd, bool state){ - if (state) { - ShowWindow(hwnd, SW_MINIMIZE); - } else { - ShowWindow(hwnd, SW_RESTORE); - } - } - - void win_max(HWND hwnd, bool state){ - if (state) { - ShowWindow(hwnd, SW_MAXIMIZE); - } else { - ShowWindow(hwnd, SW_RESTORE); - } - } -#endif \ No newline at end of file diff --git a/window/win_sys.h b/window/win_sys.h index 0a7cbe61..3710eb91 100644 --- a/window/win_sys.h +++ b/window/win_sys.h @@ -20,26 +20,23 @@ intptr scaleX(); double sys_scale(int32_t display_id) { #if defined(IS_MACOSX) - CGDirectDisplayID displayID = (CGDirectDisplayID) display_id; if (displayID == -1) { displayID = CGMainDisplayID(); } + CGDisplayModeRef modeRef = CGDisplayCopyDisplayMode(displayID); - double pixelWidth = CGDisplayModeGetPixelWidth(modeRef); double targetWidth = CGDisplayModeGetWidth(modeRef); - + return pixelWidth / targetWidth; #elif defined(USE_X11) - char *displayname = NULL; - Display *dpy = XOpenDisplay(displayname); - + Display *dpy = XOpenDisplay(NULL); + int scr = 0; /* Screen number */ double xres = ((((double) DisplayWidth(dpy, scr)) * 25.4) / ((double) DisplayWidthMM(dpy, scr))); - // https://github.com/glfw/glfw/issues/1019#issuecomment-302772498 char *rms = XResourceManagerString(dpy); if (rms) { XrmDatabase db = XrmGetStringDatabase(rms); @@ -75,7 +72,6 @@ intptr scaleX(){ HDC desktopDc = GetDC(NULL); // Get native resolution intptr horizontalDPI = GetDeviceCaps(desktopDc, LOGPIXELSX); - // intptr verticalDPI = GetDeviceCaps(desktopDc, LOGPIXELSY); return horizontalDPI; #endif } @@ -86,9 +82,7 @@ intptr scaleY(){ #elif defined(USE_X11) return 0; #elif defined(IS_WINDOWS) - // Get desktop dc HDC desktopDc = GetDC(NULL); - // Get native resolution intptr verticalDPI = GetDeviceCaps(desktopDc, LOGPIXELSY); return verticalDPI; #endif @@ -100,7 +94,6 @@ Bounds get_bounds(uintptr pid, uintptr isHwnd){ if (!IsValid()) { return bounds; } #if defined(IS_MACOSX) - // Bounds bounds; AXValueRef axp = NULL; AXValueRef axs = NULL; @@ -136,9 +129,7 @@ Bounds get_bounds(uintptr pid, uintptr isHwnd){ if (axs != NULL) { CFRelease(axs); } return bounds; - #elif defined(USE_X11) - // Ignore X errors XDismissErrors(); MData win; @@ -153,7 +144,6 @@ Bounds get_bounds(uintptr pid, uintptr isHwnd){ bounds.H = client.H + frame.H; return bounds; - #elif defined(IS_WINDOWS) HWND hwnd; if (isHwnd == 0) { @@ -171,7 +161,6 @@ Bounds get_bounds(uintptr pid, uintptr isHwnd){ bounds.H = rect.bottom - rect.top; return bounds; - #endif } @@ -181,11 +170,8 @@ Bounds get_client(uintptr pid, uintptr isHwnd){ if (!IsValid()) { return bounds; } #if defined(IS_MACOSX) - return get_bounds(pid, isHwnd); - #elif defined(USE_X11) - Display *rDisplay = XOpenDisplay(NULL); // Ignore X errors @@ -227,7 +213,6 @@ Bounds get_client(uintptr pid, uintptr isHwnd){ XCloseDisplay(rDisplay); return bounds; - #elif defined(IS_WINDOWS) HWND hwnd; if (isHwnd == 0) { @@ -253,6 +238,5 @@ Bounds get_client(uintptr pid, uintptr isHwnd){ bounds.H = rect.bottom - rect.top; return bounds; - #endif } \ No newline at end of file diff --git a/window/window.h b/window/window.h index a8cba40f..83bd7b70 100644 --- a/window/window.h +++ b/window/window.h @@ -9,10 +9,10 @@ // except according to those terms. // #include "../base/os.h" -// #include -#include "process.h" #include "pub.h" -#include "win32.h" +#if defined(IS_MACOSX) + #include +#endif bool setHandle(uintptr handle); bool IsValid(); @@ -22,16 +22,13 @@ void initWindow(); char* get_title_by_hand(MData m_data); void close_window_by_Id(MData m_data); -//int findwindow() - +// int findwindow() uintptr initHandle = 0; void initWindow(uintptr handle){ #if defined(IS_MACOSX) - mData.CgID = 0; mData.AxID = 0; - #elif defined(USE_X11) Display *rDisplay = XOpenDisplay(NULL); // If atoms loaded @@ -45,7 +42,6 @@ void initWindow(uintptr handle){ #elif defined(IS_WINDOWS) mData.HWnd = 0; #endif - setHandle(handle); } @@ -59,7 +55,6 @@ bool Is64Bit() { MData set_handle_pid(uintptr pid, uintptr isHwnd){ MData win; - #if defined(IS_MACOSX) // Handle to a AXUIElementRef win.AxID = AXUIElementCreateApplication(pid); @@ -91,58 +86,50 @@ bool IsValid(){ MData actdata = GetActive(); #if defined(IS_MACOSX) - mData.CgID = actdata.CgID; mData.AxID = actdata.AxID; - - if (mData.CgID == 0 || mData.AxID == 0)return false; + if (mData.CgID == 0 || mData.AxID == 0){ return false; } CFTypeRef r = NULL; - // Attempt to get the window role - if (AXUIElementCopyAttributeValue(mData.AxID, - kAXRoleAttribute,&r) == kAXErrorSuccess && r){ - CFRelease (r); + if (AXUIElementCopyAttributeValue(mData.AxID, kAXRoleAttribute, &r) == kAXErrorSuccess && r){ + CFRelease(r); return true; } return false; - #elif defined(USE_X11) mData.XWin = actdata.XWin; - if (mData.XWin == 0) {return false;} + if (mData.XWin == 0) { return false; } Display *rDisplay = XOpenDisplay(NULL); // Check for a valid X-Window display - if (rDisplay == NULL) {return false;} + if (rDisplay == NULL) { return false; } // Ignore X errors XDismissErrors(); // Get the window PID property void* result = GetWindowProperty(mData, WM_PID,NULL); - if (result == NULL) {return false;} + if (result == NULL) { return false; } // Free result and return true XFree(result); XCloseDisplay(rDisplay); - return true; + return true; #elif defined(IS_WINDOWS) mData.HWnd = actdata.HWnd; - if (mData.HWnd == 0) { return false; } return IsWindow(mData.HWnd) != 0; - #endif } bool IsAxEnabled(bool options){ #if defined(IS_MACOSX) - // Statically load all required functions one time static dispatch_once_t once; dispatch_once (&once, ^{ @@ -152,19 +139,18 @@ bool IsAxEnabled(bool options){ // Validate the handle if (handle != NULL) { - *(void**) (&gAXIsProcessTrustedWithOptions) = + *(void**) (&gAXIsProcessTrustedWithOptions) = dlsym (handle, "AXIsProcessTrustedWithOptions"); - gkAXTrustedCheckOptionPrompt = (CFStringRef*) - dlsym (handle, "kAXTrustedCheckOptionPrompt"); + gkAXTrustedCheckOptionPrompt = + (CFStringRef*) dlsym (handle, "kAXTrustedCheckOptionPrompt"); } }); // Check for new OSX 10.9 function if (gAXIsProcessTrustedWithOptions) { // Check whether to show prompt - CFBooleanRef displayPrompt = options ? - kCFBooleanTrue : kCFBooleanFalse; + CFBooleanRef displayPrompt = options ? kCFBooleanTrue : kCFBooleanFalse; // Convert display prompt value into a dictionary const void* k[] = { *gkAXTrustedCheckOptionPrompt }; @@ -186,7 +172,6 @@ bool IsAxEnabled(bool options){ return AXAPIEnabled() || AXIsProcessTrusted(); #pragma clang diagnostic pop } - #elif defined(USE_X11) return true; #elif defined(IS_WINDOWS) @@ -198,7 +183,7 @@ bool IsAxEnabled(bool options){ bool setHandle(uintptr handle){ #if defined(IS_MACOSX) // Release the AX element - if (mData.AxID != NULL){ + if (mData.AxID != NULL) { CFRelease(mData.AxID); } @@ -206,7 +191,7 @@ bool setHandle(uintptr handle){ mData.CgID = 0; mData.AxID = 0; - if (handle == 0){ + if (handle == 0) { // return 0; return true; } @@ -214,7 +199,6 @@ bool setHandle(uintptr handle){ // Retrieve the window element CGWindowID cgID = (CGWindowID)handle; AXUIElementRef axID = GetUIElement(cgID); - if (axID != NULL){ mData.CgID = cgID; mData.AxID = axID; @@ -224,11 +208,8 @@ bool setHandle(uintptr handle){ // return 1; return false; - #elif defined(USE_X11) - mData.XWin = (Window)handle; - if (handle == 0){ return true; } @@ -240,9 +221,7 @@ bool setHandle(uintptr handle){ mData.XWin = 0; return false; #elif defined(IS_WINDOWS) - mData.HWnd = (HWND)handle; - if (handle == 0) { return true; } @@ -253,7 +232,6 @@ bool setHandle(uintptr handle){ mData.HWnd = 0; return false; - #endif } @@ -272,20 +250,13 @@ bool IsTopMost(void){ // Check the window validity if (!IsValid()) {return false;} #if defined(IS_MACOSX) - return false; // WARNING: Unavailable - #elif defined(USE_X11) - // Ignore X errors // XDismissErrors (); // return GetState (mData.XWin, STATE_TOPMOST); - #elif defined(IS_WINDOWS) - - return (GetWindowLongPtr(mData.HWnd, GWL_EXSTYLE) - & WS_EX_TOPMOST) != 0; - + return (GetWindowLongPtr(mData.HWnd, GWL_EXSTYLE) & WS_EX_TOPMOST) != 0; #endif } @@ -293,13 +264,10 @@ bool IsMinimized(void){ // Check the window validity if (!IsValid()) {return false;} #if defined(IS_MACOSX) - CFBooleanRef data = NULL; - // Determine whether the window is minimized - if (AXUIElementCopyAttributeValue(mData.AxID, - kAXMinimizedAttribute, (CFTypeRef*) &data) - == kAXErrorSuccess && data != NULL) { + if (AXUIElementCopyAttributeValue(mData.AxID, kAXMinimizedAttribute, + (CFTypeRef*) &data) == kAXErrorSuccess && data != NULL) { // Convert resulting data into a bool bool result = CFBooleanGetValue(data); CFRelease(data); @@ -307,52 +275,36 @@ bool IsMinimized(void){ } return false; - #elif defined(USE_X11) - // Ignore X errors // XDismissErrors(); // return GetState(mData.XWin, STATE_MINIMIZE); - #elif defined(IS_WINDOWS) - - return (GetWindowLongPtr(mData.HWnd, GWL_STYLE) - & WS_MINIMIZE) != 0; - + return (GetWindowLongPtr(mData.HWnd, GWL_STYLE) & WS_MINIMIZE) != 0; #endif } ////// - bool IsMaximized(void){ // Check the window validity if (!IsValid()) {return false;} #if defined(IS_MACOSX) - return false; // WARNING: Unavailable - #elif defined(USE_X11) - // Ignore X errors // XDismissErrors(); // return GetState(mData.XWin, STATE_MAXIMIZE); - #elif defined(IS_WINDOWS) - - return (GetWindowLongPtr(mData.HWnd, GWL_STYLE) - & WS_MAXIMIZE) != 0; - + return (GetWindowLongPtr(mData.HWnd, GWL_STYLE) & WS_MAXIMIZE) != 0; #endif } -void SetActive(const MData win){ +void SetActive(const MData win) { // Check if the window is valid if (!IsValid()) { return; } #if defined(IS_MACOSX) - // Attempt to raise the specified window object - if (AXUIElementPerformAction(win.AxID, kAXRaiseAction) - != kAXErrorSuccess) { + if (AXUIElementPerformAction(win.AxID, kAXRaiseAction) != kAXErrorSuccess) { pid_t pid = 0; // Attempt to retrieve the PID of the window if (AXUIElementGetPid(win.AxID, &pid) @@ -362,10 +314,6 @@ void SetActive(const MData win){ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - // NOTE: Until Apple actually removes - // these functions, there's no real - // reason to switch to the NS* flavor - ProcessSerialNumber psn; // Attempt to retrieve the process psn if (GetProcessForPID(pid, &psn) == 0) { @@ -377,7 +325,6 @@ void SetActive(const MData win){ } #elif defined(USE_X11) - // Ignore X errors XDismissErrors(); @@ -410,24 +357,20 @@ void SetActive(const MData win){ XRaiseWindow(rDisplay, win.XWin); // Set the specified window's input focus - XSetInputFocus(rDisplay, win.XWin, - RevertToParent, CurrentTime); + XSetInputFocus(rDisplay, win.XWin, RevertToParent, CurrentTime); } XCloseDisplay(rDisplay); #elif defined(IS_WINDOWS) - if (IsMinimized()) { ShowWindow(win.HWnd, SW_RESTORE); } SetForegroundWindow(win.HWnd); - #endif } -MData GetActive(void){ +MData GetActive(void) { #if defined(IS_MACOSX) - MData result; // Ignore deprecated warnings #pragma clang diagnostic push @@ -435,8 +378,7 @@ MData GetActive(void){ ProcessSerialNumber psn; pid_t pid; // Attempt to retrieve the front process - if (GetFrontProcess(&psn) != 0 || - GetProcessPID(&psn, &pid) != 0) { + if (GetFrontProcess(&psn) != 0 || GetProcessPID(&psn, &pid) != 0) { return result; } @@ -448,30 +390,23 @@ MData GetActive(void){ AXUIElementRef element; // Retrieve the currently focused window - if (AXUIElementCopyAttributeValue(focused, - kAXFocusedWindowAttribute, (CFTypeRef*) - &element) == kAXErrorSuccess && element) { + if (AXUIElementCopyAttributeValue(focused, kAXFocusedWindowAttribute, (CFTypeRef*) &element) + == kAXErrorSuccess && element) { CGWindowID win = 0; // Use undocumented API to get WID - if (_AXUIElementGetWindow(element, &win) - == kAXErrorSuccess && win) { + if (_AXUIElementGetWindow(element, &win) == kAXErrorSuccess && win) { // Manually set internals result.CgID = win; result.AxID = element; - } - // Something went wrong - else { + } else { CFRelease(element); } } - CFRelease(focused); return result; - #elif defined(USE_X11) - MData result; Display *rDisplay = XOpenDisplay(NULL); // Check X-Window display @@ -508,9 +443,7 @@ MData GetActive(void){ // Return foreground window result.XWin = window; return result; - #elif defined(IS_WINDOWS) - // Attempt to get the foreground window multiple times in case MData result; @@ -523,11 +456,10 @@ MData GetActive(void){ result.HWnd = (HWND)handle; return result; } - Sleep (20); + Sleep(20); } return result; - #endif } @@ -536,21 +468,14 @@ void SetTopMost(bool state){ // Check window validity if (!IsValid()) {return;} #if defined(IS_MACOSX) - // WARNING: Unavailable - #elif defined(USE_X11) - // Ignore X errors // XDismissErrors(); // SetState(mData.XWin, STATE_TOPMOST, state); - #elif defined(IS_WINDOWS) - - SetWindowPos(mData.HWnd, - state ? HWND_TOPMOST : HWND_NOTOPMOST, + SetWindowPos(mData.HWnd, state ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); - #endif } @@ -573,20 +498,15 @@ void close_window_by_Id(MData m_data){ if (!IsValid()) { return; } #if defined(IS_MACOSX) AXUIElementRef b = NULL; - // Retrieve the close button of this window - if (AXUIElementCopyAttributeValue(m_data.AxID, - kAXCloseButtonAttribute, (CFTypeRef*) &b) + if (AXUIElementCopyAttributeValue(m_data.AxID, kAXCloseButtonAttribute, (CFTypeRef*) &b) == kAXErrorSuccess && b != NULL) { // Simulate button press on the close button AXUIElementPerformAction(b, kAXPressAction); CFRelease(b); } - #elif defined(USE_X11) - Display *rDisplay = XOpenDisplay(NULL); - // Ignore X errors XDismissErrors(); @@ -594,7 +514,6 @@ void close_window_by_Id(MData m_data){ XDestroyWindow(rDisplay, m_data.XWin); XCloseDisplay(rDisplay); #elif defined(IS_WINDOWS) - PostMessage(m_data.HWnd, WM_CLOSE, 0, 0); #endif } @@ -611,18 +530,29 @@ char* get_title_by_pid(uintptr pid, uintptr isHwnd){ return get_title_by_hand(win); } +char* named(void *result) { + char *name = (char*)calloc(strlen(result)+1, sizeof(char*)); + char *rptr = (char*)result; + char *nptr = name; + while (*rptr) { + *nptr = *rptr; + nptr++; + rptr++; + } + *nptr = '\0'; + + return name; +} + char* get_title_by_hand(MData m_data){ // Check if the window is valid if (!IsValid()) {return "IsValid failed.";} - #if defined(IS_MACOSX) - CFStringRef data = NULL; // Determine the current title of the window if (AXUIElementCopyAttributeValue(m_data.AxID, - kAXTitleAttribute, (CFTypeRef*) &data) - == kAXErrorSuccess && data != NULL) { + kAXTitleAttribute, (CFTypeRef*) &data) == kAXErrorSuccess && data != NULL) { char conv[512]; // Convert result to a C-String CFStringGetCString(data, conv, 512, kCFStringEncodingUTF8); @@ -635,28 +565,17 @@ char* get_title_by_hand(MData m_data){ } return ""; - #elif defined(USE_X11) - void* result; // Ignore X errors XDismissErrors(); // Get window title (UTF-8) result = GetWindowProperty(m_data, WM_NAME, NULL); - // Check result value if (result != NULL) { // Convert result to a string - char *name = (char*)calloc(strlen(result)+1, sizeof(char*)); - char *rptr = (char*)result; - char *nptr = name; - while (*rptr) { - *nptr = *rptr; - nptr++; - rptr++; - } - *nptr = '\0'; + char* name = named(result); XFree(result); if (name != NULL) { return name; } @@ -664,28 +583,17 @@ char* get_title_by_hand(MData m_data){ // Get window title (ASCII) result = GetWindowProperty(m_data, XA_WM_NAME, NULL); - // Check result value if (result != NULL) { // Convert result to a string - char *name = (char*)calloc(strlen(result)+1, sizeof(char*)); - char *rptr = (char*)result; - char *nptr = name; - while (*rptr) { - *nptr = *rptr; - nptr++; - rptr++; - } - *nptr = '\0'; + char* name = named(result); XFree(result); return name; } return ""; - #elif defined(IS_WINDOWS) - if (GetWindowText(m_data.HWnd, m_data.Title, 512) > 0){ char* name = m_data.Title; @@ -695,44 +603,36 @@ char* get_title_by_hand(MData m_data){ } return ""; - #endif } -int32 WGetPID(void){ +int32_t WGetPID(void) { // Check window validity if (!IsValid()) { return 0; } - #if defined(IS_MACOSX) - pid_t pid = 0; // Attempt to retrieve the window pid if (AXUIElementGetPid(mData.AxID, &pid)== kAXErrorSuccess) { - return pid; - } + return pid; + } return 0; - #elif defined(USE_X11) - // Ignore X errors XDismissErrors(); // Get the window PID long* result = (long*)GetWindowProperty(mData, WM_PID,NULL); - // Check result and convert it if (result == NULL) { return 0; } + int32 pid = (int32) *result; XFree(result); return pid; - #elif defined(IS_WINDOWS) - - DWORD id = 0; + DWORD id = 0; GetWindowThreadProcessId(mData.HWnd, &id); return id; - #endif } From caf3fbb9826536a671211af6e8fc6d2e55c44a66 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Fri, 21 Jan 2022 16:21:09 -0400 Subject: [PATCH 174/327] Fixed CI build --- base/win32.h | 4 ++-- screen/screengrab_c.h | 4 ++-- window/pub.h | 21 +++++++++++++-------- window/win_sys.h | 4 ++-- window/window.h | 7 ++----- 5 files changed, 21 insertions(+), 19 deletions(-) diff --git a/base/win32.h b/base/win32.h index d5b458e8..d4e24852 100644 --- a/base/win32.h +++ b/base/win32.h @@ -1,8 +1,8 @@ #if defined(IS_WINDOWS) - bool CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { + BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { uint32_t *count = (uint32_t*)dwData; (*count)++; - return true; + return TRUE; } typedef struct{ diff --git a/screen/screengrab_c.h b/screen/screengrab_c.h index 32367b50..7464c8d7 100644 --- a/screen/screengrab_c.h +++ b/screen/screengrab_c.h @@ -52,7 +52,7 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id) #elif defined(USE_X11) MMBitmapRef bitmap; Display *display; - if display_id == -1 { + if (display_id == -1) { display = XOpenDisplay(NULL); } else { display = XGetMainDisplay(); @@ -92,7 +92,7 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id) bi.bmiHeader.biClrUsed = 0; bi.bmiHeader.biClrImportant = 0; - if display_id == -1 { + if (display_id == -1) { screen = GetDC(NULL); /* Get entire screen */ } else { screen = GetDC((HWND) display_id); diff --git a/window/pub.h b/window/pub.h index a30d52f0..eee39b4f 100644 --- a/window/pub.h +++ b/window/pub.h @@ -9,10 +9,15 @@ // except according to those terms. // #include "../base/os.h" +#if defined(IS_MACOSX) + #include +#elif defined(USE_X11) + #include +#endif #ifdef RobotGo_64 - typedef int64 intptr; - typedef uint64 uintptr; + typedef int64_t intptr; + typedef uint64_t uintptr; #else typedef int32_t intptr; typedef uint32_t uintptr; // Unsigned pointer integer @@ -177,7 +182,7 @@ typedef struct _Bounds Bounds; } // Functions - static void* GetWindowProperty(MData win, Atom atom, uint32* items) { + static void* GetWindowProperty(MData win, Atom atom, uint32_t* items) { // Property variables Atom type; int format; unsigned long nItems; @@ -253,15 +258,15 @@ typedef struct _Bounds Bounds; Bounds frame; // Retrieve frame bounds if (WM_EXTENTS != None) { - long* result; uint32 nItems = 0; + long* result; uint32_t nItems = 0; // Get the window extents property result = (long*) GetWindowProperty(win, WM_EXTENTS, &nItems); if (result != NULL) { if (nItems == 4) { - frame.X = (int32) result[0]; - frame.Y = (int32) result[2]; - frame.W = (int32) result[0] + (int32) result[1]; - frame.H = (int32) result[2] + (int32) result[3]; + frame.X = (int32_t) result[0]; + frame.Y = (int32_t) result[2]; + frame.W = (int32_t) result[0] + (int32_t) result[1]; + frame.H = (int32_t) result[2] + (int32_t) result[3]; } XFree(result); diff --git a/window/win_sys.h b/window/win_sys.h index 3710eb91..236d3ae5 100644 --- a/window/win_sys.h +++ b/window/win_sys.h @@ -164,7 +164,7 @@ Bounds get_bounds(uintptr pid, uintptr isHwnd){ #endif } -Bounds get_client(uintptr pid, uintptr isHwnd){ +Bounds get_client(uintptr pid, uintptr isHwnd) { // Check if the window is valid Bounds bounds; if (!IsValid()) { return bounds; } @@ -183,7 +183,7 @@ Bounds get_client(uintptr pid, uintptr isHwnd){ Window root, parent; Window* children; unsigned int count; - int32 x = 0, y = 0; + int32_t x = 0, y = 0; // Check if the window is the root XQueryTree(rDisplay, win.XWin, diff --git a/window/window.h b/window/window.h index 83bd7b70..6ff49351 100644 --- a/window/window.h +++ b/window/window.h @@ -10,9 +10,6 @@ // #include "../base/os.h" #include "pub.h" -#if defined(IS_MACOSX) - #include -#endif bool setHandle(uintptr handle); bool IsValid(); @@ -447,7 +444,7 @@ MData GetActive(void) { // Attempt to get the foreground window multiple times in case MData result; - uint8 times = 0; + uint8_t times = 0; while (++times < 20) { HWND handle; handle = GetForegroundWindow(); @@ -626,7 +623,7 @@ int32_t WGetPID(void) { // Check result and convert it if (result == NULL) { return 0; } - int32 pid = (int32) *result; + int32_t pid = (int32_t) *result; XFree(result); return pid; #elif defined(IS_WINDOWS) From acfb61e8ce4a2a44ac8f0559393830e7e417ca8d Mon Sep 17 00:00:00 2001 From: vcaesar Date: Fri, 21 Jan 2022 16:25:37 -0400 Subject: [PATCH 175/327] Update missed type --- window/pub.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/window/pub.h b/window/pub.h index eee39b4f..bf7b8fd0 100644 --- a/window/pub.h +++ b/window/pub.h @@ -199,7 +199,7 @@ typedef struct _Bounds Bounds; // Copy items result if (items != NULL) { - *items = (uint32) nItems; + *items = (uint32_t) nItems; } return result; } From 477a7b473ca51ea680670def9e2cfecc8e886c36 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sat, 22 Jan 2022 11:53:03 -0400 Subject: [PATCH 176/327] Refactor the Alert() code and remove some code --- base/snprintf.h | 46 -- base/snprintf_c.h | 1019 --------------------------------------- examples/window/main.go | 5 +- mouse/goMouse.h | 38 -- robotgo.go | 18 +- robotgo_mac_win.go | 10 + robotgo_x11.go | 22 + window/alert.h | 17 - window/alert_c.h | 133 +---- 9 files changed, 43 insertions(+), 1265 deletions(-) delete mode 100644 base/snprintf.h delete mode 100644 base/snprintf_c.h delete mode 100644 window/alert.h diff --git a/base/snprintf.h b/base/snprintf.h deleted file mode 100644 index 60046e56..00000000 --- a/base/snprintf.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef _PORTABLE_SNPRINTF_H_ -#define _PORTABLE_SNPRINTF_H_ - -#define PORTABLE_SNPRINTF_VERSION_MAJOR 2 -#define PORTABLE_SNPRINTF_VERSION_MINOR 2 - -#include "os.h" -#if defined(IS_MACOSX) - #define HAVE_SNPRINTF -#else - #define HAVE_SNPRINTF - #define PREFER_PORTABLE_SNPRINTF -#endif - -#include -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -#ifdef HAVE_SNPRINTF -#include -#else -extern int snprintf(char *, size_t, const char *, /*args*/ ...); -extern int vsnprintf(char *, size_t, const char *, va_list); -#endif - -#if defined(HAVE_SNPRINTF) && defined(PREFER_PORTABLE_SNPRINTF) -extern int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args*/ ...); -extern int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap); -#define snprintf portable_snprintf -#define vsnprintf portable_vsnprintf -#endif - -extern int asprintf (char **ptr, const char *fmt, /*args*/ ...); -extern int vasprintf (char **ptr, const char *fmt, va_list ap); -extern int asnprintf (char **ptr, size_t str_m, const char *fmt, /*args*/ ...); -extern int vasnprintf(char **ptr, size_t str_m, const char *fmt, va_list ap); - -#endif - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/base/snprintf_c.h b/base/snprintf_c.h deleted file mode 100644 index 22ae3677..00000000 --- a/base/snprintf_c.h +++ /dev/null @@ -1,1019 +0,0 @@ -/* - * snprintf.c - a portable implementation of snprintf - * - * AUTHOR - * Mark Martinec , April 1999. - * - * Copyright 1999, Mark Martinec. All rights reserved. - * - * TERMS AND CONDITIONS - * This program is free software; you can redistribute it and/or modify - * it under the terms of the "Frontier Artistic License" which comes - * with this Kit. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the Frontier Artistic License for more details. - * - * You should have received a copy of the Frontier Artistic License - * with this Kit in the file named LICENSE.txt . - * If not, I'll be glad to provide one. - * - * FEATURES - * - careful adherence to specs regarding flags, field width and precision; - * - good performance for large string handling (large format, large - * argument or large paddings). Performance is similar to system's sprintf - * and in several cases significantly better (make sure you compile with - * optimizations turned on, tell the compiler the code is strict ANSI - * if necessary to give it more freedom for optimizations); - * - return value semantics per ISO/IEC 9899:1999 ("ISO C99"); - * - written in standard ISO/ANSI C - requires an ANSI C compiler. - * - * SUPPORTED CONVERSION SPECIFIERS AND DATA TYPES - * - * This snprintf only supports the following conversion specifiers: - * s, c, d, u, o, x, X, p (and synonyms: i, D, U, O - see below) - * with flags: '-', '+', ' ', '0' and '#'. - * An asterisk is supported for field width as well as precision. - * - * Length modifiers 'h' (short int), 'l' (long int), - * and 'll' (long long int) are supported. - * NOTE: - * If macro SNPRINTF_LONGLONG_SUPPORT is not defined (default) the - * length modifier 'll' is recognized but treated the same as 'l', - * which may cause argument value truncation! Defining - * SNPRINTF_LONGLONG_SUPPORT requires that your system's sprintf also - * handles length modifier 'll'. long long int is a language extension - * which may not be portable. - * - * Conversion of numeric data (conversion specifiers d, u, o, x, X, p) - * with length modifiers (none or h, l, ll) is left to the system routine - * sprintf, but all handling of flags, field width and precision as well as - * c and s conversions is done very carefully by this portable routine. - * If a string precision (truncation) is specified (e.g. %.8s) it is - * guaranteed the string beyond the specified precision will not be referenced. - * - * Length modifiers h, l and ll are ignored for c and s conversions (data - * types wint_t and wchar_t are not supported). - * - * The following common synonyms for conversion characters are supported: - * - i is a synonym for d - * - D is a synonym for ld, explicit length modifiers are ignored - * - U is a synonym for lu, explicit length modifiers are ignored - * - O is a synonym for lo, explicit length modifiers are ignored - * The D, O and U conversion characters are nonstandard, they are supported - * for backward compatibility only, and should not be used for new code. - * - * The following is specifically NOT supported: - * - flag ' (thousands' grouping character) is recognized but ignored - * - numeric conversion specifiers: f, e, E, g, G and synonym F, - * as well as the new a and A conversion specifiers - * - length modifier 'L' (long double) and 'q' (quad - use 'll' instead) - * - wide character/string conversions: lc, ls, and nonstandard - * synonyms C and S - * - writeback of converted string length: conversion character n - * - the n$ specification for direct reference to n-th argument - * - locales - * - * It is permitted for str_m to be zero, and it is permitted to specify NULL - * pointer for resulting string argument if str_m is zero (as per ISO C99). - * - * The return value is the number of characters which would be generated - * for the given input, excluding the trailing null. If this value - * is greater or equal to str_m, not all characters from the result - * have been stored in str, output bytes beyond the (str_m-1) -th character - * are discarded. If str_m is greater than zero it is guaranteed - * the resulting string will be null-terminated. - * - * NOTE that this matches the ISO C99, OpenBSD, and GNU C library 2.1, - * but is different from some older and vendor implementations, - * and is also different from XPG, XSH5, SUSv2 specifications. - * For historical discussion on changes in the semantics and standards - * of snprintf see printf(3) man page in the Linux programmers manual. - * - * Routines asprintf and vasprintf return a pointer (in the ptr argument) - * to a buffer sufficiently large to hold the resulting string. This pointer - * should be passed to free(3) to release the allocated storage when it is - * no longer needed. If sufficient space cannot be allocated, these functions - * will return -1 and set ptr to be a NULL pointer. These two routines are a - * GNU C library extensions (glibc). - * - * Routines asnprintf and vasnprintf are similar to asprintf and vasprintf, - * yet, like snprintf and vsnprintf counterparts, will write at most str_m-1 - * characters into the allocated output string, the last character in the - * allocated buffer then gets the terminating null. If the formatted string - * length (the return value) is greater than or equal to the str_m argument, - * the resulting string was truncated and some of the formatted characters - * were discarded. These routines present a handy way to limit the amount - * of allocated memory to some sane value. - * - * AVAILABILITY - * http://www.ijs.si/software/snprintf/ - * - * REVISION HISTORY - * 1999-04 V0.9 Mark Martinec - * - initial version, some modifications after comparing printf - * man pages for Digital Unix 4.0, Solaris 2.6 and HPUX 10, - * and checking how Perl handles sprintf (differently!); - * 1999-04-09 V1.0 Mark Martinec - * - added main test program, fixed remaining inconsistencies, - * added optional (long long int) support; - * 1999-04-12 V1.1 Mark Martinec - * - support the 'p' conversion (pointer to void); - * - if a string precision is specified - * make sure the string beyond the specified precision - * will not be referenced (e.g. by strlen); - * 1999-04-13 V1.2 Mark Martinec - * - support synonyms %D=%ld, %U=%lu, %O=%lo; - * - speed up the case of long format string with few conversions; - * 1999-06-30 V1.3 Mark Martinec - * - fixed runaway loop (eventually crashing when str_l wraps - * beyond 2^31) while copying format string without - * conversion specifiers to a buffer that is too short - * (thanks to Edwin Young for - * spotting the problem); - * - added macros PORTABLE_SNPRINTF_VERSION_(MAJOR|MINOR) - * to snprintf.h - * 2000-02-14 V2.0 (never released) Mark Martinec - * - relaxed license terms: The Artistic License now applies. - * You may still apply the GNU GENERAL PUBLIC LICENSE - * as was distributed with previous versions, if you prefer; - * - changed REVISION HISTORY dates to use ISO 8601 date format; - * - added vsnprintf (patch also independently proposed by - * Caolan McNamara 2000-05-04, and Keith M Willenson 2000-06-01) - * 2000-06-27 V2.1 Mark Martinec - * - removed POSIX check for str_m<1; value 0 for str_m is - * allowed by ISO C99 (and GNU C library 2.1) - (pointed out - * on 2000-05-04 by Caolan McNamara, caolan@ csn dot ul dot ie). - * Besides relaxed license this change in standards adherence - * is the main reason to bump up the major version number; - * - added nonstandard routines asnprintf, vasnprintf, asprintf, - * vasprintf that dynamically allocate storage for the - * resulting string; these routines are not compiled by default, - * see comments where NEED_V?ASN?PRINTF macros are defined; - * - autoconf contributed by Caolan McNamara - * 2000-10-06 V2.2 Mark Martinec - * - BUG FIX: the %c conversion used a temporary variable - * that was no longer in scope when referenced, - * possibly causing incorrect resulting character; - * - BUG FIX: make precision and minimal field width unsigned - * to handle huge values (2^31 <= n < 2^32) correctly; - * also be more careful in the use of signed/unsigned/size_t - * internal variables - probably more careful than many - * vendor implementations, but there may still be a case - * where huge values of str_m, precision or minimal field - * could cause incorrect behaviour; - * - use separate variables for signed/unsigned arguments, - * and for short/int, long, and long long argument lengths - * to avoid possible incompatibilities on certain - * computer architectures. Also use separate variable - * arg_sign to hold sign of a numeric argument, - * to make code more transparent; - * - some fiddling with zero padding and "0x" to make it - * Linux compatible; - * - systematically use macros fast_memcpy and fast_memset - * instead of case-by-case hand optimization; determine some - * breakeven string lengths for different architectures; - * - terminology change: 'format' -> 'conversion specifier', - * 'C9x' -> 'ISO/IEC 9899:1999 ("ISO C99")', - * 'alternative form' -> 'alternate form', - * 'data type modifier' -> 'length modifier'; - * - several comments rephrased and new ones added; - * - make compiler not complain about 'credits' defined but - * not used; - */ - - -/* Define HAVE_SNPRINTF if your system already has snprintf and vsnprintf. - * - * If HAVE_SNPRINTF is defined this module will not produce code for - * snprintf and vsnprintf, unless PREFER_PORTABLE_SNPRINTF is defined as well, - * causing this portable version of snprintf to be called portable_snprintf - * (and portable_vsnprintf). - */ -/* #define HAVE_SNPRINTF */ - -/* Define PREFER_PORTABLE_SNPRINTF if your system does have snprintf and - * vsnprintf but you would prefer to use the portable routine(s) instead. - * In this case the portable routine is declared as portable_snprintf - * (and portable_vsnprintf) and a macro 'snprintf' (and 'vsnprintf') - * is defined to expand to 'portable_v?snprintf' - see file snprintf.h . - * Defining this macro is only useful if HAVE_SNPRINTF is also defined, - * but does does no harm if defined nevertheless. - */ -/* #define PREFER_PORTABLE_SNPRINTF */ - -/* Define SNPRINTF_LONGLONG_SUPPORT if you want to support - * data type (long long int) and length modifier 'll' (e.g. %lld). - * If undefined, 'll' is recognized but treated as a single 'l'. - * - * If the system's sprintf does not handle 'll' - * the SNPRINTF_LONGLONG_SUPPORT must not be defined! - * - * This is off by default as (long long int) is a language extension. - */ -/* #define SNPRINTF_LONGLONG_SUPPORT */ - -/* Define NEED_SNPRINTF_ONLY if you only need snprintf, and not vsnprintf. - * If NEED_SNPRINTF_ONLY is defined, the snprintf will be defined directly, - * otherwise both snprintf and vsnprintf routines will be defined - * and snprintf will be a simple wrapper around vsnprintf, at the expense - * of an extra procedure call. - */ -/* #define NEED_SNPRINTF_ONLY */ - -/* Define NEED_V?ASN?PRINTF macros if you need library extension - * routines asprintf, vasprintf, asnprintf, vasnprintf respectively, - * and your system library does not provide them. They are all small - * wrapper routines around portable_vsnprintf. Defining any of the four - * NEED_V?ASN?PRINTF macros automatically turns off NEED_SNPRINTF_ONLY - * and turns on PREFER_PORTABLE_SNPRINTF. - * - * Watch for name conflicts with the system library if these routines - * are already present there. - * - * NOTE: vasprintf and vasnprintf routines need va_copy() from stdarg.h, as - * specified by C99, to be able to traverse the same list of arguments twice. - * I don't know of any other standard and portable way of achieving the same. - * With some versions of gcc you may use __va_copy(). You might even get away - * with "ap2 = ap", in this case you must not call va_end(ap2) ! - * #define va_copy(ap2,ap) ap2 = ap - */ -/* #define NEED_ASPRINTF */ -/* #define NEED_ASNPRINTF */ -/* #define NEED_VASPRINTF */ -/* #define NEED_VASNPRINTF */ - - -/* Define the following macros if desired: - * SOLARIS_COMPATIBLE, SOLARIS_BUG_COMPATIBLE, - * HPUX_COMPATIBLE, HPUX_BUG_COMPATIBLE, LINUX_COMPATIBLE, - * DIGITAL_UNIX_COMPATIBLE, DIGITAL_UNIX_BUG_COMPATIBLE, - * PERL_COMPATIBLE, PERL_BUG_COMPATIBLE, - * - * - For portable applications it is best not to rely on peculiarities - * of a given implementation so it may be best not to define any - * of the macros that select compatibility and to avoid features - * that vary among the systems. - * - * - Selecting compatibility with more than one operating system - * is not strictly forbidden but is not recommended. - * - * - 'x'_BUG_COMPATIBLE implies 'x'_COMPATIBLE . - * - * - 'x'_COMPATIBLE refers to (and enables) a behaviour that is - * documented in a sprintf man page on a given operating system - * and actually adhered to by the system's sprintf (but not on - * most other operating systems). It may also refer to and enable - * a behaviour that is declared 'undefined' or 'implementation specific' - * in the man page but a given implementation behaves predictably - * in a certain way. - * - * - 'x'_BUG_COMPATIBLE refers to (and enables) a behaviour of system's sprintf - * that contradicts the sprintf man page on the same operating system. - * - * - I do not claim that the 'x'_COMPATIBLE and 'x'_BUG_COMPATIBLE - * conditionals take into account all idiosyncrasies of a particular - * implementation, there may be other incompatibilities. - */ - - - -/* ============================================= */ -/* NO USER SERVICABLE PARTS FOLLOWING THIS POINT */ -/* ============================================= */ - -#define PORTABLE_SNPRINTF_VERSION_MAJOR 2 -#define PORTABLE_SNPRINTF_VERSION_MINOR 2 - -#if defined(NEED_ASPRINTF) || defined(NEED_ASNPRINTF) || defined(NEED_VASPRINTF) || defined(NEED_VASNPRINTF) -# if defined(NEED_SNPRINTF_ONLY) -# undef NEED_SNPRINTF_ONLY -# endif -# if !defined(PREFER_PORTABLE_SNPRINTF) -# define PREFER_PORTABLE_SNPRINTF -# endif -#endif - -#if defined(SOLARIS_BUG_COMPATIBLE) && !defined(SOLARIS_COMPATIBLE) -#define SOLARIS_COMPATIBLE -#endif - -#if defined(HPUX_BUG_COMPATIBLE) && !defined(HPUX_COMPATIBLE) -#define HPUX_COMPATIBLE -#endif - -#if defined(DIGITAL_UNIX_BUG_COMPATIBLE) && !defined(DIGITAL_UNIX_COMPATIBLE) -#define DIGITAL_UNIX_COMPATIBLE -#endif - -#if defined(PERL_BUG_COMPATIBLE) && !defined(PERL_COMPATIBLE) -#define PERL_COMPATIBLE -#endif - -#if defined(LINUX_BUG_COMPATIBLE) && !defined(LINUX_COMPATIBLE) -#define LINUX_COMPATIBLE -#endif - -#include "snprintf.h" -#include -#include -#include -#include -#include -#include -#include - -#ifdef isdigit -#undef isdigit -#endif -#define isdigit(c) ((c) >= '0' && (c) <= '9') - -/* For copying strings longer or equal to 'breakeven_point' - * it is more efficient to call memcpy() than to do it inline. - * The value depends mostly on the processor architecture, - * but also on the compiler and its optimization capabilities. - * The value is not critical, some small value greater than zero - * will be just fine if you don't care to squeeze every drop - * of performance out of the code. - * - * Small values favor memcpy, large values favor inline code. - */ -#if defined(__alpha__) || defined(__alpha) -# define breakeven_point 2 /* AXP (DEC Alpha) - gcc or cc or egcs */ -#endif -#if defined(__i386__) || defined(__i386) -# define breakeven_point 12 /* Intel Pentium/Linux - gcc 2.96 */ -#endif -#if defined(__hppa) -# define breakeven_point 10 /* HP-PA - gcc */ -#endif -#if defined(__sparc__) || defined(__sparc) -# define breakeven_point 33 /* Sun Sparc 5 - gcc 2.8.1 */ -#endif - -/* some other values of possible interest: */ -/* #define breakeven_point 8 */ /* VAX 4000 - vaxc */ -/* #define breakeven_point 19 */ /* VAX 4000 - gcc 2.7.0 */ - -#ifndef breakeven_point -# define breakeven_point 6 /* some reasonable one-size-fits-all value */ -#endif - -#define fast_memcpy(d,s,n) \ - { register size_t nn = (size_t)(n); \ - if (nn >= breakeven_point) memcpy((d), (s), nn); \ - else if (nn > 0) { /* proc call overhead is worth only for large strings*/\ - register char *dd; register const char *ss; \ - for (ss=(s), dd=(d); nn>0; nn--) *dd++ = *ss++; } } - -#define fast_memset(d,c,n) \ - { register size_t nn = (size_t)(n); \ - if (nn >= breakeven_point) memset((d), (int)(c), nn); \ - else if (nn > 0) { /* proc call overhead is worth only for large strings*/\ - register char *dd; register const int cc=(int)(c); \ - for (dd=(d); nn>0; nn--) *dd++ = cc; } } - -/* prototypes */ - -#if defined(NEED_ASPRINTF) -int asprintf (char **ptr, const char *fmt, /*args*/ ...); -#endif -#if defined(NEED_VASPRINTF) -int vasprintf (char **ptr, const char *fmt, va_list ap); -#endif -#if defined(NEED_ASNPRINTF) -int asnprintf (char **ptr, size_t str_m, const char *fmt, /*args*/ ...); -#endif -#if defined(NEED_VASNPRINTF) -int vasnprintf (char **ptr, size_t str_m, const char *fmt, va_list ap); -#endif - -#if defined(HAVE_SNPRINTF) -/* declare our portable snprintf routine under name portable_snprintf */ -/* declare our portable vsnprintf routine under name portable_vsnprintf */ -#else -/* declare our portable routines under names snprintf and vsnprintf */ -#define portable_snprintf snprintf -#if !defined(NEED_SNPRINTF_ONLY) -#define portable_vsnprintf vsnprintf -#endif -#endif - -#if !defined(HAVE_SNPRINTF) || defined(PREFER_PORTABLE_SNPRINTF) -int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args*/ ...); -#if !defined(NEED_SNPRINTF_ONLY) -int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap); -#endif -#endif - -/* declarations */ - -#if defined(NEED_ASPRINTF) -int asprintf(char **ptr, const char *fmt, /*args*/ ...) { - va_list ap; - size_t str_m; - int str_l; - - *ptr = NULL; - va_start(ap, fmt); /* measure the required size */ - str_l = portable_vsnprintf(NULL, (size_t)0, fmt, ap); - va_end(ap); - assert(str_l >= 0); /* possible integer overflow if str_m > INT_MAX */ - *ptr = (char *) malloc(str_m = (size_t)str_l + 1); - if (*ptr == NULL) { errno = ENOMEM; str_l = -1; } - else { - int str_l2; - va_start(ap, fmt); - str_l2 = portable_vsnprintf(*ptr, str_m, fmt, ap); - va_end(ap); - assert(str_l2 == str_l); - } - return str_l; -} -#endif - -#if defined(NEED_VASPRINTF) -int vasprintf(char **ptr, const char *fmt, va_list ap) { - size_t str_m; - int str_l; - - *ptr = NULL; - { va_list ap2; - va_copy(ap2, ap); /* don't consume the original ap, we'll need it again */ - str_l = portable_vsnprintf(NULL, (size_t)0, fmt, ap2);/*get required size*/ - va_end(ap2); - } - assert(str_l >= 0); /* possible integer overflow if str_m > INT_MAX */ - *ptr = (char *) malloc(str_m = (size_t)str_l + 1); - if (*ptr == NULL) { errno = ENOMEM; str_l = -1; } - else { - int str_l2 = portable_vsnprintf(*ptr, str_m, fmt, ap); - assert(str_l2 == str_l); - } - return str_l; -} -#endif - -#if defined(NEED_ASNPRINTF) -int asnprintf (char **ptr, size_t str_m, const char *fmt, /*args*/ ...) { - va_list ap; - int str_l; - - *ptr = NULL; - va_start(ap, fmt); /* measure the required size */ - str_l = portable_vsnprintf(NULL, (size_t)0, fmt, ap); - va_end(ap); - assert(str_l >= 0); /* possible integer overflow if str_m > INT_MAX */ - if ((size_t)str_l + 1 < str_m) str_m = (size_t)str_l + 1; /* truncate */ - /* if str_m is 0, no buffer is allocated, just set *ptr to NULL */ - if (str_m == 0) { /* not interested in resulting string, just return size */ - } else { - *ptr = (char *) malloc(str_m); - if (*ptr == NULL) { errno = ENOMEM; str_l = -1; } - else { - int str_l2; - va_start(ap, fmt); - str_l2 = portable_vsnprintf(*ptr, str_m, fmt, ap); - va_end(ap); - assert(str_l2 == str_l); - } - } - return str_l; -} -#endif - -#if defined(NEED_VASNPRINTF) -int vasnprintf (char **ptr, size_t str_m, const char *fmt, va_list ap) { - int str_l; - - *ptr = NULL; - { va_list ap2; - va_copy(ap2, ap); /* don't consume the original ap, we'll need it again */ - str_l = portable_vsnprintf(NULL, (size_t)0, fmt, ap2);/*get required size*/ - va_end(ap2); - } - assert(str_l >= 0); /* possible integer overflow if str_m > INT_MAX */ - if ((size_t)str_l + 1 < str_m) str_m = (size_t)str_l + 1; /* truncate */ - /* if str_m is 0, no buffer is allocated, just set *ptr to NULL */ - if (str_m == 0) { /* not interested in resulting string, just return size */ - } else { - *ptr = (char *) malloc(str_m); - if (*ptr == NULL) { errno = ENOMEM; str_l = -1; } - else { - int str_l2 = portable_vsnprintf(*ptr, str_m, fmt, ap); - assert(str_l2 == str_l); - } - } - return str_l; -} -#endif - -/* - * If the system does have snprintf and the portable routine is not - * specifically required, this module produces no code for snprintf/vsnprintf. - */ -#if !defined(HAVE_SNPRINTF) || defined(PREFER_PORTABLE_SNPRINTF) - -#if !defined(NEED_SNPRINTF_ONLY) -int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args*/ ...) { - va_list ap; - int str_l; - - va_start(ap, fmt); - str_l = portable_vsnprintf(str, str_m, fmt, ap); - va_end(ap); - return str_l; -} -#endif - -#if defined(NEED_SNPRINTF_ONLY) -int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args*/ ...) { -#else -int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap) { -#endif - -#if defined(NEED_SNPRINTF_ONLY) - va_list ap; -#endif - size_t str_l = 0; - const char *p = fmt; - -/* In contrast with POSIX, the ISO C99 now says - * that str can be NULL and str_m can be 0. - * This is more useful than the old: if (str_m < 1) return -1; */ - -#if defined(NEED_SNPRINTF_ONLY) - va_start(ap, fmt); -#endif - if (!p) p = ""; - while (*p) { - if (*p != '%') { - /* if (str_l < str_m) str[str_l++] = *p++; -- this would be sufficient */ - /* but the following code achieves better performance for cases - * where format string is long and contains few conversions */ - const char *q = strchr(p+1,'%'); - size_t n = !q ? strlen(p) : (q-p); - if (str_l < str_m) { - size_t avail = str_m-str_l; - fast_memcpy(str+str_l, p, (n>avail?avail:n)); - } - p += n; str_l += n; - } else { - const char *starting_p; - size_t min_field_width = 0, precision = 0; - int zero_padding = 0, precision_specified = 0, justify_left = 0; - int alternate_form = 0, force_sign = 0; - int space_for_positive = 1; /* If both the ' ' and '+' flags appear, - the ' ' flag should be ignored. */ - char length_modifier = '\0'; /* allowed values: \0, h, l, L */ - char tmp[32];/* temporary buffer for simple numeric->string conversion */ - - const char *str_arg; /* string address in case of string argument */ - size_t str_arg_l; /* natural field width of arg without padding - and sign */ - unsigned char uchar_arg; - /* unsigned char argument value - only defined for c conversion. - N.B. standard explicitly states the char argument for - the c conversion is unsigned */ - - size_t number_of_zeros_to_pad = 0; - /* number of zeros to be inserted for numeric conversions - as required by the precision or minimal field width */ - - size_t zero_padding_insertion_ind = 0; - /* index into tmp where zero padding is to be inserted */ - - char fmt_spec = '\0'; - /* current conversion specifier character */ - - starting_p = p; p++; /* skip '%' */ - /* parse flags */ - while (*p == '0' || *p == '-' || *p == '+' || - *p == ' ' || *p == '#' || *p == '\'') { - switch (*p) { - case '0': zero_padding = 1; break; - case '-': justify_left = 1; break; - case '+': force_sign = 1; space_for_positive = 0; break; - case ' ': force_sign = 1; - /* If both the ' ' and '+' flags appear, the ' ' flag should be ignored */ -#ifdef PERL_COMPATIBLE - /* ... but in Perl the last of ' ' and '+' applies */ - space_for_positive = 1; -#endif - break; - case '#': alternate_form = 1; break; - case '\'': break; - } - p++; - } - /* If the '0' and '-' flags both appear, the '0' flag should be ignored. */ - - /* parse field width */ - if (*p == '*') { - int j; - p++; j = va_arg(ap, int); - if (j >= 0) min_field_width = j; - else { min_field_width = -j; justify_left = 1; } - } else if (isdigit((int)(*p))) { - /* size_t could be wider than unsigned int; - make sure we treat argument like common implementations do */ - unsigned int uj = *p++ - '0'; - while (isdigit((int)(*p))) uj = 10*uj + (unsigned int)(*p++ - '0'); - min_field_width = uj; - } - /* parse precision */ - if (*p == '.') { - p++; precision_specified = 1; - if (*p == '*') { - int j = va_arg(ap, int); - p++; - if (j >= 0) precision = j; - else { - precision_specified = 0; precision = 0; - /* NOTE: - * Solaris 2.6 man page claims that in this case the precision - * should be set to 0. Digital Unix 4.0, HPUX 10 and BSD man page - * claim that this case should be treated as unspecified precision, - * which is what we do here. - */ - } - } else if (isdigit((int)(*p))) { - /* size_t could be wider than unsigned int; - make sure we treat argument like common implementations do */ - unsigned int uj = *p++ - '0'; - while (isdigit((int)(*p))) uj = 10*uj + (unsigned int)(*p++ - '0'); - precision = uj; - } - } - /* parse 'h', 'l' and 'll' length modifiers */ - if (*p == 'h' || *p == 'l') { - length_modifier = *p; p++; - if (length_modifier == 'l' && *p == 'l') { /* double l = long long */ -#ifdef SNPRINTF_LONGLONG_SUPPORT - length_modifier = '2'; /* double l encoded as '2' */ -#else - length_modifier = 'l'; /* treat it as a single 'l' */ -#endif - p++; - } - } - fmt_spec = *p; - /* common synonyms: */ - switch (fmt_spec) { - case 'i': fmt_spec = 'd'; break; - case 'D': fmt_spec = 'd'; length_modifier = 'l'; break; - case 'U': fmt_spec = 'u'; length_modifier = 'l'; break; - case 'O': fmt_spec = 'o'; length_modifier = 'l'; break; - default: break; - } - /* get parameter value, do initial processing */ - switch (fmt_spec) { - case '%': /* % behaves similar to 's' regarding flags and field widths */ - case 'c': /* c behaves similar to 's' regarding flags and field widths */ - case 's': - length_modifier = '\0'; /* wint_t and wchar_t not supported */ - /* the result of zero padding flag with non-numeric conversion specifier*/ - /* is undefined. Solaris and HPUX 10 does zero padding in this case, */ - /* Digital Unix and Linux does not. */ -#if !defined(SOLARIS_COMPATIBLE) && !defined(HPUX_COMPATIBLE) - zero_padding = 0; /* turn zero padding off for string conversions */ -#endif - str_arg_l = 1; - switch (fmt_spec) { - case '%': - str_arg = p; break; - case 'c': { - int j = va_arg(ap, int); - uchar_arg = (unsigned char) j; /* standard demands unsigned char */ - str_arg = (const char *) &uchar_arg; - break; - } - case 's': - str_arg = va_arg(ap, const char *); - if (!str_arg) str_arg_l = 0; - /* make sure not to address string beyond the specified precision !!! */ - else if (!precision_specified) str_arg_l = strlen(str_arg); - /* truncate string if necessary as requested by precision */ - else if (precision == 0) str_arg_l = 0; - else { - /* memchr on HP does not like n > 2^31 !!! */ - const char *q = memchr(str_arg, '\0', - precision <= 0x7fffffff ? precision : 0x7fffffff); - str_arg_l = !q ? precision : (q-str_arg); - } - break; - default: break; - } - break; - case 'd': case 'u': case 'o': case 'x': case 'X': case 'p': { - /* NOTE: the u, o, x, X and p conversion specifiers imply - the value is unsigned; d implies a signed value */ - - int arg_sign = 0; - /* 0 if numeric argument is zero (or if pointer is NULL for 'p'), - +1 if greater than zero (or nonzero for unsigned arguments), - -1 if negative (unsigned argument is never negative) */ - - int int_arg = 0; unsigned int uint_arg = 0; - /* only defined for length modifier h, or for no length modifiers */ - - long int long_arg = 0; unsigned long int ulong_arg = 0; - /* only defined for length modifier l */ - - void *ptr_arg = NULL; - /* pointer argument value -only defined for p conversion */ - -#ifdef SNPRINTF_LONGLONG_SUPPORT - long long int long_long_arg = 0; - unsigned long long int ulong_long_arg = 0; - /* only defined for length modifier ll */ -#endif - if (fmt_spec == 'p') { - /* HPUX 10: An l, h, ll or L before any other conversion character - * (other than d, i, u, o, x, or X) is ignored. - * Digital Unix: - * not specified, but seems to behave as HPUX does. - * Solaris: If an h, l, or L appears before any other conversion - * specifier (other than d, i, u, o, x, or X), the behavior - * is undefined. (Actually %hp converts only 16-bits of address - * and %llp treats address as 64-bit data which is incompatible - * with (void *) argument on a 32-bit system). - */ -#ifdef SOLARIS_COMPATIBLE -# ifdef SOLARIS_BUG_COMPATIBLE - /* keep length modifiers even if it represents 'll' */ -# else - if (length_modifier == '2') length_modifier = '\0'; -# endif -#else - length_modifier = '\0'; -#endif - ptr_arg = va_arg(ap, void *); - if (ptr_arg != NULL) arg_sign = 1; - } else if (fmt_spec == 'd') { /* signed */ - switch (length_modifier) { - case '\0': - case 'h': - /* It is non-portable to specify a second argument of char or short - * to va_arg, because arguments seen by the called function - * are not char or short. C converts char and short arguments - * to int before passing them to a function. - */ - int_arg = va_arg(ap, int); - if (int_arg > 0) arg_sign = 1; - else if (int_arg < 0) arg_sign = -1; - break; - case 'l': - long_arg = va_arg(ap, long int); - if (long_arg > 0) arg_sign = 1; - else if (long_arg < 0) arg_sign = -1; - break; -#ifdef SNPRINTF_LONGLONG_SUPPORT - case '2': - long_long_arg = va_arg(ap, long long int); - if (long_long_arg > 0) arg_sign = 1; - else if (long_long_arg < 0) arg_sign = -1; - break; -#endif - } - } else { /* unsigned */ - switch (length_modifier) { - case '\0': - case 'h': - uint_arg = va_arg(ap, unsigned int); - if (uint_arg) arg_sign = 1; - break; - case 'l': - ulong_arg = va_arg(ap, unsigned long int); - if (ulong_arg) arg_sign = 1; - break; -#ifdef SNPRINTF_LONGLONG_SUPPORT - case '2': - ulong_long_arg = va_arg(ap, unsigned long long int); - if (ulong_long_arg) arg_sign = 1; - break; -#endif - } - } - str_arg = tmp; str_arg_l = 0; - /* NOTE: - * For d, i, u, o, x, and X conversions, if precision is specified, - * the '0' flag should be ignored. This is so with Solaris 2.6, - * Digital UNIX 4.0, HPUX 10, Linux, FreeBSD, NetBSD; but not with Perl. - */ -#ifndef PERL_COMPATIBLE - if (precision_specified) zero_padding = 0; -#endif - if (fmt_spec == 'd') { - if (force_sign && arg_sign >= 0) - tmp[str_arg_l++] = space_for_positive ? ' ' : '+'; - /* leave negative numbers for sprintf to handle, - to avoid handling tricky cases like (short int)(-32768) */ -#ifdef LINUX_COMPATIBLE - } else if (fmt_spec == 'p' && force_sign && arg_sign > 0) { - tmp[str_arg_l++] = space_for_positive ? ' ' : '+'; -#endif - } else if (alternate_form) { - if (arg_sign != 0 && (fmt_spec == 'x' || fmt_spec == 'X') ) - { tmp[str_arg_l++] = '0'; tmp[str_arg_l++] = fmt_spec; } - /* alternate form should have no effect for p conversion, but ... */ -#ifdef HPUX_COMPATIBLE - else if (fmt_spec == 'p' - /* HPUX 10: for an alternate form of p conversion, - * a nonzero result is prefixed by 0x. */ -#ifndef HPUX_BUG_COMPATIBLE - /* Actually it uses 0x prefix even for a zero value. */ - && arg_sign != 0 -#endif - ) { tmp[str_arg_l++] = '0'; tmp[str_arg_l++] = 'x'; } -#endif - } - zero_padding_insertion_ind = str_arg_l; - if (!precision_specified) precision = 1; /* default precision is 1 */ - if (precision == 0 && arg_sign == 0 -#if defined(HPUX_BUG_COMPATIBLE) || defined(LINUX_COMPATIBLE) - && fmt_spec != 'p' - /* HPUX 10 man page claims: With conversion character p the result of - * converting a zero value with a precision of zero is a null string. - * Actually HP returns all zeroes, and Linux returns "(nil)". */ -#endif - ) { - /* converted to null string */ - /* When zero value is formatted with an explicit precision 0, - the resulting formatted string is empty (d, i, u, o, x, X, p). */ - } else { - char f[5]; int f_l = 0; - f[f_l++] = '%'; /* construct a simple format string for sprintf */ - if (!length_modifier) { } - else if (length_modifier=='2') { f[f_l++] = 'l'; f[f_l++] = 'l'; } - else f[f_l++] = length_modifier; - f[f_l++] = fmt_spec; f[f_l++] = '\0'; - if (fmt_spec == 'p') str_arg_l += sprintf(tmp+str_arg_l, f, ptr_arg); - else if (fmt_spec == 'd') { /* signed */ - switch (length_modifier) { - case '\0': - case 'h': str_arg_l+=sprintf(tmp+str_arg_l, f, int_arg); break; - case 'l': str_arg_l+=sprintf(tmp+str_arg_l, f, long_arg); break; -#ifdef SNPRINTF_LONGLONG_SUPPORT - case '2': str_arg_l+=sprintf(tmp+str_arg_l,f,long_long_arg); break; -#endif - } - } else { /* unsigned */ - switch (length_modifier) { - case '\0': - case 'h': str_arg_l+=sprintf(tmp+str_arg_l, f, uint_arg); break; - case 'l': str_arg_l+=sprintf(tmp+str_arg_l, f, ulong_arg); break; -#ifdef SNPRINTF_LONGLONG_SUPPORT - case '2': str_arg_l+=sprintf(tmp+str_arg_l,f,ulong_long_arg);break; -#endif - } - } - /* include the optional minus sign and possible "0x" - in the region before the zero padding insertion point */ - if (zero_padding_insertion_ind < str_arg_l && - tmp[zero_padding_insertion_ind] == '-') { - zero_padding_insertion_ind++; - } - if (zero_padding_insertion_ind+1 < str_arg_l && - tmp[zero_padding_insertion_ind] == '0' && - (tmp[zero_padding_insertion_ind+1] == 'x' || - tmp[zero_padding_insertion_ind+1] == 'X') ) { - zero_padding_insertion_ind += 2; - } - } - { size_t num_of_digits = str_arg_l - zero_padding_insertion_ind; - if (alternate_form && fmt_spec == 'o' -#ifdef HPUX_COMPATIBLE /* ("%#.o",0) -> "" */ - && (str_arg_l > 0) -#endif -#ifdef DIGITAL_UNIX_BUG_COMPATIBLE /* ("%#o",0) -> "00" */ -#else - /* unless zero is already the first character */ - && !(zero_padding_insertion_ind < str_arg_l - && tmp[zero_padding_insertion_ind] == '0') -#endif - ) { /* assure leading zero for alternate-form octal numbers */ - if (!precision_specified || precision < num_of_digits+1) { - /* precision is increased to force the first character to be zero, - except if a zero value is formatted with an explicit precision - of zero */ - precision = num_of_digits+1; precision_specified = 1; - } - } - /* zero padding to specified precision? */ - if (num_of_digits < precision) - number_of_zeros_to_pad = precision - num_of_digits; - } - /* zero padding to specified minimal field width? */ - if (!justify_left && zero_padding) { - int n = min_field_width - (str_arg_l+number_of_zeros_to_pad); - if (n > 0) number_of_zeros_to_pad += n; - } - break; - } - default: /* unrecognized conversion specifier, keep format string as-is*/ - zero_padding = 0; /* turn zero padding off for non-numeric convers. */ -#ifndef DIGITAL_UNIX_COMPATIBLE - justify_left = 1; min_field_width = 0; /* reset flags */ -#endif -#if defined(PERL_COMPATIBLE) || defined(LINUX_COMPATIBLE) - /* keep the entire format string unchanged */ - str_arg = starting_p; str_arg_l = p - starting_p; - /* well, not exactly so for Linux, which does something inbetween, - * and I don't feel an urge to imitate it: "%+++++hy" -> "%+y" */ -#else - /* discard the unrecognized conversion, just keep * - * the unrecognized conversion character */ - str_arg = p; str_arg_l = 0; -#endif - if (*p) str_arg_l++; /* include invalid conversion specifier unchanged - if not at end-of-string */ - break; - } - if (*p) p++; /* step over the just processed conversion specifier */ - /* insert padding to the left as requested by min_field_width; - this does not include the zero padding in case of numerical conversions*/ - if (!justify_left) { /* left padding with blank or zero */ - int n = min_field_width - (str_arg_l+number_of_zeros_to_pad); - if (n > 0) { - if (str_l < str_m) { - size_t avail = str_m-str_l; - fast_memset(str+str_l, (zero_padding?'0':' '), (n>avail?avail:n)); - } - str_l += n; - } - } - /* zero padding as requested by the precision or by the minimal field width - * for numeric conversions required? */ - if (number_of_zeros_to_pad <= 0) { - /* will not copy first part of numeric right now, * - * force it to be copied later in its entirety */ - zero_padding_insertion_ind = 0; - } else { - /* insert first part of numerics (sign or '0x') before zero padding */ - int n = zero_padding_insertion_ind; - if (n > 0) { - if (str_l < str_m) { - size_t avail = str_m-str_l; - fast_memcpy(str+str_l, str_arg, (n>avail?avail:n)); - } - str_l += n; - } - /* insert zero padding as requested by the precision or min field width */ - n = number_of_zeros_to_pad; - if (n > 0) { - if (str_l < str_m) { - size_t avail = str_m-str_l; - fast_memset(str+str_l, '0', (n>avail?avail:n)); - } - str_l += n; - } - } - /* insert formatted string - * (or as-is conversion specifier for unknown conversions) */ - { int n = str_arg_l - zero_padding_insertion_ind; - if (n > 0) { - if (str_l < str_m) { - size_t avail = str_m-str_l; - fast_memcpy(str+str_l, str_arg+zero_padding_insertion_ind, - (n>avail?avail:n)); - } - str_l += n; - } - } - /* insert right padding */ - if (justify_left) { /* right blank padding to the field width */ - int n = min_field_width - (str_arg_l+number_of_zeros_to_pad); - if (n > 0) { - if (str_l < str_m) { - size_t avail = str_m-str_l; - fast_memset(str+str_l, ' ', (n>avail?avail:n)); - } - str_l += n; - } - } - } - } -#if defined(NEED_SNPRINTF_ONLY) - va_end(ap); -#endif - if (str_m > 0) { /* make sure the string is null-terminated - even at the expense of overwriting the last character - (shouldn't happen, but just in case) */ - str[str_l <= str_m-1 ? str_l : str_m-1] = '\0'; - } - /* Return the number of characters formatted (excluding trailing null - * character), that is, the number of characters that would have been - * written to the buffer if it were large enough. - * - * The value of str_l should be returned, but str_l is of unsigned type - * size_t, and snprintf is int, possibly leading to an undetected - * integer overflow, resulting in a negative return value, which is illegal. - * Both XSH5 and ISO C99 (at least the draft) are silent on this issue. - * Should errno be set to EOVERFLOW and EOF returned in this case??? - */ - return (int) str_l; -} -#endif diff --git a/examples/window/main.go b/examples/window/main.go index 292ee35b..3b53fb8d 100644 --- a/examples/window/main.go +++ b/examples/window/main.go @@ -19,12 +19,11 @@ import ( func alert() { // show Alert Window - abool := robotgo.ShowAlert("hello", "robotgo") + abool := robotgo.Alert("hello", "robotgo") if abool { fmt.Println("ok@@@", "ok") } - robotgo.ShowAlert("hello", "robotgo", "Ok", "Cancel") - + robotgo.Alert("hello", "robotgo", "Ok", "Cancel") } func get() { diff --git a/mouse/goMouse.h b/mouse/goMouse.h index 9b7fc61f..a3cf34b6 100644 --- a/mouse/goMouse.h +++ b/mouse/goMouse.h @@ -13,32 +13,9 @@ // Global delays. int mouseDelay = 0; -// int keyboardDelay = 10; - - -// int CheckMouseButton(const char * const b, -// MMMouseButton * const button){ -// if (!button) return -1; - -// if (strcmp(b, "left") == 0) { -// *button = LEFT_BUTTON; -// } -// else if (strcmp(b, "right") == 0) { -// *button = RIGHT_BUTTON; -// } -// else if (strcmp(b, "middle") == 0) { -// *button = CENTER_BUTTON; -// } else { -// return -2; -// } - -// return 0; -// } int move_mouse(int32_t x, int32_t y){ MMPointInt32 point; - // int x = 103; - // int y = 104; point = MMPointInt32Make(x, y); moveMouse(point); @@ -47,16 +24,11 @@ int move_mouse(int32_t x, int32_t y){ int drag_mouse(int32_t x, int32_t y, MMMouseButton button){ - // const size_t x = 10; - // const size_t y = 20; - // MMMouseButton button = LEFT_BUTTON; - MMPointInt32 point; point = MMPointInt32Make(x, y); dragMouse(point, button); microsleep(mouseDelay); - // printf("%s\n", "gyp-----"); return 0; } @@ -73,15 +45,10 @@ bool move_mouse_smooth(int32_t x, int32_t y, double lowSpeed, MMPointInt32 get_mouse_pos(){ MMPointInt32 pos = getMousePos(); - - // Return object with .x and .y. - // printf("%zu\n%zu\n", pos.x, pos.y ); return pos; } int mouse_click(MMMouseButton button, bool doubleC){ - // MMMouseButton button = LEFT_BUTTON; - // bool doubleC = false; if (!doubleC) { clickMouse(button); } else { @@ -94,7 +61,6 @@ int mouse_click(MMMouseButton button, bool doubleC){ } int mouse_toggle(char* d, MMMouseButton button){ - // MMMouseButton button = LEFT_BUTTON; bool down = false; if (strcmp(d, "down") == 0) { down = true; @@ -111,9 +77,7 @@ int mouse_toggle(char* d, MMMouseButton button){ } int set_mouse_delay(size_t val){ - // int val = 10; mouseDelay = val; - return 0; } @@ -125,7 +89,6 @@ int scroll(int x, int y, int msDelay){ } int scroll_mouse(size_t scrollMagnitude, char *s){ - // int scrollMagnitude = 20; MMMouseWheelDirection scrollDirection; if (strcmp(s, "up") == 0) { @@ -133,7 +96,6 @@ int scroll_mouse(size_t scrollMagnitude, char *s){ } else if (strcmp(s, "down") == 0) { scrollDirection = DIRECTION_DOWN; } else { - // return "Invalid scroll direction specified."; return 1; } diff --git a/robotgo.go b/robotgo.go index 79eac1e2..4599ab90 100644 --- a/robotgo.go +++ b/robotgo.go @@ -1214,23 +1214,13 @@ ____ __ ____ __ .__ __. _______ ______ ____ __ ____ */ -// ShowAlert show a alert window -// Displays alert with the attributes. -// If cancel button is not given, only the default button is displayed -// -// Examples: -// robotgo.ShowAlert("hi", "window", "ok", "cancel") -func ShowAlert(title, msg string, args ...string) bool { +func alertArgs(args ...string) (string, string) { var ( - // title string - // msg string defaultBtn = "Ok" cancelBtn = "Cancel" ) if len(args) > 0 { - // title = args[0] - // msg = args[1] defaultBtn = args[0] } @@ -1238,6 +1228,12 @@ func ShowAlert(title, msg string, args ...string) bool { cancelBtn = args[1] } + return defaultBtn, cancelBtn +} + +func showAlert(title, msg string, args ...string) bool { + defaultBtn, cancelBtn := alertArgs(args...) + cTitle := C.CString(title) cMsg := C.CString(msg) defaultButton := C.CString(defaultBtn) diff --git a/robotgo_mac_win.go b/robotgo_mac_win.go index df183eaa..f7827231 100644 --- a/robotgo_mac_win.go +++ b/robotgo_mac_win.go @@ -55,3 +55,13 @@ func ActivePID(pid int32, args ...int) error { func DisplaysNum() int { return getNumDisplays() } + +// Alert show a alert window +// Displays alert with the attributes. +// If cancel button is not given, only the default button is displayed +// +// Examples: +// robotgo.Alert("hi", "window", "ok", "cancel") +func Alert(title, msg string, args ...string) bool { + return showAlert(title, msg, args...) +} diff --git a/robotgo_x11.go b/robotgo_x11.go index 301dbad1..524a24e7 100644 --- a/robotgo_x11.go +++ b/robotgo_x11.go @@ -172,3 +172,25 @@ func DisplaysNum() int { return int(reply.Number) } + +// Alert show a alert window +// Displays alert with the attributes. +// If cancel button is not given, only the default button is displayed +// +// Examples: +// robotgo.Alert("hi", "window", "ok", "cancel") +func Alert(title, msg string, args ...string) bool { + defaultBtn, cancelBtn := alertArgs(args...) + c := `xmessage -center ` + msg + + ` -title ` + title + ` -buttons ` + defaultBtn + ":0," + cancelBtn + ":1" + ` -default Ok` + out, err := Run(c) + if err != nil { + fmt.Println("Alert: ", err, ". ", strint(out)) + return false + } + + if strint(out) == "1" { + return false + } + return true +} diff --git a/window/alert.h b/window/alert.h deleted file mode 100644 index 9eb5e9c5..00000000 --- a/window/alert.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#ifndef ALERT_H -#define ALERT_H - -#if defined(_MSC_VER) - #include "ms_stdbool.h" -#else - #include -#endif - -/* Displays alert with given attributes, and blocks execution until the user - * responds. Returns 0 if defaultButton was pressed, 1 if cancelButton was - * pressed, or -1 if an error occurred. */ -int showAlert(const char *title, const char *msg, - const char *defaultButton, const char *cancelButton); - -#endif /* ALERT_H */ diff --git a/window/alert_c.h b/window/alert_c.h index db7455e8..8fd68c9d 100644 --- a/window/alert_c.h +++ b/window/alert_c.h @@ -1,35 +1,10 @@ -#include "alert.h" // #include "os.h" -#include #if defined(IS_MACOSX) #include -#elif defined(USE_X11) - #include /* For fputs() */ - #include /* For exit() */ - #include /* For wait() */ - #include /* For fork() */ - #include /* For pid_t */ - #include "../base/snprintf.h" /* For asprintf() */ #endif -#if defined(USE_X11) -enum { - TASK_SUCCESS = 0, - FORK_FAILED = -1, - EXEC_FAILED = -2 -}; - -/* - * Unfortunately, X has no standard method of displaying alerts, so instead we - * have to rely on the shell command "xmessage" (or nicer-looking equivalents). - * - * The return value and arguments are the same as those from to runTask() - * (see below). - */ -static int xmessage(char *argv[], int *exit_status); - -#elif defined(IS_MACOSX) +#if defined(IS_MACOSX) #define CFStringCreateWithUTF8String(string) \ ((string) == NULL ? NULL : CFStringCreateWithCString(NULL, \ string, \ @@ -56,41 +31,7 @@ int showAlert(const char *title, const char *msg, if (err != 0) { return -1; } return (responseFlags == kCFUserNotificationDefaultResponse) ? 0 : 1; #elif defined(USE_X11) - /* Note that args[0] is set by the xmessage() function. */ - const char *args[10] = {NULL, msg, "-title", title, "-center"}; - int response, ret; - char *buttonList = NULL; /* To be free()'d. */ - - if (defaultButton == NULL) defaultButton = "OK"; - - // snprintf.h - if (cancelButton == NULL) { - asprintf(&buttonList, "%s:2", defaultButton); - } else { - asprintf(&buttonList, "%s:2,%s:3", defaultButton, cancelButton); - } - - if (buttonList == NULL) { return -1; /* asprintf() failed. */ } - args[5] = "-buttons"; - args[6] = buttonList; - args[7] = "-default"; - args[8] = defaultButton; - args[9] = NULL; - - ret = xmessage((char **)args, &response); - if (buttonList != NULL) { - free(buttonList); - buttonList = NULL; - } - - if (ret != TASK_SUCCESS) { - if (ret == EXEC_FAILED) { - fputs("xmessage or equivalent not found.\n", stderr); - } - return -1; - } - - return (response == 2) ? 0 : 1; + return 0; #else /* TODO: Display custom buttons instead of the pre-defined "OK" * and "Cancel". */ @@ -100,73 +41,3 @@ int showAlert(const char *title, const char *msg, #endif } -#if defined(USE_X11) - -/* - * Attempts to run the given task synchronously with the given arguments. - * - * If |exit_status| is non-NULL and the task ran successfully, |exit_status| is - * set to the exit code of the task on return. - * - * Returns -1 if process could not be forked, -2 if the task could not be run, - * or 0 if the task was ran successfully. - */ -static int runTask(const char *taskname, char * const argv[], int *exit_status); - -static int xmessage(char *argv[], int *exit_status) { - // static const char * const MSG_PROGS[] = {"gmessage", "gxmessage", - // "kmessage", "xmessage"}; - static const char * const MSG_PROGS[] = {"xmessage"}; - static int PREV_MSG_INDEX = -1; - #define MSG_PROGS_LEN (sizeof(MSG_PROGS) / sizeof(MSG_PROGS[0])) - - char *prog = NULL; - int ret; - - /* Save some fork()'ing and attempt to use last program if possible. */ - if (PREV_MSG_INDEX >= 0) { - assert(PREV_MSG_INDEX < MSG_PROGS_LEN); - - prog = argv[0] = (char *)MSG_PROGS[PREV_MSG_INDEX]; - ret = runTask(prog, argv, exit_status); - } else { - /* Otherwise, try running each xmessage alternative until one works or - * we run out of options. */ - size_t i; - for (i = 0; i < MSG_PROGS_LEN; ++i) { - prog = argv[0] = (char *)MSG_PROGS[i]; - ret = runTask(prog, argv, exit_status); - if (ret != EXEC_FAILED) break; - } - - if (ret == TASK_SUCCESS) PREV_MSG_INDEX = i; - } - - return ret; -} - -static int runTask(const char *taskname, char * const argv[], int *exit_status) { - pid_t pid = fork(); - int status; - - switch (pid) { - case -1: /* Failed to fork */ - perror("fork"); - return FORK_FAILED; /* Failed to fork. */ - case 0: /* Child process */ - if (strcmp(argv[0], "xmessage") == 0){ - execvp(taskname, argv); - perror("execvp failed"); - } - exit(42); /* Failed to run task. */ - default: /* Parent process */ - wait(&status); /* Block execution until finished. */ - - if (!WIFEXITED(status) || (status = WEXITSTATUS(status)) == 42) { - return EXEC_FAILED; /* Task failed to run. */ - } - if (exit_status != NULL) *exit_status = status; - return TASK_SUCCESS; /* Success! */ - } -} -#endif From 63f914ae62786e8a33e77d5afd50557e97b732f7 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sat, 22 Jan 2022 12:46:46 -0400 Subject: [PATCH 177/327] Fixed windows warning and x11 error --- base/os.h | 8 ++++++++ robotgo_x11.go | 5 +++-- screen/screengrab_c.h | 2 +- window/pub.h | 8 -------- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/base/os.h b/base/os.h index 5d08c4fe..5957fc3a 100644 --- a/base/os.h +++ b/base/os.h @@ -60,4 +60,12 @@ #endif #endif +#ifdef RobotGo_64 + typedef int64_t intptr; + typedef uint64_t uintptr; +#else + typedef int32_t intptr; + typedef uint32_t uintptr; // Unsigned pointer integer +#endif + #endif /* OS_H */ diff --git a/robotgo_x11.go b/robotgo_x11.go index 524a24e7..8ef4eaed 100644 --- a/robotgo_x11.go +++ b/robotgo_x11.go @@ -15,6 +15,7 @@ package robotgo import ( "errors" + "fmt" "log" "github.com/robotn/xgb" @@ -185,11 +186,11 @@ func Alert(title, msg string, args ...string) bool { ` -title ` + title + ` -buttons ` + defaultBtn + ":0," + cancelBtn + ":1" + ` -default Ok` out, err := Run(c) if err != nil { - fmt.Println("Alert: ", err, ". ", strint(out)) + fmt.Println("Alert: ", err, ". ", string(out)) return false } - if strint(out) == "1" { + if string(out) == "1" { return false } return true diff --git a/screen/screengrab_c.h b/screen/screengrab_c.h index 7464c8d7..72f8203a 100644 --- a/screen/screengrab_c.h +++ b/screen/screengrab_c.h @@ -95,7 +95,7 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id) if (display_id == -1) { screen = GetDC(NULL); /* Get entire screen */ } else { - screen = GetDC((HWND) display_id); + screen = GetDC((HWND) (uintptr) display_id); } if (screen == NULL) { return NULL; } diff --git a/window/pub.h b/window/pub.h index bf7b8fd0..4f0766e2 100644 --- a/window/pub.h +++ b/window/pub.h @@ -15,14 +15,6 @@ #include #endif -#ifdef RobotGo_64 - typedef int64_t intptr; - typedef uint64_t uintptr; -#else - typedef int32_t intptr; - typedef uint32_t uintptr; // Unsigned pointer integer -#endif - struct _MData{ #if defined(IS_MACOSX) CGWindowID CgID; // Handle to a CGWindowID From 8defbda0cdebd749043f98222f0156872ec49af3 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sat, 22 Jan 2022 12:53:04 -0400 Subject: [PATCH 178/327] Move type def to type.h --- base/os.h | 8 -------- base/types.h | 8 ++++++++ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/base/os.h b/base/os.h index 5957fc3a..5d08c4fe 100644 --- a/base/os.h +++ b/base/os.h @@ -60,12 +60,4 @@ #endif #endif -#ifdef RobotGo_64 - typedef int64_t intptr; - typedef uint64_t uintptr; -#else - typedef int32_t intptr; - typedef uint32_t uintptr; // Unsigned pointer integer -#endif - #endif /* OS_H */ diff --git a/base/types.h b/base/types.h index 4b88a1de..0e68a830 100644 --- a/base/types.h +++ b/base/types.h @@ -9,6 +9,14 @@ /* Some generic, cross-platform types. */ +#ifdef RobotGo_64 + typedef int64_t intptr; + typedef uint64_t uintptr; +#else + typedef int32_t intptr; + typedef uint32_t uintptr; // Unsigned pointer integer +#endif + struct _MMPoint { size_t x; size_t y; From bafa051f92055c00c12a94b620f0a76c2faf4c40 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 23 Jan 2022 14:17:15 -0400 Subject: [PATCH 179/327] Update x11 alert() code and remove ScaleY() --- robotgo.go | 8 -------- robotgo_x11.go | 7 ++++++- window/goWindow.h | 34 ++++++++++++++++------------------ window/win_sys.h | 12 ------------ window/window.h | 13 +------------ 5 files changed, 23 insertions(+), 51 deletions(-) diff --git a/robotgo.go b/robotgo.go index 4599ab90..c60374c4 100644 --- a/robotgo.go +++ b/robotgo.go @@ -422,13 +422,6 @@ func ScaleX() int { return int(C.scale_x()) } -// Deprecated: use the ScaledF(), -// -// ScaleY get primary display vertical DPI scale factor, drop -func ScaleY() int { - return int(C.scale_y()) -} - // Deprecated: use the ScaledF(), // // Scale get the screen scale (only windows old), drop @@ -1254,7 +1247,6 @@ func showAlert(title, msg string, args ...string) bool { func IsValid() bool { abool := C.is_valid() gbool := bool(abool) - // fmt.Println("bool---------", gbool) return gbool } diff --git a/robotgo_x11.go b/robotgo_x11.go index 8ef4eaed..558567fe 100644 --- a/robotgo_x11.go +++ b/robotgo_x11.go @@ -183,7 +183,12 @@ func DisplaysNum() int { func Alert(title, msg string, args ...string) bool { defaultBtn, cancelBtn := alertArgs(args...) c := `xmessage -center ` + msg + - ` -title ` + title + ` -buttons ` + defaultBtn + ":0," + cancelBtn + ":1" + ` -default Ok` + ` -title ` + title + ` -buttons ` + defaultBtn + ":0," + if cancleBtn != "" { + c += cancelBtn + ":1" + } + c += ` -default ` + defaultBtn + out, err := Run(c) if err != nil { fmt.Println("Alert: ", err, ". ", string(out)) diff --git a/window/goWindow.h b/window/goWindow.h index fd8a7947..9bdcd250 100644 --- a/window/goWindow.h +++ b/window/goWindow.h @@ -14,29 +14,18 @@ int show_alert(const char *title, const char *msg, const char *defaultButton, const char *cancelButton){ - - int alert = showAlert(title, msg, defaultButton, cancelButton); - return alert; + + return showAlert(title, msg, defaultButton, cancelButton); } intptr scale_x(){ return scaleX(); } -intptr scale_y(){ - return scaleY(); -} - bool is_valid(){ - bool abool = IsValid(); - return abool; + return IsValid(); } -// int find_window(char* name){ -// int z = findwindow(name); -// return z; -// } - void min_window(uintptr pid, bool state, uintptr isHwnd){ #if defined(IS_MACOSX) // return 0; @@ -80,8 +69,7 @@ void close_window(uintptr pid, uintptr isHwnd){ } bool set_handle(uintptr handle){ - bool hwnd = setHandle(handle); - return hwnd; + return setHandle(handle); } uintptr get_handle(){ @@ -96,9 +84,19 @@ uintptr get_handle(){ #endif } +// uint32 uintptr +uintptr getHandle() { + #if defined(IS_MACOSX) + return (uintptr)mData.CgID; + #elif defined(USE_X11) + return (uintptr)mData.XWin; + #elif defined(IS_WINDOWS) + return (uintptr)mData.HWnd; + #endif +} + uintptr bget_handle(){ - uintptr hwnd = getHandle(); - return hwnd; + return getHandle(); } void set_active(const MData win){ diff --git a/window/win_sys.h b/window/win_sys.h index 236d3ae5..1d64d627 100644 --- a/window/win_sys.h +++ b/window/win_sys.h @@ -76,18 +76,6 @@ intptr scaleX(){ #endif } -intptr scaleY(){ - #if defined(IS_MACOSX) - return 0; - #elif defined(USE_X11) - return 0; - #elif defined(IS_WINDOWS) - HDC desktopDc = GetDC(NULL); - intptr verticalDPI = GetDeviceCaps(desktopDc, LOGPIXELSY); - return verticalDPI; - #endif -} - Bounds get_bounds(uintptr pid, uintptr isHwnd){ // Check if the window is valid Bounds bounds; diff --git a/window/window.h b/window/window.h index 6ff49351..a8cc058f 100644 --- a/window/window.h +++ b/window/window.h @@ -74,7 +74,7 @@ void set_handle_pid_mData(uintptr pid, uintptr isHwnd){ mData = win; } -bool IsValid(){ +bool IsValid() { initWindow(initHandle); if (!IsAxEnabled(true)) { printf("%s\n", "Window: Accessibility API is disabled!\n" @@ -232,17 +232,6 @@ bool setHandle(uintptr handle){ #endif } -// uint32 uintptr -uintptr getHandle() { - #if defined(IS_MACOSX) - return (uintptr)mData.CgID; - #elif defined(USE_X11) - return (uintptr)mData.XWin; - #elif defined(IS_WINDOWS) - return (uintptr)mData.HWnd; - #endif -} - bool IsTopMost(void){ // Check the window validity if (!IsValid()) {return false;} From b8b8450f67d59ccda0f1827244dab426b8f89280 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 23 Jan 2022 14:22:57 -0400 Subject: [PATCH 180/327] Fixed x11 typo error --- robotgo_x11.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/robotgo_x11.go b/robotgo_x11.go index 558567fe..cd807b98 100644 --- a/robotgo_x11.go +++ b/robotgo_x11.go @@ -184,7 +184,7 @@ func Alert(title, msg string, args ...string) bool { defaultBtn, cancelBtn := alertArgs(args...) c := `xmessage -center ` + msg + ` -title ` + title + ` -buttons ` + defaultBtn + ":0," - if cancleBtn != "" { + if cancelBtn != "" { c += cancelBtn + ":1" } c += ` -default ` + defaultBtn From 168a26ff5dae36df48029911ddee875fee1b3039 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 26 Jan 2022 09:19:21 -0800 Subject: [PATCH 181/327] add image Save quality support --- go.mod | 2 +- go.sum | 5 ++--- img.go | 8 ++++---- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index 0d96a29d..28c7fb66 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 github.com/vcaesar/gops v0.22.0 - github.com/vcaesar/imgo v0.30.0 + github.com/vcaesar/imgo v0.30.1 github.com/vcaesar/keycode v0.10.0 github.com/vcaesar/tt v0.20.0 golang.org/x/image v0.0.0-20211028202545-6944b10bf410 // indirect diff --git a/go.sum b/go.sum index 16a189ab..b1cda640 100644 --- a/go.sum +++ b/go.sum @@ -35,8 +35,8 @@ github.com/tklauser/numcpus v0.3.0 h1:ILuRUQBtssgnxw0XXIjKUC56fgnOrFoQQ/4+DeU2bi github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8= github.com/vcaesar/gops v0.22.0 h1:aWHWxY3fvUuaJGph+LegYUSEU/874WJT7MInd8OUmP0= github.com/vcaesar/gops v0.22.0/go.mod h1:GFNGo9xpCfjcfd/Hovi9RSrpd4FdaQt8V92TzpU22w4= -github.com/vcaesar/imgo v0.30.0 h1:ODQVX0EFJEh+WkKahCBtE0SqcDCIjl/kjiOplR0Ouh8= -github.com/vcaesar/imgo v0.30.0/go.mod h1:8TGnt5hjaMgwDByvMFIzUDSh5uSea4n1tAbSvnhvA6U= +github.com/vcaesar/imgo v0.30.1 h1:B7QMm2mZY+SGoEvvJwNi+eAv21ptvk2YT1IbP2OzyLE= +github.com/vcaesar/imgo v0.30.1/go.mod h1:n4EluJIN/0UYYGPHBCY/BWlIjdRUdY5U6obtP2lrgdM= github.com/vcaesar/keycode v0.10.0 h1:Qx5QE8ZXHyRyjoA2QOxBp25OKMKB+zxMVqm0FWGV0d4= github.com/vcaesar/keycode v0.10.0/go.mod h1:JNlY7xbKsh+LAGfY2j4M3znVrGEm5W1R8s/Uv6BJcfQ= github.com/vcaesar/tt v0.20.0 h1:9t2Ycb9RNHcP0WgQgIaRKJBB+FrRdejuaL6uWIHuoBA= @@ -45,7 +45,6 @@ github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPR github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= golang.org/x/image v0.0.0-20211028202545-6944b10bf410 h1:hTftEOvwiOq2+O8k2D5/Q7COC7k5Qcrgc2TFURJYnvQ= golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= diff --git a/img.go b/img.go index 0e2a3205..25bbf827 100644 --- a/img.go +++ b/img.go @@ -34,8 +34,8 @@ func Read(path string) (image.Image, error) { } // Save create a image file with the image.Image -func Save(img image.Image, path string) error { - return imgo.Save(path, img) +func Save(img image.Image, path string, quality ...int) error { + return imgo.Save(path, img, quality...) } // SaveImg save the image by []byte @@ -49,8 +49,8 @@ func SavePng(img image.Image, path string) error { } // SaveJpeg save the image by image.Image -func SaveJpeg(img image.Image, path string) error { - return imgo.SaveToJpeg(path, img) +func SaveJpeg(img image.Image, path string, quality ...int) error { + return imgo.SaveToJpeg(path, img, quality...) } // ToByteImg convert image.Image to []byte From 18243a21925a338123bb5118f9fc81137aa55d28 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 26 Jan 2022 09:26:16 -0800 Subject: [PATCH 182/327] Add multi screen examples code and fixed args --- examples/screen/main.go | 25 ++++++++++++++++++++++++- robotgo.go | 8 ++++---- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/examples/screen/main.go b/examples/screen/main.go index 118a8b90..aaa04afa 100644 --- a/examples/screen/main.go +++ b/examples/screen/main.go @@ -12,6 +12,7 @@ package main import ( "fmt" + "strconv" "github.com/go-vgo/robotgo" // "go-vgo/robotgo" @@ -26,8 +27,24 @@ func bitmap() { gbitMap := robotgo.CaptureGo() fmt.Println("Go CaptureScreen...", gbitMap.Width) // fmt.Println("...", gbitmap.Width, gbitmap.BytesPerPixel) - // robotgo.SaveCapture("saveCapture.png", 10, 20, 100, 100) + + img := robotgo.CaptureImg() + robotgo.Save(img, "save.png") + + num := robotgo.DisplaysNum() + for i := 0; i < num; i++ { + robotgo.DisplayID = i + img1 := robotgo.CaptureImg() + path1 := "save_" + strconv.Itoa(i) + robotgo.Save(img1, path1+".png") + robotgo.SaveJpeg(img1, path1+".jpeg", 50) + + img2 := robotgo.CaptureImg(10, 10, 20, 20) + path2 := "test_" + strconv.Itoa(i) + robotgo.Save(img2, path2+".png") + robotgo.SaveJpeg(img2, path2+".jpeg", 50) + } } func color() { @@ -64,6 +81,12 @@ func screen() { // gets the screen width and height sx, sy := robotgo.GetScreenSize() fmt.Println("get screen size: ", sx, sy) + for i := 0; i < robotgo.DisplaysNum(); i++ { + s1 := robotgo.ScaleF(i) + fmt.Println("ScaleF: ", s1) + } + sx, sy = robotgo.GetScaleSize() + fmt.Println("get screen sclae size: ", sx, sy) color() } diff --git a/robotgo.go b/robotgo.go index c60374c4..9ac4b871 100644 --- a/robotgo.go +++ b/robotgo.go @@ -222,9 +222,9 @@ func GetPixelColor(x, y int, displayId ...int) string { } // GetMouseColor get the mouse pos's color -func GetMouseColor() string { +func GetMouseColor(displayId ...int) string { x, y := GetMousePos() - return GetPixelColor(x, y) + return GetPixelColor(x, y, displayId...) } func displayIdx(id ...int) int { @@ -319,8 +319,8 @@ func CaptureScreen(args ...int) CBitmap { } else { // Get the main screen rect. rect := GetScreenRect(displayId) - x = C.int32_t(rect.X) - y = C.int32_t(rect.Y) + // x = C.int32_t(rect.X) + // y = C.int32_t(rect.Y) w = C.int32_t(rect.W) h = C.int32_t(rect.H) } From 76abeff3ff4eac67800938d120b949a3dd49c63c Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 26 Jan 2022 09:41:06 -0800 Subject: [PATCH 183/327] add GetClient bounds support --- robotgo.go | 6 ++++++ robotgo_mac_win.go | 10 ++++++++++ robotgo_x11.go | 17 +++++++++++++++++ window/win_sys.h | 17 ++++++----------- window/window.h | 7 +++---- 5 files changed, 42 insertions(+), 15 deletions(-) diff --git a/robotgo.go b/robotgo.go index 9ac4b871..e2561431 100644 --- a/robotgo.go +++ b/robotgo.go @@ -1401,6 +1401,12 @@ func internalGetBounds(pid int32, hwnd int) (int, int, int, int) { return int(bounds.X), int(bounds.Y), int(bounds.W), int(bounds.H) } +// internalGetClient get the window client bounds +func internalGetClient(pid int32, hwnd int) (int, int, int, int) { + bounds := C.get_client(C.uintptr(pid), C.uintptr(hwnd)) + return int(bounds.X), int(bounds.Y), int(bounds.W), int(bounds.H) +} + // Is64Bit determine whether the sys is 64bit func Is64Bit() bool { b := C.Is64Bit() diff --git a/robotgo_mac_win.go b/robotgo_mac_win.go index f7827231..88c1bb96 100644 --- a/robotgo_mac_win.go +++ b/robotgo_mac_win.go @@ -23,6 +23,16 @@ func GetBounds(pid int32, args ...int) (int, int, int, int) { return internalGetBounds(pid, hwnd) } +// GetClient get the window client bounds +func GetClient(pid int32, args ...int) (int, int, int, int) { + var hwnd int + if len(args) > 0 { + hwnd = args[0] + } + + return internalGetClient(pid, hwnd) +} + // internalGetTitle get the window title func internalGetTitle(pid int32, args ...int32) string { var isHwnd int32 diff --git a/robotgo_x11.go b/robotgo_x11.go index cd807b98..1bd0018e 100644 --- a/robotgo_x11.go +++ b/robotgo_x11.go @@ -44,6 +44,23 @@ func GetBounds(pid int32, args ...int) (int, int, int, int) { return internalGetBounds(int32(xid), hwnd) } +// GetClient get the window client bounds +func GetClient(pid int32, args ...int) (int, int, int, int) { + var hwnd int + if len(args) > 0 { + hwnd = args[0] + return internalGetClient(pid, hwnd) + } + + xid, err := GetXId(xu, pid) + if err != nil { + log.Println("Get Xid from Pid errors is: ", err) + return 0, 0, 0, 0 + } + + return internalGetClient(int32(xid), hwnd) +} + // internalGetTitle get the window title func internalGetTitle(pid int32, args ...int32) string { var hwnd int32 diff --git a/window/win_sys.h b/window/win_sys.h index 1d64d627..92ea3a5a 100644 --- a/window/win_sys.h +++ b/window/win_sys.h @@ -88,22 +88,20 @@ Bounds get_bounds(uintptr pid, uintptr isHwnd){ AXUIElementRef AxID = AXUIElementCreateApplication(pid); // Determine the current point of the window - if (AXUIElementCopyAttributeValue( - AxID, kAXPositionAttribute, (CFTypeRef*) &axp) + if (AXUIElementCopyAttributeValue(AxID, kAXPositionAttribute, (CFTypeRef*) &axp) != kAXErrorSuccess || axp == NULL){ goto exit; } // Determine the current size of the window - if (AXUIElementCopyAttributeValue( - AxID, kAXSizeAttribute, (CFTypeRef*) &axs) + if (AXUIElementCopyAttributeValue(AxID, kAXSizeAttribute, (CFTypeRef*) &axs) != kAXErrorSuccess || axs == NULL){ goto exit; } CGPoint p; CGSize s; // Attempt to convert both values into atomic types - if (AXValueGetValue(axp, kAXValueCGPointType, &p) && + if (AXValueGetValue(axp, kAXValueCGPointType, &p) && AXValueGetValue(axs, kAXValueCGSizeType, &s)){ bounds.X = p.x; bounds.Y = p.y; @@ -174,8 +172,7 @@ Bounds get_client(uintptr pid, uintptr isHwnd) { int32_t x = 0, y = 0; // Check if the window is the root - XQueryTree(rDisplay, win.XWin, - &root, &parent, &children, &count); + XQueryTree(rDisplay, win.XWin, &root, &parent, &children, &count); if (children) { XFree(children); } // Retrieve window attributes @@ -183,9 +180,8 @@ Bounds get_client(uintptr pid, uintptr isHwnd) { XGetWindowAttributes(rDisplay, win.XWin, &attr); // Coordinates must be translated - if (parent != attr.root){ - XTranslateCoordinates(rDisplay, win.XWin, attr.root, attr.x, - attr.y, &x, &y, &parent); + if (parent != attr.root) { + XTranslateCoordinates(rDisplay, win.XWin, attr.root, attr.x, attr.y, &x, &y, &parent); } // Coordinates can be left alone else { @@ -209,7 +205,6 @@ Bounds get_client(uintptr pid, uintptr isHwnd) { hwnd = (HWND)pid; } - RECT rect = { 0 }; GetClientRect(hwnd, &rect); diff --git a/window/window.h b/window/window.h index a8cc058f..6b799740 100644 --- a/window/window.h +++ b/window/window.h @@ -532,13 +532,12 @@ char* named(void *result) { char* get_title_by_hand(MData m_data){ // Check if the window is valid - if (!IsValid()) {return "IsValid failed.";} + if (!IsValid()) { return "IsValid failed."; } #if defined(IS_MACOSX) CFStringRef data = NULL; - // Determine the current title of the window - if (AXUIElementCopyAttributeValue(m_data.AxID, - kAXTitleAttribute, (CFTypeRef*) &data) == kAXErrorSuccess && data != NULL) { + if (AXUIElementCopyAttributeValue(m_data.AxID, kAXTitleAttribute, (CFTypeRef*) &data) == + kAXErrorSuccess && data != NULL) { char conv[512]; // Convert result to a C-String CFStringGetCString(data, conv, 512, kCFStringEncodingUTF8); From 427d2b4d616ff7b410ea2c3fa5308dd792120715 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 26 Jan 2022 09:58:23 -0800 Subject: [PATCH 184/327] Update README.md --- README.md | 85 +++++++++++++++++++++++++++++++--------------------- README_zh.md | 8 ++--- 2 files changed, 55 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index ae7ba915..376414c2 100644 --- a/README.md +++ b/README.md @@ -19,8 +19,6 @@ RobotGo supports Mac, Windows, and Linux(X11); and robotgo supports arm64 and x86-amd64. -[Chinese Simplified](https://github.com/go-vgo/robotgo/blob/master/README_zh.md) - ## Contents - [Docs](#docs) - [Binding](#binding) @@ -37,9 +35,7 @@ RobotGo supports Mac, Windows, and Linux(X11); and robotgo supports arm64 and x8 ## Docs - [GoDoc](https://godoc.org/github.com/go-vgo/robotgo)
- - [API Docs](https://github.com/go-vgo/robotgo/blob/master/docs/doc.md) (Deprecated, no updated) - - [Chinese Docs](https://github.com/go-vgo/robotgo/blob/master/docs/doc_zh.md) (Deprecated, no updated) ## Binding: [ADB](https://github.com/vcaesar/adb), packaging android adb API. @@ -70,17 +66,15 @@ xcode-select --install [MinGW-w64](https://sourceforge.net/projects/mingw-w64/files) (Use recommended) ``` -Or the other GCC (But you should compile the "libpng" with yourself. -Or you can removed the bitmap.go. - -In the plans, the bitmap.go will moves to the bitmap dir, but break the API. ) +Or the other GCC (But you should compile the "libpng" with yourself when use the bitmap.) ``` #### For everything else: ``` -GCC, -libpng (bitmap) +GCC + +libpng (Just used by bitmap) X11 with the XTest extension (also known as the Xtst library) @@ -99,20 +93,31 @@ xsel xclip # gcc sudo apt install gcc libc6-dev -sudo apt install libx11-dev xorg-dev libxtst-dev libpng++-dev +# x11 +sudo apt install libx11-dev xorg-dev libxtst-dev + +# Bitmap +sudo apt install libpng++-dev +# Hook sudo apt install xcb libxcb-xkb-dev x11-xkb-utils libx11-xcb-dev libxkbcommon-x11-dev libxkbcommon-dev +# Clipboard sudo apt install xsel xclip ``` ##### Fedora: ```yml -sudo dnf install libXtst-devel libxkbcommon-devel libxkbcommon-x11-devel xorg-x11-xkb-utils-devel +sudo dnf install libXtst-devel +# Bitmap sudo dnf install libpng-devel +# Hook +sudo dnf install libxkbcommon-devel libxkbcommon-x11-devel xorg-x11-xkb-utils-devel + +# Clipboard sudo dnf install xsel xclip ``` @@ -241,10 +246,21 @@ func main() { bit := robotgo.CaptureScreen(10, 10, 30, 30) defer robotgo.FreeBitmap(bit) - robotgo.SaveBitmap(bit, "test_1.png") img := robotgo.ToImage(bit) imgo.Save("test.png", img) + + num := robotgo.DisplaysNum() + for i := 0; i < num; i++ { + robotgo.DisplayID = i + img1 := robotgo.CaptureImg() + path1 := "save_" + strconv.Itoa(i) + robotgo.Save(img1, path1+".png") + robotgo.SaveJpeg(img1, path1+".jpeg", 50) + + img2 := robotgo.CaptureImg(10, 10, 20, 20) + robotgo.Save(img2, "test_"+strconv.Itoa(i)+".png") + } } ``` @@ -257,30 +273,31 @@ import ( "fmt" "github.com/go-vgo/robotgo" + "github.com/vcaesar/bitmap" ) func main() { - bitmap := robotgo.CaptureScreen(10, 20, 30, 40) + bit := robotgo.CaptureScreen(10, 20, 30, 40) // use `defer robotgo.FreeBitmap(bit)` to free the bitmap - defer robotgo.FreeBitmap(bitmap) + defer robotgo.FreeBitmap(bit) - fmt.Println("bitmap...", bitmap) - img := robotgo.ToImage(bitmap) - robotgo.SavePng(img, "test_1.png") + fmt.Println("bitmap...", bit) + img := robotgo.ToImage(bit) + // robotgo.SavePng(img, "test_1.png") + robotgo.Save(img, "test_1.png") bit2 := robotgo.ToCBitmap(robotgo.ImgToBitmap(img)) - fx, fy := robotgo.FindBitmap(bit2) + fx, fy := bitmap.Find(bit2) fmt.Println("FindBitmap------ ", fx, fy) robotgo.Move(fx, fy) - arr := robotgo.FindAllBitmap(bit2) + arr := bitmap.FindAll(bit2) fmt.Println("Find all bitmap: ", arr) - robotgo.SaveBitmap(bitmap, "test.png") - fx, fy = robotgo.FindBitmap(bitmap) + fx, fy = bitmap.Find(bit) fmt.Println("FindBitmap------ ", fx, fy) - robotgo.SaveBitmap(bitmap, "test.png") + bitmap.Save(bit, "test.png") } ``` @@ -354,7 +371,7 @@ package main import ( "fmt" - "github.com/go-vgo/robotgo" + // "github.com/go-vgo/robotgo" hook "github.com/robotn/gohook" ) @@ -366,18 +383,18 @@ func main() { func add() { fmt.Println("--- Please press ctrl + shift + q to stop hook ---") - robotgo.EventHook(hook.KeyDown, []string{"q", "ctrl", "shift"}, func(e hook.Event) { + hook.Register(hook.KeyDown, []string{"q", "ctrl", "shift"}, func(e hook.Event) { fmt.Println("ctrl-shift-q") - robotgo.EventEnd() + hook.End() }) fmt.Println("--- Please press w---") - robotgo.EventHook(hook.KeyDown, []string{"w"}, func(e hook.Event) { + hook.Register(hook.KeyDown, []string{"w"}, func(e hook.Event) { fmt.Println("w") }) - s := robotgo.EventStart() - <-robotgo.EventProcess(s) + s := hook.Start() + <-hook.Process(s) } func low() { @@ -390,17 +407,17 @@ func low() { } func event() { - ok := robotgo.AddEvents("q", "ctrl", "shift") + ok := hook.AddEvents("q", "ctrl", "shift") if ok { fmt.Println("add events...") } - keve := robotgo.AddEvent("k") + keve := hook.AddEvent("k") if keve { fmt.Println("you press... ", "k") } - mleft := robotgo.AddEvent("mleft") + mleft := hook.AddEvent("mleft") if mleft { fmt.Println("you press... ", "mouse left button") } @@ -439,7 +456,7 @@ func main() { robotgo.Kill(100) } - abool := robotgo.ShowAlert("test", "robotgo") + abool := robotgo.Alert("test", "robotgo") if abool { fmt.Println("ok@@@ ", "ok") } @@ -460,7 +477,7 @@ go build main.go #### Other to windows -Install Requirements (Ubuntu): +Install Requirements (Ubuntu, Just used by bitmap.): ```bash sudo apt install gcc-multilib sudo apt install gcc-mingw-w64 diff --git a/README_zh.md b/README_zh.md index 29aa363c..7bac20c9 100644 --- a/README_zh.md +++ b/README_zh.md @@ -15,7 +15,7 @@ RobotGo 支持 Mac, Windows, and Linux(X11).
-提 Issues 请到 [Github](https://github.com/go-vgo/robotgo), 便于统一管理和即时更新 +提 Issues 请到 [Github](https://github.com/go-vgo/robotgo), 便于统一管理和即时更新; `REDAME_zh.md 已废弃, 不再更新` ## Contents - [Docs](#docs) @@ -34,8 +34,8 @@ RobotGo 支持 Mac, Windows, and Linux(X11). ## Docs - [GoDoc](https://godoc.org/github.com/go-vgo/robotgo)
-- [中文文档](https://github.com/go-vgo/robotgo/blob/master/docs/doc_zh.md) (弃用) -- [English Docs](https://github.com/go-vgo/robotgo/blob/master/docs/doc.md) (弃用) + ## Binding: @@ -430,7 +430,7 @@ func main() { robotgo.Kill(100) } - abool := robotgo.ShowAlert("test", "robotgo") + abool := robotgo.Alert("test", "robotgo") if abool { fmt.Println("ok@@@ ", "ok") } From 8ad853dca2283f02fbaf84531c639b0978d5aed3 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 26 Jan 2022 10:28:57 -0800 Subject: [PATCH 185/327] Update README.md and removed type_string_delayed --- README.md | 16 ++++---- base/bitmap_free_c.h | 11 ++---- base/endian.h | 2 +- base/ms_stdbool.h | 2 - base/rgb.h | 15 ++------ base/types.h | 42 ++++++--------------- base/win32.h | 1 - key/keycode_c.h | 51 +++++++++---------------- key/keypress.h | 6 --- key/keypress_c.h | 86 +++++++------------------------------------ mouse/mouse_c.h | 49 ++++++------------------ robotgo.go | 19 ---------- screen/screengrab_c.h | 23 +++++------- 13 files changed, 79 insertions(+), 244 deletions(-) diff --git a/README.md b/README.md index 376414c2..1b6cecbb 100644 --- a/README.md +++ b/README.md @@ -251,16 +251,16 @@ func main() { imgo.Save("test.png", img) num := robotgo.DisplaysNum() - for i := 0; i < num; i++ { - robotgo.DisplayID = i - img1 := robotgo.CaptureImg() + for i := 0; i < num; i++ { + robotgo.DisplayID = i + img1 := robotgo.CaptureImg() path1 := "save_" + strconv.Itoa(i) - robotgo.Save(img1, path1+".png") - robotgo.SaveJpeg(img1, path1+".jpeg", 50) + robotgo.Save(img1, path1+".png") + robotgo.SaveJpeg(img1, path1+".jpeg", 50) - img2 := robotgo.CaptureImg(10, 10, 20, 20) - robotgo.Save(img2, "test_"+strconv.Itoa(i)+".png") - } + img2 := robotgo.CaptureImg(10, 10, 20, 20) + robotgo.Save(img2, "test_"+strconv.Itoa(i)+".png") + } } ``` diff --git a/base/bitmap_free_c.h b/base/bitmap_free_c.h index e4c751f3..2c97af91 100644 --- a/base/bitmap_free_c.h +++ b/base/bitmap_free_c.h @@ -2,14 +2,9 @@ #include #include -MMBitmapRef createMMBitmap_c( - uint8_t *buffer, - size_t width, - size_t height, - size_t bytewidth, - uint8_t bitsPerPixel, - uint8_t bytesPerPixel -){ +MMBitmapRef createMMBitmap_c(uint8_t *buffer, size_t width, size_t height, + size_t bytewidth, uint8_t bitsPerPixel, uint8_t bytesPerPixel +) { MMBitmapRef bitmap = malloc(sizeof(MMBitmap)); if (bitmap == NULL) { return NULL; } diff --git a/base/endian.h b/base/endian.h index 2bc7c521..cbc7c542 100644 --- a/base/endian.h +++ b/base/endian.h @@ -82,7 +82,7 @@ #define bitswap16(i) bswap_16(i) /* Linux system function */ #else /* Default macro */ #define bitswap16(i) (((uint16_t)(i) & 0xFF00) >> 8) | \ - (((uint16_t)(i) & 0x00FF) << 8) + (((uint16_t)(i) & 0x00FF) << 8) #endif #endif /* bitswap16 */ diff --git a/base/ms_stdbool.h b/base/ms_stdbool.h index a6554452..1aae547f 100644 --- a/base/ms_stdbool.h +++ b/base/ms_stdbool.h @@ -10,7 +10,6 @@ #define __bool_true_false_are_defined 1 #ifndef __cplusplus - #if defined(true) || defined(false) || defined(bool) #error "Boolean type already defined" #endif @@ -21,7 +20,6 @@ }; typedef unsigned char bool; - #endif /* !__cplusplus */ #endif /* MS_STDBOOL_H */ diff --git a/base/rgb.h b/base/rgb.h index db0e3f79..0810fc4a 100644 --- a/base/rgb.h +++ b/base/rgb.h @@ -12,7 +12,6 @@ #include #endif - /* RGB colors in MMBitmaps are stored as BGR for convenience in converting * to/from certain formats (mainly OpenGL). * @@ -46,8 +45,7 @@ typedef uint32_t MMRGBHex; #define RGB_TO_HEX(red, green, blue) (((red) << 16) | ((green) << 8) | (blue)) /* Convenience wrapper for MMRGBColors. */ -H_INLINE MMRGBHex hexFromMMRGB(MMRGBColor rgb) -{ +H_INLINE MMRGBHex hexFromMMRGB(MMRGBColor rgb) { return RGB_TO_HEX(rgb.red, rgb.green, rgb.blue); } @@ -56,8 +54,7 @@ H_INLINE MMRGBHex hexFromMMRGB(MMRGBColor rgb) #define BLUE_FROM_HEX(hex) (hex & 0xFF) /* Converts hexadecimal color to MMRGBColor. */ -H_INLINE MMRGBColor MMRGBFromHex(MMRGBHex hex) -{ +H_INLINE MMRGBColor MMRGBFromHex(MMRGBHex hex) { MMRGBColor color; color.red = RED_FROM_HEX(hex); color.green = GREEN_FROM_HEX(hex); @@ -73,9 +70,7 @@ H_INLINE MMRGBColor MMRGBFromHex(MMRGBHex hex) /* Returns whether two colors are similar within the given range, |tolerance|. * Tolerance can be in the range 0.0f - 1.0f, where 0 denotes the exact * color and 1 denotes any color. */ -H_INLINE int MMRGBColorSimilarToColor(MMRGBColor c1, MMRGBColor c2, - float tolerance) -{ +H_INLINE int MMRGBColorSimilarToColor(MMRGBColor c1, MMRGBColor c2, float tolerance) { /* Speedy case */ if (tolerance <= 0.0f) { return MMRGBColorEqualToColor(c1, c2); @@ -87,12 +82,10 @@ H_INLINE int MMRGBColorSimilarToColor(MMRGBColor c1, MMRGBColor c2, (d2 * d2) + (d3 * d3)) <= (tolerance * 442.0f); } - } /* Identical to MMRGBColorSimilarToColor, only for hex values. */ -H_INLINE int MMRGBHexSimilarToColor(MMRGBHex h1, MMRGBHex h2, float tolerance) -{ +H_INLINE int MMRGBHexSimilarToColor(MMRGBHex h1, MMRGBHex h2, float tolerance) { if (tolerance <= 0.0f) { return h1 == h2; } else { diff --git a/base/types.h b/base/types.h index 0e68a830..d76ef3e7 100644 --- a/base/types.h +++ b/base/types.h @@ -8,7 +8,6 @@ #include /* Some generic, cross-platform types. */ - #ifdef RobotGo_64 typedef int64_t intptr; typedef uint64_t uintptr; @@ -21,87 +20,74 @@ struct _MMPoint { size_t x; size_t y; }; - typedef struct _MMPoint MMPoint; struct _MMPointInt32 { int32_t x; int32_t y; }; - typedef struct _MMPointInt32 MMPointInt32; struct _MMSize { size_t width; size_t height; }; - typedef struct _MMSize MMSize; struct _MMSizeInt32 { int32_t w; int32_t h; }; - typedef struct _MMSizeInt32 MMSizeInt32; - struct _MMRect { MMPoint origin; MMSize size; }; - typedef struct _MMRect MMRect; struct _MMRectInt32 { MMPointInt32 origin; MMSizeInt32 size; }; - typedef struct _MMRectInt32 MMRectInt32; -H_INLINE MMPoint MMPointMake(size_t x, size_t y) -{ +H_INLINE MMPoint MMPointMake(size_t x, size_t y) { MMPoint point; point.x = x; point.y = y; return point; } -H_INLINE MMPointInt32 MMPointInt32Make(int32_t x, int32_t y) -{ +H_INLINE MMPointInt32 MMPointInt32Make(int32_t x, int32_t y) { MMPointInt32 point; point.x = x; point.y = y; return point; } -H_INLINE MMSize MMSizeMake(size_t width, size_t height) -{ +H_INLINE MMSize MMSizeMake(size_t width, size_t height) { MMSize size; size.width = width; size.height = height; return size; } -H_INLINE MMSizeInt32 MMSizeInt32Make(int32_t w, int32_t h) -{ +H_INLINE MMSizeInt32 MMSizeInt32Make(int32_t w, int32_t h) { MMSizeInt32 size; size.w = w; size.h = h; return size; } -H_INLINE MMRect MMRectMake(size_t x, size_t y, size_t width, size_t height) -{ +H_INLINE MMRect MMRectMake(size_t x, size_t y, size_t width, size_t height) { MMRect rect; rect.origin = MMPointMake(x, y); rect.size = MMSizeMake(width, height); return rect; } -H_INLINE MMRectInt32 MMRectInt32Make(int32_t x, int32_t y, int32_t w, int32_t h) -{ +H_INLINE MMRectInt32 MMRectInt32Make(int32_t x, int32_t y, int32_t w, int32_t h) { MMRectInt32 rect; rect.origin = MMPointInt32Make(x, y); rect.size = MMSizeInt32Make(w, h); @@ -112,18 +98,14 @@ H_INLINE MMRectInt32 MMRectInt32Make(int32_t x, int32_t y, int32_t w, int32_t h) #define MMPointZero MMPointMake(0, 0) #if defined(IS_MACOSX) + #define CGPointFromMMPoint(p) CGPointMake((CGFloat)(p).x, (CGFloat)(p).y) + #define MMPointFromCGPoint(p) MMPointMake((size_t)(p).x, (size_t)(p).y) -#define CGPointFromMMPoint(p) CGPointMake((CGFloat)(p).x, (CGFloat)(p).y) -#define MMPointFromCGPoint(p) MMPointMake((size_t)(p).x, (size_t)(p).y) - -#define CGPointFromMMPointInt32(p) CGPointMake((CGFloat)(p).x, (CGFloat)(p).y) -#define MMPointInt32FromCGPoint(p) MMPointInt32Make((int32_t)(p).x, (int32_t)(p).y) - + #define CGPointFromMMPointInt32(p) CGPointMake((CGFloat)(p).x, (CGFloat)(p).y) + #define MMPointInt32FromCGPoint(p) MMPointInt32Make((int32_t)(p).x, (int32_t)(p).y) #elif defined(IS_WINDOWS) - -#define MMPointFromPOINT(p) MMPointMake((size_t)p.x, (size_t)p.y) -#define MMPointInt32FromPOINT(p) MMPointInt32Make((int32_t)p.x, (int32_t)p.y) - + #define MMPointFromPOINT(p) MMPointMake((size_t)p.x, (size_t)p.y) + #define MMPointInt32FromPOINT(p) MMPointInt32Make((int32_t)p.x, (int32_t)p.y) #endif #endif /* TYPES_H */ diff --git a/base/win32.h b/base/win32.h index d4e24852..6dfecc73 100644 --- a/base/win32.h +++ b/base/win32.h @@ -30,5 +30,4 @@ // printf("%d\n", info.hWnd); return info.hWnd; } - #endif \ No newline at end of file diff --git a/key/keycode_c.h b/key/keycode_c.h index 8e54dcba..97c5a50d 100644 --- a/key/keycode_c.h +++ b/key/keycode_c.h @@ -1,19 +1,16 @@ #include "keycode.h" #if defined(IS_MACOSX) + #include + #include /* For kVK_ constants, and TIS functions. */ -#include -#include /* For kVK_ constants, and TIS functions. */ - -/* Returns string representation of key, if it is printable. - * Ownership follows the Create Rule; that is, it is the caller's - * responsibility to release the returned object. */ -CFStringRef createStringForKey(CGKeyCode keyCode); - -MMKeyCode keyCodeForCharFallBack(const char c); + /* Returns string representation of key, if it is printable. + * Ownership follows the Create Rule; that is, it is the caller's + * responsibility to release the returned object. */ + CFStringRef createStringForKey(CGKeyCode keyCode); + MMKeyCode keyCodeForCharFallBack(const char c); #elif defined(USE_X11) - /* * Structs to store key mappings not handled by XStringToKeysym() on some * Linux systems. @@ -77,11 +74,9 @@ MMKeyCode keyCodeForChar(const char c){ /* Generate table of keycodes and characters. */ if (charToCodeDict == NULL) { size_t i; - charToCodeDict = CFDictionaryCreateMutable(kCFAllocatorDefault, - 128, - &kCFCopyStringDictionaryKeyCallBacks, - NULL); - if (charToCodeDict == NULL) return K_NOT_A_KEY; + charToCodeDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 128, + &kCFCopyStringDictionaryKeyCallBacks, NULL); + if (charToCodeDict == NULL) { return K_NOT_A_KEY; } /* Loop through every keycode (0 - 127) to find its current mapping. */ for (i = 0; i < 128; ++i) { @@ -135,7 +130,7 @@ MMKeyCode keyCodeForChar(const char c){ * mapping table. */ struct XSpecialCharacterMapping* xs = XSpecialCharacterTable; while (xs->name) { - if (c == xs->name ) { + if (c == xs->name) { code = xs->code; // break; @@ -152,34 +147,22 @@ MMKeyCode keyCodeForChar(const char c){ #endif } - #if defined(IS_MACOSX) - CFStringRef createStringForKey(CGKeyCode keyCode){ TISInputSourceRef currentKeyboard = TISCopyCurrentASCIICapableKeyboardInputSource(); - CFDataRef layoutData = - (CFDataRef)TISGetInputSourceProperty(currentKeyboard, - kTISPropertyUnicodeKeyLayoutData); + CFDataRef layoutData = (CFDataRef) TISGetInputSourceProperty( + currentKeyboard, kTISPropertyUnicodeKeyLayoutData); if (layoutData == nil) { return 0; } - const UCKeyboardLayout *keyboardLayout = - (const UCKeyboardLayout *)CFDataGetBytePtr(layoutData); - + const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout *) CFDataGetBytePtr(layoutData); UInt32 keysDown = 0; UniChar chars[4]; UniCharCount realLength; - UCKeyTranslate(keyboardLayout, - keyCode, - kUCKeyActionDisplay, - 0, - LMGetKbdType(), - kUCKeyTranslateNoDeadKeysBit, - &keysDown, - sizeof(chars) / sizeof(chars[0]), - &realLength, - chars); + UCKeyTranslate(keyboardLayout, keyCode, kUCKeyActionDisplay, 0, LMGetKbdType(), + kUCKeyTranslateNoDeadKeysBit, &keysDown, + sizeof(chars) / sizeof(chars[0]), &realLength, chars); CFRelease(currentKeyboard); return CFStringCreateWithCharacters(kCFAllocatorDefault, chars, 1); diff --git a/key/keypress.h b/key/keypress.h index 20e84d69..946a66e5 100644 --- a/key/keypress.h +++ b/key/keypress.h @@ -17,7 +17,6 @@ extern "C" #endif #if defined(IS_MACOSX) - typedef enum { MOD_NONE = 0, MOD_META = kCGEventFlagMaskCommand, @@ -25,9 +24,7 @@ extern "C" MOD_CONTROL = kCGEventFlagMaskControl, MOD_SHIFT = kCGEventFlagMaskShift } MMKeyFlags; - #elif defined(USE_X11) - enum _MMKeyFlags { MOD_NONE = 0, MOD_META = Mod4Mask, @@ -37,9 +34,7 @@ extern "C" }; typedef unsigned int MMKeyFlags; - #elif defined(IS_WINDOWS) - enum _MMKeyFlags { MOD_NONE = 0, /* These are already defined by the Win32 API */ @@ -50,7 +45,6 @@ extern "C" }; typedef unsigned int MMKeyFlags; - #endif #if defined(IS_WINDOWS) diff --git a/key/keypress_c.h b/key/keypress_c.h index 8fd05029..ecd8234d 100644 --- a/key/keypress_c.h +++ b/key/keypress_c.h @@ -3,7 +3,6 @@ #include "../base/microsleep.h" #include /* For isupper() */ - #if defined(IS_MACOSX) #include #import @@ -18,34 +17,29 @@ #define WIN32_KEY_EVENT_WAIT(key, flags) \ (win32KeyEvent(key, flags), Sleep(DEADBEEF_RANDRANGE(0, 1))) #elif defined(USE_X11) - #define X_KEY_EVENT(display, key, is_press) \ - (XTestFakeKeyEvent(display, \ - XKeysymToKeycode(display, key), \ - is_press, CurrentTime), \ - XSync(display, false)) - #define X_KEY_EVENT_WAIT(display, key, is_press) \ - (X_KEY_EVENT(display, key, is_press), \ - microsleep(DEADBEEF_UNIFORM(0.0, 0.5))) + #define X_KEY_EVENT(display, key, is_press) ( \ + XTestFakeKeyEvent(display, XKeysymToKeycode(display, key), is_press, CurrentTime), + XSync(display, false)) + #define X_KEY_EVENT_WAIT(display, key, is_press) ( \ + X_KEY_EVENT(display, key, is_press), microsleep(DEADBEEF_UNIFORM(0.0, 0.5))) #endif #if defined(IS_MACOSX) -static io_connect_t _getAuxiliaryKeyDriver(void){ +static io_connect_t _getAuxiliaryKeyDriver(void) { static mach_port_t sEventDrvrRef = 0; mach_port_t masterPort, service, iter; kern_return_t kr; if (!sEventDrvrRef) { - kr = IOMasterPort( bootstrap_port, &masterPort ); + kr = IOMasterPort(bootstrap_port, &masterPort); assert(KERN_SUCCESS == kr); - kr = IOServiceGetMatchingServices(masterPort, - IOServiceMatching( kIOHIDSystemClass), &iter ); + kr = IOServiceGetMatchingServices(masterPort, IOServiceMatching(kIOHIDSystemClass), &iter); assert(KERN_SUCCESS == kr); service = IOIteratorNext( iter ); assert(service); - kr = IOServiceOpen(service, - mach_task_self(), kIOHIDParamConnectType, &sEventDrvrRef ); + kr = IOServiceOpen(service, mach_task_self(), kIOHIDParamConnectType, &sEventDrvrRef); assert(KERN_SUCCESS == kr); IOObjectRelease(service); @@ -56,7 +50,7 @@ static io_connect_t _getAuxiliaryKeyDriver(void){ #endif #if defined(IS_WINDOWS) -void win32KeyEvent(int key, MMKeyFlags flags){ +void win32KeyEvent(int key, MMKeyFlags flags) { int scan = MapVirtualKey(key & 0xff, MAPVK_VK_TO_VSC); /* Set the scan code for extended keys */ @@ -103,7 +97,6 @@ void win32KeyEvent(int key, MMKeyFlags flags){ // if ( flags & KEYEVENTF_KEYUP ) { // scan |= 0x80; // } - // keybd_event(key, scan, flags, 0); INPUT keyInput; @@ -118,7 +111,7 @@ void win32KeyEvent(int key, MMKeyFlags flags){ } #endif -void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags){ +void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags) { #if defined(IS_MACOSX) /* The media keys all have 1000 added to them to help us detect them. */ if (code >= 1000) { @@ -133,12 +126,11 @@ void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags){ event.compound.subType = NX_SUBTYPE_AUX_CONTROL_BUTTONS; event.compound.misc.L[0] = evtInfo; - kr = IOHIDPostEvent( _getAuxiliaryKeyDriver(), - NX_SYSDEFINED, loc, &event, kNXEventDataVersion, 0, FALSE ); + kr = IOHIDPostEvent(_getAuxiliaryKeyDriver(), + NX_SYSDEFINED, loc, &event, kNXEventDataVersion, 0, FALSE); assert( KERN_SUCCESS == kr ); } else { - CGEventRef keyEvent = CGEventCreateKeyboardEvent(NULL, - (CGKeyCode)code, down); + CGEventRef keyEvent = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)code, down); assert(keyEvent != NULL); CGEventSetType(keyEvent, down ? kCGEventKeyDown : kCGEventKeyUp); @@ -269,13 +261,11 @@ void toggleUnicode(UniChar ch, const bool down){ XFlush(dpy); KeyCode code = XKeysymToKeycode(dpy, sym); - XTestFakeKeyEvent(dpy, code, True, 1); XTestFakeKeyEvent(dpy, code, False, 1); XFlush(dpy); XCloseDisplay(dpy); - return 0; } #endif @@ -313,52 +303,4 @@ void unicodeType(const unsigned value){ microsleep(5.0); toggleUniKey(value, false); #endif -} - -// todo: removed -void typeStringDelayed(const char *str, const unsigned cpm){ - - /* Characters per second */ - const double cps = (double)cpm / 60.0; - - /* Average milli-seconds per character */ - const double mspc = (cps == 0.0) ? 0.0 : 1000.0 / cps; - - unsigned long n; - unsigned short c; - unsigned short c1; - unsigned short c2; - unsigned short c3; - - while (*str != '\0') { - c = *str++; - - // warning, the following utf8 decoder - // doesn't perform validation - if (c <= 0x7F) { - // 0xxxxxxx one byte - n = c; - } else if ((c & 0xE0) == 0xC0) { - // 110xxxxx two bytes - c1 = (*str++) & 0x3F; - n = ((c & 0x1F) << 6) | c1; - } else if ((c & 0xF0) == 0xE0) { - // 1110xxxx three bytes - c1 = (*str++) & 0x3F; - c2 = (*str++) & 0x3F; - n = ((c & 0x0F) << 12) | (c1 << 6) | c2; - } else if ((c & 0xF8) == 0xF0) { - // 11110xxx four bytes - c1 = (*str++) & 0x3F; - c2 = (*str++) & 0x3F; - c3 = (*str++) & 0x3F; - n = ((c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3; - } - - unicodeType(n); - - if (mspc > 0) { - microsleep(mspc + (DEADBEEF_UNIFORM(0.0, 0.5))); - } - } } \ No newline at end of file diff --git a/mouse/mouse_c.h b/mouse/mouse_c.h index d6da85d9..a34e44b5 100644 --- a/mouse/mouse_c.h +++ b/mouse/mouse_c.h @@ -30,18 +30,15 @@ #define MMMouseDownToCGEventType(button) \ ((button) == (LEFT_BUTTON) ? kCGEventLeftMouseDown \ - : ((button) == RIGHT_BUTTON ? kCGEventRightMouseDown \ - : kCGEventOtherMouseDown)) + : ((button) == RIGHT_BUTTON ? kCGEventRightMouseDown : kCGEventOtherMouseDown)) #define MMMouseUpToCGEventType(button) \ ((button) == LEFT_BUTTON ? kCGEventLeftMouseUp \ - : ((button) == RIGHT_BUTTON ? kCGEventRightMouseUp \ - : kCGEventOtherMouseUp)) + : ((button) == RIGHT_BUTTON ? kCGEventRightMouseUp : kCGEventOtherMouseUp)) #define MMMouseDragToCGEventType(button) \ ((button) == LEFT_BUTTON ? kCGEventLeftMouseDragged \ - : ((button) == RIGHT_BUTTON ? kCGEventRightMouseDragged \ - : kCGEventOtherMouseDragged)) + : ((button) == RIGHT_BUTTON ? kCGEventRightMouseDragged : kCGEventOtherMouseDragged)) #elif defined(IS_WINDOWS) @@ -50,13 +47,11 @@ #define MMMouseUpToMEventF(button) \ ((button) == LEFT_BUTTON ? MOUSEEVENTF_LEFTUP \ - : ((button) == RIGHT_BUTTON ? MOUSEEVENTF_RIGHTUP \ - : MOUSEEVENTF_MIDDLEUP)) + : ((button) == RIGHT_BUTTON ? MOUSEEVENTF_RIGHTUP : MOUSEEVENTF_MIDDLEUP)) #define MMMouseDownToMEventF(button) \ ((button) == LEFT_BUTTON ? MOUSEEVENTF_LEFTDOWN \ - : ((button) == RIGHT_BUTTON ? MOUSEEVENTF_RIGHTDOWN \ - : MOUSEEVENTF_MIDDLEDOWN)) + : ((button) == RIGHT_BUTTON ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_MIDDLEDOWN)) #endif @@ -158,8 +153,8 @@ MMPointInt32 getMousePos(){ unsigned int more_garbage; Display *display = XGetMainDisplay(); - XQueryPointer(display, XDefaultRootWindow(display), &garb1, &garb2, - &x, &y, &garb_x, &garb_y, &more_garbage); + XQueryPointer(display, XDefaultRootWindow(display), &garb1, &garb2, &x, &y, + &garb_x, &garb_y, &more_garbage); return MMPointInt32Make(x, y); #elif defined(IS_WINDOWS) @@ -179,8 +174,7 @@ void toggleMouse(bool down, MMMouseButton button){ #if defined(IS_MACOSX) const CGPoint currentPos = CGPointFromMMPoint(getMousePos()); const CGEventType mouseType = MMMouseToCGEventType(down, button); - CGEventRef event = CGEventCreateMouseEvent(NULL, - mouseType, currentPos, (CGMouseButton)button); + CGEventRef event = CGEventCreateMouseEvent(NULL, mouseType, currentPos, (CGMouseButton)button); CGEventPost(kCGSessionEventTap, event); CFRelease(event); @@ -215,32 +209,26 @@ void clickMouse(MMMouseButton button){ */ void doubleClick(MMMouseButton button){ #if defined(IS_MACOSX) - /* Double click for Mac. */ const CGPoint currentPos = CGPointFromMMPoint(getMousePos()); const CGEventType mouseTypeDown = MMMouseToCGEventType(true, button); const CGEventType mouseTypeUP = MMMouseToCGEventType(false, button); - CGEventRef event = CGEventCreateMouseEvent( - NULL, mouseTypeDown, currentPos, kCGMouseButtonLeft); + CGEventRef event = CGEventCreateMouseEvent(NULL, mouseTypeDown, currentPos, kCGMouseButtonLeft); /* Set event to double click. */ CGEventSetIntegerValueField(event, kCGMouseEventClickState, 2); - CGEventPost(kCGHIDEventTap, event); CGEventSetType(event, mouseTypeUP); CGEventPost(kCGHIDEventTap, event); CFRelease(event); - #else - /* Double click for everything else. */ clickMouse(button); microsleep(200); clickMouse(button); - #endif } @@ -272,13 +260,9 @@ void scrollMouse(int scrollMagnitude, MMMouseWheelDirection scrollDirection){ /* Make scroll magnitude negative if we're scrolling down. */ cleanScrollMagnitude = cleanScrollMagnitude * scrollDirection; - event = CGEventCreateScrollWheelEvent(NULL, - kCGScrollEventUnitLine, wheel, cleanScrollMagnitude, 0); - + event = CGEventCreateScrollWheelEvent(NULL, kCGScrollEventUnitLine, wheel, cleanScrollMagnitude, 0); CGEventPost(kCGHIDEventTap, event); - #elif defined(USE_X11) - int x; int dir = 4; /* Button 4 is up, 5 is down. */ Display *display = XGetMainDisplay(); @@ -293,9 +277,7 @@ void scrollMouse(int scrollMagnitude, MMMouseWheelDirection scrollDirection){ } XSync(display, false); - #elif defined(IS_WINDOWS) - mouseScrollInput.type = INPUT_MOUSE; mouseScrollInput.mi.dx = 0; mouseScrollInput.mi.dy = 0; @@ -305,7 +287,6 @@ void scrollMouse(int scrollMagnitude, MMMouseWheelDirection scrollDirection){ mouseScrollInput.mi.mouseData = WHEEL_DELTA * scrollDirection * cleanScrollMagnitude; SendInput(1, &mouseScrollInput, sizeof(mouseScrollInput)); - #endif } @@ -322,16 +303,12 @@ void scrollMouseXY(int x, int y) { /* Set up the OS specific solution */ #if defined(__APPLE__) - CGEventRef event; - event = CGEventCreateScrollWheelEvent(NULL, kCGScrollEventUnitPixel, 2, y, x); CGEventPost(kCGHIDEventTap, event); CFRelease(event); - #elif defined(USE_X11) - int ydir = 4; /* Button 4 is up, 5 is down. */ int xdir = 6; Display *display = XGetMainDisplay(); @@ -355,9 +332,7 @@ void scrollMouseXY(int x, int y) { } XSync(display, false); - #elif defined(IS_WINDOWS) - mouseScrollInputH.type = INPUT_MOUSE; mouseScrollInputH.mi.dx = 0; mouseScrollInputH.mi.dy = 0; @@ -408,9 +383,7 @@ bool smoothlyMoveMouse(MMPointInt32 endPoint, double lowSpeed, double highSpeed) double velo_x = 0.0, velo_y = 0.0; double distance; - while ((distance = - crude_hypot((double)pos.x - endPoint.x, (double)pos.y - endPoint.y) - ) > 1.0) { + while ((distance =crude_hypot((double)pos.x - endPoint.x, (double)pos.y - endPoint.y)) > 1.0) { double gravity = DEADBEEF_UNIFORM(5.0, 500.0); // double gravity = DEADBEEF_UNIFORM(lowSpeed, highSpeed); diff --git a/robotgo.go b/robotgo.go index e2561431..ea02289b 100644 --- a/robotgo.go +++ b/robotgo.go @@ -1136,25 +1136,6 @@ func PasteStr(str string) string { return KeyTap("v", "control") } -// Deprecated: use the TypeStr(), -// -// TypeString send a string, support unicode(no linux support) -// TypeStr(string: The string to send), Wno-deprecated -// -// This function will be removed in version v1.0.0 -func TypeString(str string, delay ...int) { - tt.Drop("TypeString", "TypeStr") - var cdelay C.size_t - cstr := C.CString(str) - if len(delay) > 0 { - cdelay = C.size_t(delay[0]) - } - - C.type_string_delayed(cstr, cdelay) - - C.free(unsafe.Pointer(cstr)) -} - // TypeStrDelay type string delayed func TypeStrDelay(str string, delay int) { TypeStr(str) diff --git a/screen/screengrab_c.h b/screen/screengrab_c.h index 72f8203a..1b13b67f 100644 --- a/screen/screengrab_c.h +++ b/screen/screengrab_c.h @@ -37,13 +37,10 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id) bufferSize = CFDataGetLength(imageData); buffer = malloc(bufferSize); - CFDataGetBytes(imageData, CFRangeMake(0, bufferSize), buffer); - bitmap = createMMBitmap_c(buffer, - CGImageGetWidth(image), CGImageGetHeight(image), - CGImageGetBytesPerRow(image), CGImageGetBitsPerPixel(image), - CGImageGetBitsPerPixel(image) / 8); + bitmap = createMMBitmap_c(buffer, CGImageGetWidth(image), CGImageGetHeight(image), + CGImageGetBytesPerRow(image), CGImageGetBitsPerPixel(image),CGImageGetBitsPerPixel(image) / 8); CFRelease(imageData); CGImageRelease(image); @@ -58,16 +55,15 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id) display = XGetMainDisplay(); } - XImage *image = XGetImage(display, XDefaultRootWindow(display), + XImage *image = XGetImage(display, XDefaultRootWindow(display), (int)rect.origin.x, (int)rect.origin.y, - (unsigned int)rect.size.w, (unsigned int)rect.size.h, - AllPlanes, ZPixmap); + (unsigned int)rect.size.w, (unsigned int)rect.size.h, AllPlanes, ZPixmap); XCloseDisplay(display); if (image == NULL) { return NULL; } bitmap = createMMBitmap_c((uint8_t *)image->data, - rect.size.w, rect.size.h, (size_t)image->bytes_per_line, - (uint8_t)image->bits_per_pixel, (uint8_t)image->bits_per_pixel / 8); + rect.size.w, rect.size.h, (size_t)image->bytes_per_line, + (uint8_t)image->bits_per_pixel, (uint8_t)image->bits_per_pixel / 8); image->data = NULL; /* Steal ownership of bitmap data so we don't have to copy it. */ XDestroyImage(image); @@ -103,9 +99,8 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id) dib = CreateDIBSection(screen, &bi, DIB_RGB_COLORS, &data, NULL, 0); /* Copy the data into a bitmap struct. */ - if ((screenMem = CreateCompatibleDC(screen)) == NULL || - SelectObject(screenMem, dib) == NULL || - !BitBlt(screenMem, (int)0, (int)0, (int)rect.size.w, (int)rect.size.h, + if ((screenMem = CreateCompatibleDC(screen)) == NULL || SelectObject(screenMem, dib) == NULL || + !BitBlt(screenMem, (int)0, (int)0, (int)rect.size.w, (int)rect.size.h, screen, rect.origin.x, rect.origin.y, SRCCOPY) ) { @@ -118,7 +113,7 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id) } bitmap = createMMBitmap_c(NULL, rect.size.w, rect.size.h, 4 * rect.size.w, - (uint8_t)bi.bmiHeader.biBitCount, 4); + (uint8_t)bi.bmiHeader.biBitCount, 4); /* Copy the data to our pixel buffer. */ if (bitmap != NULL) { From 70f6c276accb3868bfcd63f0c15dea4f4d5c4e7d Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 26 Jan 2022 10:33:42 -0800 Subject: [PATCH 186/327] remove type_string --- key/goKey.h | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/key/goKey.h b/key/goKey.h index 29dfa310..b1f79c67 100644 --- a/key/goKey.h +++ b/key/goKey.h @@ -172,23 +172,23 @@ int CheckKeyCodes(char* k, MMKeyCode *key){ int CheckKeyFlags(char* f, MMKeyFlags* flags){ if (!flags) { return -1; } - if ( strcmp(f, "alt") == 0 || strcmp(f, "ralt") == 0 || + if (strcmp(f, "alt") == 0 || strcmp(f, "ralt") == 0 || strcmp(f, "lalt") == 0 ) { *flags = MOD_ALT; } - else if( strcmp(f, "command") == 0 || strcmp(f, "cmd") == 0 || + else if(strcmp(f, "command") == 0 || strcmp(f, "cmd") == 0 || strcmp(f, "rcmd") == 0 || strcmp(f, "lcmd") == 0 ) { *flags = MOD_META; } - else if( strcmp(f, "control") == 0 || strcmp(f, "ctrl") == 0 || + else if(strcmp(f, "control") == 0 || strcmp(f, "ctrl") == 0 || strcmp(f, "rctrl") == 0 || strcmp(f, "lctrl") == 0 ) { *flags = MOD_CONTROL; } - else if( strcmp(f, "shift") == 0 || strcmp(f, "right_shift") == 0 || + else if(strcmp(f, "shift") == 0 || strcmp(f, "right_shift") == 0 || strcmp(f, "rshift") == 0 || strcmp(f, "lshift") == 0 ) { *flags = MOD_SHIFT; } - else if( strcmp(f, "none") == 0 ) { + else if(strcmp(f, "none") == 0 ) { *flags = (MMKeyFlags) MOD_NONE; } else { return -2; @@ -332,6 +332,7 @@ char* key_Toggles(char* k, char* keyArr[], int num) { return ""; } +// remove char* key_toggle(char* k, char* d, char* akey, char* keyT){ MMKeyFlags flags = (MMKeyFlags) MOD_NONE; MMKeyCode key; @@ -390,13 +391,6 @@ char* key_toggle(char* k, char* d, char* akey, char* keyT){ return ""; } -void type_string(char *str){ - typeStringDelayed(str, 0); -} - -void type_string_delayed(char *str, size_t cpm){ - typeStringDelayed(str, cpm); -} void set_keyboard_delay(size_t val){ keyboardDelay = val; From 5c0f1d340b3e7309b4024f080957204402eb98ab Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 26 Jan 2022 10:46:02 -0800 Subject: [PATCH 187/327] fixed x11 error --- key/keypress_c.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/key/keypress_c.h b/key/keypress_c.h index ecd8234d..e9e0d9fe 100644 --- a/key/keypress_c.h +++ b/key/keypress_c.h @@ -18,7 +18,7 @@ (win32KeyEvent(key, flags), Sleep(DEADBEEF_RANDRANGE(0, 1))) #elif defined(USE_X11) #define X_KEY_EVENT(display, key, is_press) ( \ - XTestFakeKeyEvent(display, XKeysymToKeycode(display, key), is_press, CurrentTime), + XTestFakeKeyEvent(display, XKeysymToKeycode(display, key), is_press, CurrentTime), \ XSync(display, false)) #define X_KEY_EVENT_WAIT(display, key, is_press) ( \ X_KEY_EVENT(display, key, is_press), microsleep(DEADBEEF_UNIFORM(0.0, 0.5))) @@ -36,7 +36,7 @@ static io_connect_t _getAuxiliaryKeyDriver(void) { kr = IOServiceGetMatchingServices(masterPort, IOServiceMatching(kIOHIDSystemClass), &iter); assert(KERN_SUCCESS == kr); - service = IOIteratorNext( iter ); + service = IOIteratorNext(iter); assert(service); kr = IOServiceOpen(service, mach_task_self(), kIOHIDParamConnectType, &sEventDrvrRef); @@ -116,7 +116,7 @@ void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags) { /* The media keys all have 1000 added to them to help us detect them. */ if (code >= 1000) { code = code - 1000; /* Get the real keycode. */ - NXEventData event; + NXEventData event; kern_return_t kr; IOGPoint loc = { 0, 0 }; @@ -128,7 +128,7 @@ void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags) { kr = IOHIDPostEvent(_getAuxiliaryKeyDriver(), NX_SYSDEFINED, loc, &event, kNXEventDataVersion, 0, FALSE); - assert( KERN_SUCCESS == kr ); + assert(KERN_SUCCESS == kr); } else { CGEventRef keyEvent = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)code, down); assert(keyEvent != NULL); From cd7ed72bf247ff88e7661a73b421483067ddac84 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 27 Jan 2022 10:08:44 -0800 Subject: [PATCH 188/327] Add more test code and Update README.md --- README.md | 7 ++++--- robotgo_test.go | 21 +++++++++++++++++++-- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 1b6cecbb..7e03083e 100644 --- a/README.md +++ b/README.md @@ -312,6 +312,7 @@ import ( "github.com/go-vgo/robotgo" "github.com/vcaesar/gcv" + "github.com/vcaesar/bitmap" ) func main() { @@ -328,10 +329,10 @@ func opencv() { fmt.Println(gcv.FindImgFile(name1, name)) fmt.Println(gcv.FindAllImgFile(name1, name)) - bit := robotgo.OpenBitmap(name1) - defer robotgo.FindBitmap(bit) + bit := bitmap.Open(name1) + defer robotgo.FreeBitmap(bit) fmt.Print("find bitmap: ") - fmt.Println(robotgo.FindBitmap(bit)) + fmt.Println(bitmap.Find(bit)) // bit0 := robotgo.CaptureScreen() // img := robotgo.ToImage(bit0) diff --git a/robotgo_test.go b/robotgo_test.go index 142e8aca..4f882a22 100644 --- a/robotgo_test.go +++ b/robotgo_test.go @@ -59,7 +59,7 @@ func TestMoveMouseSmooth(t *testing.T) { } func TestDragMouse(t *testing.T) { - DragMouse(500, 500) + DragSmooth(500, 500) MilliSleep(50) x, y := GetMousePos() @@ -151,6 +151,23 @@ func TestKeyCode(t *testing.T) { tt.Equal(t, "=", s) } +func TestImage(t *testing.T) { + bit := CaptureScreen() + defer FreeBitmap(bit) + tt.NotNil(t, bit) + + img := ToImage(bit) + err := SavePng(img, "robot_test.png") + tt.Nil(t, err) + + img1 := CaptureImg(10, 10, 20, 20) + e := Save(img1, "robot_img.jpeg", 50) + tt.Nil(t, e) + + tt.Equal(t, 20, Width(img1)) + tt.Equal(t, 20, Height(img1)) +} + func TestPs(t *testing.T) { id, err := Pids() tt.Not(t, "[]", id) @@ -192,6 +209,6 @@ func TestPs(t *testing.T) { // log.Println("tap...") // }() -// i := ShowAlert("t", "msg") +// i := Alert("t", "msg") // tt.Zero(t, i) // } From 149d0f83071b01d1e88e73f0f74e2c1c74525289 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Fri, 28 Jan 2022 12:35:05 -0800 Subject: [PATCH 189/327] Refactor error return to clear type, fixed some sleep --- examples/key/main.go | 4 ++-- robotgo.go | 54 ++++++++++++++++++++++++++++---------------- robotgo_test.go | 14 ++++++------ 3 files changed, 43 insertions(+), 29 deletions(-) diff --git a/examples/key/main.go b/examples/key/main.go index d4aa8b3f..c2828912 100644 --- a/examples/key/main.go +++ b/examples/key/main.go @@ -45,7 +45,7 @@ func keyTap() { // hide window err := robotgo.KeyTap("h", "cmd") - if err != "" { + if err != nil { fmt.Println("robotgo.KeyTap run error is: ", err) } @@ -82,7 +82,7 @@ func keyToggle() { robotgo.KeyToggle("q", "up", "alt", "cmd", "shift") err := robotgo.KeyToggle("enter", "down") - if err != "" { + if err != nil { fmt.Println("robotgo.KeyToggle run error is: ", err) } } diff --git a/robotgo.go b/robotgo.go index ea02289b..8e7c830d 100644 --- a/robotgo.go +++ b/robotgo.go @@ -48,7 +48,7 @@ package robotgo import "C" import ( - "fmt" + "errors" "image" // "os" @@ -697,7 +697,7 @@ func MovesClick(x, y int, args ...interface{}) { // Examples: // robotgo.Toggle("left") // default is down // robotgo.Toggle("left", "up") -func Toggle(key ...string) int { +func Toggle(key ...string) error { var button C.MMMouseButton = C.LEFT_BUTTON if len(key) > 0 { button = CheckMouse(key[0]) @@ -710,7 +710,10 @@ func Toggle(key ...string) int { i := C.mouse_toggle(down, button) C.free(unsafe.Pointer(down)) MilliSleep(MouseSleep) - return int(i) + if int(i) == 0 { + return nil + } + return errors.New("Undefined params.") } // Deprecated: use the Toggle(), @@ -830,6 +833,14 @@ func SetMouseDelay(delay int) { */ +func toErr(str *C.char) error { + gstr := C.GoString(str) + if gstr == "" { + return nil + } + return errors.New(gstr) +} + // KeyTap tap the keyboard code; // // See keys: @@ -843,7 +854,7 @@ func SetMouseDelay(delay int) { // arr := []string{"alt", "command"} // robotgo.KeyTap("i", arr) // -func KeyTap(tapKey string, args ...interface{}) string { +func KeyTap(tapKey string, args ...interface{}) error { var ( akey string keyT = "null" @@ -876,7 +887,7 @@ func KeyTap(tapKey string, args ...interface{}) string { str := C.key_Taps(zkey, (**C.char)(unsafe.Pointer(&ckeyArr[0])), C.int(num), 0) MilliSleep(KeySleep) - return C.GoString(str) + return toErr(str) } // key delay @@ -917,7 +928,7 @@ func KeyTap(tapKey string, args ...interface{}) string { C.int(num), C.int(keyDelay)) MilliSleep(KeySleep) - return C.GoString(str) + return toErr(str) } amod := C.CString(akey) @@ -928,7 +939,7 @@ func KeyTap(tapKey string, args ...interface{}) string { C.free(unsafe.Pointer(amodt)) MilliSleep(KeySleep) - return C.GoString(str) + return toErr(str) } // KeyToggle toggle the keyboard, if there not have args default is "down" @@ -942,7 +953,7 @@ func KeyTap(tapKey string, args ...interface{}) string { // // robotgo.KeyToggle("a", "up", "alt", "cmd") // -func KeyToggle(key string, args ...string) string { +func KeyToggle(key string, args ...string) error { if len(args) <= 0 { args = append(args, "down") } @@ -966,7 +977,7 @@ func KeyToggle(key string, args ...string) string { str := C.key_Toggles(ckey, (**C.char)(unsafe.Pointer(&ckeyArr[0])), C.int(num)) MilliSleep(KeySleep) - return C.GoString(str) + return toErr(str) } // use key_toggle() @@ -998,24 +1009,27 @@ func KeyToggle(key string, args ...string) string { C.free(unsafe.Pointer(cmKeyT)) MilliSleep(KeySleep) - return C.GoString(str) + return toErr(str) } // KeyPress press key string -func KeyPress(key string) { - KeyDown(key) - Sleep(1 + rand.Intn(3)) - KeyUp(key) +func KeyPress(key string) error { + err := KeyDown(key) + if err != nil { + return err + } + MilliSleep(1 + rand.Intn(3)) + return KeyUp(key) } // KeyDown press down a key -func KeyDown(key string) { - KeyToggle(key, "down") +func KeyDown(key string) error { + return KeyToggle(key) } // KeyUp press up a key -func KeyUp(key string) { - KeyToggle(key, "up") +func KeyUp(key string) error { + return KeyToggle(key, "up") } // ReadAll read string from clipboard @@ -1123,10 +1137,10 @@ func TypeStr(str string, args ...float64) { // PasteStr paste a string, support UTF-8, // write the string to clipboard and tap `cmd + v` -func PasteStr(str string) string { +func PasteStr(str string) error { err := clipboard.WriteAll(str) if err != nil { - return fmt.Sprint(err) + return err } if runtime.GOOS == "darwin" { diff --git a/robotgo_test.go b/robotgo_test.go index 4f882a22..d70649f7 100644 --- a/robotgo_test.go +++ b/robotgo_test.go @@ -102,21 +102,21 @@ func TestMoveSmoothRelative(t *testing.T) { func TestMouseToggle(t *testing.T) { e := Toggle("right") - tt.Zero(t, e) + tt.Nil(t, e) e = Toggle("right", "up") - tt.Zero(t, e) + tt.Nil(t, e) } func TestKey(t *testing.T) { e := KeyTap("v", "cmd") - tt.Empty(t, e) + tt.Nil(t, e) e = KeyTap("enter") - tt.Empty(t, e) + tt.Nil(t, e) e = KeyToggle("v", "up") - tt.Empty(t, e) + tt.Nil(t, e) } func TestClip(t *testing.T) { @@ -133,7 +133,7 @@ func TestTypeStr(t *testing.T) { tt.Equal(t, 115, c) e := PasteStr("s") - tt.Empty(t, e) + tt.Nil(t, e) s1 := "abc\\\\cd/s@世界" uc := ToUC(s1) @@ -210,5 +210,5 @@ func TestPs(t *testing.T) { // }() // i := Alert("t", "msg") -// tt.Zero(t, i) +// tt.True(t, i) // } From ed45411f5c596f7ad3af65b095fbca88cef47074 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 31 Jan 2022 17:25:23 -0800 Subject: [PATCH 190/327] Update godoc --- doc.go | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 doc.go diff --git a/doc.go b/doc.go new file mode 100644 index 00000000..d668b874 --- /dev/null +++ b/doc.go @@ -0,0 +1,119 @@ +// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// https://github.com/go-vgo/robotgo/blob/master/LICENSE +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +package robotgo + +/* +Keys are supported: + "A-Z a-z 0-9" + + "backspace" + "delete" + "enter" + "tab" + "esc" + "escape" + "up" Up arrow key + "down" Down arrow key + "right" Right arrow key + "left" Left arrow key + "home" + "end" + "pageup" + "pagedown" + + "f1" + "f2" + "f3" + "f4" + "f5" + "f6" + "f7" + "f8" + "f9" + "f10" + "f11" + "f12" + "f13" + "f14" + "f15" + "f16" + "f17" + "f18" + "f19" + "f20" + "f21" + "f22" + "f23" + "f24" + + "cmd" is the "win" key for windows + "lcmd" left command + "rcmd" right command + // "command" + "alt" + "lalt" left alt + "ralt" right alt + "ctrl" + "lctrl" left ctrl + "rctrl" right ctrl + "control" + "shift" + "lshift" left shift + "rshift" right shift + // "right_shift" + "capslock" + "space" + "print" + "printscreen" // No Mac support + "insert" + "menu" Windows only + + "audio_mute" Mute the volume + "audio_vol_down" Lower the volume + "audio_vol_up" Increase the volume + "audio_play" + "audio_stop" + "audio_pause" + "audio_prev" Previous Track + "audio_next" Next Track + "audio_rewind" Linux only + "audio_forward" Linux only + "audio_repeat" Linux only + "audio_random" Linux only + + + "num0" + "num1" + "num2" + "num3" + "num4" + "num5" + "num6" + "num7" + "num8" + "num9" + "num_lock" + + "num." + "num+" + "num-" + "num*" + "num/" + "num_clear" + "num_enter" + "num_equal" + + "lights_mon_up" Turn up monitor brightness No Windows support + "lights_mon_down" Turn down monitor brightness No Windows support + "lights_kbd_toggle" Toggle keyboard backlight on/off No Windows support + "lights_kbd_up" Turn up keyboard backlight brightness No Windows support + "lights_kbd_down" Turn down keyboard backlight brightness No Windows support +*/ From 99963bc6fc4a942bfb0b614da356c75156eb4993 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 31 Jan 2022 23:12:24 -0800 Subject: [PATCH 191/327] Refactor some keyboard C code to go --- examples/key/main.go | 6 +- key.go | 672 +++++++++++++++++++++++++++++++++++++++++++ key/goKey.h | 392 +------------------------ key/keycode.h | 68 +++++ key/keycode_c.h | 110 +------ keycode.go | 11 + robotgo.go | 399 +------------------------ 7 files changed, 768 insertions(+), 890 deletions(-) create mode 100644 key.go diff --git a/examples/key/main.go b/examples/key/main.go index c2828912..142ae340 100644 --- a/examples/key/main.go +++ b/examples/key/main.go @@ -49,15 +49,15 @@ func keyTap() { fmt.Println("robotgo.KeyTap run error is: ", err) } - robotgo.KeyTap("h", "cmd", 12) + robotgo.KeyTap("h", "cmd") // press "i", "alt", "command" Key combination robotgo.KeyTap("i", "alt", "command") - robotgo.KeyTap("i", "alt", "cmd", 11) + robotgo.KeyTap("i", "alt", "cmd") arr := []string{"alt", "cmd"} robotgo.KeyTap("i", arr) - robotgo.KeyTap("i", arr, 12) + robotgo.KeyTap("i", arr) robotgo.KeyTap("i", "cmd", " alt", "shift") diff --git a/key.go b/key.go new file mode 100644 index 00000000..2c7dd955 --- /dev/null +++ b/key.go @@ -0,0 +1,672 @@ +// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// https://github.com/go-vgo/robotgo/blob/master/LICENSE +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +package robotgo + +/* +// #include "key/keycode.h" +#include "key/goKey.h" +*/ +import "C" + +import ( + "errors" + "math/rand" + "reflect" + "runtime" + "strconv" + "strings" + "unsafe" + + "github.com/go-vgo/robotgo/clipboard" + "github.com/vcaesar/tt" +) + +const ( + // KeyA define key "a" + KeyA = "a" + KeyB = "b" + KeyC = "c" + KeyD = "d" + KeyE = "e" + KeyF = "f" + KeyG = "g" + KeyH = "h" + KeyI = "i" + KeyJ = "j" + KeyK = "k" + KeyL = "l" + KeyM = "m" + KeyN = "n" + KeyO = "o" + KeyP = "p" + KeyQ = "q" + KeyR = "r" + KeyS = "s" + KeyT = "t" + KeyU = "u" + KeyV = "v" + KeyW = "w" + KeyX = "x" + KeyY = "y" + KeyZ = "z" + // + Key0 = "0" + Key1 = "1" + Key2 = "2" + Key3 = "3" + Key4 = "4" + Key5 = "5" + Key6 = "6" + Key7 = "7" + Key8 = "8" + Key9 = "9" + + // Backspace backspace key string + Backspace = "backspace" + Delete = "delete" + Enter = "enter" + Tab = "tab" + Esc = "esc" + Escape = "escape" + Up = "up" // Up arrow key + Down = "down" // Down arrow key + Right = "right" // Right arrow key + Left = "left" // Left arrow key + Home = "home" + End = "end" + Pageup = "pageup" + Pagedown = "pagedown" + + F1 = "f1" + F2 = "f2" + F3 = "f3" + F4 = "f4" + F5 = "f5" + F6 = "f6" + F7 = "f7" + F8 = "f8" + F9 = "f9" + F10 = "f10" + F11 = "f11" + F12 = "f12" + F13 = "f13" + F14 = "f14" + F15 = "f15" + F16 = "f16" + F17 = "f17" + F18 = "f18" + F19 = "f19" + F20 = "f20" + F21 = "f21" + F22 = "f22" + F23 = "f23" + F24 = "f24" + + Cmd = "cmd" // is the "win" key for windows + Lcmd = "lcmd" // left command + Rcmd = "rcmd" // right command + // "command" + Alt = "alt" + Lalt = "lalt" // left alt + Ralt = "ralt" // right alt + Ctrl = "ctrl" + Lctrl = "lctrl" // left ctrl + Rctrl = "rctrl" // right ctrl + Control = "control" + Shift = "shift" + Lshift = "lshift" // left shift + Rshift = "rshift" // right shift + // "right_shift" + Capslock = "capslock" + Space = "space" + Print = "print" + Printscreen = "printscreen" // No Mac support + Insert = "insert" + Menu = "menu" // Windows only + + AudioMute = "audio_mute" // Mute the volume + AudioVolDown = "audio_vol_down" // Lower the volume + AudioVolUp = "audio_vol_up" // Increase the volume + AudioPlay = "audio_play" + AudioStop = "audio_stop" + AudioPause = "audio_pause" + AudioPrev = "audio_prev" // Previous Track + AudioNext = "audio_next" // Next Track + AudioRewind = "audio_rewind" // Linux only + AudioForward = "audio_forward" // Linux only + AudioRepeat = "audio_repeat" // Linux only + AudioRandom = "audio_random" // Linux only + + Num0 = "num0" // numpad 0 + Num1 = "num1" + Num2 = "num2" + Num3 = "num3" + Num4 = "num4" + Num5 = "num5" + Num6 = "num6" + Num7 = "num7" + Num8 = "num8" + Num9 = "num9" + NumLock = "num_lock" + + NumDecimal = "num." + NumPlus = "num+" + NumMinus = "num-" + NumMul = "num*" + NumDiv = "num/" + NumClear = "num_clear" + NumEnter = "num_enter" + NumEqual = "num_equal" + + LightsMonUp = "lights_mon_up" // Turn up monitor brightness No Windows support + LightsMonDown = "lights_mon_down" // Turn down monitor brightness No Windows support + LightsKbdToggle = "lights_kbd_toggle" // Toggle keyboard backlight on/off No Windows support + LightsKbdUp = "lights_kbd_up" // Turn up keyboard backlight brightness No Windows support + LightsKbdDown = "lights_kbd_down" +) + +// keyNames define MMKeyCode map +var keyNames = map[string]C.MMKeyCode{ + "backspace": C.K_BACKSPACE, + "delete": C.K_DELETE, + "enter": C.K_RETURN, + "tab": C.K_TAB, + "esc": C.K_ESCAPE, + "escape": C.K_ESCAPE, + "up": C.K_UP, + "down": C.K_DOWN, + "right": C.K_RIGHT, + "left": C.K_LEFT, + "home": C.K_HOME, + "end": C.K_END, + "pageup": C.K_PAGEUP, + "pagedown": C.K_PAGEDOWN, + // + "f1": C.K_F1, + "f2": C.K_F2, + "f3": C.K_F3, + "f4": C.K_F4, + "f5": C.K_F5, + "f6": C.K_F6, + "f7": C.K_F7, + "f8": C.K_F8, + "f9": C.K_F9, + "f10": C.K_F10, + "f11": C.K_F11, + "f12": C.K_F12, + "f13": C.K_F13, + "f14": C.K_F14, + "f15": C.K_F15, + "f16": C.K_F16, + "f17": C.K_F17, + "f18": C.K_F18, + "f19": C.K_F19, + "f20": C.K_F20, + "f21": C.K_F21, + "f22": C.K_F22, + "f23": C.K_F23, + "f24": C.K_F24, + // + "cmd": C.K_META, + "lcmd": C.K_LMETA, + "rcmd": C.K_RMETA, + "command": C.K_META, + "alt": C.K_ALT, + "lalt": C.K_LALT, + "ralt": C.K_RALT, + "ctrl": C.K_CONTROL, + "lctrl": C.K_LCONTROL, + "rctrl": C.K_RCONTROL, + "control": C.K_CONTROL, + "shift": C.K_SHIFT, + "lshift": C.K_LSHIFT, + "rshift": C.K_RSHIFT, + "right_shift": C.K_RSHIFT, + "capslock": C.K_CAPSLOCK, + "space": C.K_SPACE, + "print": C.K_PRINTSCREEN, + "printscreen": C.K_PRINTSCREEN, + "insert": C.K_INSERT, + "menu": C.K_MENU, + + "audio_mute": C.K_AUDIO_VOLUME_MUTE, + "audio_vol_down": C.K_AUDIO_VOLUME_DOWN, + "audio_vol_up": C.K_AUDIO_VOLUME_UP, + "audio_play": C.K_AUDIO_PLAY, + "audio_stop": C.K_AUDIO_STOP, + "audio_pause": C.K_AUDIO_PAUSE, + "audio_prev": C.K_AUDIO_PREV, + "audio_next": C.K_AUDIO_NEXT, + "audio_rewind": C.K_AUDIO_REWIND, + "audio_forward": C.K_AUDIO_FORWARD, + "audio_repeat": C.K_AUDIO_REPEAT, + "audio_random": C.K_AUDIO_RANDOM, + + "num0": C.K_NUMPAD_0, + "num1": C.K_NUMPAD_1, + "num2": C.K_NUMPAD_2, + "num3": C.K_NUMPAD_3, + "num4": C.K_NUMPAD_4, + "num5": C.K_NUMPAD_5, + "num6": C.K_NUMPAD_6, + "num7": C.K_NUMPAD_7, + "num8": C.K_NUMPAD_8, + "num9": C.K_NUMPAD_9, + "num_lock": C.K_NUMPAD_LOCK, + + // todo: removed + "numpad_0": C.K_NUMPAD_0, + "numpad_1": C.K_NUMPAD_1, + "numpad_2": C.K_NUMPAD_2, + "numpad_3": C.K_NUMPAD_3, + "numpad_4": C.K_NUMPAD_4, + "numpad_5": C.K_NUMPAD_5, + "numpad_6": C.K_NUMPAD_6, + "numpad_7": C.K_NUMPAD_7, + "numpad_8": C.K_NUMPAD_8, + "numpad_9": C.K_NUMPAD_9, + "numpad_lock": C.K_NUMPAD_LOCK, + + "num.": C.K_NUMPAD_DECIMAL, + "num+": C.K_NUMPAD_PLUS, + "num-": C.K_NUMPAD_MINUS, + "num*": C.K_NUMPAD_MUL, + "num/": C.K_NUMPAD_DIV, + "num_clear": C.K_NUMPAD_CLEAR, + "num_enter": C.K_NUMPAD_ENTER, + "num_equal": C.K_NUMPAD_EQUAL, + + "lights_mon_up": C.K_LIGHTS_MON_UP, + "lights_mon_down": C.K_LIGHTS_MON_DOWN, + "lights_kbd_toggle": C.K_LIGHTS_KBD_TOGGLE, + "lights_kbd_up": C.K_LIGHTS_KBD_UP, + "lights_kbd_down": C.K_LIGHTS_KBD_DOWN, + + // { NULL: C.K_NOT_A_KEY } +} + +func tapKeyCode(code C.MMKeyCode, flags C.MMKeyFlags) { + C.toggleKeyCode(code, true, flags) + MilliSleep(5) + C.toggleKeyCode(code, false, flags) +} + +var keyErr = errors.New("Invalid key flag specified.") + +func checkKeyCodes(k string) (key C.MMKeyCode, err error) { + if k == "" { + return + } + + if len(k) == 1 { + val := C.CString(k) + key = C.keyCodeForChar(*val) + C.free(unsafe.Pointer(val)) + if key == C.K_NOT_A_KEY { + err = keyErr + return + } + return + } + + if v, ok := keyNames[k]; ok { + key = v + if key == C.K_NOT_A_KEY { + err = keyErr + return + } + } + return +} + +func checkKeyFlags(f string) (flags C.MMKeyFlags) { + m := map[string]C.MMKeyFlags{ + "alt": C.MOD_ALT, + "ralt": C.MOD_ALT, + "lalt": C.MOD_ALT, + "cmd": C.MOD_META, + "rcmd": C.MOD_META, + "lcmd": C.MOD_META, + "ctrl": C.MOD_CONTROL, + "rctrl": C.MOD_CONTROL, + "lctrl": C.MOD_CONTROL, + "shift": C.MOD_SHIFT, + "rshift": C.MOD_SHIFT, + "lshift": C.MOD_SHIFT, + "none": C.MOD_NONE, + } + + if v, ok := m[f]; ok { + return v + } + return +} + +func getFlagsFromValue(value []string) (flags C.MMKeyFlags) { + if len(value) <= 0 { + return + } + + for i := 0; i < len(value); i++ { + var f C.MMKeyFlags = C.MOD_NONE + + f = checkKeyFlags(value[i]) + flags = (C.MMKeyFlags)(flags | f) + } + + return +} + +func keyTaps(k string, keyArr []string) error { + flags := getFlagsFromValue(keyArr) + key, err := checkKeyCodes(k) + if err != nil { + return err + } + + tapKeyCode(key, flags) + MilliSleep(KeySleep) + return nil +} + +func keyToggles(k string, keyArr []string) error { + down := false + if keyArr[0] == "down" { + down = true + } + + flags := getFlagsFromValue(keyArr) + key, err := checkKeyCodes(k) + if err != nil { + return err + } + + C.toggleKeyCode(key, C.bool(down), flags) + MilliSleep(KeySleep) + return nil +} + +/* + __ ___ ___________ ____ .______ ______ ___ .______ _______ +| |/ / | ____\ \ / / | _ \ / __ \ / \ | _ \ | \ +| ' / | |__ \ \/ / | |_) | | | | | / ^ \ | |_) | | .--. | +| < | __| \_ _/ | _ < | | | | / /_\ \ | / | | | | +| . \ | |____ | | | |_) | | `--' | / _____ \ | |\ \----.| '--' | +|__|\__\ |_______| |__| |______/ \______/ /__/ \__\ | _| `._____||_______/ + +*/ + +// ToInterfaces []string to []interface{} +func ToInterfaces(fields []string) []interface{} { + res := make([]interface{}, 0, len(fields)) + for _, s := range fields { + res = append(res, s) + } + return res +} + +// ToStrings []interface{} to []string +func ToStrings(fields []interface{}) []string { + res := make([]string, 0, len(fields)) + for _, s := range fields { + res = append(res, s.(string)) + } + return res +} + +func toErr(str *C.char) error { + gstr := C.GoString(str) + if gstr == "" { + return nil + } + return errors.New(gstr) +} + +// KeyTap tap the keyboard code; +// +// See keys: +// https://github.com/go-vgo/robotgo/blob/master/docs/keys.md +// +// Examples: +// robotgo.KeySleep = 100 // 100 millisecond +// robotgo.KeyTap("a") +// robotgo.KeyTap("i", "alt", "command") +// +// arr := []string{"alt", "command"} +// robotgo.KeyTap("i", arr) +// +func KeyTap(tapKey string, args ...interface{}) error { + var keyArr []string + + tapKey = strings.ToLower(tapKey) + if _, ok := Special[tapKey]; ok { + tapKey = Special[tapKey] + if len(args) <= 0 { + args = append(args, "shift") + } + } + + if len(args) > 0 { + if reflect.TypeOf(args[0]) == reflect.TypeOf(keyArr) { + keyArr = args[0].([]string) + } else { + keyArr = ToStrings(args) + } + } + + return keyTaps(tapKey, keyArr) +} + +// KeyToggle toggle the keyboard, if there not have args default is "down" +// +// See keys: +// https://github.com/go-vgo/robotgo/blob/master/docs/keys.md +// +// Examples: +// robotgo.KeyToggle("a") +// robotgo.KeyToggle("a", "up") +// +// robotgo.KeyToggle("a", "up", "alt", "cmd") +// +func KeyToggle(key string, args ...string) error { + if len(args) <= 0 { + args = append(args, "down") + } + + key = strings.ToLower(key) + if _, ok := Special[key]; ok { + key = Special[key] + if len(args) <= 1 { + args = append(args, "shift") + } + } + + return keyToggles(key, args) +} + +// KeyPress press key string +func KeyPress(key string) error { + err := KeyDown(key) + if err != nil { + return err + } + + MilliSleep(1 + rand.Intn(3)) + return KeyUp(key) +} + +// KeyDown press down a key +func KeyDown(key string) error { + return KeyToggle(key) +} + +// KeyUp press up a key +func KeyUp(key string) error { + return KeyToggle(key, "up") +} + +// ReadAll read string from clipboard +func ReadAll() (string, error) { + return clipboard.ReadAll() +} + +// WriteAll write string to clipboard +func WriteAll(text string) error { + return clipboard.WriteAll(text) +} + +// CharCodeAt char code at utf-8 +func CharCodeAt(s string, n int) rune { + i := 0 + for _, r := range s { + if i == n { + return r + } + i++ + } + + return 0 +} + +// UnicodeType tap uint32 unicode +func UnicodeType(str uint32) { + cstr := C.uint(str) + C.unicodeType(cstr) +} + +// ToUC trans string to unicode []string +func ToUC(text string) []string { + var uc []string + + for _, r := range text { + textQ := strconv.QuoteToASCII(string(r)) + textUnQ := textQ[1 : len(textQ)-1] + + st := strings.Replace(textUnQ, "\\u", "U", -1) + if st == "\\\\" { + st = "\\" + } + if st == `\"` { + st = `"` + } + uc = append(uc, st) + } + + return uc +} + +func inputUTF(str string) { + cstr := C.CString(str) + C.input_utf(cstr) + + C.free(unsafe.Pointer(cstr)) +} + +// TypeStr send a string, support UTF-8 +// +// robotgo.TypeStr(string: The string to send, float64: microsleep time, x11 option) +// +// Examples: +// robotgo.TypeStr("abc@123, hi, こんにちは") +// +func TypeStr(str string, args ...float64) { + var tm, tm1 = 0.0, 7.0 + + if len(args) > 0 { + tm = args[0] + } + if len(args) > 1 { + tm1 = args[1] + } + + if runtime.GOOS == "linux" { + strUc := ToUC(str) + for i := 0; i < len(strUc); i++ { + ru := []rune(strUc[i]) + if len(ru) <= 1 { + ustr := uint32(CharCodeAt(strUc[i], 0)) + UnicodeType(ustr) + } else { + inputUTF(strUc[i]) + MicroSleep(tm1) + } + + MicroSleep(tm) + } + return + } + + for i := 0; i < len([]rune(str)); i++ { + ustr := uint32(CharCodeAt(str, i)) + UnicodeType(ustr) + // if len(args) > 0 { + MicroSleep(tm) + // } + } + MilliSleep(KeySleep) +} + +// PasteStr paste a string, support UTF-8, +// write the string to clipboard and tap `cmd + v` +func PasteStr(str string) error { + err := clipboard.WriteAll(str) + if err != nil { + return err + } + + if runtime.GOOS == "darwin" { + return KeyTap("v", "command") + } + + return KeyTap("v", "control") +} + +// TypeStrDelay type string delayed +func TypeStrDelay(str string, delay int) { + TypeStr(str) + Sleep(delay) +} + +// Deprecated: use the TypeStr(), +// +// TypeStringDelayed type string delayed, Wno-deprecated +// +// This function will be removed in version v1.0.0 +func TypeStringDelayed(str string, delay int) { + tt.Drop("TypeStringDelayed", "TypeStrDelay") + TypeStrDelay(str, delay) +} + +// SetKeyDelay set keyboard delay +func SetKeyDelay(delay int) { + C.set_keyboard_delay(C.size_t(delay)) +} + +// Deprecated: use the SetKeyDelay(), +// +// SetKeyboardDelay set keyboard delay, Wno-deprecated, +// +// This function will be removed in version v1.0.0 +func SetKeyboardDelay(delay int) { + tt.Drop("SetKeyboardDelay", "SetKeyDelay") + SetKeyDelay(delay) +} + +// SetDelay set the key and mouse delay +func SetDelay(d ...int) { + v := 10 + if len(d) > 0 { + v = d[0] + } + + SetMouseDelay(v) + SetKeyDelay(v) +} diff --git a/key/goKey.h b/key/goKey.h index b1f79c67..2c2021c2 100644 --- a/key/goKey.h +++ b/key/goKey.h @@ -1,397 +1,7 @@ -// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// https://github.com/go-vgo/robotgo/blob/master/LICENSE -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. +// Copyright 2016 The go-vgo Project Developers. #include "../base/types.h" // #include "keycode.h" // #include "keypress.h" #include "keypress_c.h" #include "keycode_c.h" - - -int keyboardDelay = 0; - -struct KeyNames{ - const char* name; - MMKeyCode key; -}key_names[] = { - { "backspace", K_BACKSPACE }, - { "delete", K_DELETE }, - { "enter", K_RETURN }, - { "tab", K_TAB }, - { "esc", K_ESCAPE }, - { "escape", K_ESCAPE }, - { "up", K_UP }, - { "down", K_DOWN }, - { "right", K_RIGHT }, - { "left", K_LEFT }, - { "home", K_HOME }, - { "end", K_END }, - { "pageup", K_PAGEUP }, - { "pagedown", K_PAGEDOWN }, - // - { "f1", K_F1 }, - { "f2", K_F2 }, - { "f3", K_F3 }, - { "f4", K_F4 }, - { "f5", K_F5 }, - { "f6", K_F6 }, - { "f7", K_F7 }, - { "f8", K_F8 }, - { "f9", K_F9 }, - { "f10", K_F10 }, - { "f11", K_F11 }, - { "f12", K_F12 }, - { "f13", K_F13 }, - { "f14", K_F14 }, - { "f15", K_F15 }, - { "f16", K_F16 }, - { "f17", K_F17 }, - { "f18", K_F18 }, - { "f19", K_F19 }, - { "f20", K_F20 }, - { "f21", K_F21 }, - { "f22", K_F22 }, - { "f23", K_F23 }, - { "f24", K_F24 }, - // - { "cmd", K_META }, - { "lcmd", K_LMETA }, - { "rcmd", K_RMETA }, - { "command", K_META }, - { "alt", K_ALT }, - { "lalt", K_LALT }, - { "ralt", K_RALT }, - { "ctrl", K_CONTROL }, - { "lctrl", K_LCONTROL }, - { "rctrl", K_RCONTROL }, - { "control", K_CONTROL }, - { "shift", K_SHIFT }, - { "lshift", K_LSHIFT }, - { "rshift", K_RSHIFT }, - { "right_shift", K_RSHIFT }, - { "capslock", K_CAPSLOCK }, - { "space", K_SPACE }, - { "print", K_PRINTSCREEN }, - { "printscreen", K_PRINTSCREEN }, - { "insert", K_INSERT }, - { "menu", K_MENU }, - - { "audio_mute", K_AUDIO_VOLUME_MUTE }, - { "audio_vol_down", K_AUDIO_VOLUME_DOWN }, - { "audio_vol_up", K_AUDIO_VOLUME_UP }, - { "audio_play", K_AUDIO_PLAY }, - { "audio_stop", K_AUDIO_STOP }, - { "audio_pause", K_AUDIO_PAUSE }, - { "audio_prev", K_AUDIO_PREV }, - { "audio_next", K_AUDIO_NEXT }, - { "audio_rewind", K_AUDIO_REWIND }, - { "audio_forward", K_AUDIO_FORWARD }, - { "audio_repeat", K_AUDIO_REPEAT }, - { "audio_random", K_AUDIO_RANDOM }, - - { "num0", K_NUMPAD_0 }, - { "num1", K_NUMPAD_1 }, - { "num2", K_NUMPAD_2 }, - { "num3", K_NUMPAD_3 }, - { "num4", K_NUMPAD_4 }, - { "num5", K_NUMPAD_5 }, - { "num6", K_NUMPAD_6 }, - { "num7", K_NUMPAD_7 }, - { "num8", K_NUMPAD_8 }, - { "num9", K_NUMPAD_9 }, - { "num_lock", K_NUMPAD_LOCK }, - - // todo: removed - { "numpad_0", K_NUMPAD_0 }, - { "numpad_1", K_NUMPAD_1 }, - { "numpad_2", K_NUMPAD_2 }, - { "numpad_3", K_NUMPAD_3 }, - { "numpad_4", K_NUMPAD_4 }, - { "numpad_5", K_NUMPAD_5 }, - { "numpad_6", K_NUMPAD_6 }, - { "numpad_7", K_NUMPAD_7 }, - { "numpad_8", K_NUMPAD_8 }, - { "numpad_9", K_NUMPAD_9 }, - { "numpad_lock", K_NUMPAD_LOCK }, - - {"num.", K_NUMPAD_DECIMAL }, - {"num+", K_NUMPAD_PLUS }, - {"num-", K_NUMPAD_MINUS }, - {"num*", K_NUMPAD_MUL }, - {"num/", K_NUMPAD_DIV }, - {"num_clear", K_NUMPAD_CLEAR }, - {"num_enter", K_NUMPAD_ENTER }, - {"num_equal", K_NUMPAD_EQUAL }, - - { "lights_mon_up", K_LIGHTS_MON_UP }, - { "lights_mon_down", K_LIGHTS_MON_DOWN }, - { "lights_kbd_toggle",K_LIGHTS_KBD_TOGGLE }, - { "lights_kbd_up", K_LIGHTS_KBD_UP }, - { "lights_kbd_down", K_LIGHTS_KBD_DOWN }, - - { NULL, K_NOT_A_KEY } /* end marker */ -}; - -int CheckKeyCodes(char* k, MMKeyCode *key){ - if (!key) { return -1; } - - if (strlen(k) == 1) { - *key = keyCodeForChar(*k); - if (*key == K_NOT_A_KEY) { - return -2; - } - - return 0; - } - - *key = K_NOT_A_KEY; - - struct KeyNames* kn = key_names; - while (kn->name) { - if (strcmp(k, kn->name) == 0){ - *key = kn->key; - break; - } - kn++; - } - - if (*key == K_NOT_A_KEY) { - return -2; - } - - return 0; -} - -int CheckKeyFlags(char* f, MMKeyFlags* flags){ - if (!flags) { return -1; } - - if (strcmp(f, "alt") == 0 || strcmp(f, "ralt") == 0 || - strcmp(f, "lalt") == 0 ) { - *flags = MOD_ALT; - } - else if(strcmp(f, "command") == 0 || strcmp(f, "cmd") == 0 || - strcmp(f, "rcmd") == 0 || strcmp(f, "lcmd") == 0 ) { - *flags = MOD_META; - } - else if(strcmp(f, "control") == 0 || strcmp(f, "ctrl") == 0 || - strcmp(f, "rctrl") == 0 || strcmp(f, "lctrl") == 0 ) { - *flags = MOD_CONTROL; - } - else if(strcmp(f, "shift") == 0 || strcmp(f, "right_shift") == 0 || - strcmp(f, "rshift") == 0 || strcmp(f, "lshift") == 0 ) { - *flags = MOD_SHIFT; - } - else if(strcmp(f, "none") == 0 ) { - *flags = (MMKeyFlags) MOD_NONE; - } else { - return -2; - } - - return 0; -} - -int GetFlagsFromValue(char* value[], MMKeyFlags* flags, int num){ - if (!flags) {return -1;} - - int i; - for ( i= 0; i ', XK_greater}, + {'=', XK_equal}, + {'@', XK_at}, + {':', XK_colon}, + {';', XK_semicolon}, + {'{', XK_braceleft}, + {'}', XK_braceright}, + {'|', XK_bar}, + {'^', XK_asciicircum}, + {'(', XK_parenleft}, + {')', XK_parenright}, + {' ', XK_space}, + {'/', XK_slash}, + {'\\', XK_backslash}, + {'`', XK_grave}, + {'"', XK_quoteright}, + {'\'', XK_quotedbl}, + {'\t', XK_Tab}, + {'\n', XK_Return} +}; + #elif defined(IS_WINDOWS) enum _MMKeyCode { @@ -308,6 +369,13 @@ enum _MMKeyCode { K_NUMPAD_CLEAR = K_NOT_A_KEY, K_NUMPAD_ENTER = VK_RETURN, K_NUMPAD_EQUAL = VK_OEM_PLUS, + K_NUMPAD_LB = VK_OEM_4, + K_NUMPAD_RB = VK_OEM_6, + K_Backslash = VK_OEM_5, + K_Semicolon = VK_OEM_1, + K_Quote = VK_OEM_7, + K_Slash = VK_OEM_2, + K_Grave = VK_OEM_3, K_AUDIO_VOLUME_MUTE = VK_VOLUME_MUTE, K_AUDIO_VOLUME_DOWN = VK_VOLUME_DOWN, diff --git a/key/keycode_c.h b/key/keycode_c.h index 97c5a50d..6336ae79 100644 --- a/key/keycode_c.h +++ b/key/keycode_c.h @@ -8,61 +8,9 @@ * Ownership follows the Create Rule; that is, it is the caller's * responsibility to release the returned object. */ CFStringRef createStringForKey(CGKeyCode keyCode); - - MMKeyCode keyCodeForCharFallBack(const char c); -#elif defined(USE_X11) -/* - * Structs to store key mappings not handled by XStringToKeysym() on some - * Linux systems. - */ - -struct XSpecialCharacterMapping { - char name; - MMKeyCode code; -}; - -struct XSpecialCharacterMapping XSpecialCharacterTable[] = { - {'~', XK_asciitilde}, - {'_', XK_underscore}, - {'[', XK_bracketleft}, - {']', XK_bracketright}, - {'!', XK_exclam}, - {'#', XK_numbersign}, - {'$', XK_dollar}, - {'%', XK_percent}, - {'&', XK_ampersand}, - {'*', XK_asterisk}, - {'+', XK_plus}, - {',', XK_comma}, - {'-', XK_minus}, - {'.', XK_period}, - {'?', XK_question}, - {'<', XK_less}, - {'>', XK_greater}, - {'=', XK_equal}, - {'@', XK_at}, - {':', XK_colon}, - {';', XK_semicolon}, - {'{', XK_braceleft}, - {'}', XK_braceright}, - {'|', XK_bar}, - {'^', XK_asciicircum}, - {'(', XK_parenleft}, - {')', XK_parenright}, - {' ', XK_space}, - {'/', XK_slash}, - {'\\', XK_backslash}, - {'`', XK_grave}, - {'"', XK_quoteright}, - {'\'', XK_quotedbl}, - // {'\'', XK_quoteright}, - {'\t', XK_Tab}, - {'\n', XK_Return} -}; - #endif -MMKeyCode keyCodeForChar(const char c){ +MMKeyCode keyCodeForChar(const char c) { #if defined(IS_MACOSX) /* OS X does not appear to have a built-in function for this, so instead we * have to write our own. */ @@ -89,20 +37,13 @@ MMKeyCode keyCodeForChar(const char c){ } charStr = CFStringCreateWithCharacters(kCFAllocatorDefault, &character, 1); - /* Our values may be NULL (0), so we need to use this function. */ - if (!CFDictionaryGetValueIfPresent(charToCodeDict, charStr, - (const void **)&code)) { + if (!CFDictionaryGetValueIfPresent(charToCodeDict, charStr, (const void **)&code)) { code = UINT16_MAX; /* Error */ } - CFRelease(charStr); // TISGetInputSourceProperty may return nil so we need fallback - if (code == UINT16_MAX) { - code = keyCodeForCharFallBack(c); - } - if (code == UINT16_MAX) { return K_NOT_A_KEY; } @@ -142,7 +83,6 @@ MMKeyCode keyCodeForChar(const char c){ if (code == NoSymbol) { return K_NOT_A_KEY; } - return code; #endif } @@ -167,50 +107,4 @@ CFStringRef createStringForKey(CGKeyCode keyCode){ return CFStringCreateWithCharacters(kCFAllocatorDefault, chars, 1); } - -MMKeyCode keyCodeForCharFallBack(const char c) { - switch (c) { - case 'A': return kVK_ANSI_A; - case 'B': return kVK_ANSI_B; - case 'C': return kVK_ANSI_C; - case 'D': return kVK_ANSI_D; - case 'E': return kVK_ANSI_E; - case 'F': return kVK_ANSI_F; - case 'G': return kVK_ANSI_G; - case 'H': return kVK_ANSI_H; - case 'I': return kVK_ANSI_I; - case 'J': return kVK_ANSI_J; - case 'K': return kVK_ANSI_K; - case 'L': return kVK_ANSI_L; - case 'M': return kVK_ANSI_M; - case 'N': return kVK_ANSI_N; - case 'O': return kVK_ANSI_O; - case 'P': return kVK_ANSI_P; - case 'Q': return kVK_ANSI_Q; - case 'R': return kVK_ANSI_R; - case 'S': return kVK_ANSI_S; - case 'T': return kVK_ANSI_T; - case 'U': return kVK_ANSI_U; - case 'V': return kVK_ANSI_V; - case 'W': return kVK_ANSI_W; - case 'X': return kVK_ANSI_X; - case 'Y': return kVK_ANSI_Y; - case 'Z': return kVK_ANSI_Z; - - - case '0': return kVK_ANSI_0; - case '1': return kVK_ANSI_1; - case '2': return kVK_ANSI_2; - case '3': return kVK_ANSI_3; - case '4': return kVK_ANSI_4; - case '5': return kVK_ANSI_5; - case '6': return kVK_ANSI_6; - case '7': return kVK_ANSI_7; - case '8': return kVK_ANSI_8; - case '9': return kVK_ANSI_9; - } - - return K_NOT_A_KEY; -} - #endif diff --git a/keycode.go b/keycode.go index bd4108fc..4b9e9348 100644 --- a/keycode.go +++ b/keycode.go @@ -19,6 +19,17 @@ type uMap map[string]uint16 // MouseMap robotgo hook mouse's code map var MouseMap = keycode.MouseMap +const ( + // Mleft mouse left button + Mleft = "left" + Mright = "right" + Center = "center" + WheelDown = "wheelDown" + WheelUp = "wheelUp" + WheelLeft = "wheelLeft" + WheelRight = "wheelRight" +) + // Keycode robotgo hook key's code map var Keycode = keycode.Keycode diff --git a/robotgo.go b/robotgo.go index 8e7c830d..6f178661 100644 --- a/robotgo.go +++ b/robotgo.go @@ -33,16 +33,12 @@ package robotgo #cgo darwin LDFLAGS: -framework Carbon -framework CoreFoundation #cgo linux CFLAGS: -I/usr/src -#cgo linux LDFLAGS: -L/usr/src -lX11 -lXtst -lm -// #cgo linux LDFLAGS: -lX11-xcb -lxcb -lxcb-xkb -lxkbcommon -lxkbcommon-x11 +#cgo linux LDFLAGS: -L/usr/src -lm -lX11 -lXtst -// #cgo windows LDFLAGS: -lgdi32 -luser32 -lpng -lz #cgo windows LDFLAGS: -lgdi32 -luser32 // -// #include #include "screen/goScreen.h" #include "mouse/goMouse.h" -#include "key/goKey.h" #include "window/goWindow.h" */ import "C" @@ -50,19 +46,10 @@ import "C" import ( "errors" "image" - - // "os" - "reflect" "runtime" - "strconv" - "strings" "time" "unsafe" - // "syscall" - "math/rand" - - "github.com/go-vgo/robotgo/clipboard" "github.com/vcaesar/tt" ) @@ -142,7 +129,7 @@ func Sleep(tm int) { time.Sleep(time.Duration(tm) * time.Second) } -// MicroSleep time C.microsleep(tm) +// MicroSleep time C.microsleep(tm), use the MilliSleep func MicroSleep(tm float64) { C.microsleep(C.double(tm)) } @@ -351,6 +338,13 @@ func FreeBitmap(bitmap CBitmap) { C.bitmap_dealloc(C.MMBitmapRef(bitmap)) } +// FreeBitmapArr free and dealloc the C bitmap array +func FreeBitmapArr(bit ...CBitmap) { + for i := 0; i < len(bit); i++ { + FreeBitmap(bit[i]) + } +} + // ToMMBitmapRef trans CBitmap to C.MMBitmapRef func ToMMBitmapRef(bit CBitmap) C.MMBitmapRef { return C.MMBitmapRef(bit) @@ -396,14 +390,12 @@ func ToRGBA(bit CBitmap) *image.RGBA { } // SetXDisplayName set XDisplay name (Linux) -func SetXDisplayName(name string) string { +func SetXDisplayName(name string) error { cname := C.CString(name) str := C.set_XDisplay_name(cname) - - gstr := C.GoString(str) C.free(unsafe.Pointer(cname)) - return gstr + return toErr(str) } // GetXDisplayName get XDisplay name (Linux) @@ -823,375 +815,6 @@ func SetMouseDelay(delay int) { C.set_mouse_delay(cdelay) } -/* - __ ___ ___________ ____ .______ ______ ___ .______ _______ -| |/ / | ____\ \ / / | _ \ / __ \ / \ | _ \ | \ -| ' / | |__ \ \/ / | |_) | | | | | / ^ \ | |_) | | .--. | -| < | __| \_ _/ | _ < | | | | / /_\ \ | / | | | | -| . \ | |____ | | | |_) | | `--' | / _____ \ | |\ \----.| '--' | -|__|\__\ |_______| |__| |______/ \______/ /__/ \__\ | _| `._____||_______/ - -*/ - -func toErr(str *C.char) error { - gstr := C.GoString(str) - if gstr == "" { - return nil - } - return errors.New(gstr) -} - -// KeyTap tap the keyboard code; -// -// See keys: -// https://github.com/go-vgo/robotgo/blob/master/docs/keys.md -// -// Examples: -// robotgo.KeySleep = 100 // 100 millisecond -// robotgo.KeyTap("a") -// robotgo.KeyTap("i", "alt", "command") -// -// arr := []string{"alt", "command"} -// robotgo.KeyTap("i", arr) -// -func KeyTap(tapKey string, args ...interface{}) error { - var ( - akey string - keyT = "null" - keyArr []string - num int - keyDelay int // This is legacy and drop option, use robotgo.KeySleep - ) - - if _, ok := Special[tapKey]; ok { - tapKey = Special[tapKey] - if len(args) <= 0 { - args = append(args, "shift") - } - } - - // var ckeyArr []*C.char - ckeyArr := make([](*C.char), 0) - // zkey := C.CString(args[0]) - zkey := C.CString(tapKey) - defer C.free(unsafe.Pointer(zkey)) - - // args not key delay - if len(args) > 2 && (reflect.TypeOf(args[2]) != reflect.TypeOf(num)) { - num = len(args) - for i := 0; i < num; i++ { - s := args[i].(string) - ckeyArr = append(ckeyArr, (*C.char)(unsafe.Pointer(C.CString(s)))) - } - - str := C.key_Taps(zkey, - (**C.char)(unsafe.Pointer(&ckeyArr[0])), C.int(num), 0) - MilliSleep(KeySleep) - return toErr(str) - } - - // key delay - if len(args) > 0 { - if reflect.TypeOf(args[0]) == reflect.TypeOf(keyArr) { - - keyArr = args[0].([]string) - num = len(keyArr) - for i := 0; i < num; i++ { - ckeyArr = append(ckeyArr, (*C.char)(unsafe.Pointer(C.CString(keyArr[i])))) - } - - if len(args) > 1 { - keyDelay = args[1].(int) - } - } else { - akey = args[0].(string) - - if len(args) > 1 { - if reflect.TypeOf(args[1]) == reflect.TypeOf(akey) { - keyT = args[1].(string) - if len(args) > 2 { - keyDelay = args[2].(int) - } - } else { - keyDelay = args[1].(int) - } - } - } - - } else { - akey = "null" - keyArr = []string{"null"} - } - - if akey == "" && len(keyArr) != 0 { - str := C.key_Taps(zkey, (**C.char)(unsafe.Pointer(&ckeyArr[0])), - C.int(num), C.int(keyDelay)) - - MilliSleep(KeySleep) - return toErr(str) - } - - amod := C.CString(akey) - amodt := C.CString(keyT) - str := C.key_tap(zkey, amod, amodt, C.int(keyDelay)) - - C.free(unsafe.Pointer(amod)) - C.free(unsafe.Pointer(amodt)) - - MilliSleep(KeySleep) - return toErr(str) -} - -// KeyToggle toggle the keyboard, if there not have args default is "down" -// -// See keys: -// https://github.com/go-vgo/robotgo/blob/master/docs/keys.md -// -// Examples: -// robotgo.KeyToggle("a") -// robotgo.KeyToggle("a", "up") -// -// robotgo.KeyToggle("a", "up", "alt", "cmd") -// -func KeyToggle(key string, args ...string) error { - if len(args) <= 0 { - args = append(args, "down") - } - - if _, ok := Special[key]; ok { - key = Special[key] - if len(args) <= 1 { - args = append(args, "shift") - } - } - - ckey := C.CString(key) - defer C.free(unsafe.Pointer(ckey)) - - ckeyArr := make([](*C.char), 0) - if len(args) > 3 { - num := len(args) - for i := 0; i < num; i++ { - ckeyArr = append(ckeyArr, (*C.char)(unsafe.Pointer(C.CString(args[i])))) - } - - str := C.key_Toggles(ckey, (**C.char)(unsafe.Pointer(&ckeyArr[0])), C.int(num)) - MilliSleep(KeySleep) - return toErr(str) - } - - // use key_toggle() - var ( - down, mKey, mKeyT = "null", "null", "null" - // keyDelay = 10 - ) - - if len(args) > 0 { - down = args[0] - - if len(args) > 1 { - mKey = args[1] - if len(args) > 2 { - mKeyT = args[2] - } - } - } - - cdown := C.CString(down) - cmKey := C.CString(mKey) - cmKeyT := C.CString(mKeyT) - - str := C.key_toggle(ckey, cdown, cmKey, cmKeyT) - // str := C.key_Toggle(ckey, cdown, cmKey, cmKeyT, C.int(keyDelay)) - - C.free(unsafe.Pointer(cdown)) - C.free(unsafe.Pointer(cmKey)) - C.free(unsafe.Pointer(cmKeyT)) - - MilliSleep(KeySleep) - return toErr(str) -} - -// KeyPress press key string -func KeyPress(key string) error { - err := KeyDown(key) - if err != nil { - return err - } - MilliSleep(1 + rand.Intn(3)) - return KeyUp(key) -} - -// KeyDown press down a key -func KeyDown(key string) error { - return KeyToggle(key) -} - -// KeyUp press up a key -func KeyUp(key string) error { - return KeyToggle(key, "up") -} - -// ReadAll read string from clipboard -func ReadAll() (string, error) { - return clipboard.ReadAll() -} - -// WriteAll write string to clipboard -func WriteAll(text string) error { - return clipboard.WriteAll(text) -} - -// CharCodeAt char code at utf-8 -func CharCodeAt(s string, n int) rune { - i := 0 - for _, r := range s { - if i == n { - return r - } - i++ - } - - return 0 -} - -// UnicodeType tap uint32 unicode -func UnicodeType(str uint32) { - cstr := C.uint(str) - C.unicodeType(cstr) -} - -// ToUC trans string to unicode []string -func ToUC(text string) []string { - var uc []string - - for _, r := range text { - textQ := strconv.QuoteToASCII(string(r)) - textUnQ := textQ[1 : len(textQ)-1] - - st := strings.Replace(textUnQ, "\\u", "U", -1) - if st == "\\\\" { - st = "\\" - } - if st == `\"` { - st = `"` - } - uc = append(uc, st) - } - - return uc -} - -func inputUTF(str string) { - cstr := C.CString(str) - C.input_utf(cstr) - - C.free(unsafe.Pointer(cstr)) -} - -// TypeStr send a string, support UTF-8 -// -// robotgo.TypeStr(string: The string to send, float64: microsleep time, x11 option) -// -// Examples: -// robotgo.TypeStr("abc@123, hi, こんにちは") -// -func TypeStr(str string, args ...float64) { - var tm, tm1 = 0.0, 7.0 - - if len(args) > 0 { - tm = args[0] - } - if len(args) > 1 { - tm1 = args[1] - } - - if runtime.GOOS == "linux" { - strUc := ToUC(str) - for i := 0; i < len(strUc); i++ { - ru := []rune(strUc[i]) - if len(ru) <= 1 { - ustr := uint32(CharCodeAt(strUc[i], 0)) - UnicodeType(ustr) - } else { - inputUTF(strUc[i]) - MicroSleep(tm1) - } - - MicroSleep(tm) - } - - return - } - - for i := 0; i < len([]rune(str)); i++ { - ustr := uint32(CharCodeAt(str, i)) - UnicodeType(ustr) - - // if len(args) > 0 { - MicroSleep(tm) - // } - } - MilliSleep(KeySleep) -} - -// PasteStr paste a string, support UTF-8, -// write the string to clipboard and tap `cmd + v` -func PasteStr(str string) error { - err := clipboard.WriteAll(str) - if err != nil { - return err - } - - if runtime.GOOS == "darwin" { - return KeyTap("v", "command") - } - - return KeyTap("v", "control") -} - -// TypeStrDelay type string delayed -func TypeStrDelay(str string, delay int) { - TypeStr(str) - Sleep(delay) -} - -// Deprecated: use the TypeStr(), -// -// TypeStringDelayed type string delayed, Wno-deprecated -// -// This function will be removed in version v1.0.0 -func TypeStringDelayed(str string, delay int) { - tt.Drop("TypeStringDelayed", "TypeStrDelay") - TypeStrDelay(str, delay) -} - -// SetKeyDelay set keyboard delay -func SetKeyDelay(delay int) { - C.set_keyboard_delay(C.size_t(delay)) -} - -// Deprecated: use the SetKeyDelay(), -// -// SetKeyboardDelay set keyboard delay, Wno-deprecated, -// -// This function will be removed in version v1.0.0 -func SetKeyboardDelay(delay int) { - tt.Drop("SetKeyboardDelay", "SetKeyDelay") - SetKeyDelay(delay) -} - -// SetDelay set the key and mouse delay -func SetDelay(d ...int) { - v := 10 - if len(d) > 0 { - v = d[0] - } - - SetMouseDelay(v) - SetKeyDelay(v) -} - /* ____ __ ____ __ .__ __. _______ ______ ____ __ ____ \ \ / \ / / | | | \ | | | \ / __ \ \ \ / \ / / From 82cde2281e2d004a7a5ed189d3f121a2d8b3cc5c Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 31 Jan 2022 23:14:53 -0800 Subject: [PATCH 192/327] Update issue and PR template --- .github/issue_template.md | 3 ++- .github/pull_request_template.md | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/issue_template.md b/.github/issue_template.md index 09f368c5..507ae818 100644 --- a/.github/issue_template.md +++ b/.github/issue_template.md @@ -1,11 +1,12 @@ 1. Please **speak English**, this is the language everybody of us can speak and write. 2. Please take a moment to **search** that an issue **doesn't already exist**. 3. Please make sure `Golang, GCC` is installed correctly before installing RobotGo. -4. Please ask questions or config/deploy problems on our Gitter channel: https://gitter.im/go-vgo/robotgo + 5. Please give all relevant information below for bug reports, incomplete details will be handled as an invalid report. **You MUST delete the content above including this line before posting, otherwise your issue will be invalid.** + - Robotgo version (or commit ref): - Go version: - Gcc version: diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index b6fa0cfa..c331d4f8 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -9,6 +9,7 @@ The pull request will be closed without any reasons if it does not satisfy any o **You MUST delete the content above including this line before posting, otherwise your pull request will be invalid.** + **Please provide Issues links to:** - Issues: #1 From 250232958345f6f7c6ad72bda50388a0224e1a9c Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 31 Jan 2022 23:18:31 -0800 Subject: [PATCH 193/327] Remove SetKeydelay code --- key.go | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/key.go b/key.go index 2c7dd955..5b5e722e 100644 --- a/key.go +++ b/key.go @@ -644,29 +644,3 @@ func TypeStringDelayed(str string, delay int) { tt.Drop("TypeStringDelayed", "TypeStrDelay") TypeStrDelay(str, delay) } - -// SetKeyDelay set keyboard delay -func SetKeyDelay(delay int) { - C.set_keyboard_delay(C.size_t(delay)) -} - -// Deprecated: use the SetKeyDelay(), -// -// SetKeyboardDelay set keyboard delay, Wno-deprecated, -// -// This function will be removed in version v1.0.0 -func SetKeyboardDelay(delay int) { - tt.Drop("SetKeyboardDelay", "SetKeyDelay") - SetKeyDelay(delay) -} - -// SetDelay set the key and mouse delay -func SetDelay(d ...int) { - v := 10 - if len(d) > 0 { - v = d[0] - } - - SetMouseDelay(v) - SetKeyDelay(v) -} From 4599d66f5b25b3be219e6af265aef0aef635cc58 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 31 Jan 2022 23:41:31 -0800 Subject: [PATCH 194/327] Fixed CI build --- key.go | 7 ++++--- key/keypress_c.h | 2 +- mouse/mouse_c.h | 5 +---- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/key.go b/key.go index 5b5e722e..3ae063c2 100644 --- a/key.go +++ b/key.go @@ -307,9 +307,10 @@ func checkKeyCodes(k string) (key C.MMKeyCode, err error) { } if len(k) == 1 { - val := C.CString(k) - key = C.keyCodeForChar(*val) - C.free(unsafe.Pointer(val)) + val1 := C.CString(k) + defer C.free(unsafe.Pointer(val1)) + + key = C.keyCodeForChar(*val1) if key == C.K_NOT_A_KEY { err = keyErr return diff --git a/key/keypress_c.h b/key/keypress_c.h index e9e0d9fe..a6cf987b 100644 --- a/key/keypress_c.h +++ b/key/keypress_c.h @@ -1,5 +1,5 @@ #include "keypress.h" -// #include "../base/deadbeef_rand_c.h" +#include "../base/deadbeef_rand_c.h" #include "../base/microsleep.h" #include /* For isupper() */ diff --git a/mouse/mouse_c.h b/mouse/mouse_c.h index a34e44b5..366ae2e2 100644 --- a/mouse/mouse_c.h +++ b/mouse/mouse_c.h @@ -1,8 +1,5 @@ #include "mouse.h" -// #include "../screen/screen.h" -// #include "../screen/screen_c.h" -#include "../base/deadbeef_rand_c.h" -// #include "../deadbeef_rand.h" +#include "../base/deadbeef_rand.h" #include "../base/microsleep.h" #include /* For floor() */ From 00fa7ff5fc378d2c98658c73980b26287a502704 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 1 Feb 2022 00:05:51 -0800 Subject: [PATCH 195/327] Fixed Linux CI build --- key/goKey.h | 1 + 1 file changed, 1 insertion(+) diff --git a/key/goKey.h b/key/goKey.h index 2c2021c2..5153edef 100644 --- a/key/goKey.h +++ b/key/goKey.h @@ -1,5 +1,6 @@ // Copyright 2016 The go-vgo Project Developers. +#include #include "../base/types.h" // #include "keycode.h" // #include "keypress.h" From 2d52e2c0088e8b56ec97bb04b98c6774cbb4d47f Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 2 Feb 2022 21:20:02 -0800 Subject: [PATCH 196/327] Add more keyUp args and SetDelay() support, add more test code --- key.go | 31 +++++++++++++++++++++---------- robotgo_test.go | 11 +++++++++++ 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/key.go b/key.go index 3ae063c2..743e17fc 100644 --- a/key.go +++ b/key.go @@ -379,9 +379,9 @@ func keyTaps(k string, keyArr []string) error { } func keyToggles(k string, keyArr []string) error { - down := false - if keyArr[0] == "down" { - down = true + down := true + if keyArr[0] == "up" { + down = false } flags := getFlagsFromValue(keyArr) @@ -494,24 +494,24 @@ func KeyToggle(key string, args ...string) error { } // KeyPress press key string -func KeyPress(key string) error { - err := KeyDown(key) +func KeyPress(key string, args ...string) error { + err := KeyDown(key, args...) if err != nil { return err } MilliSleep(1 + rand.Intn(3)) - return KeyUp(key) + return KeyUp(key, args...) } // KeyDown press down a key -func KeyDown(key string) error { - return KeyToggle(key) +func KeyDown(key string, args ...string) error { + return KeyToggle(key, args...) } // KeyUp press up a key -func KeyUp(key string) error { - return KeyToggle(key, "up") +func KeyUp(key string, args ...string) error { + return KeyToggle(key, append(args, "up")...) } // ReadAll read string from clipboard @@ -645,3 +645,14 @@ func TypeStringDelayed(str string, delay int) { tt.Drop("TypeStringDelayed", "TypeStrDelay") TypeStrDelay(str, delay) } + +// SetDelay set the key and mouse delay +func SetDelay(d ...int) { + v := 10 + if len(d) > 0 { + v = d[0] + } + + KeySleep = v + MouseSleep = v +} diff --git a/robotgo_test.go b/robotgo_test.go index d70649f7..8e9e1e2a 100644 --- a/robotgo_test.go +++ b/robotgo_test.go @@ -117,6 +117,14 @@ func TestKey(t *testing.T) { e = KeyToggle("v", "up") tt.Nil(t, e) + + e = KeyDown("a") + tt.Nil(t, e) + e = KeyUp("a") + tt.Nil(t, e) + + e = KeyPress("b") + tt.Nil(t, e) } func TestClip(t *testing.T) { @@ -149,6 +157,9 @@ func TestKeyCode(t *testing.T) { s := Special["+"] tt.Equal(t, "=", s) + + tt.Equal(t, "0", Key0) + tt.Equal(t, "a", KeyA) } func TestImage(t *testing.T) { From f0b614d78ec8e3d6679a935890476b64a08d3bb0 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 3 Feb 2022 01:41:46 -0800 Subject: [PATCH 197/327] Removed msc, macro and other C code --- base/MMBitmap.h | 78 ++------------ base/base.go | 2 + base/deadbeef_rand.h | 15 +-- base/deadbeef_rand_c.h | 3 +- base/endian.h | 123 ---------------------- base/microsleep.h | 14 +-- base/ms_stdbool.h | 25 ----- base/ms_stdint.h | 224 ----------------------------------------- base/os.h | 2 +- base/rgb.h | 37 ++----- base/types.h | 45 +-------- base/xdisplay.h | 29 ------ base/xdisplay_c.h | 3 +- key.go | 4 +- key/goKey.h | 2 - key/key.go | 11 ++ key/key_windows.go | 4 + key/keycode.h | 9 -- key/keycode_c.h | 15 +-- key/keypress.h | 48 +-------- key/keypress_c.h | 53 +++++----- mouse/mouse.go | 11 ++ mouse/mouse.h | 68 +------------ mouse/mouse_c.h | 148 +++++++++++---------------- mouse/mouse_darwin.go | 4 + mouse/mouse_windows.go | 4 + mouse/mouse_x11.go | 4 + screen/goScreen.h | 9 +- screen/screen.go | 1 + screen/screen.h | 29 ------ screen/screen_c.h | 6 +- screen/screengrab.h | 22 ---- screen/screengrab_c.h | 15 +-- window/alert_c.h | 11 +- window/window.go | 1 + 35 files changed, 182 insertions(+), 897 deletions(-) create mode 100644 base/base.go delete mode 100644 base/endian.h delete mode 100644 base/ms_stdbool.h delete mode 100644 base/ms_stdint.h delete mode 100644 base/xdisplay.h create mode 100644 key/key.go create mode 100644 key/key_windows.go create mode 100644 mouse/mouse.go create mode 100644 mouse/mouse_darwin.go create mode 100644 mouse/mouse_windows.go create mode 100644 mouse/mouse_x11.go create mode 100644 screen/screen.go delete mode 100644 screen/screen.h delete mode 100644 screen/screengrab.h create mode 100644 window/window.go diff --git a/base/MMBitmap.h b/base/MMBitmap.h index 9e73feb6..fbbdfc15 100644 --- a/base/MMBitmap.h +++ b/base/MMBitmap.h @@ -5,23 +5,12 @@ #include "types.h" #include "rgb.h" #include -// #include -#if defined(_MSC_VER) - #include "ms_stdint.h" -#else - #include -#endif - -#ifdef __cplusplus -extern "C" -{ -#endif +#include struct _MMBitmap { - uint8_t *imageBuffer; /* Pixels stored in Quad I format; i.e., origin is in - * top left. Length should be height * bytewidth. */ - size_t width; /* Never 0, unless image is NULL. */ - size_t height; /* Never 0, unless image is NULL. */ + uint8_t *imageBuffer; /* Pixels stored in Quad I format; */ + int32_t width; /* Never 0, unless image is NULL. */ + int32_t height; /* Never 0, unless image is NULL. */ size_t bytewidth; /* The aligned width (width + padding). */ uint8_t bitsPerPixel; /* Should be either 24 or 32. */ uint8_t bytesPerPixel; /* For convenience; should be bitsPerPixel / 8. */ @@ -29,65 +18,18 @@ struct _MMBitmap { typedef struct _MMBitmap MMBitmap; typedef MMBitmap *MMBitmapRef; -// MMBitmapRef bitmap; - -/* Creates new MMBitmap with the given values. - * Follows the Create Rule (caller is responsible for destroy()'ing object). */ -MMBitmapRef createMMBitmap_c(uint8_t *buffer, size_t width, size_t height, - size_t bytewidth, uint8_t bitsPerPixel, - uint8_t bytesPerPixel); - -/* Releases memory occupied by MMBitmap. */ -void destroyMMBitmap(MMBitmapRef bitmap); - -/* Releases memory occupied by MMBitmap. Acts via CallBack method*/ -void destroyMMBitmapBuffer(char * bitmapBuffer, void * hint); - -// /* Returns copy of MMBitmap, to be destroy()'d by caller. */ -// MMBitmapRef copyMMBitmap(MMBitmapRef bitmap); -// /* Returns copy of one MMBitmap juxtaposed in another (to be destroy()'d -// * by the caller.), or NULL on error. */ -// MMBitmapRef copyMMBitmapFromPortion(MMBitmapRef source, MMRect rect); +#define MMBitmapPointInBounds(image, p) ((p).x < (image)->width && (p).y < (image)->height) -#define MMBitmapPointInBounds(image, p) ((p).x < (image)->width && \ - (p).y < (image)->height) -#define MMBitmapRectInBounds(image, r) \ - (((r).origin.x + (r).size.width <= (image)->width) && \ - ((r).origin.y + (r).size.height <= (image)->height)) - -#define MMBitmapGetBounds(image) MMRectMake(0, 0, image->width, image->height) - -/* Get pointer to pixel of MMBitmapRef. No bounds checking is performed (check - * yourself before calling this with MMBitmapPointInBounds(). */ -#define MMRGBColorRefAtPoint(image, x, y) \ - (MMRGBColor *)(assert(MMBitmapPointInBounds(image, MMPointMake(x, y))), \ - ((image)->imageBuffer) + (((image)->bytewidth * (y)) \ - + ((x) * (image)->bytesPerPixel))) +/* Get pointer to pixel of MMBitmapRef. No bounds checking is performed */ +#define MMRGBColorRefAtPoint(image, x, y) ( \ + MMRGBColor *)(assert(MMBitmapPointInBounds(image, MMPointInt32Make(x, y))), \ + ((image)->imageBuffer) + (((image)->bytewidth * (y)) + ((x) * (image)->bytesPerPixel))) /* Dereference pixel of MMBitmapRef. Again, no bounds checking is performed. */ #define MMRGBColorAtPoint(image, x, y) *MMRGBColorRefAtPoint(image, x, y) /* Hex/integer value of color at point. */ -#define MMRGBHexAtPoint(image, x, y) \ - hexFromMMRGB(MMRGBColorAtPoint(image, x, y)) - -// /* Increment either point.x or point.y depending on the position of point.x. -// * That is, if x + 1 is >= width, increment y and start x at the beginning. -// * Otherwise, increment x. -// * -// * This is used as a convenience macro to scan rows when calling functions such -// * as findColorInRectAt() and findBitmapInBitmapAt(). */ -// #define ITER_NEXT_POINT(pixel, width, start_x) \ -// do { \ -// if (++(pixel).x >= (width)) { \ -// (pixel).x = start_x; \ -// ++(point).y; \ -// } \ -// } while (0); - -#ifdef __cplusplus -} -#endif +#define MMRGBHexAtPoint(image, x, y) hexFromMMRGB(MMRGBColorAtPoint(image, x, y)) #endif /* MMBITMAP_H */ \ No newline at end of file diff --git a/base/base.go b/base/base.go new file mode 100644 index 00000000..8ffa8e92 --- /dev/null +++ b/base/base.go @@ -0,0 +1,2 @@ +// https://github.com/golang/go/issues/26366 +package base diff --git a/base/deadbeef_rand.h b/base/deadbeef_rand.h index ec569a24..02e3d4e0 100644 --- a/base/deadbeef_rand.h +++ b/base/deadbeef_rand.h @@ -4,11 +4,7 @@ #include #define DEADBEEF_MAX UINT32_MAX - -/* Dead Beef Random Number Generator - * From: http://inglorion.net/software/deadbeef_rand - * A fast, portable psuedo-random number generator by BJ Amsterdam Zuidoost. - * Stated in license terms: "Feel free to use the code in your own software." */ +/* Dead Beef Random Number Generator From: http://inglorion.net/software/deadbeef_rand */ /* Generates a random number between 0 and DEADBEEF_MAX. */ uint32_t deadbeef_rand(void); @@ -22,14 +18,11 @@ uint32_t deadbeef_generate_seed(void); /* Seeds with the above function. */ #define deadbeef_srand_time() deadbeef_srand(deadbeef_generate_seed()) -/* Returns random double in the range [a, b). - * Taken directly from the rand() man page. */ +/* Returns random double in the range [a, b).*/ #define DEADBEEF_UNIFORM(a, b) \ ((a) + (deadbeef_rand() / (((double)DEADBEEF_MAX / (b - a) + 1)))) -/* Returns random integer in the range [a, b). - * Also taken from the rand() man page. */ -#define DEADBEEF_RANDRANGE(a, b) \ - (uint32_t)DEADBEEF_UNIFORM(a, b) +/* Returns random integer in the range [a, b).*/ +#define DEADBEEF_RANDRANGE(a, b) (uint32_t)DEADBEEF_UNIFORM(a, b) #endif /* DEADBEEF_RAND_H */ diff --git a/base/deadbeef_rand_c.h b/base/deadbeef_rand_c.h index d33062f9..1a0173fb 100644 --- a/base/deadbeef_rand_c.h +++ b/base/deadbeef_rand_c.h @@ -15,8 +15,7 @@ void deadbeef_srand(uint32_t x) { deadbeef_beef = 0xdeadbeef; } -/* Taken directly from the documentation: - * http://inglorion.net/software/cstuff/deadbeef_rand/ */ +/* Taken directly from the documentation: http://inglorion.net/software/cstuff/deadbeef_rand/ */ uint32_t deadbeef_generate_seed(void) { uint32_t t = (uint32_t)time(NULL); uint32_t c = (uint32_t)clock(); diff --git a/base/endian.h b/base/endian.h deleted file mode 100644 index cbc7c542..00000000 --- a/base/endian.h +++ /dev/null @@ -1,123 +0,0 @@ -#pragma once -#ifndef ENDIAN_H -#define ENDIAN_H - -#include "os.h" - -/* - * (Mostly) cross-platform endian definitions and bit swapping macros. - * Unfortunately, there is no standard C header for this, so we just - * include the most common ones and fallback to our own custom macros. - */ - -#if defined(__linux__) /* Linux */ - #include - #include -#elif (defined(__FreeBSD__) && __FreeBSD_version >= 470000) || \ - defined(__OpenBSD__) || defined(__NetBSD__) /* (Free|Open|Net)BSD */ - #include - #define __BIG_ENDIAN BIG_ENDIAN - #define __LITTLE_ENDIAN LITTLE_ENDIAN - #define __BYTE_ORDER BYTE_ORDER -#elif defined(IS_MACOSX) || (defined(BSD) && (BSD >= 199103)) /* Other BSD */ - #include - #define __BIG_ENDIAN BIG_ENDIAN - #define __LITTLE_ENDIAN LITTLE_ENDIAN - #define __BYTE_ORDER BYTE_ORDER -#elif defined(IS_WINDOWS) /* Windows is assumed to be little endian only. */ - #define __BIG_ENDIAN 4321 - #define __LITTLE_ENDIAN 1234 - #define __BYTE_ORDER __LITTLE_ENDIAN -#endif - -/* Fallback to custom constants. */ -#if !defined(__BIG_ENDIAN) - #define __BIG_ENDIAN 4321 -#endif - -#if !defined(__LITTLE_ENDIAN) - #define __LITTLE_ENDIAN 1234 -#endif - -/* Prefer compiler flag settings if given. */ -#if defined(MM_BIG_ENDIAN) - #undef __BYTE_ORDER /* Avoid redefined macro compiler warning. */ - #define __BYTE_ORDER __BIG_ENDIAN -#elif defined(MM_LITTLE_ENDIAN) - #undef __BYTE_ORDER /* Avoid redefined macro compiler warning. */ - #define __BYTE_ORDER __LITTLE_ENDIAN -#endif - -/* Define default endian-ness. */ -#ifndef __LITTLE_ENDIAN - #define __LITTLE_ENDIAN 1234 -#endif /* __LITTLE_ENDIAN */ - -#ifndef __BIG_ENDIAN - #define __BIG_ENDIAN 4321 -#endif /* __BIG_ENDIAN */ - -#ifndef __BYTE_ORDER - #warning "Byte order not defined on your system; assuming little endian" - #define __BYTE_ORDER __LITTLE_ENDIAN -#endif /* __BYTE_ORDER */ - -#if __BYTE_ORDER != __BIG_ENDIAN && __BYTE_ORDER != __LITTLE_ENDIAN - #error "__BYTE_ORDER set to unknown byte order" -#endif - -#if defined(IS_MACOSX) - #include - - /* OS X system functions. */ - #define bitswap16(i) OSSwapInt16(i) - #define bitswap32(i) OSSwapInt32(i) - #define swapLittleAndHost32(i) OSSwapLittleToHostInt32(i) - #define swapLittleAndHost16(i) OSSwapLittleToHostInt16(i) -#else - #ifndef bitswap16 - #if defined(bswap16) - #define bitswap16(i) bswap16(i) /* FreeBSD system function */ - #elif defined(bswap_16) - #define bitswap16(i) bswap_16(i) /* Linux system function */ - #else /* Default macro */ - #define bitswap16(i) (((uint16_t)(i) & 0xFF00) >> 8) | \ - (((uint16_t)(i) & 0x00FF) << 8) - #endif - #endif /* bitswap16 */ - - #ifndef bitswap32 - #if defined(bswap32) - #define bitswap32(i) bswap32(i) /* FreeBSD system function. */ - #elif defined(bswap_32) - #define bitswap32(i) bswap_32(i) /* Linux system function. */ - #else /* Default macro */ - #define bitswap32(i) (((uint32_t)(i) & 0xFF000000) >> 24) | \ - ((uint32_t)((i) & 0x00FF0000) >> 8) | \ - ((uint32_t)((i) & 0x0000FF00) << 8) | \ - ((uint32_t)((i) & 0x000000FF) << 24) - #endif - #endif /* bitswap32 */ -#endif - -#if __BYTE_ORDER == __BIG_ENDIAN - /* Little endian to/from host byte order (big endian). */ - #ifndef swapLittleAndHost16 - #define swapLittleAndHost16(i) bitswap16(i) - #endif /* swapLittleAndHost16 */ - - #ifndef swapLittleAndHost32 - #define swapLittleAndHost32(i) bitswap32(i) - #endif /* swapLittleAndHost32 */ -#elif __BYTE_ORDER == __LITTLE_ENDIAN - /* We are already little endian, so no conversion is needed. */ - #ifndef swapLittleAndHost16 - #define swapLittleAndHost16(i) i - #endif /* swapLittleAndHost16 */ - - #ifndef swapLittleAndHost32 - #define swapLittleAndHost32(i) i - #endif /* swapLittleAndHost32 */ -#endif - -#endif /* ENDIAN_H */ diff --git a/base/microsleep.h b/base/microsleep.h index 777831c7..2c08258e 100644 --- a/base/microsleep.h +++ b/base/microsleep.h @@ -5,6 +5,7 @@ #include "os.h" #include "inline_keywords.h" +// todo: removed #if !defined(IS_WINDOWS) /* Make sure nanosleep gets defined even when using C89. */ #if !defined(__USE_POSIX199309) || !__USE_POSIX199309 @@ -14,21 +15,12 @@ #include /* For nanosleep() */ #endif -/* - * A more widely supported alternative to usleep(), based on Sleep() in Windows - * and nanosleep() everywhere else. - * - * Pauses execution for the given amount of milliseconds. - */ +/* A more widely supported alternative to usleep(), based on Sleep() in Windows and nanosleep() */ H_INLINE void microsleep(double milliseconds) { #if defined(IS_WINDOWS) Sleep((DWORD)milliseconds); /* (Unfortunately truncated to a 32-bit integer.) */ #else - /* Technically, nanosleep() is not an ANSI function, but it is the most - * supported precise sleeping function I can find. - * - * If it is really necessary, it may be possible to emulate this with some - * hack using select() in the future if we really have to. */ + /* Technically, nanosleep() is not an ANSI function */ struct timespec sleepytime; sleepytime.tv_sec = milliseconds / 1000; sleepytime.tv_nsec = (milliseconds - (sleepytime.tv_sec * 1000)) * 1000000; diff --git a/base/ms_stdbool.h b/base/ms_stdbool.h deleted file mode 100644 index 1aae547f..00000000 --- a/base/ms_stdbool.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once -#if !defined(MS_STDBOOL_H) && \ - (!defined(__bool_true_false_are_defined) || __bool_true_false_are_defined) -#define MS_STDBOOL_H - -#ifndef _MSC_VER - #error "Use this header only with Microsoft Visual C++ compilers!" -#endif /* _MSC_VER */ - -#define __bool_true_false_are_defined 1 - -#ifndef __cplusplus - #if defined(true) || defined(false) || defined(bool) - #error "Boolean type already defined" - #endif - - enum { - false = 0, - true = 1 - }; - - typedef unsigned char bool; -#endif /* !__cplusplus */ - -#endif /* MS_STDBOOL_H */ diff --git a/base/ms_stdint.h b/base/ms_stdint.h deleted file mode 100644 index 24c33ef0..00000000 --- a/base/ms_stdint.h +++ /dev/null @@ -1,224 +0,0 @@ -/* ISO C9x compliant stdint.h for Microsoft Visual Studio - * Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 - * - * Copyright (c) 2006-2008 Alexander Chemeris - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. The name of the author may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _MSC_VER - #error "Use this header only with Microsoft Visual C++ compilers!" -#endif /* _MSC_VER */ - -#ifndef MSC_STDINT_H -#define MSC_STDINT_H - -#if _MSC_VER > 1000 - #pragma once -#endif - -#include - -/* For Visual Studio 6 in C++ mode and for many Visual Studio versions when - * compiling for ARM we should wrap include with 'extern "C++" {}' - * or compiler give many errors like this: */ -#if defined(__cplusplus) -extern "C" { -#endif /* __cplusplus */ - #include -#if defined(__cplusplus) -} -#endif /* __cplusplus */ - -/* Define _W64 macros to mark types changing their size, like intptr_t. */ -#ifndef _W64 - #if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 - #define _W64 __w64 - #else - #define _W64 - #endif -#endif - - -/* 7.18.1 Integer types */ - -/* 7.18.1.1 Exact-width integer types */ - -/* Visual Studio 6 and Embedded Visual C++ 4 doesn't - * realize that, e.g. char has the same size as __int8 - * so we give up on __intX for them. */ -#if _MSC_VER < 1300 - typedef signed char int8_t; - typedef signed short int16_t; - typedef signed int int32_t; - typedef unsigned char uint8_t; - typedef unsigned short uint16_t; - typedef unsigned int uint32_t; -#else - typedef signed __int8 int8_t; - typedef signed __int16 int16_t; - typedef signed __int32 int32_t; - typedef unsigned __int8 uint8_t; - typedef unsigned __int16 uint16_t; - typedef unsigned __int32 uint32_t; -#endif -typedef signed __int64 int64_t; -typedef unsigned __int64 uint64_t; - -/* 7.18.1.2 Minimum-width integer types */ -typedef int8_t int_least8_t; -typedef int16_t int_least16_t; -typedef int32_t int_least32_t; -typedef int64_t int_least64_t; -typedef uint8_t uint_least8_t; -typedef uint16_t uint_least16_t; -typedef uint32_t uint_least32_t; -typedef uint64_t uint_least64_t; - -/* 7.18.1.3 Fastest minimum-width integer types */ -typedef int8_t int_fast8_t; -typedef int16_t int_fast16_t; -typedef int32_t int_fast32_t; -typedef int64_t int_fast64_t; -typedef uint8_t uint_fast8_t; -typedef uint16_t uint_fast16_t; -typedef uint32_t uint_fast32_t; -typedef uint64_t uint_fast64_t; - -/* 7.18.1.4 Integer types capable of holding object pointers */ -#if defined(_WIN64) - typedef signed __int64 intptr_t; - typedef unsigned __int64 uintptr_t; -#else - typedef _W64 signed int intptr_t; - typedef _W64 unsigned int uintptr_t; -#endif /* _WIN64 ] */ - -/* 7.18.1.5 Greatest-width integer types */ -typedef int64_t intmax_t; -typedef uint64_t uintmax_t; - -/* 7.18.2 Limits of specified-width integer types */ - -/* See footnote 220 at page 257 and footnote 221 at page 259 */ -#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) - - /* 7.18.2.1 Limits of exact-width integer types */ - #define INT8_MIN ((int8_t)_I8_MIN) - #define INT8_MAX _I8_MAX - #define INT16_MIN ((int16_t)_I16_MIN) - #define INT16_MAX _I16_MAX - #define INT32_MIN ((int32_t)_I32_MIN) - #define INT32_MAX _I32_MAX - #define INT64_MIN ((int64_t)_I64_MIN) - #define INT64_MAX _I64_MAX - #define UINT8_MAX _UI8_MAX - #define UINT16_MAX _UI16_MAX - #define UINT32_MAX _UI32_MAX - #define UINT64_MAX _UI64_MAX - - /* 7.18.2.2 Limits of minimum-width integer types */ - #define INT_LEAST8_MIN INT8_MIN - #define INT_LEAST8_MAX INT8_MAX - #define INT_LEAST16_MIN INT16_MIN - #define INT_LEAST16_MAX INT16_MAX - #define INT_LEAST32_MIN INT32_MIN - #define INT_LEAST32_MAX INT32_MAX - #define INT_LEAST64_MIN INT64_MIN - #define INT_LEAST64_MAX INT64_MAX - #define UINT_LEAST8_MAX UINT8_MAX - #define UINT_LEAST16_MAX UINT16_MAX - #define UINT_LEAST32_MAX UINT32_MAX - #define UINT_LEAST64_MAX UINT64_MAX - - /* 7.18.2.4 Limits of integer types capable of holding object pointers */ - #if defined(_WIN64) - #define INTPTR_MIN INT64_MIN - #define INTPTR_MAX INT64_MAX - #define UINTPTR_MAX UINT64_MAX - #else - #define INTPTR_MIN INT32_MIN - #define INTPTR_MAX INT32_MAX - #define UINTPTR_MAX UINT32_MAX - #endif - - /* 7.18.3 Limits of other integer types */ - - #if defined(_WIN64) - #define PTRDIFF_MIN _I64_MIN - #define PTRDIFF_MAX _I64_MAX - #else - #define PTRDIFF_MIN _I32_MIN - #define PTRDIFF_MAX _I32_MAX - #endif /* _WIN64 */ - - #define SIG_ATOMIC_MIN INT_MIN - #define SIG_ATOMIC_MAX INT_MAX - - #ifndef SIZE_MAX - #if defined(_WIN64) - #define SIZE_MAX _UI64_MAX - #else - #define SIZE_MAX _UI32_MAX - #endif - #endif - - /* WCHAR_MIN and WCHAR_MAX are also defined in */ - #ifndef WCHAR_MIN - #define WCHAR_MIN 0 - #endif /* WCHAR_MIN */ - - #ifndef WCHAR_MAX - #define WCHAR_MAX _UI16_MAX - #endif /* WCHAR_MAX */ - - #define WINT_MIN 0 - #define WINT_MAX _UI16_MAX -#endif /* __STDC_LIMIT_MACROS */ - - -/* 7.18.4 Limits of other integer types */ - -#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) /* See footnote 224 at page 260 */ - - /* 7.18.4.1 Macros for minimum-width integer constants */ - - #define INT8_C(val) val##i8 - #define INT16_C(val) val##i16 - #define INT32_C(val) val##i32 - #define INT64_C(val) val##i64 - - #define UINT8_C(val) val##ui8 - #define UINT16_C(val) val##ui16 - #define UINT32_C(val) val##ui32 - #define UINT64_C(val) val##ui64 - - /* 7.18.4.2 Macros for greatest-width integer constants */ - #define INTMAX_C INT64_C - #define UINTMAX_C UINT64_C - -#endif /* __STDC_CONSTANT_MACROS */ - -#endif /* MSC_STDINT_H */ diff --git a/base/os.h b/base/os.h index 5d08c4fe..8baad8ac 100644 --- a/base/os.h +++ b/base/os.h @@ -14,7 +14,7 @@ #endif /* IS_MACOSX */ #if !defined(IS_WINDOWS) && (defined(WIN32) || defined(_WIN32) || \ - defined(__WIN32__) || defined(__WINDOWS__) || defined(__CYGWIN__)) + defined(__WIN32__) || defined(__WINDOWS__) || defined(__CYGWIN__)) #define IS_WINDOWS #endif /* IS_WINDOWS */ diff --git a/base/rgb.h b/base/rgb.h index 0810fc4a..4fbe1479 100644 --- a/base/rgb.h +++ b/base/rgb.h @@ -5,20 +5,7 @@ #include /* For abs() */ #include #include "inline_keywords.h" /* For H_INLINE */ -// #include -#if defined(_MSC_VER) - #include "ms_stdint.h" -#else - #include -#endif - -/* RGB colors in MMBitmaps are stored as BGR for convenience in converting - * to/from certain formats (mainly OpenGL). - * - * It is best not to rely on the order (simply use rgb.{blue,green,red} to - * access values), but some situations (e.g., glReadPixels) require one to - * do so. In that case, check to make sure to use MMRGB_IS_BGR for future - * compatibility. */ +#include /* #define MMRGB_IS_BGR (offsetof(MMRGBColor, red) > offsetof(MMRGBColor, blue)) */ #define MMRGB_IS_BGR 1 @@ -28,20 +15,15 @@ struct _MMRGBColor { uint8_t green; uint8_t red; }; - typedef struct _MMRGBColor MMRGBColor; -/* MMRGBHex is a hexadecimal color value, akin to HTML's, in the form 0xRRGGBB - * where RR is the red value expressed as hexadecimal, GG is the green value, - * and BB is the blue value. */ +/* MMRGBHex is a hexadecimal color value*/ typedef uint32_t MMRGBHex; #define MMRGBHEX_MIN 0x000000 #define MMRGBHEX_MAX 0xFFFFFF -/* Converts rgb color to hexadecimal value. - * |red|, |green|, and |blue| should each be of the type |uint8_t|, where the - * range is 0 - 255. */ +/* Converts rgb color to hexadecimal value. */ #define RGB_TO_HEX(red, green, blue) (((red) << 16) | ((green) << 8) | (blue)) /* Convenience wrapper for MMRGBColors. */ @@ -67,9 +49,7 @@ H_INLINE MMRGBColor MMRGBFromHex(MMRGBHex hex) { (c1).blue == (c2).blue && \ (c1).green == (c2).green) -/* Returns whether two colors are similar within the given range, |tolerance|. - * Tolerance can be in the range 0.0f - 1.0f, where 0 denotes the exact - * color and 1 denotes any color. */ +/* Returns whether two colors are similar within the given range, |tolerance|.*/ H_INLINE int MMRGBColorSimilarToColor(MMRGBColor c1, MMRGBColor c2, float tolerance) { /* Speedy case */ if (tolerance <= 0.0f) { @@ -78,8 +58,7 @@ H_INLINE int MMRGBColorSimilarToColor(MMRGBColor c1, MMRGBColor c2, float tolera uint8_t d1 = c1.red - c2.red; uint8_t d2 = c1.green - c2.green; uint8_t d3 = c1.blue - c2.blue; - return sqrt((double)(d1 * d1) + - (d2 * d2) + + return sqrt((double)(d1 * d1) + (d2 * d2) + (d3 * d3)) <= (tolerance * 442.0f); } } @@ -89,14 +68,10 @@ H_INLINE int MMRGBHexSimilarToColor(MMRGBHex h1, MMRGBHex h2, float tolerance) { if (tolerance <= 0.0f) { return h1 == h2; } else { - // uint8_t d1 = RED_FROM_HEX(h1) - RED_FROM_HEX(h2); - // uint8_t d2 = GREEN_FROM_HEX(h1) - GREEN_FROM_HEX(h2); - // uint8_t d3 = BLUE_FROM_HEX(h1) - BLUE_FROM_HEX(h2); int d1 = RED_FROM_HEX(h1) - RED_FROM_HEX(h2); int d2 = GREEN_FROM_HEX(h1) - GREEN_FROM_HEX(h2); int d3 = BLUE_FROM_HEX(h1) - BLUE_FROM_HEX(h2); - return sqrt((double)(d1 * d1) + - (d2 * d2) + + return sqrt((double)(d1 * d1) + (d2 * d2) + (d3 * d3)) <= (tolerance * 442.0f); } } diff --git a/base/types.h b/base/types.h index d76ef3e7..84f772c7 100644 --- a/base/types.h +++ b/base/types.h @@ -16,49 +16,24 @@ typedef uint32_t uintptr; // Unsigned pointer integer #endif -struct _MMPoint { - size_t x; - size_t y; -}; -typedef struct _MMPoint MMPoint; - struct _MMPointInt32 { int32_t x; int32_t y; }; typedef struct _MMPointInt32 MMPointInt32; -struct _MMSize { - size_t width; - size_t height; -}; -typedef struct _MMSize MMSize; - struct _MMSizeInt32 { int32_t w; int32_t h; }; typedef struct _MMSizeInt32 MMSizeInt32; -struct _MMRect { - MMPoint origin; - MMSize size; -}; -typedef struct _MMRect MMRect; - struct _MMRectInt32 { MMPointInt32 origin; MMSizeInt32 size; }; typedef struct _MMRectInt32 MMRectInt32; -H_INLINE MMPoint MMPointMake(size_t x, size_t y) { - MMPoint point; - point.x = x; - point.y = y; - return point; -} - H_INLINE MMPointInt32 MMPointInt32Make(int32_t x, int32_t y) { MMPointInt32 point; point.x = x; @@ -66,13 +41,6 @@ H_INLINE MMPointInt32 MMPointInt32Make(int32_t x, int32_t y) { return point; } -H_INLINE MMSize MMSizeMake(size_t width, size_t height) { - MMSize size; - size.width = width; - size.height = height; - return size; -} - H_INLINE MMSizeInt32 MMSizeInt32Make(int32_t w, int32_t h) { MMSizeInt32 size; size.w = w; @@ -80,13 +48,6 @@ H_INLINE MMSizeInt32 MMSizeInt32Make(int32_t w, int32_t h) { return size; } -H_INLINE MMRect MMRectMake(size_t x, size_t y, size_t width, size_t height) { - MMRect rect; - rect.origin = MMPointMake(x, y); - rect.size = MMSizeMake(width, height); - return rect; -} - H_INLINE MMRectInt32 MMRectInt32Make(int32_t x, int32_t y, int32_t w, int32_t h) { MMRectInt32 rect; rect.origin = MMPointInt32Make(x, y); @@ -94,13 +55,9 @@ H_INLINE MMRectInt32 MMRectInt32Make(int32_t x, int32_t y, int32_t w, int32_t h) return rect; } -// -#define MMPointZero MMPointMake(0, 0) +#define MMPointZero MMPointInt32Make(0, 0) #if defined(IS_MACOSX) - #define CGPointFromMMPoint(p) CGPointMake((CGFloat)(p).x, (CGFloat)(p).y) - #define MMPointFromCGPoint(p) MMPointMake((size_t)(p).x, (size_t)(p).y) - #define CGPointFromMMPointInt32(p) CGPointMake((CGFloat)(p).x, (CGFloat)(p).y) #define MMPointInt32FromCGPoint(p) MMPointInt32Make((int32_t)(p).x, (int32_t)(p).y) #elif defined(IS_WINDOWS) diff --git a/base/xdisplay.h b/base/xdisplay.h deleted file mode 100644 index 3c8663c2..00000000 --- a/base/xdisplay.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once -#ifndef XDISPLAY_H -#define XDISPLAY_H - -#include - -/* Returns the main display, closed either on exit or when closeMainDisplay() - * is invoked. This removes a bit of the overhead of calling XOpenDisplay() & - * XCloseDisplay() everytime the main display needs to be used. - * - * Note that this is almost certainly not thread safe. */ -Display *XGetMainDisplay(void); - -/* Closes the main display if it is open, or does nothing if not. */ -void XCloseMainDisplay(void); - -#ifdef __cplusplus -extern "C" -{ -#endif - -char *getXDisplay(void); -void setXDisplay(char *name); - -#ifdef __cplusplus -} -#endif - -#endif /* XDISPLAY_H */ diff --git a/base/xdisplay_c.h b/base/xdisplay_c.h index f96e835b..fa455b2c 100644 --- a/base/xdisplay_c.h +++ b/base/xdisplay_c.h @@ -1,6 +1,6 @@ -#include "xdisplay.h" #include /* For fputs() */ #include /* For atexit() */ +#include static Display *mainDisplay = NULL; static int registered = 0; @@ -55,4 +55,3 @@ void setXDisplay(char *name) { char *getXDisplay(void) { return displayName; } - diff --git a/key.go b/key.go index 743e17fc..de09a156 100644 --- a/key.go +++ b/key.go @@ -511,7 +511,9 @@ func KeyDown(key string, args ...string) error { // KeyUp press up a key func KeyUp(key string, args ...string) error { - return KeyToggle(key, append(args, "up")...) + arr := []string{"up"} + arr = append(arr, args...) + return KeyToggle(key, arr...) } // ReadAll read string from clipboard diff --git a/key/goKey.h b/key/goKey.h index 5153edef..b377f6c6 100644 --- a/key/goKey.h +++ b/key/goKey.h @@ -2,7 +2,5 @@ #include #include "../base/types.h" -// #include "keycode.h" -// #include "keypress.h" #include "keypress_c.h" #include "keycode_c.h" diff --git a/key/key.go b/key/key.go new file mode 100644 index 00000000..6daa8367 --- /dev/null +++ b/key/key.go @@ -0,0 +1,11 @@ +// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// https://github.com/go-vgo/robotgo/blob/master/LICENSE +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +package key diff --git a/key/key_windows.go b/key/key_windows.go new file mode 100644 index 00000000..808cd693 --- /dev/null +++ b/key/key_windows.go @@ -0,0 +1,4 @@ +//go:build windows +// +build windows + +package key diff --git a/key/keycode.h b/key/keycode.h index e7a114bd..4a6771ac 100644 --- a/key/keycode.h +++ b/key/keycode.h @@ -4,11 +4,6 @@ #include "../base/os.h" -#ifdef __cplusplus -extern "C" -{ -#endif - #if defined(IS_MACOSX) #include /* Really only need */ @@ -406,7 +401,3 @@ typedef int MMKeyCode; MMKeyCode keyCodeForChar(const char c); #endif /* KEYCODE_H */ - -#ifdef __cplusplus -} -#endif diff --git a/key/keycode_c.h b/key/keycode_c.h index 6336ae79..dfcc71ff 100644 --- a/key/keycode_c.h +++ b/key/keycode_c.h @@ -4,16 +4,13 @@ #include #include /* For kVK_ constants, and TIS functions. */ - /* Returns string representation of key, if it is printable. - * Ownership follows the Create Rule; that is, it is the caller's - * responsibility to release the returned object. */ + /* Returns string representation of key, if it is printable. */ CFStringRef createStringForKey(CGKeyCode keyCode); #endif MMKeyCode keyCodeForChar(const char c) { #if defined(IS_MACOSX) - /* OS X does not appear to have a built-in function for this, so instead we - * have to write our own. */ + /* OS X does not appear to have a built-in function for this, so instead it. */ static CFMutableDictionaryRef charToCodeDict = NULL; CGKeyCode code; UniChar character = c; @@ -58,17 +55,13 @@ MMKeyCode keyCodeForChar(const char c) { return code; #elif defined(USE_X11) - MMKeyCode code; - char buf[2]; buf[0] = c; buf[1] = '\0'; - code = XStringToKeysym(buf); + MMKeyCode code = XStringToKeysym(buf); if (code == NoSymbol) { - /* Some special keys are apparently not handled properly by - * XStringToKeysym() on some systems, so search for them instead in our - * mapping table. */ + /* Some special keys are apparently not handled properly */ struct XSpecialCharacterMapping* xs = XSpecialCharacterTable; while (xs->name) { if (c == xs->name) { diff --git a/key/keypress.h b/key/keypress.h index 946a66e5..6b74da79 100644 --- a/key/keypress.h +++ b/key/keypress.h @@ -4,17 +4,7 @@ #include "../base/os.h" #include "keycode.h" - -#if defined(_MSC_VER) - #include "../base/ms_stdbool.h" -#else - #include -#endif - -#ifdef __cplusplus -extern "C" -{ -#endif +#include #if defined(IS_MACOSX) typedef enum { @@ -32,7 +22,6 @@ extern "C" MOD_CONTROL = ControlMask, MOD_SHIFT = ShiftMask }; - typedef unsigned int MMKeyFlags; #elif defined(IS_WINDOWS) enum _MMKeyFlags { @@ -43,43 +32,12 @@ extern "C" MOD_SHIFT = 0, */ MOD_META = MOD_WIN }; - typedef unsigned int MMKeyFlags; #endif #if defined(IS_WINDOWS) -/* Send win32 key event for given key. */ -void win32KeyEvent(int key, MMKeyFlags flags); -#endif - -/* Toggles the given key down or up. */ -void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags); - -/* Toggles the key down and then up. */ -void tapKeyCode(MMKeyCode code, MMKeyFlags flags); - -/* Toggles the key corresponding to the given UTF character up or down. */ -void toggleKey(char c, const bool down, MMKeyFlags flags); -void tapKey(char c, MMKeyFlags flags); - -/* Sends a UTF-8 string without modifiers. */ -void typeString(const char *str); -/* Sends a Unicode character without modifiers. */ -void unicodeType(const unsigned value); - -/* Macro to convert WPM to CPM integers. - * (the average English word length is 5.1 characters.) */ -#define WPM_TO_CPM(WPM) (unsigned)(5.1 * WPM) - -/* Sends UTF-8 string without modifiers and - * with partially random delays between each letter. - * Note that deadbeef_srand() must be called before this function - * if you actually want randomness. - * */ -void typeStringDelayed(const char *str, const unsigned cpm); - -#ifdef __cplusplus -} + /* Send win32 key event for given key. */ + void win32KeyEvent(int key, MMKeyFlags flags); #endif #endif /* KEYPRESS_H */ diff --git a/key/keypress_c.h b/key/keypress_c.h index a6cf987b..3c6774c5 100644 --- a/key/keypress_c.h +++ b/key/keypress_c.h @@ -14,14 +14,20 @@ /* Convenience wrappers around ugly APIs. */ #if defined(IS_WINDOWS) - #define WIN32_KEY_EVENT_WAIT(key, flags) \ - (win32KeyEvent(key, flags), Sleep(DEADBEEF_RANDRANGE(0, 1))) + void WIN32_KEY_EVENT_WAIT(MMKeyCode key, DWORD flags) { + win32KeyEvent(key, flags); + Sleep(DEADBEEF_RANDRANGE(0, 1)); + } #elif defined(USE_X11) - #define X_KEY_EVENT(display, key, is_press) ( \ - XTestFakeKeyEvent(display, XKeysymToKeycode(display, key), is_press, CurrentTime), \ - XSync(display, false)) - #define X_KEY_EVENT_WAIT(display, key, is_press) ( \ - X_KEY_EVENT(display, key, is_press), microsleep(DEADBEEF_UNIFORM(0.0, 0.5))) + void X_KEY_EVENT(Display *display, MMKeyCode key, bool is_press) ( + XTestFakeKeyEvent(display, XKeysymToKeycode(display, key), is_press, CurrentTime); + XSync(display, false); + } + + void X_KEY_EVENT_WAIT(Display *display, MMKeyCode key, bool is_press) { + X_KEY_EVENT(display, key, is_press); + microsleep(DEADBEEF_UNIFORM(0.0, 0.5); + } #endif #if defined(IS_MACOSX) @@ -143,10 +149,10 @@ void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags) { const DWORD dwFlags = down ? 0 : KEYEVENTF_KEYUP; /* Parse modifier keys. */ - if (flags & MOD_META) WIN32_KEY_EVENT_WAIT(K_META, dwFlags); - if (flags & MOD_ALT) WIN32_KEY_EVENT_WAIT(K_ALT, dwFlags); - if (flags & MOD_CONTROL) WIN32_KEY_EVENT_WAIT(K_CONTROL, dwFlags); - if (flags & MOD_SHIFT) WIN32_KEY_EVENT_WAIT(K_SHIFT, dwFlags); + if (flags & MOD_META) { WIN32_KEY_EVENT_WAIT(K_META, dwFlags); } + if (flags & MOD_ALT) { WIN32_KEY_EVENT_WAIT(K_ALT, dwFlags); } + if (flags & MOD_CONTROL) { WIN32_KEY_EVENT_WAIT(K_CONTROL, dwFlags); } + if (flags & MOD_SHIFT) { WIN32_KEY_EVENT_WAIT(K_SHIFT, dwFlags); } win32KeyEvent(code, dwFlags); #elif defined(USE_X11) @@ -154,10 +160,10 @@ void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags) { const Bool is_press = down ? True : False; /* Just to be safe. */ /* Parse modifier keys. */ - if (flags & MOD_META) X_KEY_EVENT_WAIT(display, K_META, is_press); - if (flags & MOD_ALT) X_KEY_EVENT_WAIT(display, K_ALT, is_press); - if (flags & MOD_CONTROL) X_KEY_EVENT_WAIT(display, K_CONTROL, is_press); - if (flags & MOD_SHIFT) X_KEY_EVENT_WAIT(display, K_SHIFT, is_press); + if (flags & MOD_META) { X_KEY_EVENT_WAIT(display, K_META, is_press); } + if (flags & MOD_ALT) { X_KEY_EVENT_WAIT(display, K_ALT, is_press); } + if (flags & MOD_CONTROL) { X_KEY_EVENT_WAIT(display, K_CONTROL, is_press); } + if (flags & MOD_SHIFT) { X_KEY_EVENT_WAIT(display, K_SHIFT, is_press); } X_KEY_EVENT(display, code, is_press); #endif @@ -206,9 +212,9 @@ void toggleKey(char c, const bool down, MMKeyFlags flags){ #if defined(IS_WINDOWS) modifiers = keyCode >> 8; // Pull out modifers. - if ((modifiers & 1) != 0) flags |= MOD_SHIFT; // Uptdate flags from keycode modifiers. - if ((modifiers & 2) != 0) flags |= MOD_CONTROL; - if ((modifiers & 4) != 0) flags |= MOD_ALT; + if ((modifiers & 1) != 0) { flags |= MOD_SHIFT; } // Uptdate flags from keycode modifiers. + if ((modifiers & 2) != 0) { flags |= MOD_CONTROL; } + if ((modifiers & 4) != 0) { flags |= MOD_ALT; } keyCode = keyCode & 0xff; // Mask out modifiers. #endif @@ -222,12 +228,11 @@ void tapKey(char c, MMKeyFlags flags){ } #if defined(IS_MACOSX) -void toggleUnicode(UniChar ch, const bool down){ - /* This function relies on the convenient - * CGEventKeyboardSetUnicodeString(), which allows us to not have to - * convert characters to a keycode, but does not support adding modifier - * flags. It is therefore only used in typeStringDelayed() - * -- if you need modifier keys, use the above functions instead. */ +void toggleUnicode(UniChar ch, const bool down) { + /* This function relies on the convenient CGEventKeyboardSetUnicodeString(), + convert characters to a keycode, but does not support adding modifier flags. + It is only used in typeString(). + -- if you need modifier keys, use the above functions instead. */ CGEventRef keyEvent = CGEventCreateKeyboardEvent(NULL, 0, down); if (keyEvent == NULL) { fputs("Could not create keyboard event.\n", stderr); diff --git a/mouse/mouse.go b/mouse/mouse.go new file mode 100644 index 00000000..e22c34b1 --- /dev/null +++ b/mouse/mouse.go @@ -0,0 +1,11 @@ +// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// https://github.com/go-vgo/robotgo/blob/master/LICENSE +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +package mouse diff --git a/mouse/mouse.h b/mouse/mouse.h index ef061c51..9bfab1f1 100644 --- a/mouse/mouse.h +++ b/mouse/mouse.h @@ -4,24 +4,10 @@ #include "../base/os.h" #include "../base/types.h" - -#if defined(_MSC_VER) - #include "../base/ms_stdbool.h" -#else - #include -#endif - -#ifdef __cplusplus -// #ifdefined(__cplusplus)||defined(c_plusplus) -extern "C" -{ -#endif +#include #if defined(IS_MACOSX) - - // #include #include - // #include typedef enum { LEFT_BUTTON = kCGMouseButtonLeft, @@ -32,9 +18,7 @@ extern "C" WheelLeft = 6, WheelRight = 7, } MMMouseButton; - #elif defined(USE_X11) - enum _MMMouseButton { LEFT_BUTTON = 1, CENTER_BUTTON = 2, @@ -45,9 +29,7 @@ extern "C" WheelRight = 7, }; typedef unsigned int MMMouseButton; - #elif defined(IS_WINDOWS) - enum _MMMouseButton { LEFT_BUTTON = 1, CENTER_BUTTON = 2, @@ -58,62 +40,14 @@ extern "C" WheelRight = 7, }; typedef unsigned int MMMouseButton; - #else #error "No mouse button constants set for platform" #endif -#define MMMouseButtonIsValid(button) \ - (button == LEFT_BUTTON || button == RIGHT_BUTTON || \ - button == CENTER_BUTTON || button == WheelDown || \ - button == WheelUp || button == WheelLeft || \ - button == WheelRight) - enum __MMMouseWheelDirection { DIRECTION_DOWN = -1, DIRECTION_UP = 1 }; typedef int MMMouseWheelDirection; -/* Immediately moves the mouse to the given point on-screen. - * It is up to the caller to ensure that this point is within the - * screen boundaries. */ -void moveMouse(MMPointInt32 point); - -/* Like moveMouse, moves the mouse to the given point on-screen, but marks - * the event as the mouse being dragged on platforms where it is supported. - * It is up to the caller to ensure that this point is within the screen - * boundaries. */ -void dragMouse(MMPointInt32 point, const MMMouseButton button); - -/* Smoothly moves the mouse from the current position to the given point. - * deadbeef_srand() should be called before using this function. - * - * Returns false if unsuccessful (i.e. a point was hit that is outside of the - * screen boundaries), or true if successful. */ -bool smoothlyMoveMouse(MMPointInt32 endPoint, double lowSpeed, double highSpeed); -// bool smoothlyMoveMouse(MMPoint point); - -/* Returns the coordinates of the mouse on the current screen. */ -MMPointInt32 getMousePos(void); - -/* Holds down or releases the mouse with the given button in the current - * position. */ -void toggleMouse(bool down, MMMouseButton button); - -/* Clicks the mouse with the given button in the current position. */ -void clickMouse(MMMouseButton button); - -/* Double clicks the mouse with the given button. */ -void doubleClick(MMMouseButton button); - -/* Scrolls the mouse in the stated direction. - * TODO: Add a smoothly scroll mouse next. */ -void scrollMouse(int scrollMagnitude, MMMouseWheelDirection scrollDirection); - -//#ifdefined(__cplusplus)||defined(c_plusplus) -#ifdef __cplusplus -} -#endif - #endif /* MOUSE_H */ \ No newline at end of file diff --git a/mouse/mouse_c.h b/mouse/mouse_c.h index 366ae2e2..4f464c69 100644 --- a/mouse/mouse_c.h +++ b/mouse/mouse_c.h @@ -3,7 +3,6 @@ #include "../base/microsleep.h" #include /* For floor() */ - #if defined(IS_MACOSX) // #include #include @@ -12,58 +11,61 @@ #include #include #include - // #include "../base/xdisplay_c.h" -#endif - -#if !defined(M_SQRT2) - #define M_SQRT2 1.4142135623730950488016887 /* Fix for MSVC. */ #endif /* Some convenience macros for converting our enums to the system API types. */ #if defined(IS_MACOSX) +CGEventType MMMouseDownToCGEventType(MMMouseButton button) { + if (button == LEFT_BUTTON) { + return kCGEventLeftMouseDown; + } + if (button == RIGHT_BUTTON) { + return kCGEventRightMouseDown; + } + return kCGEventOtherMouseDown; +} -#define MMMouseToCGEventType(down, button) \ - (down ? MMMouseDownToCGEventType(button) : MMMouseUpToCGEventType(button)) - -#define MMMouseDownToCGEventType(button) \ - ((button) == (LEFT_BUTTON) ? kCGEventLeftMouseDown \ - : ((button) == RIGHT_BUTTON ? kCGEventRightMouseDown : kCGEventOtherMouseDown)) +CGEventType MMMouseUpToCGEventType(MMMouseButton button) { + if (button == LEFT_BUTTON) { return kCGEventLeftMouseUp; } + if (button == RIGHT_BUTTON) { return kCGEventRightMouseUp; } + return kCGEventOtherMouseUp; +} -#define MMMouseUpToCGEventType(button) \ - ((button) == LEFT_BUTTON ? kCGEventLeftMouseUp \ - : ((button) == RIGHT_BUTTON ? kCGEventRightMouseUp : kCGEventOtherMouseUp)) +CGEventType MMMouseDragToCGEventType(MMMouseButton button) { + if (button == LEFT_BUTTON) { return kCGEventLeftMouseDragged; } + if (button == RIGHT_BUTTON) { return kCGEventRightMouseDragged; } + return kCGEventOtherMouseDragged; +} -#define MMMouseDragToCGEventType(button) \ - ((button) == LEFT_BUTTON ? kCGEventLeftMouseDragged \ - : ((button) == RIGHT_BUTTON ? kCGEventRightMouseDragged : kCGEventOtherMouseDragged)) +CGEventType MMMouseToCGEventType(bool down, MMMouseButton button) { + if (down) { return MMMouseDownToCGEventType(button); } + return MMMouseUpToCGEventType(button); +} #elif defined(IS_WINDOWS) + +DWORD MMMouseUpToMEventF(MMMouseButton button) { + if (button == LEFT_BUTTON) { return MOUSEEVENTF_LEFTUP; } + if (button == RIGHT_BUTTON) { return MOUSEEVENTF_RIGHTUP; } + return MOUSEEVENTF_MIDDLEUP; +} -#define MMMouseToMEventF(down, button) \ - (down ? MMMouseDownToMEventF(button) : MMMouseUpToMEventF(button)) - -#define MMMouseUpToMEventF(button) \ - ((button) == LEFT_BUTTON ? MOUSEEVENTF_LEFTUP \ - : ((button) == RIGHT_BUTTON ? MOUSEEVENTF_RIGHTUP : MOUSEEVENTF_MIDDLEUP)) - -#define MMMouseDownToMEventF(button) \ - ((button) == LEFT_BUTTON ? MOUSEEVENTF_LEFTDOWN \ - : ((button) == RIGHT_BUTTON ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_MIDDLEDOWN)) +DWORD MMMouseDownToMEventF(MMMouseButton button) { + if (button == LEFT_BUTTON) { return MOUSEEVENTF_LEFTDOWN; } + if (button == RIGHT_BUTTON) { return MOUSEEVENTF_RIGHTDOWN; } + return MOUSEEVENTF_MIDDLEDOWN; +} +DWORD MMMouseToMEventF(bool down, MMMouseButton button) { + if (down) { return MMMouseDownToMEventF(button); } + return MMMouseUpToMEventF(button); +} #endif #if defined(IS_MACOSX) -/** - * Calculate the delta for a mouse move and add them to the event. - * @param event The mouse move event (by ref). - * @param point The new mouse x and y. - */ +/* Calculate the delta for a mouse move and add them to the event. */ void calculateDeltas(CGEventRef *event, MMPointInt32 point){ - /** - * The next few lines are a workaround for games not detecting mouse moves. - * See this issue for more information: - * https://github.com/go-vgo/robotgo/issues/159 - */ + /* The next few lines are a workaround for games not detecting mouse moves. */ CGEventRef get = CGEventCreate(NULL); CGPoint mouse = CGEventGetLocation(get); @@ -78,11 +80,7 @@ void calculateDeltas(CGEventRef *event, MMPointInt32 point){ } #endif - -/** - * Move the mouse to a specific point. - * @param point The coordinates to move the mouse to (x, y). - */ +/* Move the mouse to a specific point. */ void moveMouse(MMPointInt32 point){ #if defined(IS_MACOSX) CGEventRef move = CGEventCreateMouseEvent(NULL, kCGEventMouseMoved, @@ -117,7 +115,6 @@ void moveMouse(MMPointInt32 point){ mouseInput.mi.dwExtraInfo = 0; mouseInput.mi.mouseData = 0; SendInput(1, &mouseInput, sizeof(mouseInput)); - #endif } @@ -136,7 +133,7 @@ void dragMouse(MMPointInt32 point, const MMMouseButton button){ #endif } -MMPointInt32 getMousePos(){ +MMPointInt32 getMousePos() { #if defined(IS_MACOSX) CGEventRef event = CGEventCreate(NULL); CGPoint point = CGEventGetLocation(event); @@ -144,9 +141,9 @@ MMPointInt32 getMousePos(){ return MMPointInt32FromCGPoint(point); #elif defined(USE_X11) - int x, y; /* This is all we care about. Seriously. */ - Window garb1, garb2; /* Why you can't specify NULL as a parameter */ - int garb_x, garb_y; /* is beyond me. */ + int x, y; /* This is all we care about. Seriously. */ + Window garb1, garb2; /* Why you can't specify NULL as a parameter */ + int garb_x, garb_y; /* is beyond me. */ unsigned int more_garbage; Display *display = XGetMainDisplay(); @@ -157,17 +154,12 @@ MMPointInt32 getMousePos(){ #elif defined(IS_WINDOWS) POINT point; GetCursorPos(&point); - return MMPointInt32FromPOINT(point); #endif } -/** - * Press down a button, or release it. - * @param down True for down, false for up. - * @param button The button to press down or release. - */ -void toggleMouse(bool down, MMMouseButton button){ +/* Press down a button, or release it. */ +void toggleMouse(bool down, MMMouseButton button) { #if defined(IS_MACOSX) const CGPoint currentPos = CGPointFromMMPoint(getMousePos()); const CGEventType mouseType = MMMouseToCGEventType(down, button); @@ -200,10 +192,7 @@ void clickMouse(MMMouseButton button){ toggleMouse(false, button); } -/** - * Special function for sending double clicks, needed for Mac OS X. - * @param button Button to click. - */ +/* Special function for sending double clicks, needed for Mac OS X. */ void doubleClick(MMMouseButton button){ #if defined(IS_MACOSX) /* Double click for Mac. */ @@ -229,20 +218,14 @@ void doubleClick(MMMouseButton button){ #endif } -/** - * Function used to scroll the screen in the required direction. - * This uses the magnitude to scroll the required amount in the direction. - * TODO Requires further fine tuning based on the requirements. - */ +/* Function used to scroll the screen in the required direction. */ void scrollMouse(int scrollMagnitude, MMMouseWheelDirection scrollDirection){ #if defined(IS_WINDOWS) - // Fix for #97 https://github.com/go-vgo/robotgo/issues/97, // C89 needs variables declared on top of functions (mouseScrollInput) INPUT mouseScrollInput; #endif - /* Direction should only be considered based on the scrollDirection. This - * Should not interfere. */ + /* Direction should only be considered based on the scrollDirection. This Should not interfere. */ int cleanScrollMagnitude = abs(scrollMagnitude); if (!(scrollDirection == DIRECTION_UP || scrollDirection == DIRECTION_DOWN)) { return; @@ -250,7 +233,6 @@ void scrollMouse(int scrollMagnitude, MMMouseWheelDirection scrollDirection){ /* Set up the OS specific solution */ #if defined(__APPLE__) - CGWheelCount wheel = 1; CGEventRef event; @@ -289,15 +271,12 @@ void scrollMouse(int scrollMagnitude, MMMouseWheelDirection scrollDirection){ void scrollMouseXY(int x, int y) { #if defined(IS_WINDOWS) - // Fix for #97, - // C89 needs variables declared on top of functions (mouseScrollInput) + // Fix for #97, C89 needs variables declared on top of functions (mouseScrollInput) INPUT mouseScrollInputH; INPUT mouseScrollInputV; #endif - /* Direction should only be considered based on the scrollDirection. This - * Should not interfere. */ - + /* Direction should only be considered based on the scrollDirection. This Should not interfere. */ /* Set up the OS specific solution */ #if defined(__APPLE__) CGEventRef event; @@ -317,8 +296,7 @@ void scrollMouseXY(int x, int y) { xdir = 7; } - int xi; - int yi; + int xi; int yi; for (xi = 0; xi < abs(x); xi++) { XTestFakeButtonEvent(display, xdir, 1, CurrentTime); XTestFakeButtonEvent(display, xdir, 0, CurrentTime); @@ -351,16 +329,11 @@ void scrollMouseXY(int x, int y) { #endif } -/* - * A crude, fast hypot() approximation to get around the fact that hypot() is - * not a standard ANSI C function. - * - * It is not particularly accurate but that does not matter for our use case. - * - * Taken from this StackOverflow answer: - * http://stackoverflow.com/questions/3506404/fast-hypotenuse-algorithm-for-embedded-processor#3507882 - * - */ +/* A crude, fast hypot() approximation to get around the fact that hypot() is not a standard ANSI C function. */ +#if !defined(M_SQRT2) + #define M_SQRT2 1.4142135623730950488016887 /* Fix for MSVC. */ +#endif + static double crude_hypot(double x, double y){ double big = fabs(x); /* max(|x|, |y|) */ double small = fabs(y); /* min(|x|, |y|) */ @@ -381,7 +354,6 @@ bool smoothlyMoveMouse(MMPointInt32 endPoint, double lowSpeed, double highSpeed) double distance; while ((distance =crude_hypot((double)pos.x - endPoint.x, (double)pos.y - endPoint.y)) > 1.0) { - double gravity = DEADBEEF_UNIFORM(5.0, 500.0); // double gravity = DEADBEEF_UNIFORM(lowSpeed, highSpeed); double veloDistance; @@ -396,12 +368,10 @@ bool smoothlyMoveMouse(MMPointInt32 endPoint, double lowSpeed, double highSpeed) pos.x += floor(velo_x + 0.5); pos.y += floor(velo_y + 0.5); - /* Make sure we are in the screen boundaries! - * (Strange things will happen if we are not.) */ + /* Make sure we are in the screen boundaries! (Strange things will happen if we are not.) */ if (pos.x >= screenSize.w || pos.y >= screenSize.h) { return false; } - moveMouse(pos); /* Wait 1 - 3 milliseconds. */ diff --git a/mouse/mouse_darwin.go b/mouse/mouse_darwin.go new file mode 100644 index 00000000..de4c9b45 --- /dev/null +++ b/mouse/mouse_darwin.go @@ -0,0 +1,4 @@ +//go:build darwin +// +build darwin + +package mouse diff --git a/mouse/mouse_windows.go b/mouse/mouse_windows.go new file mode 100644 index 00000000..588de029 --- /dev/null +++ b/mouse/mouse_windows.go @@ -0,0 +1,4 @@ +//go:build windows +// +build windows + +package mouse diff --git a/mouse/mouse_x11.go b/mouse/mouse_x11.go new file mode 100644 index 00000000..3b452a3b --- /dev/null +++ b/mouse/mouse_x11.go @@ -0,0 +1,4 @@ +//go:build !darwin && !windows +// +build !darwin,!windows + +package mouse diff --git a/screen/goScreen.h b/screen/goScreen.h index 3a38f87e..b1222367 100644 --- a/screen/goScreen.h +++ b/screen/goScreen.h @@ -14,11 +14,9 @@ #include "screengrab_c.h" #include "screen_c.h" #include -// #include "../MMBitmap_c.h" void padHex(MMRGBHex color, char* hex) { // Length needs to be 7 because snprintf includes a terminating null. - // Use %06x to pad hex value with leading 0s. snprintf(hex, 7, "%06x", color); } @@ -29,7 +27,6 @@ char* pad_hex(MMRGBHex color) { char* str = (char*)calloc(100, sizeof(char*)); if (str) { strcpy(str, hex); } - return str; } @@ -56,7 +53,6 @@ MMRGBHex get_px_color(int32_t x, int32_t y, int32_t display_id) { bitmap = copyMMBitmapFromDisplayInRect(MMRectInt32Make(x, y, 1, 1), display_id); // bitmap = MMRectMake(x, y, 1, 1); - color = MMRGBHexAtPoint(bitmap, 0, 0); destroyMMBitmap(bitmap); @@ -79,7 +75,7 @@ MMSizeInt32 get_screen_size() { char* set_XDisplay_name(char* name) { #if defined(USE_X11) setXDisplay(name); - return "success"; + return ""; #else return "SetXDisplayName is only supported on Linux"; #endif @@ -88,8 +84,8 @@ char* set_XDisplay_name(char* name) { char* get_XDisplay_name() { #if defined(USE_X11) const char* display = getXDisplay(); + char* sd = (char*)calloc(100, sizeof(char*)); - if (sd) { strcpy(sd, display); } return sd; #else @@ -126,7 +122,6 @@ void bitmap_dealloc(MMBitmapRef bitmap) { // capture_screen capture screen MMBitmapRef capture_screen(int32_t x, int32_t y, int32_t w, int32_t h, int32_t display_id) { MMBitmapRef bitmap = copyMMBitmapFromDisplayInRect(MMRectInt32Make(x, y, w, h), display_id); - // printf("%s\n", bitmap); return bitmap; } diff --git a/screen/screen.go b/screen/screen.go new file mode 100644 index 00000000..7424d9d0 --- /dev/null +++ b/screen/screen.go @@ -0,0 +1 @@ +package screen diff --git a/screen/screen.h b/screen/screen.h deleted file mode 100644 index 9cc9887b..00000000 --- a/screen/screen.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once -#ifndef SCREEN_H -#define SCREEN_H - -#include "../base/types.h" - -#if defined(_MSC_VER) - #include "../base/ms_stdbool.h" -#else - #include -#endif - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* Returns the size of the main display. */ -MMSizeInt32 getMainDisplaySize(void); - -/* Convenience function that returns whether the given point is in the bounds - * of the main screen. */ -bool pointVisibleOnMainDisplay(MMPointInt32 point); - -#ifdef __cplusplus -} -#endif - -#endif /* SCREEN_H */ diff --git a/screen/screen_c.h b/screen/screen_c.h index 9845ff07..8c353cd4 100644 --- a/screen/screen_c.h +++ b/screen/screen_c.h @@ -1,4 +1,3 @@ -#include "screen.h" //#include "../base/os.h" #if defined(IS_MACOSX) @@ -8,7 +7,7 @@ // #include "../base/xdisplay_c.h" #endif -MMSizeInt32 getMainDisplaySize(void){ +MMSizeInt32 getMainDisplaySize(void) { #if defined(IS_MACOSX) CGDirectDisplayID displayID = CGMainDisplayID(); CGRect displayRect = CGDisplayBounds(displayID); @@ -53,8 +52,7 @@ MMRectInt32 getScreenRect(int32_t display_id) { const int screen = DefaultScreen(display); return MMRectInt32Make( - (int32_t)0, - (int32_t)0, + (int32_t)0, (int32_t)0, (int32_t)DisplayWidth(display, screen), (int32_t)DisplayHeight(display, screen)); #elif defined(IS_WINDOWS) diff --git a/screen/screengrab.h b/screen/screengrab.h deleted file mode 100644 index 728925af..00000000 --- a/screen/screengrab.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once -#ifndef SCREENGRAB_H -#define SCREENGRAB_H - -#include "../base/types.h" -// #include "../base/MMBitmap_c.h" -#include "../base/bitmap_free_c.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* Returns a raw bitmap of screengrab of the display (to be destroyed()'d by - * caller), or NULL on error. */ -MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id); - -#ifdef __cplusplus -} -#endif - -#endif /* SCREENGRAB_H */ diff --git a/screen/screengrab_c.h b/screen/screengrab_c.h index 1b13b67f..196afce9 100644 --- a/screen/screengrab_c.h +++ b/screen/screengrab_c.h @@ -1,6 +1,4 @@ -#include "screengrab.h" -// #include "../base/bmp_io_c.h" -#include "../base/endian.h" +#include "../base/bitmap_free_c.h" #include /* malloc() */ #if defined(IS_MACOSX) @@ -12,8 +10,6 @@ #include #include "../base/xdisplay_c.h" #elif defined(IS_WINDOWS) - // #include "windows.h" - // #include #include #endif @@ -99,11 +95,10 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id) dib = CreateDIBSection(screen, &bi, DIB_RGB_COLORS, &data, NULL, 0); /* Copy the data into a bitmap struct. */ - if ((screenMem = CreateCompatibleDC(screen)) == NULL || SelectObject(screenMem, dib) == NULL || - !BitBlt(screenMem, (int)0, (int)0, (int)rect.size.w, (int)rect.size.h, - screen, rect.origin.x, rect.origin.y, SRCCOPY) - ) { - + bool smem = (screenMem = CreateCompatibleDC(screen)) == NULL; + bool bitb = BitBlt(screenMem, (int)0, (int)0, (int)rect.size.w, (int)rect.size.h, + screen, rect.origin.x, rect.origin.y, SRCCOPY); + if (smem || SelectObject(screenMem, dib) == NULL || !bitb) { /* Error copying data. */ ReleaseDC(NULL, screen); DeleteObject(dib); diff --git a/window/alert_c.h b/window/alert_c.h index 8fd68c9d..5d67733e 100644 --- a/window/alert_c.h +++ b/window/alert_c.h @@ -1,14 +1,13 @@ // #include "os.h" - #if defined(IS_MACOSX) #include #endif #if defined(IS_MACOSX) - #define CFStringCreateWithUTF8String(string) \ - ((string) == NULL ? NULL : CFStringCreateWithCString(NULL, \ - string, \ - kCFStringEncodingUTF8)) + CFStringRef CFStringCreateWithUTF8String(const char *title) { + if (title == NULL) { return NULL; } + return CFStringCreateWithCString(NULL, title, kCFStringEncodingUTF8); + } #endif int showAlert(const char *title, const char *msg, @@ -36,7 +35,7 @@ int showAlert(const char *title, const char *msg, /* TODO: Display custom buttons instead of the pre-defined "OK" * and "Cancel". */ int response = MessageBox(NULL, msg, title, - (cancelButton == NULL) ? MB_OK : MB_OKCANCEL); + (cancelButton == NULL) ? MB_OK : MB_OKCANCEL ); return (response == IDOK) ? 0 : 1; #endif } diff --git a/window/window.go b/window/window.go new file mode 100644 index 00000000..1788c404 --- /dev/null +++ b/window/window.go @@ -0,0 +1 @@ +package window From d82ca8cee4d7c2234e4301fdbefa3fac0e635bd3 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 3 Feb 2022 03:03:32 -0800 Subject: [PATCH 198/327] Refactor some mouse and window C code to Go --- key/keycode_c.h | 30 +++++------ key/keypress_c.h | 2 +- mouse/goMouse.h | 106 -------------------------------------- mouse/mouse.h | 6 --- mouse/mouse_c.h | 50 ------------------ robotgo.go | 116 +++++++++++++++--------------------------- screen/goScreen.h | 8 --- screen/screengrab_c.h | 4 +- window/goWindow.h | 58 ++------------------- window/pub.h | 3 -- window/win_sys.h | 13 ++--- window/window.h | 65 ++++++++++------------- 12 files changed, 97 insertions(+), 364 deletions(-) delete mode 100644 mouse/goMouse.h diff --git a/key/keycode_c.h b/key/keycode_c.h index dfcc71ff..4af3175e 100644 --- a/key/keycode_c.h +++ b/key/keycode_c.h @@ -81,23 +81,23 @@ MMKeyCode keyCodeForChar(const char c) { } #if defined(IS_MACOSX) -CFStringRef createStringForKey(CGKeyCode keyCode){ - TISInputSourceRef currentKeyboard = TISCopyCurrentASCIICapableKeyboardInputSource(); - CFDataRef layoutData = (CFDataRef) TISGetInputSourceProperty( - currentKeyboard, kTISPropertyUnicodeKeyLayoutData); + CFStringRef createStringForKey(CGKeyCode keyCode){ + TISInputSourceRef currentKeyboard = TISCopyCurrentASCIICapableKeyboardInputSource(); + CFDataRef layoutData = (CFDataRef) TISGetInputSourceProperty( + currentKeyboard, kTISPropertyUnicodeKeyLayoutData); - if (layoutData == nil) { return 0; } + if (layoutData == nil) { return 0; } - const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout *) CFDataGetBytePtr(layoutData); - UInt32 keysDown = 0; - UniChar chars[4]; - UniCharCount realLength; + const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout *) CFDataGetBytePtr(layoutData); + UInt32 keysDown = 0; + UniChar chars[4]; + UniCharCount realLength; - UCKeyTranslate(keyboardLayout, keyCode, kUCKeyActionDisplay, 0, LMGetKbdType(), - kUCKeyTranslateNoDeadKeysBit, &keysDown, - sizeof(chars) / sizeof(chars[0]), &realLength, chars); - CFRelease(currentKeyboard); + UCKeyTranslate(keyboardLayout, keyCode, kUCKeyActionDisplay, 0, LMGetKbdType(), + kUCKeyTranslateNoDeadKeysBit, &keysDown, + sizeof(chars) / sizeof(chars[0]), &realLength, chars); + CFRelease(currentKeyboard); - return CFStringCreateWithCharacters(kCFAllocatorDefault, chars, 1); -} + return CFStringCreateWithCharacters(kCFAllocatorDefault, chars, 1); + } #endif diff --git a/key/keypress_c.h b/key/keypress_c.h index 3c6774c5..74ead816 100644 --- a/key/keypress_c.h +++ b/key/keypress_c.h @@ -19,7 +19,7 @@ Sleep(DEADBEEF_RANDRANGE(0, 1)); } #elif defined(USE_X11) - void X_KEY_EVENT(Display *display, MMKeyCode key, bool is_press) ( + void X_KEY_EVENT(Display *display, MMKeyCode key, bool is_press) { XTestFakeKeyEvent(display, XKeysymToKeycode(display, key), is_press, CurrentTime); XSync(display, false); } diff --git a/mouse/goMouse.h b/mouse/goMouse.h deleted file mode 100644 index a3cf34b6..00000000 --- a/mouse/goMouse.h +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// https://github.com/go-vgo/robotgo/blob/master/LICENSE -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#include "../base/types.h" -#include "mouse_c.h" - -// Global delays. -int mouseDelay = 0; - -int move_mouse(int32_t x, int32_t y){ - MMPointInt32 point; - point = MMPointInt32Make(x, y); - moveMouse(point); - - return 0; -} - - -int drag_mouse(int32_t x, int32_t y, MMMouseButton button){ - MMPointInt32 point; - point = MMPointInt32Make(x, y); - dragMouse(point, button); - microsleep(mouseDelay); - - return 0; -} - -bool move_mouse_smooth(int32_t x, int32_t y, double lowSpeed, - double highSpeed, int msDelay){ - MMPointInt32 point; - point = MMPointInt32Make(x, y); - - bool cbool = smoothlyMoveMouse(point, lowSpeed, highSpeed); - microsleep(msDelay); - - return cbool; -} - -MMPointInt32 get_mouse_pos(){ - MMPointInt32 pos = getMousePos(); - return pos; -} - -int mouse_click(MMMouseButton button, bool doubleC){ - if (!doubleC) { - clickMouse(button); - } else { - doubleClick(button); - } - - microsleep(mouseDelay); - - return 0; -} - -int mouse_toggle(char* d, MMMouseButton button){ - bool down = false; - if (strcmp(d, "down") == 0) { - down = true; - } else if (strcmp(d, "up") == 0) { - down = false; - } else { - return 1; - } - - toggleMouse(down, button); - microsleep(mouseDelay); - - return 0; -} - -int set_mouse_delay(size_t val){ - mouseDelay = val; - return 0; -} - -int scroll(int x, int y, int msDelay){ - scrollMouseXY(x, y); - microsleep(msDelay); - - return 0; -} - -int scroll_mouse(size_t scrollMagnitude, char *s){ - MMMouseWheelDirection scrollDirection; - - if (strcmp(s, "up") == 0) { - scrollDirection = DIRECTION_UP; - } else if (strcmp(s, "down") == 0) { - scrollDirection = DIRECTION_DOWN; - } else { - return 1; - } - - scrollMouse(scrollMagnitude, scrollDirection); - microsleep(mouseDelay); - - return 0; -} diff --git a/mouse/mouse.h b/mouse/mouse.h index 9bfab1f1..52aba723 100644 --- a/mouse/mouse.h +++ b/mouse/mouse.h @@ -44,10 +44,4 @@ #error "No mouse button constants set for platform" #endif -enum __MMMouseWheelDirection { - DIRECTION_DOWN = -1, - DIRECTION_UP = 1 -}; -typedef int MMMouseWheelDirection; - #endif /* MOUSE_H */ \ No newline at end of file diff --git a/mouse/mouse_c.h b/mouse/mouse_c.h index 4f464c69..3b8fc6f2 100644 --- a/mouse/mouse_c.h +++ b/mouse/mouse_c.h @@ -219,56 +219,6 @@ void doubleClick(MMMouseButton button){ } /* Function used to scroll the screen in the required direction. */ -void scrollMouse(int scrollMagnitude, MMMouseWheelDirection scrollDirection){ - #if defined(IS_WINDOWS) - // C89 needs variables declared on top of functions (mouseScrollInput) - INPUT mouseScrollInput; - #endif - - /* Direction should only be considered based on the scrollDirection. This Should not interfere. */ - int cleanScrollMagnitude = abs(scrollMagnitude); - if (!(scrollDirection == DIRECTION_UP || scrollDirection == DIRECTION_DOWN)) { - return; - } - - /* Set up the OS specific solution */ - #if defined(__APPLE__) - CGWheelCount wheel = 1; - CGEventRef event; - - /* Make scroll magnitude negative if we're scrolling down. */ - cleanScrollMagnitude = cleanScrollMagnitude * scrollDirection; - - event = CGEventCreateScrollWheelEvent(NULL, kCGScrollEventUnitLine, wheel, cleanScrollMagnitude, 0); - CGEventPost(kCGHIDEventTap, event); - #elif defined(USE_X11) - int x; - int dir = 4; /* Button 4 is up, 5 is down. */ - Display *display = XGetMainDisplay(); - - if (scrollDirection == DIRECTION_DOWN) { - dir = 5; - } - - for (x = 0; x < cleanScrollMagnitude; x++) { - XTestFakeButtonEvent(display, dir, 1, CurrentTime); - XTestFakeButtonEvent(display, dir, 0, CurrentTime); - } - - XSync(display, false); - #elif defined(IS_WINDOWS) - mouseScrollInput.type = INPUT_MOUSE; - mouseScrollInput.mi.dx = 0; - mouseScrollInput.mi.dy = 0; - mouseScrollInput.mi.dwFlags = MOUSEEVENTF_WHEEL; - mouseScrollInput.mi.time = 0; - mouseScrollInput.mi.dwExtraInfo = 0; - mouseScrollInput.mi.mouseData = WHEEL_DELTA * scrollDirection * cleanScrollMagnitude; - - SendInput(1, &mouseScrollInput, sizeof(mouseScrollInput)); - #endif -} - void scrollMouseXY(int x, int y) { #if defined(IS_WINDOWS) // Fix for #97, C89 needs variables declared on top of functions (mouseScrollInput) diff --git a/robotgo.go b/robotgo.go index 6f178661..913d2dc7 100644 --- a/robotgo.go +++ b/robotgo.go @@ -38,13 +38,12 @@ package robotgo #cgo windows LDFLAGS: -lgdi32 -luser32 // #include "screen/goScreen.h" -#include "mouse/goMouse.h" +#include "mouse/mouse_c.h" #include "window/goWindow.h" */ import "C" import ( - "errors" "image" "runtime" "time" @@ -129,7 +128,7 @@ func Sleep(tm int) { time.Sleep(time.Duration(tm) * time.Second) } -// MicroSleep time C.microsleep(tm), use the MilliSleep +// MicroSleep time C.microsleep(tm), use the MilliSleep() func MicroSleep(tm float64) { C.microsleep(C.double(tm)) } @@ -250,8 +249,7 @@ func Scaled0(x int, f float64) int { // GetScreenSize get the screen size func GetScreenSize() (int, int) { - size := C.get_screen_size() - // fmt.Println("...", size, size.width) + size := C.getMainDisplaySize() return int(size.w), int(size.h) } @@ -368,8 +366,8 @@ func ToBitmap(bit CBitmap) Bitmap { func ToCBitmap(bit Bitmap) CBitmap { cbitmap := C.createMMBitmap_c( (*C.uint8_t)(bit.ImgBuf), - C.size_t(bit.Width), - C.size_t(bit.Height), + C.int32_t(bit.Width), + C.int32_t(bit.Height), C.size_t(bit.Bytewidth), C.uint8_t(bit.BitsPixel), C.uint8_t(bit.BytesPerPixel), @@ -411,7 +409,7 @@ func GetXDisplayName() string { // // ScaleX get the primary display horizontal DPI scale factor, drop func ScaleX() int { - return int(C.scale_x()) + return int(C.scaleX()) } // Deprecated: use the ScaledF(), @@ -502,7 +500,7 @@ func Move(x, y int) { cx := C.int32_t(x) cy := C.int32_t(y) - C.move_mouse(cx, cy) + C.moveMouse(C.MMPointInt32Make(cx, cy)) MilliSleep(MouseSleep) } @@ -532,7 +530,7 @@ func Drag(x, y int, args ...string) { button = CheckMouse(args[0]) } - C.drag_mouse(cx, cy, button) + C.dragMouse(C.MMPointInt32Make(cx, cy), button) MilliSleep(MouseSleep) } @@ -590,8 +588,8 @@ func MoveSmooth(x, y int, args ...interface{}) bool { high = 3.0 } - cbool := C.move_mouse_smooth(cx, cy, low, high, C.int(mouseDelay)) - MilliSleep(MouseSleep) + cbool := C.smoothlyMoveMouse(C.MMPointInt32Make(cx, cy), low, high) + MilliSleep(MouseSleep + mouseDelay) return bool(cbool) } @@ -618,7 +616,7 @@ func MoveSmoothRelative(x, y int, args ...interface{}) { // GetMousePos get the mouse's portion return x, y func GetMousePos() (int, int) { - pos := C.get_mouse_pos() + pos := C.getMousePos() x := int(pos.x) y := int(pos.y) @@ -645,7 +643,7 @@ func MouseClick(args ...interface{}) { func Click(args ...interface{}) { var ( button C.MMMouseButton = C.LEFT_BUTTON - double C.bool + double bool ) if len(args) > 0 { @@ -653,10 +651,15 @@ func Click(args ...interface{}) { } if len(args) > 1 { - double = C.bool(args[1].(bool)) + double = args[1].(bool) + } + + if !double { + C.clickMouse(button) + } else { + C.doubleClick(button) } - C.mouse_click(button, double) MilliSleep(MouseSleep) } @@ -694,56 +697,28 @@ func Toggle(key ...string) error { if len(key) > 0 { button = CheckMouse(key[0]) } - down := C.CString("down") - if len(key) > 1 { - down = C.CString(key[1]) - } - i := C.mouse_toggle(down, button) - C.free(unsafe.Pointer(down)) - MilliSleep(MouseSleep) - if int(i) == 0 { - return nil - } - return errors.New("Undefined params.") -} - -// Deprecated: use the Toggle(), -// -// MouseToggle toggle the mouse -// -// Examples: -// robotgo.MouseToggle("down", "right") -// robotgo.MouseToggle("up", "right") -func MouseToggle(togKey string, args ...interface{}) int { - var button C.MMMouseButton = C.LEFT_BUTTON - - if len(args) > 0 { - button = CheckMouse(args[0].(string)) + down := true + if len(key) > 1 && key[1] == "up" { + down = false } + C.toggleMouse(C.bool(down), button) + MilliSleep(MouseSleep) - down := C.CString(togKey) - i := C.mouse_toggle(down, button) + return nil +} - C.free(unsafe.Pointer(down)) - MilliSleep(MouseSleep) - return int(i) +// MouseDown send mouse down event +func MouseDown(key ...string) error { + return Toggle(key...) } -// Deprecated: use the Scroll(), -// -// ScrollMouse scroll the mouse to (x, "up") -// -// Examples: -// robotgo.ScrollMouse(10, "down") -// robotgo.ScrollMouse(10, "up") -func ScrollMouse(x int, direction string) { - cx := C.size_t(x) - cy := C.CString(direction) - C.scroll_mouse(cx, cy) - - C.free(unsafe.Pointer(cy)) - MilliSleep(MouseSleep) +// MouseUp send mouse up event +func MouseUp(key ...string) error { + if len(key) <= 0 { + key = append(key, "left") + } + return Toggle(append(key, "up")...) } // Scroll scroll the mouse to (x, y) @@ -760,10 +735,9 @@ func Scroll(x, y int, args ...int) { cx := C.int(x) cy := C.int(y) - cz := C.int(msDelay) - C.scroll(cx, cy, cz) - MilliSleep(MouseSleep) + C.scrollMouseXY(cx, cy) + MilliSleep(MouseSleep + msDelay) } // ScrollSmooth scroll the mouse smooth, @@ -809,12 +783,6 @@ func ScrollRelative(x, y int, args ...int) { Scroll(mx, my, args...) } -// SetMouseDelay set mouse delay -func SetMouseDelay(delay int) { - cdelay := C.size_t(delay) - C.set_mouse_delay(cdelay) -} - /* ____ __ ____ __ .__ __. _______ ______ ____ __ ____ \ \ / \ / / | | | \ | | | \ / __ \ \ \ / \ / / @@ -850,7 +818,7 @@ func showAlert(title, msg string, args ...string) bool { defaultButton := C.CString(defaultBtn) cancelButton := C.CString(cancelBtn) - cbool := C.show_alert(cTitle, cMsg, defaultButton, cancelButton) + cbool := C.showAlert(cTitle, cMsg, defaultButton, cancelButton) ibool := int(cbool) C.free(unsafe.Pointer(cTitle)) @@ -929,13 +897,13 @@ func CloseWindow(args ...int32) { isHwnd = args[1] } - C.close_window(C.uintptr(hwnd), C.uintptr(isHwnd)) + C.close_window_by_PId(C.uintptr(hwnd), C.uintptr(isHwnd)) } // SetHandle set the window handle func SetHandle(hwnd int) { chwnd := C.uintptr(hwnd) - C.set_handle(chwnd) + C.setHandle(chwnd) } // SetHandlePid set the window handle by pid @@ -973,14 +941,14 @@ func GetHandle() int { // This function will be removed in version v1.0.0 func GetBHandle() int { tt.Drop("GetBHandle", "GetHandle") - hwnd := C.bget_handle() + hwnd := C.b_get_handle() ghwnd := int(hwnd) //fmt.Println("gethwnd---", ghwnd) return ghwnd } func cgetTitle(hwnd, isHwnd int32) string { - title := C.get_title(C.uintptr(hwnd), C.uintptr(isHwnd)) + title := C.get_title_by_pid(C.uintptr(hwnd), C.uintptr(isHwnd)) gtitle := C.GoString(title) return gtitle diff --git a/screen/goScreen.h b/screen/goScreen.h index b1222367..fb9048d6 100644 --- a/screen/goScreen.h +++ b/screen/goScreen.h @@ -52,7 +52,6 @@ MMRGBHex get_px_color(int32_t x, int32_t y, int32_t display_id) { } bitmap = copyMMBitmapFromDisplayInRect(MMRectInt32Make(x, y, 1, 1), display_id); - // bitmap = MMRectMake(x, y, 1, 1); color = MMRGBHexAtPoint(bitmap, 0, 0); destroyMMBitmap(bitmap); @@ -66,12 +65,6 @@ char* get_pixel_color(int32_t x, int32_t y, int32_t display_id) { return s; } -MMSizeInt32 get_screen_size() { - // Get display size. - MMSizeInt32 displaySize = getMainDisplaySize(); - return displaySize; -} - char* set_XDisplay_name(char* name) { #if defined(USE_X11) setXDisplay(name); @@ -111,7 +104,6 @@ uint32_t get_num_displays() { #endif } - void bitmap_dealloc(MMBitmapRef bitmap) { if (bitmap != NULL) { destroyMMBitmap(bitmap); diff --git a/screen/screengrab_c.h b/screen/screengrab_c.h index 196afce9..883decb8 100644 --- a/screen/screengrab_c.h +++ b/screen/screengrab_c.h @@ -95,8 +95,8 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id) dib = CreateDIBSection(screen, &bi, DIB_RGB_COLORS, &data, NULL, 0); /* Copy the data into a bitmap struct. */ - bool smem = (screenMem = CreateCompatibleDC(screen)) == NULL; - bool bitb = BitBlt(screenMem, (int)0, (int)0, (int)rect.size.w, (int)rect.size.h, + BOOL smem = (screenMem = CreateCompatibleDC(screen)) == NULL; + BOOL bitb = BitBlt(screenMem, (int)0, (int)0, (int)rect.size.w, (int)rect.size.h, screen, rect.origin.x, rect.origin.y, SRCCOPY); if (smem || SelectObject(screenMem, dib) == NULL || !bitb) { /* Error copying data. */ diff --git a/window/goWindow.h b/window/goWindow.h index 9bdcd250..7ab510e1 100644 --- a/window/goWindow.h +++ b/window/goWindow.h @@ -12,27 +12,12 @@ #include "window.h" #include "win_sys.h" -int show_alert(const char *title, const char *msg, - const char *defaultButton, const char *cancelButton){ - - return showAlert(title, msg, defaultButton, cancelButton); -} - -intptr scale_x(){ - return scaleX(); -} - -bool is_valid(){ - return IsValid(); -} - void min_window(uintptr pid, bool state, uintptr isHwnd){ #if defined(IS_MACOSX) // return 0; AXUIElementRef axID = AXUIElementCreateApplication(pid); - - AXUIElementSetAttributeValue(axID, kAXMinimizedAttribute, - state ? kCFBooleanTrue : kCFBooleanFalse); + AXUIElementSetAttributeValue(axID, kAXMinimizedAttribute, + state ? kCFBooleanTrue : kCFBooleanFalse); #elif defined(USE_X11) // Ignore X errors XDismissErrors(); @@ -64,16 +49,8 @@ void max_window(uintptr pid, bool state, uintptr isHwnd){ #endif } -void close_window(uintptr pid, uintptr isHwnd){ - close_window_by_PId(pid, isHwnd); -} - -bool set_handle(uintptr handle){ - return setHandle(handle); -} - uintptr get_handle(){ - MData mData = GetActive(); + MData mData = get_active(); #if defined(IS_MACOSX) return (uintptr)mData.CgID; @@ -84,8 +61,7 @@ uintptr get_handle(){ #endif } -// uint32 uintptr -uintptr getHandle() { +uintptr b_get_handle() { #if defined(IS_MACOSX) return (uintptr)mData.CgID; #elif defined(USE_X11) @@ -95,31 +71,7 @@ uintptr getHandle() { #endif } -uintptr bget_handle(){ - return getHandle(); -} - -void set_active(const MData win){ - SetActive(win); -} - void active_PID(uintptr pid, uintptr isHwnd){ MData win = set_handle_pid(pid, isHwnd); - SetActive(win); -} - -MData get_active(){ - MData mdata = GetActive(); - return mdata; -} - -char* get_title(uintptr pid, uintptr isHwnd){ - char* title = get_title_by_pid(pid, isHwnd); - // printf("title::::%s\n", title ); - return title; -} - -int32_t get_PID(void){ - int pid = WGetPID(); - return pid; + set_active(win); } diff --git a/window/pub.h b/window/pub.h index 4f0766e2..f38d4d44 100644 --- a/window/pub.h +++ b/window/pub.h @@ -46,7 +46,6 @@ typedef struct _Bounds Bounds; static AXUIElementRef GetUIElement(CGWindowID win){ intptr pid = 0; // double_t pid = 0; - // Create array storing window CGWindowID window[1] = { win }; CFArrayRef wlist = CFArrayCreate(NULL, (const void**)window, 1, NULL); @@ -59,7 +58,6 @@ typedef struct _Bounds Bounds; if (info != NULL && CFArrayGetCount(info) > 0) { // Retrieve description from info array CFDictionaryRef desc = (CFDictionaryRef)CFArrayGetValueAtIndex(info, 0); - // Get window PID CFNumberRef data = (CFNumberRef) CFDictionaryGetValue(desc, kCGWindowOwnerPID); if (data != NULL) { @@ -269,7 +267,6 @@ typedef struct _Bounds Bounds; #elif defined(IS_WINDOWS) - // void win_min(HWND hwnd, bool state){ if (state) { ShowWindow(hwnd, SW_MINIMIZE); diff --git a/window/win_sys.h b/window/win_sys.h index 92ea3a5a..9a800608 100644 --- a/window/win_sys.h +++ b/window/win_sys.h @@ -8,10 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// #include "../base/os.h" #if defined(USE_X11) - // #include - // #include #include #endif @@ -79,7 +76,7 @@ intptr scaleX(){ Bounds get_bounds(uintptr pid, uintptr isHwnd){ // Check if the window is valid Bounds bounds; - if (!IsValid()) { return bounds; } + if (!is_valid()) { return bounds; } #if defined(IS_MACOSX) // Bounds bounds; @@ -153,7 +150,7 @@ Bounds get_bounds(uintptr pid, uintptr isHwnd){ Bounds get_client(uintptr pid, uintptr isHwnd) { // Check if the window is valid Bounds bounds; - if (!IsValid()) { return bounds; } + if (!is_valid()) { return bounds; } #if defined(IS_MACOSX) return get_bounds(pid, isHwnd); @@ -182,9 +179,7 @@ Bounds get_client(uintptr pid, uintptr isHwnd) { // Coordinates must be translated if (parent != attr.root) { XTranslateCoordinates(rDisplay, win.XWin, attr.root, attr.x, attr.y, &x, &y, &parent); - } - // Coordinates can be left alone - else { + } else { x = attr.x; y = attr.y; } @@ -200,7 +195,7 @@ Bounds get_client(uintptr pid, uintptr isHwnd) { #elif defined(IS_WINDOWS) HWND hwnd; if (isHwnd == 0) { - hwnd= GetHwndByPId(pid); + hwnd = GetHwndByPId(pid); } else { hwnd = (HWND)pid; } diff --git a/window/window.h b/window/window.h index 6b799740..77d7a496 100644 --- a/window/window.h +++ b/window/window.h @@ -8,13 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// #include "../base/os.h" #include "pub.h" bool setHandle(uintptr handle); -bool IsValid(); +bool is_valid(); bool IsAxEnabled(bool options); -MData GetActive(void); + +MData get_active(void); void initWindow(); char* get_title_by_hand(MData m_data); void close_window_by_Id(MData m_data); @@ -74,13 +74,13 @@ void set_handle_pid_mData(uintptr pid, uintptr isHwnd){ mData = win; } -bool IsValid() { +bool is_valid() { initWindow(initHandle); if (!IsAxEnabled(true)) { printf("%s\n", "Window: Accessibility API is disabled!\n" "Failed to enable access for assistive devices."); } - MData actdata = GetActive(); + MData actdata = get_active(); #if defined(IS_MACOSX) mData.CgID = actdata.CgID; @@ -131,16 +131,13 @@ bool IsAxEnabled(bool options){ static dispatch_once_t once; dispatch_once (&once, ^{ // Open the framework - void* handle = dlopen("/System/Library/Frameworks/Application" - "Services.framework/ApplicationServices", RTLD_LAZY); + void* handle = dlopen("/System/Library/Frameworks/Application" + "Services.framework/ApplicationServices", RTLD_LAZY); // Validate the handle if (handle != NULL) { - *(void**) (&gAXIsProcessTrustedWithOptions) = - dlsym (handle, "AXIsProcessTrustedWithOptions"); - - gkAXTrustedCheckOptionPrompt = - (CFStringRef*) dlsym (handle, "kAXTrustedCheckOptionPrompt"); + *(void**) (&gAXIsProcessTrustedWithOptions) = dlsym (handle, "AXIsProcessTrustedWithOptions"); + gkAXTrustedCheckOptionPrompt = (CFStringRef*) dlsym (handle, "kAXTrustedCheckOptionPrompt"); } }); @@ -207,11 +204,11 @@ bool setHandle(uintptr handle){ return false; #elif defined(USE_X11) mData.XWin = (Window)handle; - if (handle == 0){ + if (handle == 0) { return true; } - if (IsValid()){ + if (is_valid()) { return true; } @@ -223,7 +220,7 @@ bool setHandle(uintptr handle){ return true; } - if (IsValid()) { + if (is_valid()) { return true; } @@ -234,7 +231,7 @@ bool setHandle(uintptr handle){ bool IsTopMost(void){ // Check the window validity - if (!IsValid()) {return false;} + if (!is_valid()) { return false; } #if defined(IS_MACOSX) return false; // WARNING: Unavailable #elif defined(USE_X11) @@ -248,7 +245,7 @@ bool IsTopMost(void){ bool IsMinimized(void){ // Check the window validity - if (!IsValid()) {return false;} + if (!is_valid()) { return false; } #if defined(IS_MACOSX) CFBooleanRef data = NULL; // Determine whether the window is minimized @@ -273,7 +270,7 @@ bool IsMinimized(void){ ////// bool IsMaximized(void){ // Check the window validity - if (!IsValid()) {return false;} + if (!is_valid()) { return false; } #if defined(IS_MACOSX) return false; // WARNING: Unavailable #elif defined(USE_X11) @@ -285,16 +282,15 @@ bool IsMaximized(void){ #endif } -void SetActive(const MData win) { +void set_active(const MData win) { // Check if the window is valid - if (!IsValid()) { return; } + if (!is_valid()) { return; } #if defined(IS_MACOSX) // Attempt to raise the specified window object if (AXUIElementPerformAction(win.AxID, kAXRaiseAction) != kAXErrorSuccess) { pid_t pid = 0; // Attempt to retrieve the PID of the window - if (AXUIElementGetPid(win.AxID, &pid) - != kAXErrorSuccess || !pid) {return;} + if (AXUIElementGetPid(win.AxID, &pid) != kAXErrorSuccess || !pid) { return; } // Ignore deprecated warnings #pragma clang diagnostic push @@ -309,7 +305,6 @@ void SetActive(const MData win) { #pragma clang diagnostic pop } - #elif defined(USE_X11) // Ignore X errors XDismissErrors(); @@ -355,7 +350,7 @@ void SetActive(const MData win) { #endif } -MData GetActive(void) { +MData get_active(void) { #if defined(IS_MACOSX) MData result; // Ignore deprecated warnings @@ -372,7 +367,7 @@ MData GetActive(void) { // Create accessibility object using focused PID AXUIElementRef focused = AXUIElementCreateApplication(pid); - if (focused == NULL) {return result; }// Verify + if (focused == NULL) { return result; } // Verify AXUIElementRef element; // Retrieve the currently focused window @@ -449,10 +444,9 @@ MData GetActive(void) { #endif } - void SetTopMost(bool state){ // Check window validity - if (!IsValid()) {return;} + if (!is_valid()) { return; } #if defined(IS_MACOSX) // WARNING: Unavailable #elif defined(USE_X11) @@ -465,9 +459,9 @@ void SetTopMost(bool state){ #endif } -void close_main_window (){ +void close_main_window () { // Check if the window is valid - if (!IsValid()) { return; } + if (!is_valid()) { return; } close_window_by_Id(mData); } @@ -477,11 +471,10 @@ void close_window_by_PId(uintptr pid, uintptr isHwnd){ close_window_by_Id(win); } - // CloseWindow void close_window_by_Id(MData m_data){ // Check window validity - if (!IsValid()) { return; } + if (!is_valid()) { return; } #if defined(IS_MACOSX) AXUIElementRef b = NULL; // Retrieve the close button of this window @@ -506,7 +499,7 @@ void close_window_by_Id(MData m_data){ char* get_main_title(){ // Check if the window is valid - if (!IsValid()) { return "IsValid failed."; } + if (!is_valid()) { return "is_valid failed."; } return get_title_by_hand(mData); } @@ -532,7 +525,7 @@ char* named(void *result) { char* get_title_by_hand(MData m_data){ // Check if the window is valid - if (!IsValid()) { return "IsValid failed."; } + if (!is_valid()) { return "is_valid failed."; } #if defined(IS_MACOSX) CFStringRef data = NULL; // Determine the current title of the window @@ -591,16 +584,15 @@ char* get_title_by_hand(MData m_data){ #endif } -int32_t WGetPID(void) { +int32_t get_PID(void) { // Check window validity - if (!IsValid()) { return 0; } + if (!is_valid()) { return 0; } #if defined(IS_MACOSX) pid_t pid = 0; // Attempt to retrieve the window pid if (AXUIElementGetPid(mData.AxID, &pid)== kAXErrorSuccess) { return pid; } - return 0; #elif defined(USE_X11) // Ignore X errors @@ -620,4 +612,3 @@ int32_t WGetPID(void) { return id; #endif } - From 5d460e5100fa38e2585236a45edd97761edf61d2 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 3 Feb 2022 03:14:44 -0800 Subject: [PATCH 199/327] Fixed CI build --- base/os.h | 3 +-- base/types.h | 1 + key/keypress_c.h | 2 +- mouse/mouse_c.h | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/base/os.h b/base/os.h index 8baad8ac..6f6e74d2 100644 --- a/base/os.h +++ b/base/os.h @@ -5,8 +5,7 @@ /* Python versions under 2.5 don't support this macro, but it's not * terribly difficult to replicate: */ #ifndef PyModule_AddIntMacro - #define PyModule_AddIntMacro(module, macro) \ - PyModule_AddIntConstant(module, #macro, macro) + #define PyModule_AddIntMacro(module, macro) PyModule_AddIntConstant(module, #macro, macro) #endif /* PyModule_AddIntMacro */ #if !defined(IS_MACOSX) && defined(__APPLE__) && defined(__MACH__) diff --git a/base/types.h b/base/types.h index 84f772c7..01080d27 100644 --- a/base/types.h +++ b/base/types.h @@ -6,6 +6,7 @@ #include "inline_keywords.h" /* For H_INLINE */ #include #include +#include /* Some generic, cross-platform types. */ #ifdef RobotGo_64 diff --git a/key/keypress_c.h b/key/keypress_c.h index 74ead816..1f5511d7 100644 --- a/key/keypress_c.h +++ b/key/keypress_c.h @@ -26,7 +26,7 @@ void X_KEY_EVENT_WAIT(Display *display, MMKeyCode key, bool is_press) { X_KEY_EVENT(display, key, is_press); - microsleep(DEADBEEF_UNIFORM(0.0, 0.5); + microsleep(DEADBEEF_UNIFORM(0.0, 0.5)); } #endif diff --git a/mouse/mouse_c.h b/mouse/mouse_c.h index 3b8fc6f2..6e08d9a6 100644 --- a/mouse/mouse_c.h +++ b/mouse/mouse_c.h @@ -122,7 +122,7 @@ void dragMouse(MMPointInt32 point, const MMMouseButton button){ #if defined(IS_MACOSX) const CGEventType dragType = MMMouseDragToCGEventType(button); CGEventRef drag = CGEventCreateMouseEvent(NULL, dragType, - CGPointFromMMPoint(point), (CGMouseButton)button); + CGPointFromMMPointInt32(point), (CGMouseButton)button); calculateDeltas(&drag, point); @@ -161,7 +161,7 @@ MMPointInt32 getMousePos() { /* Press down a button, or release it. */ void toggleMouse(bool down, MMMouseButton button) { #if defined(IS_MACOSX) - const CGPoint currentPos = CGPointFromMMPoint(getMousePos()); + const CGPoint currentPos = CGPointFromMMPointInt32(getMousePos()); const CGEventType mouseType = MMMouseToCGEventType(down, button); CGEventRef event = CGEventCreateMouseEvent(NULL, mouseType, currentPos, (CGMouseButton)button); @@ -196,7 +196,7 @@ void clickMouse(MMMouseButton button){ void doubleClick(MMMouseButton button){ #if defined(IS_MACOSX) /* Double click for Mac. */ - const CGPoint currentPos = CGPointFromMMPoint(getMousePos()); + const CGPoint currentPos = CGPointFromMMPointInt32(getMousePos()); const CGEventType mouseTypeDown = MMMouseToCGEventType(true, button); const CGEventType mouseTypeUP = MMMouseToCGEventType(false, button); From b439c59d85fbf856391b76b90386947d15e2af0e Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 3 Feb 2022 03:21:18 -0800 Subject: [PATCH 200/327] Upload miss code fixed CI --- base/bitmap_free_c.h | 2 +- base/xdisplay_c.h | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/base/bitmap_free_c.h b/base/bitmap_free_c.h index 2c97af91..803037fb 100644 --- a/base/bitmap_free_c.h +++ b/base/bitmap_free_c.h @@ -2,7 +2,7 @@ #include #include -MMBitmapRef createMMBitmap_c(uint8_t *buffer, size_t width, size_t height, +MMBitmapRef createMMBitmap_c(uint8_t *buffer, int32_t width, int32_t height, size_t bytewidth, uint8_t bitsPerPixel, uint8_t bytesPerPixel ) { MMBitmapRef bitmap = malloc(sizeof(MMBitmap)); diff --git a/base/xdisplay_c.h b/base/xdisplay_c.h index fa455b2c..0c0dedb6 100644 --- a/base/xdisplay_c.h +++ b/base/xdisplay_c.h @@ -8,6 +8,13 @@ static int registered = 0; static char *displayName = NULL; static int hasDisplayNameChanged = 0; +void XCloseMainDisplay(void) { + if (mainDisplay != NULL) { + XCloseDisplay(mainDisplay); + mainDisplay = NULL; + } +} + Display *XGetMainDisplay(void) { /* Close the display if displayName has changed */ if (hasDisplayNameChanged) { @@ -40,13 +47,6 @@ Display *XGetMainDisplay(void) { return mainDisplay; } -void XCloseMainDisplay(void) { - if (mainDisplay != NULL) { - XCloseDisplay(mainDisplay); - mainDisplay = NULL; - } -} - void setXDisplay(char *name) { displayName = strdup(name); hasDisplayNameChanged = 1; From b543a49322e8fda51641418e79633a11b55bc04f Mon Sep 17 00:00:00 2001 From: vcaesar Date: Fri, 4 Feb 2022 00:02:34 -0800 Subject: [PATCH 201/327] Add clear scroll API and Update examples --- README.md | 9 ++++++--- base/MMBitmap.h | 4 ++-- base/inline_keywords.h | 3 +-- base/os.h | 9 +-------- base/types.h | 1 - examples/key/main.go | 7 ++++--- examples/mouse/main.go | 4 +++- examples/window/main.go | 38 ++++++++++++++++++++++---------------- key.go | 14 +++++++------- key/keycode_c.h | 7 +++++-- key/keypress_c.h | 24 +++++++++++------------- robotgo.go | 32 +++++++++++++++++++++++++++++++- robotgo_test.go | 14 +++++++++++++- window/alert_c.h | 3 +-- window/window.h | 4 +--- 15 files changed, 108 insertions(+), 65 deletions(-) diff --git a/README.md b/README.md index 7e03083e..da5c027b 100644 --- a/README.md +++ b/README.md @@ -158,7 +158,11 @@ import ( ) func main() { - // robotgo.ScrollMouse(10, "up") + robotgo.MouseSleep = 100 + + robotgo.ScrollMouse(10, "up") + robotgo.ScrollMouse(20, "right") + robotgo.Scroll(0, -10) robotgo.Scroll(100, 0) @@ -166,7 +170,6 @@ func main() { robotgo.ScrollSmooth(-10, 6) // robotgo.ScrollRelative(10, -100) - robotgo.MouseSleep = 100 robotgo.Move(10, 20) robotgo.MoveRelative(0, -10) robotgo.Drag(10, 10) @@ -193,7 +196,7 @@ import ( func main() { robotgo.TypeStr("Hello World") - robotgo.TypeStr("だんしゃり", 1.0) + robotgo.TypeStr("だんしゃり", 1) // robotgo.TypeStr("テストする") robotgo.TypeStr("Hi galaxy. こんにちは世界.") diff --git a/base/MMBitmap.h b/base/MMBitmap.h index fbbdfc15..68fccd4a 100644 --- a/base/MMBitmap.h +++ b/base/MMBitmap.h @@ -22,8 +22,8 @@ typedef MMBitmap *MMBitmapRef; #define MMBitmapPointInBounds(image, p) ((p).x < (image)->width && (p).y < (image)->height) /* Get pointer to pixel of MMBitmapRef. No bounds checking is performed */ -#define MMRGBColorRefAtPoint(image, x, y) ( \ - MMRGBColor *)(assert(MMBitmapPointInBounds(image, MMPointInt32Make(x, y))), \ +#define MMRGBColorRefAtPoint(image, x, y) \ + (MMRGBColor *)(assert(MMBitmapPointInBounds(image, MMPointInt32Make(x, y))), \ ((image)->imageBuffer) + (((image)->bytewidth * (y)) + ((x) * (image)->bytesPerPixel))) /* Dereference pixel of MMBitmapRef. Again, no bounds checking is performed. */ diff --git a/base/inline_keywords.h b/base/inline_keywords.h index a86b426b..db0cc6dc 100644 --- a/base/inline_keywords.h +++ b/base/inline_keywords.h @@ -1,7 +1,6 @@ #pragma once -/* A complicated, portable model for declaring inline functions in - * header files. */ +/* A complicated, portable model for declaring inline functions in header files. */ #if !defined(H_INLINE) #if defined(__GNUC__) #define H_INLINE static __inline__ __attribute__((always_inline)) diff --git a/base/os.h b/base/os.h index 6f6e74d2..30a063de 100644 --- a/base/os.h +++ b/base/os.h @@ -2,12 +2,6 @@ #ifndef OS_H #define OS_H -/* Python versions under 2.5 don't support this macro, but it's not - * terribly difficult to replicate: */ -#ifndef PyModule_AddIntMacro - #define PyModule_AddIntMacro(module, macro) PyModule_AddIntConstant(module, #macro, macro) -#endif /* PyModule_AddIntMacro */ - #if !defined(IS_MACOSX) && defined(__APPLE__) && defined(__MACH__) #define IS_MACOSX #endif /* IS_MACOSX */ @@ -29,8 +23,7 @@ #error "Sorry, this platform isn't supported yet!" #endif -/* Interval to align by for large buffers (e.g. bitmaps). */ -/* Must be a power of 2. */ +/* Interval to align by for large buffers (e.g. bitmaps). Must be a power of 2. */ #ifndef BYTE_ALIGN #define BYTE_ALIGN 4 /* Bytes to align pixel buffers to. */ /* #include */ diff --git a/base/types.h b/base/types.h index 01080d27..fc2d0a64 100644 --- a/base/types.h +++ b/base/types.h @@ -62,7 +62,6 @@ H_INLINE MMRectInt32 MMRectInt32Make(int32_t x, int32_t y, int32_t w, int32_t h) #define CGPointFromMMPointInt32(p) CGPointMake((CGFloat)(p).x, (CGFloat)(p).y) #define MMPointInt32FromCGPoint(p) MMPointInt32Make((int32_t)(p).x, (int32_t)(p).y) #elif defined(IS_WINDOWS) - #define MMPointFromPOINT(p) MMPointMake((size_t)p.x, (size_t)p.y) #define MMPointInt32FromPOINT(p) MMPointInt32Make((int32_t)p.x, (int32_t)p.y) #endif diff --git a/examples/key/main.go b/examples/key/main.go index 142ae340..b8f141bb 100644 --- a/examples/key/main.go +++ b/examples/key/main.go @@ -19,20 +19,21 @@ import ( func typeStr() { // importing "Hello World" - robotgo.TypeStr("Hello World!", 1.0) + robotgo.TypeStr("Hello World!", 1) robotgo.KeySleep = 100 robotgo.TypeStr("だんしゃり") robotgo.TypeStr("Hi galaxy. こんにちは世界. 你好, 再见!") - robotgo.Sleep(1) + robotgo.TypeStr("So, hi, bye!") robotgo.MilliSleep(100) ustr := uint32(robotgo.CharCodeAt("So, hi, bye!", 0)) robotgo.UnicodeType(ustr) - robotgo.PasteStr("paste string") + err := robotgo.PasteStr("paste string") + fmt.Println("PasteStr: ", err) } func keyTap() { diff --git a/examples/mouse/main.go b/examples/mouse/main.go index f797727e..3f69a9d5 100644 --- a/examples/mouse/main.go +++ b/examples/mouse/main.go @@ -68,7 +68,9 @@ func get() { func toggleAndScroll() { // scrolls the mouse either up - // robotgo.ScrollMouse(10, "up") + robotgo.ScrollMouse(10, "up") + robotgo.ScrollMouse(10, "right") + robotgo.Scroll(100, 10) robotgo.Scroll(0, -10) diff --git a/examples/window/main.go b/examples/window/main.go index 3b53fb8d..e2d3e8c6 100644 --- a/examples/window/main.go +++ b/examples/window/main.go @@ -49,26 +49,32 @@ func get() { func findIds() { // find the process id by the process name fpid, err := robotgo.FindIds("Google") - if err == nil { - fmt.Println("pids...", fpid) - if len(fpid) > 0 { - robotgo.ActivePID(fpid[0]) + if err != nil { + fmt.Println(err) + return + } - tl := robotgo.GetTitle(fpid[0]) - fmt.Println("pid[0] title is: ", tl) + fmt.Println("pids...", fpid) + if len(fpid) > 0 { + err = robotgo.ActivePID(fpid[0]) + if err != nil { + fmt.Println(err) + } - x, y, w, h := robotgo.GetBounds(fpid[0]) - fmt.Println("GetBounds is: ", x, y, w, h) + tl := robotgo.GetTitle(fpid[0]) + fmt.Println("pid[0] title is: ", tl) - // Windows - // hwnd := robotgo.FindWindow("google") - // hwnd := robotgo.GetHWND() - robotgo.MinWindow(fpid[0]) - robotgo.MaxWindow(fpid[0]) - robotgo.CloseWindow(fpid[0]) + x, y, w, h := robotgo.GetBounds(fpid[0]) + fmt.Println("GetBounds is: ", x, y, w, h) - robotgo.Kill(fpid[0]) - } + // Windows + // hwnd := robotgo.FindWindow("google") + // hwnd := robotgo.GetHWND() + robotgo.MinWindow(fpid[0]) + robotgo.MaxWindow(fpid[0]) + robotgo.CloseWindow(fpid[0]) + + robotgo.Kill(fpid[0]) } } diff --git a/key.go b/key.go index de09a156..6e601519 100644 --- a/key.go +++ b/key.go @@ -575,13 +575,13 @@ func inputUTF(str string) { // TypeStr send a string, support UTF-8 // -// robotgo.TypeStr(string: The string to send, float64: microsleep time, x11 option) +// robotgo.TypeStr(string: The string to send, int: milli_sleep time, x11 option) // // Examples: // robotgo.TypeStr("abc@123, hi, こんにちは") // -func TypeStr(str string, args ...float64) { - var tm, tm1 = 0.0, 7.0 +func TypeStr(str string, args ...int) { + var tm, tm1 = 0, 7 if len(args) > 0 { tm = args[0] @@ -599,10 +599,10 @@ func TypeStr(str string, args ...float64) { UnicodeType(ustr) } else { inputUTF(strUc[i]) - MicroSleep(tm1) + MilliSleep(tm1) } - MicroSleep(tm) + MilliSleep(tm) } return } @@ -611,7 +611,7 @@ func TypeStr(str string, args ...float64) { ustr := uint32(CharCodeAt(str, i)) UnicodeType(ustr) // if len(args) > 0 { - MicroSleep(tm) + MilliSleep(tm) // } } MilliSleep(KeySleep) @@ -635,7 +635,7 @@ func PasteStr(str string) error { // TypeStrDelay type string delayed func TypeStrDelay(str string, delay int) { TypeStr(str) - Sleep(delay) + MilliSleep(delay) } // Deprecated: use the TypeStr(), diff --git a/key/keycode_c.h b/key/keycode_c.h index 4af3175e..75b610ea 100644 --- a/key/keycode_c.h +++ b/key/keycode_c.h @@ -4,13 +4,16 @@ #include #include /* For kVK_ constants, and TIS functions. */ - /* Returns string representation of key, if it is printable. */ + /* Returns string representation of key, if it is printable. + Ownership follows the Create Rule; + it is the caller's responsibility to release the returned object. */ CFStringRef createStringForKey(CGKeyCode keyCode); #endif MMKeyCode keyCodeForChar(const char c) { #if defined(IS_MACOSX) - /* OS X does not appear to have a built-in function for this, so instead it. */ + /* OS X does not appear to have a built-in function for this, + so instead it to write our own. */ static CFMutableDictionaryRef charToCodeDict = NULL; CGKeyCode code; UniChar character = c; diff --git a/key/keypress_c.h b/key/keypress_c.h index 1f5511d7..300663df 100644 --- a/key/keypress_c.h +++ b/key/keypress_c.h @@ -169,11 +169,11 @@ void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags) { #endif } -void tapKeyCode(MMKeyCode code, MMKeyFlags flags){ - toggleKeyCode(code, true, flags); - microsleep(5.0); - toggleKeyCode(code, false, flags); -} +// void tapKeyCode(MMKeyCode code, MMKeyFlags flags){ +// toggleKeyCode(code, true, flags); +// microsleep(5.0); +// toggleKeyCode(code, false, flags); +// } #if defined(USE_X11) bool toUpper(char c) { @@ -221,11 +221,11 @@ void toggleKey(char c, const bool down, MMKeyFlags flags){ toggleKeyCode(keyCode, down, flags); } -void tapKey(char c, MMKeyFlags flags){ - toggleKey(c, true, flags); - microsleep(5.0); - toggleKey(c, false, flags); -} +// void tapKey(char c, MMKeyFlags flags){ +// toggleKey(c, true, flags); +// microsleep(5.0); +// toggleKey(c, false, flags); +// } #if defined(IS_MACOSX) void toggleUnicode(UniChar ch, const bool down) { @@ -250,9 +250,7 @@ void toggleUnicode(UniChar ch, const bool down) { #define toggleUniKey(c, down) toggleKey(c, down, MOD_NONE) int input_utf(const char *utf) { - Display *dpy; - dpy = XOpenDisplay(NULL); - + Display *dpy = XOpenDisplay(NULL); KeySym sym = XStringToKeysym(utf); // KeySym sym = XKeycodeToKeysym(dpy, utf); diff --git a/robotgo.go b/robotgo.go index 913d2dc7..b4b8f6f1 100644 --- a/robotgo.go +++ b/robotgo.go @@ -128,7 +128,9 @@ func Sleep(tm int) { time.Sleep(time.Duration(tm) * time.Second) } -// MicroSleep time C.microsleep(tm), use the MilliSleep() +// Deprecated: use the MilliSleep(), +// +// MicroSleep time C.microsleep(tm) func MicroSleep(tm float64) { C.microsleep(C.double(tm)) } @@ -740,6 +742,34 @@ func Scroll(x, y int, args ...int) { MilliSleep(MouseSleep + msDelay) } +// ScrollMouse scroll the mouse to (x, "up") +// supported: "up", "down", "left", "right" +// +// Examples: +// robotgo.ScrollMouse(10, "down") +// robotgo.ScrollMouse(10, "up") +func ScrollMouse(x int, direction ...string) { + d := "down" + if len(direction) > 0 { + d = direction[0] + } + + if d == "down" { + Scroll(0, -x) + } + if d == "up" { + Scroll(0, x) + } + + if d == "left" { + Scroll(x, 0) + } + if d == "right" { + Scroll(-x, 0) + } + // MilliSleep(MouseSleep) +} + // ScrollSmooth scroll the mouse smooth, // default scroll 5 times and sleep 100 millisecond // diff --git a/robotgo_test.go b/robotgo_test.go index 8e9e1e2a..bf3d54b3 100644 --- a/robotgo_test.go +++ b/robotgo_test.go @@ -68,7 +68,9 @@ func TestDragMouse(t *testing.T) { } func TestScrollMouse(t *testing.T) { - // ScrollMouse(120, "up") + ScrollMouse(120, "up") + ScrollMouse(100, "right") + Scroll(0, 120) MilliSleep(100) @@ -106,6 +108,12 @@ func TestMouseToggle(t *testing.T) { e = Toggle("right", "up") tt.Nil(t, e) + + e = MouseDown("left") + tt.Nil(t, e) + + e = MouseUp("left") + tt.Nil(t, e) } func TestKey(t *testing.T) { @@ -177,6 +185,10 @@ func TestImage(t *testing.T) { tt.Equal(t, 20, Width(img1)) tt.Equal(t, 20, Height(img1)) + + bit1 := ImgToBitmap(img1) + tt.Equal(t, bit1.Width, Width(img1)) + tt.Equal(t, bit1.Height, Height(img1)) } func TestPs(t *testing.T) { diff --git a/window/alert_c.h b/window/alert_c.h index 5d67733e..d5ed2bae 100644 --- a/window/alert_c.h +++ b/window/alert_c.h @@ -32,8 +32,7 @@ int showAlert(const char *title, const char *msg, #elif defined(USE_X11) return 0; #else - /* TODO: Display custom buttons instead of the pre-defined "OK" - * and "Cancel". */ + /* TODO: Display custom buttons instead of the pre-defined "OK" and "Cancel". */ int response = MessageBox(NULL, msg, title, (cancelButton == NULL) ? MB_OK : MB_OKCANCEL ); return (response == IDOK) ? 0 : 1; diff --git a/window/window.h b/window/window.h index 77d7a496..f25c60cb 100644 --- a/window/window.h +++ b/window/window.h @@ -85,7 +85,7 @@ bool is_valid() { #if defined(IS_MACOSX) mData.CgID = actdata.CgID; mData.AxID = actdata.AxID; - if (mData.CgID == 0 || mData.AxID == 0){ return false; } + if (mData.CgID == 0 || mData.AxID == 0) { return false; } CFTypeRef r = NULL; // Attempt to get the window role @@ -153,7 +153,6 @@ bool IsAxEnabled(bool options){ // Determine whether the process is actually trusted bool result = (*gAXIsProcessTrustedWithOptions)(o); - // Free memory CFRelease(o); return result; @@ -336,7 +335,6 @@ void set_active(const MData win) { } else { // Attempt to raise the specified window XRaiseWindow(rDisplay, win.XWin); - // Set the specified window's input focus XSetInputFocus(rDisplay, win.XWin, RevertToParent, CurrentTime); } From 74c3f6e08e32c6dfbfea7312d13552d81a9af6a9 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Fri, 4 Feb 2022 00:20:23 -0800 Subject: [PATCH 202/327] Add GetMainId and IsMain function support --- robotgo.go | 5 +++++ robotgo_mac.go | 24 ++++++++++++++++++++++++ robotgo_win.go | 14 ++++++++++++-- robotgo_x11.go | 19 +++++++++++++++++++ 4 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 robotgo_mac.go diff --git a/robotgo.go b/robotgo.go index b4b8f6f1..78937df3 100644 --- a/robotgo.go +++ b/robotgo.go @@ -215,6 +215,11 @@ func GetMouseColor(displayId ...int) string { return GetPixelColor(x, y, displayId...) } +// IsMain is main display +func IsMain(displayId int) bool { + return displayId == GetMainId() +} + func displayIdx(id ...int) int { display := -1 if DisplayID != -1 { diff --git a/robotgo_mac.go b/robotgo_mac.go new file mode 100644 index 00000000..0f9ce4a0 --- /dev/null +++ b/robotgo_mac.go @@ -0,0 +1,24 @@ +// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// https://github.com/go-vgo/robotgo/blob/master/LICENSE +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//go:build darwin +// +build darwin + +package robotgo + +/* +#include +*/ +import "C" + +// GetMianId get the main display id +func GetMainId() int { + return int(C.CGMainDisplayID()) +} diff --git a/robotgo_win.go b/robotgo_win.go index 6d06213e..bf6f5b8e 100644 --- a/robotgo_win.go +++ b/robotgo_win.go @@ -42,8 +42,8 @@ func SendMsg(hwnd win.HWND, msg uint32, wParam, lParam uintptr) uintptr { return win.SendMessage(hwnd, msg, wParam, lParam) } -// SetActiveWindow set window active with hwnd -func SetActiveWindow(hwnd win.HWND) win.HWND { +// SetActive set window active with hwnd +func SetActive(hwnd win.HWND) win.HWND { return win.SetActiveWindow(hwnd) } @@ -52,6 +52,16 @@ func SetFocus(hwnd win.HWND) win.HWND { return win.SetFocus(hwnd) } +// GetMian get the main display hwnd +func GetMain() win.HWND { + return win.GetActiveWindow() +} + +// GetMianId get the main display id +func GetMainId() int { + return int(GetMain()) +} + // ScaleF get the system scale val func ScaleF(displayId ...int) (f float64) { if len(displayId) > 0 && displayId[0] != -1 { diff --git a/robotgo_x11.go b/robotgo_x11.go index 1bd0018e..d6d2e6b8 100644 --- a/robotgo_x11.go +++ b/robotgo_x11.go @@ -191,6 +191,25 @@ func DisplaysNum() int { return int(reply.Number) } +// GetMianId get the main display id +func GetMainId() int { + conn, err := xgb.NewConn() + if err != nil { + return -1 + } + + setup := xproto.Setup(conn) + defaultScreen := setup.DefaultScreen(conn) + id := -1 + for i, screen := range setup.Roots { + if defaultScreen.Root == screen.Root { + id = i + break + } + } + return id +} + // Alert show a alert window // Displays alert with the attributes. // If cancel button is not given, only the default button is displayed From 4a043157adf7a735ce5561fbacb3941939f138b1 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Fri, 4 Feb 2022 00:27:17 -0800 Subject: [PATCH 203/327] Update define Fixed windows CI --- robotgo_win.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/robotgo_win.go b/robotgo_win.go index bf6f5b8e..e8aced33 100644 --- a/robotgo_win.go +++ b/robotgo_win.go @@ -42,8 +42,8 @@ func SendMsg(hwnd win.HWND, msg uint32, wParam, lParam uintptr) uintptr { return win.SendMessage(hwnd, msg, wParam, lParam) } -// SetActive set window active with hwnd -func SetActive(hwnd win.HWND) win.HWND { +// SetActiveWindow set window active with hwnd +func SetActiveWindow(hwnd win.HWND) win.HWND { return win.SetActiveWindow(hwnd) } From 264f658a465f75c2cf3d6c506cefe8ad56154baf Mon Sep 17 00:00:00 2001 From: Laurent Demailly Date: Sun, 6 Feb 2022 00:42:18 -0800 Subject: [PATCH 204/327] Fix typo in doc for GetMousePos (#462) --- robotgo.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/robotgo.go b/robotgo.go index 78937df3..6b7ebeaf 100644 --- a/robotgo.go +++ b/robotgo.go @@ -621,7 +621,7 @@ func MoveSmoothRelative(x, y int, args ...interface{}) { MoveSmooth(mx, my, args...) } -// GetMousePos get the mouse's portion return x, y +// GetMousePos get the mouse's position return x, y func GetMousePos() (int, int) { pos := C.getMousePos() x := int(pos.x) From be9b02c5888b3a94225c2fbfe2f1f29d8d6ca867 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 6 Feb 2022 00:46:41 -0800 Subject: [PATCH 205/327] Update README.md and remove unused code --- README.md | 21 +++++++++++++-------- examples/mouse/main.go | 4 ++-- screen/goScreen.h | 7 ------- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index da5c027b..4998b173 100644 --- a/README.md +++ b/README.md @@ -74,15 +74,18 @@ Or the other GCC (But you should compile the "libpng" with yourself when use the ``` GCC -libpng (Just used by bitmap) +X11 with the XTest extension (and the Xtst library) + -X11 with the XTest extension (also known as the Xtst library) +"Bitmap": + +libpng (Just used by bitmap) -Event: +"Event": xcb, xkb, libxkbcommon -Clipboard: +"Clipboard": xsel xclip ``` @@ -172,7 +175,7 @@ func main() { robotgo.Move(10, 20) robotgo.MoveRelative(0, -10) - robotgo.Drag(10, 10) + robotgo.DragSmooth(10, 10) robotgo.Click("wheelRight") robotgo.Click("left", true) @@ -208,9 +211,9 @@ func main() { robotgo.KeySleep = 100 robotgo.KeyTap("enter") // robotgo.TypeStr("en") - robotgo.KeyTap("i", "alt", "command") + robotgo.KeyTap("i", "alt", "cmd") - arr := []string{"alt", "command"} + arr := []string{"alt", "cmd"} robotgo.KeyTap("i", arr) robotgo.MilliSleep(100) @@ -507,7 +510,9 @@ Some discussions and questions, please see [issues/228](https://github.com/go-vg * [Contributors](https://github.com/go-vgo/robotgo/graphs/contributors) ## Plans -- Update Find an image on screen, read pixels from an image +- Refactor some C code to Go (such as x11, windows) +- Better multiscreen support +- Waylad supports - Update Window Handle - Try support Android, maybe support IOS diff --git a/examples/mouse/main.go b/examples/mouse/main.go index 3f69a9d5..c03e849c 100644 --- a/examples/mouse/main.go +++ b/examples/mouse/main.go @@ -25,8 +25,8 @@ func move() { // move the mouse to 100, 200 robotgo.Move(100, 200) - robotgo.Drag(10, 10) - robotgo.Drag(20, 20, "right") + // robotgo.Drag(10, 10) + // robotgo.Drag(20, 20, "right") // robotgo.DragSmooth(10, 10) robotgo.DragSmooth(100, 200, 1.0, 100.0) diff --git a/screen/goScreen.h b/screen/goScreen.h index fb9048d6..77934e63 100644 --- a/screen/goScreen.h +++ b/screen/goScreen.h @@ -58,13 +58,6 @@ MMRGBHex get_px_color(int32_t x, int32_t y, int32_t display_id) { return color; } -char* get_pixel_color(int32_t x, int32_t y, int32_t display_id) { - MMRGBHex color = get_px_color(x, y, display_id); - - char* s = pad_hex(color); - return s; -} - char* set_XDisplay_name(char* name) { #if defined(USE_X11) setXDisplay(name); From a9d995fdf6124a0682c9e03f00818cc267d251bb Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 6 Feb 2022 00:51:37 -0800 Subject: [PATCH 206/327] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4998b173..84d623e9 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ Or the other GCC (But you should compile the "libpng" with yourself when use the ``` GCC -X11 with the XTest extension (and the Xtst library) +X11 with the XTest extension (the Xtst library) "Bitmap": @@ -514,7 +514,7 @@ Some discussions and questions, please see [issues/228](https://github.com/go-vg - Better multiscreen support - Waylad supports - Update Window Handle -- Try support Android, maybe support IOS +- Try support Android and IOS ## Contributors From 8aa3348a2ae06070c0a902d67540cb98107847f8 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 8 Feb 2022 03:09:26 -0800 Subject: [PATCH 207/327] Add image and byte to CBitmap support --- robotgo.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/robotgo.go b/robotgo.go index 78937df3..004194ba 100644 --- a/robotgo.go +++ b/robotgo.go @@ -394,6 +394,17 @@ func ToRGBA(bit CBitmap) *image.RGBA { return ToRGBAGo(bmp1) } +// ImgToCBitmap trans image.Image to CBitmap +func ImgToCBitmap(img image.Image) CBitmap { + return ToCBitmap(ImgToBitmap(img)) +} + +// ByteToCBitmap trans []byte to CBitmap +func ByteToCBitmap(by []byte) CBitmap { + img, _ := ByteToImg(by) + return ImgToCBitmap(img) +} + // SetXDisplayName set XDisplay name (Linux) func SetXDisplayName(name string) error { cname := C.CString(name) From c0ef98e7129b8db0925fa575f1af3acbcfdd93d9 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 8 Feb 2022 03:47:06 -0800 Subject: [PATCH 208/327] Update key examples --- examples/key/main.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/key/main.go b/examples/key/main.go index b8f141bb..50b09dba 100644 --- a/examples/key/main.go +++ b/examples/key/main.go @@ -39,6 +39,7 @@ func typeStr() { func keyTap() { // press "enter" robotgo.KeyTap("enter") + robotgo.KeyTap(robotgo.Enter) robotgo.KeySleep = 200 robotgo.KeyTap("a") robotgo.MilliSleep(100) @@ -53,7 +54,7 @@ func keyTap() { robotgo.KeyTap("h", "cmd") // press "i", "alt", "command" Key combination - robotgo.KeyTap("i", "alt", "command") + robotgo.KeyTap(robotgo.KeyI, robotgo.Alt, robotgo.Cmd) robotgo.KeyTap("i", "alt", "cmd") arr := []string{"alt", "cmd"} @@ -74,7 +75,7 @@ func keyTap() { func keyToggle() { // robotgo.KeySleep = 150 - robotgo.KeyToggle("a", "down") + robotgo.KeyToggle(robotgo.KeyA) robotgo.KeyToggle("a", "down", "alt") robotgo.Sleep(1) @@ -82,7 +83,7 @@ func keyToggle() { robotgo.MilliSleep(100) robotgo.KeyToggle("q", "up", "alt", "cmd", "shift") - err := robotgo.KeyToggle("enter", "down") + err := robotgo.KeyToggle(robotgo.Enter) if err != nil { fmt.Println("robotgo.KeyToggle run error is: ", err) } From c395a0dcd652a426dfa6a7faddb9885afd45b867 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 9 Feb 2022 10:20:57 -0800 Subject: [PATCH 209/327] Update README.md and bytewidth C type --- README.md | 4 ++-- base/MMBitmap.h | 2 +- base/bitmap_free_c.h | 2 +- robotgo.go | 2 +- screen/screengrab_c.h | 5 +++-- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 84d623e9..013e7853 100644 --- a/README.md +++ b/README.md @@ -270,7 +270,7 @@ func main() { } ``` -#### [Bitmap](https://github.com/go-vgo/robotgo/blob/master/examples/bitmap/main.go) +#### [Bitmap](https://github.com/vcaesar/bitmap/blob/master/examples/main.go) ```Go package main @@ -370,7 +370,7 @@ func opencv() { } ``` -#### [Event](https://github.com/go-vgo/robotgo/blob/master/examples/gohook/main.go) +#### [Event](https://github.com/robotn/gohook/blob/master/examples/main.go) ```Go package main diff --git a/base/MMBitmap.h b/base/MMBitmap.h index 68fccd4a..b652a2d1 100644 --- a/base/MMBitmap.h +++ b/base/MMBitmap.h @@ -11,7 +11,7 @@ struct _MMBitmap { uint8_t *imageBuffer; /* Pixels stored in Quad I format; */ int32_t width; /* Never 0, unless image is NULL. */ int32_t height; /* Never 0, unless image is NULL. */ - size_t bytewidth; /* The aligned width (width + padding). */ + int32_t bytewidth; /* The aligned width (width + padding). */ uint8_t bitsPerPixel; /* Should be either 24 or 32. */ uint8_t bytesPerPixel; /* For convenience; should be bitsPerPixel / 8. */ }; diff --git a/base/bitmap_free_c.h b/base/bitmap_free_c.h index 803037fb..90e20a30 100644 --- a/base/bitmap_free_c.h +++ b/base/bitmap_free_c.h @@ -3,7 +3,7 @@ #include MMBitmapRef createMMBitmap_c(uint8_t *buffer, int32_t width, int32_t height, - size_t bytewidth, uint8_t bitsPerPixel, uint8_t bytesPerPixel + int32_t bytewidth, uint8_t bitsPerPixel, uint8_t bytesPerPixel ) { MMBitmapRef bitmap = malloc(sizeof(MMBitmap)); if (bitmap == NULL) { return NULL; } diff --git a/robotgo.go b/robotgo.go index 8d1f4511..f73c593c 100644 --- a/robotgo.go +++ b/robotgo.go @@ -375,7 +375,7 @@ func ToCBitmap(bit Bitmap) CBitmap { (*C.uint8_t)(bit.ImgBuf), C.int32_t(bit.Width), C.int32_t(bit.Height), - C.size_t(bit.Bytewidth), + C.int32_t(bit.Bytewidth), C.uint8_t(bit.BitsPixel), C.uint8_t(bit.BytesPerPixel), ) diff --git a/screen/screengrab_c.h b/screen/screengrab_c.h index 883decb8..adb78b48 100644 --- a/screen/screengrab_c.h +++ b/screen/screengrab_c.h @@ -35,8 +35,9 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id) buffer = malloc(bufferSize); CFDataGetBytes(imageData, CFRangeMake(0, bufferSize), buffer); - bitmap = createMMBitmap_c(buffer, CGImageGetWidth(image), CGImageGetHeight(image), - CGImageGetBytesPerRow(image), CGImageGetBitsPerPixel(image),CGImageGetBitsPerPixel(image) / 8); + bitmap = createMMBitmap_c(buffer, + CGImageGetWidth(image), CGImageGetHeight(image), CGImageGetBytesPerRow(image), + CGImageGetBitsPerPixel(image), CGImageGetBitsPerPixel(image) / 8); CFRelease(imageData); CGImageRelease(image); From a00655dbe49c251bdd3bc731feed996284f7c255 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 14 Feb 2022 03:36:06 -0800 Subject: [PATCH 210/327] Update dockerfile & appveyor --- .circleci/images/primary/Dockerfile | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index e1bca462..bddffdbe 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.17.6-stretch AS build +FROM golang:1.17.7-stretch AS build # FROM govgo/go:1.11.1 RUN apt update && apt install -y --no-install-recommends \ diff --git a/appveyor.yml b/appveyor.yml index 8fe84955..8f2e9a5a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,7 +34,7 @@ environment: PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% # - COMPILER: MINGW_W64 # ARCHITECTURE: x64 - GOVERSION: 1.17.6 + GOVERSION: 1.17.7 # GOPATH: c:\gopath # scripts that run after cloning repository From ab66b269b89e84782038f9e59c968c14568dc065 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 15 Feb 2022 14:26:44 -0800 Subject: [PATCH 211/327] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 013e7853..b5a76864 100644 --- a/README.md +++ b/README.md @@ -270,7 +270,7 @@ func main() { } ``` -#### [Bitmap](https://github.com/vcaesar/bitmap/blob/master/examples/main.go) +#### [Bitmap](https://github.com/vcaesar/bitmap/blob/main/examples/main.go) ```Go package main From 2f79ebe879a41468ddb63714cac01186d7f1827e Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 15 Feb 2022 15:03:47 -0800 Subject: [PATCH 212/327] Optimize key toggle code --- key.go | 2 +- key/keypress_c.h | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/key.go b/key.go index 6e601519..6bb48873 100644 --- a/key.go +++ b/key.go @@ -384,7 +384,7 @@ func keyToggles(k string, keyArr []string) error { down = false } - flags := getFlagsFromValue(keyArr) + flags := getFlagsFromValue(keyArr[1:]) key, err := checkKeyCodes(k) if err != nil { return err diff --git a/key/keypress_c.h b/key/keypress_c.h index 300663df..dca304ec 100644 --- a/key/keypress_c.h +++ b/key/keypress_c.h @@ -140,8 +140,9 @@ void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags) { assert(keyEvent != NULL); CGEventSetType(keyEvent, down ? kCGEventKeyDown : kCGEventKeyUp); - // CGEventSetFlags(keyEvent, flags); - CGEventSetFlags(keyEvent, (int) flags); + if (flags != 0) { + CGEventSetFlags(keyEvent, (CGEventFlags) flags); + } CGEventPost(kCGSessionEventTap, keyEvent); CFRelease(keyEvent); } From 34d0fbf4bcc10d5f780167b26e02c5f048b262c8 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 17 Feb 2022 09:47:48 -0800 Subject: [PATCH 213/327] Add uppercase key support with default and Update godoc --- key.go | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/key.go b/key.go index 6bb48873..754ca967 100644 --- a/key.go +++ b/key.go @@ -23,6 +23,7 @@ import ( "runtime" "strconv" "strings" + "unicode" "unsafe" "github.com/go-vgo/robotgo/clipboard" @@ -444,12 +445,16 @@ func toErr(str *C.char) error { // arr := []string{"alt", "command"} // robotgo.KeyTap("i", arr) // -func KeyTap(tapKey string, args ...interface{}) error { +func KeyTap(key string, args ...interface{}) error { var keyArr []string - tapKey = strings.ToLower(tapKey) - if _, ok := Special[tapKey]; ok { - tapKey = Special[tapKey] + if len(key) > 0 && unicode.IsUpper([]rune(key)[0]) { + args = append(args, "shift") + } + + key = strings.ToLower(key) + if _, ok := Special[key]; ok { + key = Special[key] if len(args) <= 0 { args = append(args, "shift") } @@ -463,7 +468,7 @@ func KeyTap(tapKey string, args ...interface{}) error { } } - return keyTaps(tapKey, keyArr) + return keyTaps(key, keyArr) } // KeyToggle toggle the keyboard, if there not have args default is "down" @@ -482,6 +487,10 @@ func KeyToggle(key string, args ...string) error { args = append(args, "down") } + if len(key) > 0 && unicode.IsUpper([]rune(key)[0]) { + args = append(args, "shift") + } + key = strings.ToLower(key) if _, ok := Special[key]; ok { key = Special[key] @@ -573,12 +582,12 @@ func inputUTF(str string) { C.free(unsafe.Pointer(cstr)) } -// TypeStr send a string, support UTF-8 +// TypeStr send a string, supported UTF-8 // -// robotgo.TypeStr(string: The string to send, int: milli_sleep time, x11 option) +// robotgo.TypeStr(string: "The string to send", int: "milli_sleep time", "x11 option") // // Examples: -// robotgo.TypeStr("abc@123, hi, こんにちは") +// robotgo.TypeStr("abc@123, hi galaxy, こんにちは") // func TypeStr(str string, args ...int) { var tm, tm1 = 0, 7 From 93a9f8194f07168422059915f1f28773b9d4d1c4 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 17 Feb 2022 10:13:11 -0800 Subject: [PATCH 214/327] Add events listen test html --- examples/index.html | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 examples/index.html diff --git a/examples/index.html b/examples/index.html new file mode 100644 index 00000000..c78a17c5 --- /dev/null +++ b/examples/index.html @@ -0,0 +1,37 @@ +

Type and check the console

+ + \ No newline at end of file From e1c5590f306ba706df54cd1aad97382f8e29c6fa Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 17 Feb 2022 10:15:49 -0800 Subject: [PATCH 215/327] Add capital letter key define --- key.go | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/key.go b/key.go index 754ca967..f99c3e8e 100644 --- a/key.go +++ b/key.go @@ -59,6 +59,33 @@ const ( KeyY = "y" KeyZ = "z" // + CapA = "A" + CapB = "B" + CapC = "C" + CapD = "D" + CapE = "E" + CapF = "F" + CapG = "G" + CapH = "H" + CapI = "I" + CapJ = "J" + CapK = "K" + CapL = "L" + CapM = "M" + CapN = "N" + CapO = "O" + CapP = "P" + CapQ = "Q" + CapR = "R" + CapS = "S" + CapT = "T" + CapU = "U" + CapV = "V" + CapW = "W" + CapX = "X" + CapY = "Y" + CapZ = "Z" + // Key0 = "0" Key1 = "1" Key2 = "2" From 389f7c680244e65896ca990a898d00c3203796e7 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 17 Feb 2022 11:44:06 -0800 Subject: [PATCH 216/327] rename win32.h to pubs.h --- base/{win32.h => pubs.h} | 0 screen/goScreen.h | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename base/{win32.h => pubs.h} (100%) diff --git a/base/win32.h b/base/pubs.h similarity index 100% rename from base/win32.h rename to base/pubs.h diff --git a/screen/goScreen.h b/screen/goScreen.h index 77934e63..2a2bc882 100644 --- a/screen/goScreen.h +++ b/screen/goScreen.h @@ -10,7 +10,7 @@ #include "../base/types.h" #include "../base/rgb.h" -#include "../base/win32.h" +#include "../base/pubs.h" #include "screengrab_c.h" #include "screen_c.h" #include From 327875857523337f51f7788929827278546fb6bf Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 17 Feb 2022 12:10:41 -0800 Subject: [PATCH 217/327] Add send key event by pid support [mac] --- key.go | 63 +++++++++++++++++++++++++++++++----------------- key/keypress_c.h | 44 ++++++++++++++++++++------------- 2 files changed, 68 insertions(+), 39 deletions(-) diff --git a/key.go b/key.go index f99c3e8e..739cff52 100644 --- a/key.go +++ b/key.go @@ -321,10 +321,10 @@ var keyNames = map[string]C.MMKeyCode{ // { NULL: C.K_NOT_A_KEY } } -func tapKeyCode(code C.MMKeyCode, flags C.MMKeyFlags) { - C.toggleKeyCode(code, true, flags) +func tapKeyCode(code C.MMKeyCode, flags C.MMKeyFlags, pid C.int32_t) { + C.toggleKeyCode(code, true, flags, pid) MilliSleep(5) - C.toggleKeyCode(code, false, flags) + C.toggleKeyCode(code, false, flags, pid) } var keyErr = errors.New("Invalid key flag specified.") @@ -394,19 +394,19 @@ func getFlagsFromValue(value []string) (flags C.MMKeyFlags) { return } -func keyTaps(k string, keyArr []string) error { +func keyTaps(k string, keyArr []string, pid int) error { flags := getFlagsFromValue(keyArr) key, err := checkKeyCodes(k) if err != nil { return err } - tapKeyCode(key, flags) + tapKeyCode(key, flags, C.int32_t(pid)) MilliSleep(KeySleep) return nil } -func keyToggles(k string, keyArr []string) error { +func keyToggles(k string, keyArr []string, pid int) error { down := true if keyArr[0] == "up" { down = false @@ -418,7 +418,7 @@ func keyToggles(k string, keyArr []string) error { return err } - C.toggleKeyCode(key, C.bool(down), flags) + C.toggleKeyCode(key, C.bool(down), flags, C.int32_t(pid)) MilliSleep(KeySleep) return nil } @@ -487,15 +487,21 @@ func KeyTap(key string, args ...interface{}) error { } } + pid := 0 if len(args) > 0 { if reflect.TypeOf(args[0]) == reflect.TypeOf(keyArr) { keyArr = args[0].([]string) } else { - keyArr = ToStrings(args) + if reflect.TypeOf(args[0]) == reflect.TypeOf(pid) { + pid = args[0].(int) + keyArr = ToStrings(args[1:]) + } else { + keyArr = ToStrings(args) + } } } - return keyTaps(key, keyArr) + return keyTaps(key, keyArr, pid) } // KeyToggle toggle the keyboard, if there not have args default is "down" @@ -509,7 +515,7 @@ func KeyTap(key string, args ...interface{}) error { // // robotgo.KeyToggle("a", "up", "alt", "cmd") // -func KeyToggle(key string, args ...string) error { +func KeyToggle(key string, args ...interface{}) error { if len(args) <= 0 { args = append(args, "down") } @@ -526,11 +532,20 @@ func KeyToggle(key string, args ...string) error { } } - return keyToggles(key, args) + pid := 0 + var keyArr []string + if len(args) > 0 && reflect.TypeOf(args[0]) == reflect.TypeOf(pid) { + pid = args[0].(int) + keyArr = ToStrings(args[1:]) + } else { + keyArr = ToStrings(args) + } + + return keyToggles(key, keyArr, pid) } // KeyPress press key string -func KeyPress(key string, args ...string) error { +func KeyPress(key string, args ...interface{}) error { err := KeyDown(key, args...) if err != nil { return err @@ -541,13 +556,13 @@ func KeyPress(key string, args ...string) error { } // KeyDown press down a key -func KeyDown(key string, args ...string) error { +func KeyDown(key string, args ...interface{}) error { return KeyToggle(key, args...) } // KeyUp press up a key -func KeyUp(key string, args ...string) error { - arr := []string{"up"} +func KeyUp(key string, args ...interface{}) error { + arr := []interface{}{"up"} arr = append(arr, args...) return KeyToggle(key, arr...) } @@ -576,9 +591,9 @@ func CharCodeAt(s string, n int) rune { } // UnicodeType tap uint32 unicode -func UnicodeType(str uint32) { +func UnicodeType(str uint32, pid int) { cstr := C.uint(str) - C.unicodeType(cstr) + C.unicodeType(cstr, C.int32_t(pid)) } // ToUC trans string to unicode []string @@ -611,7 +626,7 @@ func inputUTF(str string) { // TypeStr send a string, supported UTF-8 // -// robotgo.TypeStr(string: "The string to send", int: "milli_sleep time", "x11 option") +// robotgo.TypeStr(string: "The string to send", int: pid, "milli_sleep time", "x11 option") // // Examples: // robotgo.TypeStr("abc@123, hi galaxy, こんにちは") @@ -619,12 +634,16 @@ func inputUTF(str string) { func TypeStr(str string, args ...int) { var tm, tm1 = 0, 7 - if len(args) > 0 { + if len(args) > 1 { tm = args[0] } - if len(args) > 1 { + if len(args) > 2 { tm1 = args[1] } + pid := 0 + if len(args) > 0 { + pid = args[0] + } if runtime.GOOS == "linux" { strUc := ToUC(str) @@ -632,7 +651,7 @@ func TypeStr(str string, args ...int) { ru := []rune(strUc[i]) if len(ru) <= 1 { ustr := uint32(CharCodeAt(strUc[i], 0)) - UnicodeType(ustr) + UnicodeType(ustr, pid) } else { inputUTF(strUc[i]) MilliSleep(tm1) @@ -645,7 +664,7 @@ func TypeStr(str string, args ...int) { for i := 0; i < len([]rune(str)); i++ { ustr := uint32(CharCodeAt(str, i)) - UnicodeType(ustr) + UnicodeType(ustr, pid) // if len(args) > 0 { MilliSleep(tm) // } diff --git a/key/keypress_c.h b/key/keypress_c.h index dca304ec..f909dd77 100644 --- a/key/keypress_c.h +++ b/key/keypress_c.h @@ -14,8 +14,8 @@ /* Convenience wrappers around ugly APIs. */ #if defined(IS_WINDOWS) - void WIN32_KEY_EVENT_WAIT(MMKeyCode key, DWORD flags) { - win32KeyEvent(key, flags); + void WIN32_KEY_EVENT_WAIT(MMKeyCode key, DWORD flags, int32_t pid) { + win32KeyEvent(key, flags, pid); Sleep(DEADBEEF_RANDRANGE(0, 1)); } #elif defined(USE_X11) @@ -31,6 +31,15 @@ #endif #if defined(IS_MACOSX) + int SendTo(int32_t pid, CGEventRef event) { + if (pid != 0) { + CGEventPostToPid(pid, event); + } else { + CGEventPost(kCGSessionEventTap, event); + } + return 0; + } + static io_connect_t _getAuxiliaryKeyDriver(void) { static mach_port_t sEventDrvrRef = 0; mach_port_t masterPort, service, iter; @@ -56,7 +65,7 @@ static io_connect_t _getAuxiliaryKeyDriver(void) { #endif #if defined(IS_WINDOWS) -void win32KeyEvent(int key, MMKeyFlags flags) { +void win32KeyEvent(int key, MMKeyFlags flags, int32_t pid) { int scan = MapVirtualKey(key & 0xff, MAPVK_VK_TO_VSC); /* Set the scan code for extended keys */ @@ -117,7 +126,7 @@ void win32KeyEvent(int key, MMKeyFlags flags) { } #endif -void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags) { +void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags, int32_t pid) { #if defined(IS_MACOSX) /* The media keys all have 1000 added to them to help us detect them. */ if (code >= 1000) { @@ -143,19 +152,20 @@ void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags) { if (flags != 0) { CGEventSetFlags(keyEvent, (CGEventFlags) flags); } - CGEventPost(kCGSessionEventTap, keyEvent); + + SendTo(pid, keyEvent); CFRelease(keyEvent); } #elif defined(IS_WINDOWS) const DWORD dwFlags = down ? 0 : KEYEVENTF_KEYUP; /* Parse modifier keys. */ - if (flags & MOD_META) { WIN32_KEY_EVENT_WAIT(K_META, dwFlags); } - if (flags & MOD_ALT) { WIN32_KEY_EVENT_WAIT(K_ALT, dwFlags); } - if (flags & MOD_CONTROL) { WIN32_KEY_EVENT_WAIT(K_CONTROL, dwFlags); } - if (flags & MOD_SHIFT) { WIN32_KEY_EVENT_WAIT(K_SHIFT, dwFlags); } + if (flags & MOD_META) { WIN32_KEY_EVENT_WAIT(K_META, dwFlags, pid); } + if (flags & MOD_ALT) { WIN32_KEY_EVENT_WAIT(K_ALT, dwFlags, pid); } + if (flags & MOD_CONTROL) { WIN32_KEY_EVENT_WAIT(K_CONTROL, dwFlags, pid); } + if (flags & MOD_SHIFT) { WIN32_KEY_EVENT_WAIT(K_SHIFT, dwFlags, pid); } - win32KeyEvent(code, dwFlags); + win32KeyEvent(code, dwFlags, pid); #elif defined(USE_X11) Display *display = XGetMainDisplay(); const Bool is_press = down ? True : False; /* Just to be safe. */ @@ -193,7 +203,7 @@ void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags) { } #endif -void toggleKey(char c, const bool down, MMKeyFlags flags){ +void toggleKey(char c, const bool down, MMKeyFlags flags, int32_t pid) { MMKeyCode keyCode = keyCodeForChar(c); //Prevent unused variable warning for Mac and Linux. @@ -219,7 +229,7 @@ void toggleKey(char c, const bool down, MMKeyFlags flags){ keyCode = keyCode & 0xff; // Mask out modifiers. #endif - toggleKeyCode(keyCode, down, flags); + toggleKeyCode(keyCode, down, flags, pid); } // void tapKey(char c, MMKeyFlags flags){ @@ -229,7 +239,7 @@ void toggleKey(char c, const bool down, MMKeyFlags flags){ // } #if defined(IS_MACOSX) -void toggleUnicode(UniChar ch, const bool down) { +void toggleUnicode(UniChar ch, const bool down, int32_t pid) { /* This function relies on the convenient CGEventKeyboardSetUnicodeString(), convert characters to a keycode, but does not support adding modifier flags. It is only used in typeString(). @@ -242,7 +252,7 @@ void toggleUnicode(UniChar ch, const bool down) { CGEventKeyboardSetUnicodeString(keyEvent, 1, &ch); - CGEventPost(kCGSessionEventTap, keyEvent); + SendTo(pid, keyEvent); CFRelease(keyEvent); } #endif @@ -280,13 +290,13 @@ void toggleUnicode(UniChar ch, const bool down) { #endif // unicode type -void unicodeType(const unsigned value){ +void unicodeType(const unsigned value, int32_t pid){ #if defined(IS_MACOSX) UniChar ch = (UniChar)value; // Convert to unsigned char - toggleUnicode(ch, true); + toggleUnicode(ch, true, pid); microsleep(5.0); - toggleUnicode(ch, false); + toggleUnicode(ch, false, pid); #elif defined(IS_WINDOWS) INPUT input[2]; memset(input, 0, sizeof(input)); From 16e0808dbd1c6c0c0b86ee9626da60e0e31234bf Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 17 Feb 2022 12:21:27 -0800 Subject: [PATCH 218/327] Fixed CI build --- key/keypress.h | 2 +- key/keypress_c.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/key/keypress.h b/key/keypress.h index 6b74da79..d4613227 100644 --- a/key/keypress.h +++ b/key/keypress.h @@ -37,7 +37,7 @@ #if defined(IS_WINDOWS) /* Send win32 key event for given key. */ - void win32KeyEvent(int key, MMKeyFlags flags); + void win32KeyEvent(int key, MMKeyFlags flags, int32_t pid); #endif #endif /* KEYPRESS_H */ diff --git a/key/keypress_c.h b/key/keypress_c.h index f909dd77..2f225ed8 100644 --- a/key/keypress_c.h +++ b/key/keypress_c.h @@ -258,7 +258,7 @@ void toggleUnicode(UniChar ch, const bool down, int32_t pid) { #endif #if defined(USE_X11) - #define toggleUniKey(c, down) toggleKey(c, down, MOD_NONE) + #define toggleUniKey(c, down) toggleKey(c, down, MOD_NONE, 0) int input_utf(const char *utf) { Display *dpy = XOpenDisplay(NULL); From 60ddc20e02b6b3e1763c83ce06e7996d44a470e2 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 17 Feb 2022 12:29:18 -0800 Subject: [PATCH 219/327] Update Unicode Type args --- key.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/key.go b/key.go index 739cff52..b9a61685 100644 --- a/key.go +++ b/key.go @@ -591,8 +591,12 @@ func CharCodeAt(s string, n int) rune { } // UnicodeType tap uint32 unicode -func UnicodeType(str uint32, pid int) { +func UnicodeType(str uint32, args ...int) { cstr := C.uint(str) + pid := 0 + if len(args) > 0 { + pid = args[0] + } C.unicodeType(cstr, C.int32_t(pid)) } From 0dcc87c35544be7ff02f5d5fe51e3a6c774009af Mon Sep 17 00:00:00 2001 From: vcaesar Date: Fri, 18 Feb 2022 10:21:31 -0800 Subject: [PATCH 220/327] Optimize key code and add more examples code --- README.md | 8 +++++++- examples/key/main.go | 2 +- examples/window/main.go | 8 ++++++++ key.go | 21 +++++++++++++-------- 4 files changed, 29 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index b5a76864..1126aba0 100644 --- a/README.md +++ b/README.md @@ -199,7 +199,7 @@ import ( func main() { robotgo.TypeStr("Hello World") - robotgo.TypeStr("だんしゃり", 1) + robotgo.TypeStr("だんしゃり", 0, 1) // robotgo.TypeStr("テストする") robotgo.TypeStr("Hi galaxy. こんにちは世界.") @@ -448,6 +448,12 @@ func main() { fmt.Println("pids... ", fpid) if len(fpid) > 0 { + robotgo.TypeStr("Hi galaxy!", int(fpid[0])) + robotgo.KeyTap("a", fpid[0], "cmd") + + robotgo.KeyToggle("a", fpid[0]) + robotgo.KeyToggle("a", fpid[0], "up") + robotgo.ActivePID(fpid[0]) robotgo.Kill(fpid[0]) diff --git a/examples/key/main.go b/examples/key/main.go index 50b09dba..ec90626d 100644 --- a/examples/key/main.go +++ b/examples/key/main.go @@ -19,7 +19,7 @@ import ( func typeStr() { // importing "Hello World" - robotgo.TypeStr("Hello World!", 1) + robotgo.TypeStr("Hello World!", 0, 1) robotgo.KeySleep = 100 robotgo.TypeStr("だんしゃり") diff --git a/examples/window/main.go b/examples/window/main.go index e2d3e8c6..ffa5c874 100644 --- a/examples/window/main.go +++ b/examples/window/main.go @@ -54,6 +54,14 @@ func findIds() { return } + if len(fpid) > 0 { + robotgo.KeyTap("a", fpid[0]) + robotgo.TypeStr("Hi galaxy!", int(fpid[0])) + + robotgo.KeyToggle("a", fpid[0], "cmd") + robotgo.KeyToggle("a", fpid[0], "cmd", "up") + } + fmt.Println("pids...", fpid) if len(fpid) > 0 { err = robotgo.ActivePID(fpid[0]) diff --git a/key.go b/key.go index b9a61685..cef5bef2 100644 --- a/key.go +++ b/key.go @@ -323,7 +323,7 @@ var keyNames = map[string]C.MMKeyCode{ func tapKeyCode(code C.MMKeyCode, flags C.MMKeyFlags, pid C.int32_t) { C.toggleKeyCode(code, true, flags, pid) - MilliSleep(5) + MilliSleep(3) C.toggleKeyCode(code, false, flags, pid) } @@ -407,12 +407,20 @@ func keyTaps(k string, keyArr []string, pid int) error { } func keyToggles(k string, keyArr []string, pid int) error { + if len(keyArr) <= 0 { + keyArr = append(keyArr, "down") + } + down := true if keyArr[0] == "up" { down = false } - flags := getFlagsFromValue(keyArr[1:]) + if keyArr[0] == "up" || keyArr[0] == "down" { + keyArr = keyArr[1:] + } + flags := getFlagsFromValue(keyArr) + key, err := checkKeyCodes(k) if err != nil { return err @@ -516,9 +524,6 @@ func KeyTap(key string, args ...interface{}) error { // robotgo.KeyToggle("a", "up", "alt", "cmd") // func KeyToggle(key string, args ...interface{}) error { - if len(args) <= 0 { - args = append(args, "down") - } if len(key) > 0 && unicode.IsUpper([]rune(key)[0]) { args = append(args, "shift") @@ -633,16 +638,16 @@ func inputUTF(str string) { // robotgo.TypeStr(string: "The string to send", int: pid, "milli_sleep time", "x11 option") // // Examples: -// robotgo.TypeStr("abc@123, hi galaxy, こんにちは") +// robotgo.TypeStr("abc@123, Hi galaxy, こんにちは") // func TypeStr(str string, args ...int) { var tm, tm1 = 0, 7 if len(args) > 1 { - tm = args[0] + tm = args[1] } if len(args) > 2 { - tm1 = args[1] + tm1 = args[2] } pid := 0 if len(args) > 0 { From f110d5bf9e2f18f767e57da61aee33490138f216 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sat, 19 Feb 2022 11:48:54 -0800 Subject: [PATCH 221/327] Fixed x11 warning --- key/keypress_c.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/key/keypress_c.h b/key/keypress_c.h index 2f225ed8..3ed9b8a7 100644 --- a/key/keypress_c.h +++ b/key/keypress_c.h @@ -19,6 +19,8 @@ Sleep(DEADBEEF_RANDRANGE(0, 1)); } #elif defined(USE_X11) + Display *XGetMainDisplay(void); + void X_KEY_EVENT(Display *display, MMKeyCode key, bool is_press) { XTestFakeKeyEvent(display, XKeysymToKeycode(display, key), is_press, CurrentTime); XSync(display, false); From efc7c90b9fbcce4019fb5fc020288f3a679793ef Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 22 Feb 2022 14:33:29 -0800 Subject: [PATCH 222/327] Optimize x11 alert show --- robotgo_x11.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/robotgo_x11.go b/robotgo_x11.go index d6d2e6b8..df9eed6a 100644 --- a/robotgo_x11.go +++ b/robotgo_x11.go @@ -224,10 +224,11 @@ func Alert(title, msg string, args ...string) bool { c += cancelBtn + ":1" } c += ` -default ` + defaultBtn + c += ` -geometry 400x200` out, err := Run(c) if err != nil { - fmt.Println("Alert: ", err, ". ", string(out)) + // fmt.Println("Alert: ", err, ". ", string(out)) return false } From e7553175997941fb89a8b4451c9177474ad99383 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 22 Feb 2022 14:54:44 -0800 Subject: [PATCH 223/327] Fixed import format --- robotgo_x11.go | 1 - 1 file changed, 1 deletion(-) diff --git a/robotgo_x11.go b/robotgo_x11.go index df9eed6a..cc4dbc53 100644 --- a/robotgo_x11.go +++ b/robotgo_x11.go @@ -15,7 +15,6 @@ package robotgo import ( "errors" - "fmt" "log" "github.com/robotn/xgb" From 60bf136aa14eac04a6faf42007caaa79fa4650ae Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 27 Feb 2022 16:33:25 -0800 Subject: [PATCH 224/327] Update widows ReleaseDC code --- screen/screengrab_c.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/screen/screengrab_c.h b/screen/screengrab_c.h index adb78b48..470d3869 100644 --- a/screen/screengrab_c.h +++ b/screen/screengrab_c.h @@ -85,10 +85,12 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id) bi.bmiHeader.biClrUsed = 0; bi.bmiHeader.biClrImportant = 0; + HWND hwnd; if (display_id == -1) { screen = GetDC(NULL); /* Get entire screen */ } else { - screen = GetDC((HWND) (uintptr) display_id); + hwnd = (HWND) (uintptr) display_id; + screen = GetDC(hwnd); } if (screen == NULL) { return NULL; } @@ -101,7 +103,7 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id) screen, rect.origin.x, rect.origin.y, SRCCOPY); if (smem || SelectObject(screenMem, dib) == NULL || !bitb) { /* Error copying data. */ - ReleaseDC(NULL, screen); + ReleaseDC(hwnd, screen); DeleteObject(dib); if (screenMem != NULL) { DeleteDC(screenMem); } @@ -117,7 +119,7 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id) memcpy(bitmap->imageBuffer, data, bitmap->bytewidth * bitmap->height); } - ReleaseDC(NULL, screen); + ReleaseDC(hwnd, screen); DeleteObject(dib); DeleteDC(screenMem); From 6bf430b1cd07453d0cfa680545a1c0d5f9a8962e Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 10 Mar 2022 08:08:22 -0800 Subject: [PATCH 225/327] Update dockerfile and appveyor --- .circleci/images/primary/Dockerfile | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index bddffdbe..f7e6b9d4 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.17.7-stretch AS build +FROM golang:1.17.8-stretch AS build # FROM govgo/go:1.11.1 RUN apt update && apt install -y --no-install-recommends \ diff --git a/appveyor.yml b/appveyor.yml index 8f2e9a5a..327bd357 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,7 +34,7 @@ environment: PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% # - COMPILER: MINGW_W64 # ARCHITECTURE: x64 - GOVERSION: 1.17.7 + GOVERSION: 1.17.8 # GOPATH: c:\gopath # scripts that run after cloning repository From 895aed8f22989a2227026421bc10c1f765c32430 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 16 Mar 2022 02:12:03 -0700 Subject: [PATCH 226/327] Update CI to go 1.18 --- .circleci/config.yml | 2 +- .github/issue_template.md | 2 +- .github/workflows/go.yml | 4 ++-- .travis.yml | 3 ++- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index b88fd25f..89deecf3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,7 +5,7 @@ jobs: docker: # using custom image, see .circleci/images/primary/Dockerfile # - image: govgo/robotgoci:1.10.3 - - image: golang:1.17.6 + - image: golang:1.17.8 working_directory: /gopath/src/github.com/go-vgo/robotgo steps: - checkout diff --git a/.github/issue_template.md b/.github/issue_template.md index 507ae818..3606506c 100644 --- a/.github/issue_template.md +++ b/.github/issue_template.md @@ -1,4 +1,4 @@ -1. Please **speak English**, this is the language everybody of us can speak and write. +1. Please **speak English (English only)**, this is the language everybody of us can speak and write. 2. Please take a moment to **search** that an issue **doesn't already exist**. 3. Please make sure `Golang, GCC` is installed correctly before installing RobotGo. diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index f64bda72..c3d5ae62 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -10,10 +10,10 @@ jobs: runs-on: ${{ matrix.os }} steps: - - name: Set up Go 1.17 + - name: Set up Go 1.18 uses: actions/setup-go@v1 with: - go-version: 1.17 + go-version: 1.18 id: go - name: Check out code into the Go module directory diff --git a/.travis.yml b/.travis.yml index ca8107c7..e3651e32 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,8 @@ go: # - 1.14.x # - 1.15.x # - 1.16.x - - 1.17.x + # - 1.17.x + - 1.18.x # - tip addons: From 985c5902849f23422d4ae477b2312ab72370e879 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 21 Mar 2022 10:05:02 -0700 Subject: [PATCH 227/327] Removed Windows VIRTUALScreen size and Update examples --- .github/pull_request_template.md | 2 +- README.md | 3 ++- examples/key/main.go | 7 ++++--- screen/screen_c.h | 24 +++++++++--------------- {examples => test}/index.html | 1 + 5 files changed, 17 insertions(+), 20 deletions(-) rename {examples => test}/index.html (98%) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index c331d4f8..cd8ee71f 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -5,7 +5,7 @@ The pull request will be closed without any reasons if it does not satisfy any o 3. Please read contributing guidelines: [CONTRIBUTING](https://github.com/go-vgo/robotgo/blob/master/CONTRIBUTING.md) 4. Describe what your pull request does and which issue you're targeting (if any and **Please use English**) 5. ... if it is not related to any particular issues, explain why we should not reject your pull request. -6. The Commits must use English, must be test and No useless submissions. +6. The Commits must **use English**, must be test and No useless submissions. **You MUST delete the content above including this line before posting, otherwise your pull request will be invalid.** diff --git a/README.md b/README.md index 1126aba0..19df754e 100644 --- a/README.md +++ b/README.md @@ -202,7 +202,8 @@ func main() { robotgo.TypeStr("だんしゃり", 0, 1) // robotgo.TypeStr("テストする") - robotgo.TypeStr("Hi galaxy. こんにちは世界.") + robotgo.TypeStr("Hi, Seattle space needle, Gold gate bridge, One world trade center.") + robotgo.TypeStr("Hi galaxy, hi stars, hi MT.Rainier, hi sea. こんにちは世界.") robotgo.Sleep(1) // ustr := uint32(robotgo.CharCodeAt("Test", 0)) diff --git a/examples/key/main.go b/examples/key/main.go index ec90626d..db807f7a 100644 --- a/examples/key/main.go +++ b/examples/key/main.go @@ -18,15 +18,16 @@ import ( ) func typeStr() { - // importing "Hello World" + // typing "Hello World" robotgo.TypeStr("Hello World!", 0, 1) robotgo.KeySleep = 100 robotgo.TypeStr("だんしゃり") - robotgo.TypeStr("Hi galaxy. こんにちは世界. 你好, 再见!") + robotgo.TypeStr("Hi galaxy, hi stars, hi MT.Rainier, hi sea. こんにちは世界.") + robotgo.TypeStr("So, hi, bye! 你好, 再见!") robotgo.Sleep(1) - robotgo.TypeStr("So, hi, bye!") + robotgo.TypeStr("Hi, Seattle space needle, Gold gate bridge, One world trade center.") robotgo.MilliSleep(100) ustr := uint32(robotgo.CharCodeAt("So, hi, bye!", 0)) diff --git a/screen/screen_c.h b/screen/screen_c.h index 8c353cd4..bc7fba56 100644 --- a/screen/screen_c.h +++ b/screen/screen_c.h @@ -22,15 +22,9 @@ MMSizeInt32 getMainDisplaySize(void) { (int32_t)DisplayWidth(display, screen), (int32_t)DisplayHeight(display, screen)); #elif defined(IS_WINDOWS) - if (GetSystemMetrics(SM_CMONITORS) == 1) { - return MMSizeInt32Make( + return MMSizeInt32Make( (int32_t)GetSystemMetrics(SM_CXSCREEN), (int32_t)GetSystemMetrics(SM_CYSCREEN)); - } else { - return MMSizeInt32Make( - (int32_t)GetSystemMetrics(SM_CXVIRTUALSCREEN), - (int32_t)GetSystemMetrics(SM_CYVIRTUALSCREEN)); - } #endif } @@ -56,19 +50,19 @@ MMRectInt32 getScreenRect(int32_t display_id) { (int32_t)DisplayWidth(display, screen), (int32_t)DisplayHeight(display, screen)); #elif defined(IS_WINDOWS) - if (GetSystemMetrics(SM_CMONITORS) == 1) { + // if (GetSystemMetrics(SM_CMONITORS) == 1) { return MMRectInt32Make( (int32_t)0, (int32_t)0, (int32_t)GetSystemMetrics(SM_CXSCREEN), (int32_t)GetSystemMetrics(SM_CYSCREEN)); - } else { - return MMRectInt32Make( - (int32_t)GetSystemMetrics(SM_XVIRTUALSCREEN), - (int32_t)GetSystemMetrics(SM_YVIRTUALSCREEN), - (int32_t)GetSystemMetrics(SM_CXVIRTUALSCREEN), - (int32_t)GetSystemMetrics(SM_CYVIRTUALSCREEN)); - } + // } else { + // return MMRectInt32Make( + // (int32_t)GetSystemMetrics(SM_XVIRTUALSCREEN), + // (int32_t)GetSystemMetrics(SM_YVIRTUALSCREEN), + // (int32_t)GetSystemMetrics(SM_CXVIRTUALSCREEN), + // (int32_t)GetSystemMetrics(SM_CYVIRTUALSCREEN)); + // } #endif } diff --git a/examples/index.html b/test/index.html similarity index 98% rename from examples/index.html rename to test/index.html index c78a17c5..e18582cd 100644 --- a/examples/index.html +++ b/test/index.html @@ -27,6 +27,7 @@

Type and check the console

}); }; + // move window.onmousemove = function(events) { console.log({ event: "move", From 51ca08e484b06951043e5297ac10a3594137e7d8 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Fri, 8 Apr 2022 14:10:02 -0700 Subject: [PATCH 228/327] Fixed type x11 key bug #493 --- key/keycode_c.h | 5 +++++ key/keypress_c.h | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/key/keycode_c.h b/key/keycode_c.h index 75b610ea..01f1bdbc 100644 --- a/key/keycode_c.h +++ b/key/keycode_c.h @@ -79,6 +79,11 @@ MMKeyCode keyCodeForChar(const char c) { if (code == NoSymbol) { return K_NOT_A_KEY; } + + // x11 key bug + if (c == 60) { + code = 44; + } return code; #endif } diff --git a/key/keypress_c.h b/key/keypress_c.h index 3ed9b8a7..64c1fd1d 100644 --- a/key/keypress_c.h +++ b/key/keypress_c.h @@ -20,7 +20,7 @@ } #elif defined(USE_X11) Display *XGetMainDisplay(void); - + void X_KEY_EVENT(Display *display, MMKeyCode key, bool is_press) { XTestFakeKeyEvent(display, XKeysymToKeycode(display, key), is_press, CurrentTime); XSync(display, false); From a2e387b44880fe539e04e9ed1301c220905c08ce Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sat, 9 Apr 2022 10:33:02 -0700 Subject: [PATCH 229/327] Optimize keyboard code and Update examples --- README.md | 2 +- examples/key/main.go | 2 +- key.go | 2 +- key/goKey.h | 6 ------ key/keypress.h | 3 +++ key/keypress_c.h | 1 + 6 files changed, 7 insertions(+), 9 deletions(-) delete mode 100644 key/goKey.h diff --git a/README.md b/README.md index 19df754e..2f11fc9d 100644 --- a/README.md +++ b/README.md @@ -202,7 +202,7 @@ func main() { robotgo.TypeStr("だんしゃり", 0, 1) // robotgo.TypeStr("テストする") - robotgo.TypeStr("Hi, Seattle space needle, Gold gate bridge, One world trade center.") + robotgo.TypeStr("Hi, Seattle space needle, Golden gate bridge, One world trade center.") robotgo.TypeStr("Hi galaxy, hi stars, hi MT.Rainier, hi sea. こんにちは世界.") robotgo.Sleep(1) diff --git a/examples/key/main.go b/examples/key/main.go index db807f7a..b2eb9e35 100644 --- a/examples/key/main.go +++ b/examples/key/main.go @@ -27,7 +27,7 @@ func typeStr() { robotgo.TypeStr("So, hi, bye! 你好, 再见!") robotgo.Sleep(1) - robotgo.TypeStr("Hi, Seattle space needle, Gold gate bridge, One world trade center.") + robotgo.TypeStr("Hi, Seattle space needle, Golden gate bridge, One world trade center.") robotgo.MilliSleep(100) ustr := uint32(robotgo.CharCodeAt("So, hi, bye!", 0)) diff --git a/key.go b/key.go index cef5bef2..190270aa 100644 --- a/key.go +++ b/key.go @@ -12,7 +12,7 @@ package robotgo /* // #include "key/keycode.h" -#include "key/goKey.h" +#include "key/keypress_c.h" */ import "C" diff --git a/key/goKey.h b/key/goKey.h deleted file mode 100644 index b377f6c6..00000000 --- a/key/goKey.h +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright 2016 The go-vgo Project Developers. - -#include -#include "../base/types.h" -#include "keypress_c.h" -#include "keycode_c.h" diff --git a/key/keypress.h b/key/keypress.h index d4613227..6e69c710 100644 --- a/key/keypress.h +++ b/key/keypress.h @@ -2,7 +2,10 @@ #ifndef KEYPRESS_H #define KEYPRESS_H +#include #include "../base/os.h" +#include "../base/types.h" + #include "keycode.h" #include diff --git a/key/keypress_c.h b/key/keypress_c.h index 64c1fd1d..4d4959f1 100644 --- a/key/keypress_c.h +++ b/key/keypress_c.h @@ -1,6 +1,7 @@ #include "keypress.h" #include "../base/deadbeef_rand_c.h" #include "../base/microsleep.h" +#include "keycode_c.h" #include /* For isupper() */ #if defined(IS_MACOSX) From 8744c88f5f457f0498ddefbc975c6b1a23868e54 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 13 Apr 2022 13:03:56 -0700 Subject: [PATCH 230/327] Update dockerfile and CI --- .circleci/config.yml | 2 +- .circleci/images/primary/Dockerfile | 2 +- appveyor.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 89deecf3..0f0e25b7 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,7 +5,7 @@ jobs: docker: # using custom image, see .circleci/images/primary/Dockerfile # - image: govgo/robotgoci:1.10.3 - - image: golang:1.17.8 + - image: golang:1.18.1 working_directory: /gopath/src/github.com/go-vgo/robotgo steps: - checkout diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index f7e6b9d4..a3c88f88 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.17.8-stretch AS build +FROM golang:1.18.1-stretch AS build # FROM govgo/go:1.11.1 RUN apt update && apt install -y --no-install-recommends \ diff --git a/appveyor.yml b/appveyor.yml index 327bd357..a7c14274 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,7 +34,7 @@ environment: PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% # - COMPILER: MINGW_W64 # ARCHITECTURE: x64 - GOVERSION: 1.17.8 + GOVERSION: 1.18.1 # GOPATH: c:\gopath # scripts that run after cloning repository From 7df3bc38000c5f00e1afb7cba619a14a16ee96aa Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 14 Apr 2022 08:57:09 -0700 Subject: [PATCH 231/327] Add more key and mouse examples code --- examples/key/main.go | 9 +++++++++ examples/mouse/main.go | 9 +++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/examples/key/main.go b/examples/key/main.go index b2eb9e35..84e12574 100644 --- a/examples/key/main.go +++ b/examples/key/main.go @@ -74,6 +74,14 @@ func keyTap() { robotgo.KeyTap("a", "control") } +func special() { + robotgo.TypeStr("{}") + robotgo.KeyTap("[", "]") + + robotgo.KeyToggle("(") + robotgo.KeyToggle("(", "up") +} + func keyToggle() { // robotgo.KeySleep = 150 robotgo.KeyToggle(robotgo.KeyA) @@ -113,6 +121,7 @@ func key() { //////////////////////////////////////////////////////////////////////////////// typeStr() + special() keyTap() keyToggle() diff --git a/examples/mouse/main.go b/examples/mouse/main.go index c03e849c..b49806c6 100644 --- a/examples/mouse/main.go +++ b/examples/mouse/main.go @@ -25,9 +25,7 @@ func move() { // move the mouse to 100, 200 robotgo.Move(100, 200) - // robotgo.Drag(10, 10) - // robotgo.Drag(20, 20, "right") - // + // drag mouse with smooth robotgo.DragSmooth(10, 10) robotgo.DragSmooth(100, 200, 1.0, 100.0) @@ -37,7 +35,7 @@ func move() { robotgo.MoveSmoothRelative(10, -100, 1.0, 30.0) for i := 0; i < 1080; i += 1000 { - fmt.Println(i) + fmt.Println("i: ", i) // MoveMouse(800, i) robotgo.Move(800, i) } @@ -74,6 +72,9 @@ func toggleAndScroll() { robotgo.Scroll(100, 10) robotgo.Scroll(0, -10) + robotgo.Toggle("left") + robotgo.Toggle("left", "up") + // toggles the right mouse button robotgo.Toggle("right") robotgo.Toggle("right", "up") From c5cdd0a33ffb0c26b96b637a96446e4ca89e0d8b Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sat, 28 May 2022 23:32:26 -0700 Subject: [PATCH 232/327] Update gomod and CI fixed dependabot alert --- .circleci/config.yml | 2 +- .circleci/images/primary/Dockerfile | 2 +- appveyor.yml | 2 +- go.mod | 11 +++++----- go.sum | 33 ++++++++++++++--------------- 5 files changed, 24 insertions(+), 26 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0f0e25b7..095cf75f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,7 +5,7 @@ jobs: docker: # using custom image, see .circleci/images/primary/Dockerfile # - image: govgo/robotgoci:1.10.3 - - image: golang:1.18.1 + - image: golang:1.18.2 working_directory: /gopath/src/github.com/go-vgo/robotgo steps: - checkout diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index a3c88f88..b46ba1bb 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.18.1-stretch AS build +FROM golang:1.18.2-stretch AS build # FROM govgo/go:1.11.1 RUN apt update && apt install -y --no-install-recommends \ diff --git a/appveyor.yml b/appveyor.yml index a7c14274..5ca85e1a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,7 +34,7 @@ environment: PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% # - COMPILER: MINGW_W64 # ARCHITECTURE: x64 - GOVERSION: 1.18.1 + GOVERSION: 1.18.2 # GOPATH: c:\gopath # scripts that run after cloning repository diff --git a/go.mod b/go.mod index 28c7fb66..3a267796 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( // github.com/robotn/gohook v0.31.3 github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 - github.com/vcaesar/gops v0.22.0 + github.com/vcaesar/gops v0.23.0 github.com/vcaesar/imgo v0.30.1 github.com/vcaesar/keycode v0.10.0 github.com/vcaesar/tt v0.20.0 @@ -22,12 +22,11 @@ require ( github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/otiai10/mint v1.3.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect - github.com/shirou/gopsutil/v3 v3.21.12 // indirect - github.com/tklauser/go-sysconf v0.3.9 // indirect - github.com/tklauser/numcpus v0.3.0 // indirect + github.com/shirou/gopsutil/v3 v3.22.4 // indirect + github.com/tklauser/go-sysconf v0.3.10 // indirect + github.com/tklauser/numcpus v0.4.0 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect - golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect + golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27 // indirect ) // replace golang.org/x/sys => github.com/golang/sys v0.0.0-20190109145017-48ac38b7c8cb diff --git a/go.sum b/go.sum index b1cda640..c661775c 100644 --- a/go.sum +++ b/go.sum @@ -5,8 +5,9 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/lxn/win v0.0.0-20210218163916-a377121e959e h1:H+t6A/QJMbhCSEH5rAuRxh+CtW96g0Or0Fxa9IKr4uc= @@ -24,17 +25,17 @@ github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 h1:2lhSR8N3T6I30q096DT7 github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934/go.mod h1:SxQhJskUJ4rleVU44YvnrdvxQr0tKy5SRSigBrCgyyQ= github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 h1:2uX8QRLkkxn2EpAQ6I3KhA79BkdRZfvugJUzJadiJwk= github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770/go.mod h1:svkDXUDQjUiWzLrA0OZgHc4lbOts3C+uRfP6/yjwYnU= -github.com/shirou/gopsutil/v3 v3.21.12 h1:VoGxEW2hpmz0Vt3wUvHIl9fquzYLNpVpgNNB7pGJimA= -github.com/shirou/gopsutil/v3 v3.21.12/go.mod h1:BToYZVTlSVlfazpDDYFnsVZLaoRG+g8ufT6fPQLdJzA= +github.com/shirou/gopsutil/v3 v3.22.4 h1:srAQaiX6jX/cYL6q29aE0m8lOskT9CurZ9N61YR3yoI= +github.com/shirou/gopsutil/v3 v3.22.4/go.mod h1:D01hZJ4pVHPpCTZ3m3T2+wDF2YAGfd+H4ifUguaQzHM= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/tklauser/go-sysconf v0.3.9 h1:JeUVdAOWhhxVcU6Eqr/ATFHgXk/mmiItdKeJPev3vTo= -github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs= -github.com/tklauser/numcpus v0.3.0 h1:ILuRUQBtssgnxw0XXIjKUC56fgnOrFoQQ/4+DeU2biQ= -github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8= -github.com/vcaesar/gops v0.22.0 h1:aWHWxY3fvUuaJGph+LegYUSEU/874WJT7MInd8OUmP0= -github.com/vcaesar/gops v0.22.0/go.mod h1:GFNGo9xpCfjcfd/Hovi9RSrpd4FdaQt8V92TzpU22w4= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw= +github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk= +github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o= +github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ= +github.com/vcaesar/gops v0.23.0 h1:gY/E5UJfLpImJjE7tiTJIVRcKOWxi7YX1J/CUHK8gXk= +github.com/vcaesar/gops v0.23.0/go.mod h1:3IepRPE6qK9Wy8MGLJx2N3o77fuO1Ec7FvPHyEuou8I= github.com/vcaesar/imgo v0.30.1 h1:B7QMm2mZY+SGoEvvJwNi+eAv21ptvk2YT1IbP2OzyLE= github.com/vcaesar/imgo v0.30.1/go.mod h1:n4EluJIN/0UYYGPHBCY/BWlIjdRUdY5U6obtP2lrgdM= github.com/vcaesar/keycode v0.10.0 h1:Qx5QE8ZXHyRyjoA2QOxBp25OKMKB+zxMVqm0FWGV0d4= @@ -56,10 +57,8 @@ golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27 h1:XDXtA5hveEEV8JB2l7nhMTp3t3cHp9ZpwcdjqyEWLlo= +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -68,5 +67,5 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IV golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From e08e05307eaec88653a294821b0a179041aad76d Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 13 Jun 2022 11:38:35 -0700 Subject: [PATCH 233/327] Updated dockerfile and CI --- .circleci/config.yml | 3 +-- .circleci/images/primary/Dockerfile | 2 +- appveyor.yml | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 095cf75f..8eda2c07 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,7 +5,7 @@ jobs: docker: # using custom image, see .circleci/images/primary/Dockerfile # - image: govgo/robotgoci:1.10.3 - - image: golang:1.18.2 + - image: golang:1.18.3 working_directory: /gopath/src/github.com/go-vgo/robotgo steps: - checkout @@ -20,7 +20,6 @@ jobs: - run: apt -y install xvfb # # override: - # - run: go get -u github.com/go-vgo/robotgo - run: go get -v -t -d ./... - run: xvfb-run go test -v ./... # diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index b46ba1bb..4d211525 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.18.2-stretch AS build +FROM golang:1.18.3-stretch AS build # FROM govgo/go:1.11.1 RUN apt update && apt install -y --no-install-recommends \ diff --git a/appveyor.yml b/appveyor.yml index 5ca85e1a..d98e4654 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,7 +34,7 @@ environment: PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% # - COMPILER: MINGW_W64 # ARCHITECTURE: x64 - GOVERSION: 1.18.2 + GOVERSION: 1.18.3 # GOPATH: c:\gopath # scripts that run after cloning repository From 1934220f501a03b984e238ffa1f7f06a289695fc Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 23 Jun 2022 21:11:41 -0700 Subject: [PATCH 234/327] Fixed Windows bitmap copy #501 --- base/MMBitmap.h | 1 + screen/screengrab_c.h | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/base/MMBitmap.h b/base/MMBitmap.h index b652a2d1..85b4a2e2 100644 --- a/base/MMBitmap.h +++ b/base/MMBitmap.h @@ -11,6 +11,7 @@ struct _MMBitmap { uint8_t *imageBuffer; /* Pixels stored in Quad I format; */ int32_t width; /* Never 0, unless image is NULL. */ int32_t height; /* Never 0, unless image is NULL. */ + int32_t bytewidth; /* The aligned width (width + padding). */ uint8_t bitsPerPixel; /* Should be either 24 or 32. */ uint8_t bytesPerPixel; /* For convenience; should be bitsPerPixel / 8. */ diff --git a/screen/screengrab_c.h b/screen/screengrab_c.h index 470d3869..1118391d 100644 --- a/screen/screengrab_c.h +++ b/screen/screengrab_c.h @@ -98,10 +98,11 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id) dib = CreateDIBSection(screen, &bi, DIB_RGB_COLORS, &data, NULL, 0); /* Copy the data into a bitmap struct. */ - BOOL smem = (screenMem = CreateCompatibleDC(screen)) == NULL; - BOOL bitb = BitBlt(screenMem, (int)0, (int)0, (int)rect.size.w, (int)rect.size.h, + BOOL b = (screenMem = CreateCompatibleDC(screen)) == NULL || + SelectObject(screenMem, dib) == NULL || + !BitBlt(screenMem, (int)0, (int)0, (int)rect.size.w, (int)rect.size.h, screen, rect.origin.x, rect.origin.y, SRCCOPY); - if (smem || SelectObject(screenMem, dib) == NULL || !bitb) { + if (b) { /* Error copying data. */ ReleaseDC(hwnd, screen); DeleteObject(dib); From ee25e577e58f15ff6caa551bdd9c96e626ee89f7 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 26 Jun 2022 10:23:17 -0700 Subject: [PATCH 235/327] add get the HWND by PID support --- robotgo.go | 5 +++++ screen/goScreen.h | 9 +++++++++ 2 files changed, 14 insertions(+) diff --git a/robotgo.go b/robotgo.go index f73c593c..420c22cc 100644 --- a/robotgo.go +++ b/robotgo.go @@ -236,6 +236,11 @@ func getNumDisplays() int { return int(C.get_num_displays()) } +// GetHwndByPId get the hwnd by pid +func GetHwndByPId(pid int) int { + return int(C.get_hwnd_by_pid(C.uintptr(pid))) +} + // SysScale get the sys scale func SysScale(displayId ...int) float64 { display := displayIdx(displayId...) diff --git a/screen/goScreen.h b/screen/goScreen.h index 2a2bc882..b9c0a162 100644 --- a/screen/goScreen.h +++ b/screen/goScreen.h @@ -97,6 +97,15 @@ uint32_t get_num_displays() { #endif } +uintptr get_hwnd_by_pid(uintptr pid) { + #if defined(IS_WINDOWS) + HWND hwnd = GetHwndByPId(pid); + return (uintptr)hwnd; + #else + return 0; + #endif +} + void bitmap_dealloc(MMBitmapRef bitmap) { if (bitmap != NULL) { destroyMMBitmap(bitmap); From 31c248aedd5ff8afd42513d544ac02dea326c433 Mon Sep 17 00:00:00 2001 From: Weilong Wang Date: Sun, 31 Jul 2022 16:47:14 +0800 Subject: [PATCH 236/327] convert img lose 1 pixel bug --- img.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/img.go b/img.go index 25bbf827..edc32e6b 100644 --- a/img.go +++ b/img.go @@ -122,7 +122,7 @@ func ImgToBitmap(m image.Image) (bit Bitmap) { // ToUint8p convert the []uint8 to uint8 pointer func ToUint8p(dst []uint8) *uint8 { src := make([]uint8, len(dst)+10) - for i := 0; i < len(dst)-4; i += 4 { + for i := 0; i <= len(dst)-4; i += 4 { src[i+3] = dst[i+3] src[i] = dst[i+2] src[i+1] = dst[i+1] @@ -151,7 +151,7 @@ func val(p *uint8, n int) uint8 { } func copyToVUint8A(dst []uint8, src *uint8) { - for i := 0; i < len(dst)-4; i += 4 { + for i := 0; i <= len(dst)-4; i += 4 { dst[i] = val(src, i+2) dst[i+1] = val(src, i+1) dst[i+2] = val(src, i) From f428ffb1fb8f5d67d1f9f79a465a23cce5616874 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 6 Sep 2022 14:51:08 -0700 Subject: [PATCH 237/327] Update: Bump CI to 1.19 --- .circleci/config.yml | 2 +- .circleci/images/primary/Dockerfile | 2 +- .github/workflows/go.yml | 4 ++-- .travis.yml | 3 ++- appveyor.yml | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 8eda2c07..dc9f59a9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,7 +5,7 @@ jobs: docker: # using custom image, see .circleci/images/primary/Dockerfile # - image: govgo/robotgoci:1.10.3 - - image: golang:1.18.3 + - image: golang:1.19.1 working_directory: /gopath/src/github.com/go-vgo/robotgo steps: - checkout diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index 4d211525..d4649aa2 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.18.3-stretch AS build +FROM golang:1.19.1-stretch AS build # FROM govgo/go:1.11.1 RUN apt update && apt install -y --no-install-recommends \ diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index c3d5ae62..dd31edad 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -10,10 +10,10 @@ jobs: runs-on: ${{ matrix.os }} steps: - - name: Set up Go 1.18 + - name: Set up Go 1.19 uses: actions/setup-go@v1 with: - go-version: 1.18 + go-version: 1.19 id: go - name: Check out code into the Go module directory diff --git a/.travis.yml b/.travis.yml index e3651e32..4d2c3fb1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,8 @@ go: # - 1.15.x # - 1.16.x # - 1.17.x - - 1.18.x + # - 1.18.x + - 1.19.x # - tip addons: diff --git a/appveyor.yml b/appveyor.yml index d98e4654..c5e38ea2 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,7 +34,7 @@ environment: PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% # - COMPILER: MINGW_W64 # ARCHITECTURE: x64 - GOVERSION: 1.18.3 + GOVERSION: 1.19.1 # GOPATH: c:\gopath # scripts that run after cloning repository From 47ca6812fe19e337282bfee60c10a59eb2c7e261 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 12 Sep 2022 15:20:48 -0700 Subject: [PATCH 238/327] Update README.md --- README.md | 8 ++++---- README_zh.md | 4 +++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 2f11fc9d..b09f5189 100644 --- a/README.md +++ b/README.md @@ -163,8 +163,8 @@ import ( func main() { robotgo.MouseSleep = 100 - robotgo.ScrollMouse(10, "up") - robotgo.ScrollMouse(20, "right") + robotgo.ScrollDir(10, "up") + robotgo.ScrollDir(20, "right") robotgo.Scroll(0, -10) robotgo.Scroll(100, 0) @@ -242,7 +242,7 @@ import ( ) func main() { - x, y := robotgo.GetMousePos() + x, y := robotgo.Location() fmt.Println("pos: ", x, y) color := robotgo.GetPixelColor(100, 200) @@ -455,7 +455,7 @@ func main() { robotgo.KeyToggle("a", fpid[0]) robotgo.KeyToggle("a", fpid[0], "up") - robotgo.ActivePID(fpid[0]) + robotgo.ActivePid(fpid[0]) robotgo.Kill(fpid[0]) } diff --git a/README_zh.md b/README_zh.md index 7bac20c9..c6f84d92 100644 --- a/README_zh.md +++ b/README_zh.md @@ -1,5 +1,7 @@ # Robotgo +## !!! Warning: this page not updated !!! + [![Build Status](https://github.com/go-vgo/robotgo/workflows/Go/badge.svg)](https://github.com/go-vgo/robotgo/commits/master) [![CircleCI Status](https://circleci.com/gh/go-vgo/robotgo.svg?style=shield)](https://circleci.com/gh/go-vgo/robotgo) [![Build Status](https://travis-ci.org/go-vgo/robotgo.svg)](https://travis-ci.org/go-vgo/robotgo) @@ -67,7 +69,7 @@ xcode-select --install ``` Or the other GCC (But you should compile the "libpng" with yourself. -Or you can removed the bitmap.go ) +Or you can removed the bitmap.go.) ``` #### For everything else (Linux 等其他系统): From e9b5a9251e1689ec54241d569ff5fa2d4a8b650a Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 13 Sep 2022 15:49:21 -0700 Subject: [PATCH 239/327] Update: Unified pid and xid name, Update godoc, fixed typo --- README.md | 2 +- base/pubs.h | 4 ++-- examples/window/main.go | 6 +++--- mouse/mouse_c.h | 2 +- robotgo.go | 47 +++++++++++++++++++++++++++-------------- robotgo_mac.go | 2 +- robotgo_mac_win.go | 8 ++++--- robotgo_win.go | 2 +- robotgo_x11.go | 23 ++++++++++---------- screen/goScreen.h | 2 +- window/goWindow.h | 4 ++-- window/win_sys.h | 4 ++-- window/window.h | 2 +- 13 files changed, 63 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index b09f5189..a375d6f9 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ Golang GCC ``` -#### For Mac OS X: +#### For MacOS: Xcode Command Line Tools (And Privacy setting: [#277](https://github.com/go-vgo/robotgo/issues/277) ) diff --git a/base/pubs.h b/base/pubs.h index 6dfecc73..1ad716ba 100644 --- a/base/pubs.h +++ b/base/pubs.h @@ -22,12 +22,12 @@ return TRUE; } - HWND GetHwndByPId(DWORD dwProcessId) { + HWND GetHwndByPid(DWORD dwProcessId) { WNDINFO info = {0}; info.hWnd = NULL; info.dwPid = dwProcessId; EnumWindows(EnumWindowsProc, (LPARAM)&info); - // printf("%d\n", info.hWnd); + return info.hWnd; } #endif \ No newline at end of file diff --git a/examples/window/main.go b/examples/window/main.go index ffa5c874..7e39b5ba 100644 --- a/examples/window/main.go +++ b/examples/window/main.go @@ -28,7 +28,7 @@ func alert() { func get() { // get the current process id - pid := robotgo.GetPID() + pid := robotgo.GetPid() fmt.Println("pid----", pid) // get current Window Active @@ -64,7 +64,7 @@ func findIds() { fmt.Println("pids...", fpid) if len(fpid) > 0 { - err = robotgo.ActivePID(fpid[0]) + err = robotgo.ActivePid(fpid[0]) if err != nil { fmt.Println(err) } @@ -87,7 +87,7 @@ func findIds() { } func active() { - robotgo.ActivePID(100) + robotgo.ActivePid(100) // robotgo.Sleep(2) robotgo.ActiveName("code") robotgo.Sleep(1) diff --git a/mouse/mouse_c.h b/mouse/mouse_c.h index 6e08d9a6..a53bdf5f 100644 --- a/mouse/mouse_c.h +++ b/mouse/mouse_c.h @@ -192,7 +192,7 @@ void clickMouse(MMMouseButton button){ toggleMouse(false, button); } -/* Special function for sending double clicks, needed for Mac OS X. */ +/* Special function for sending double clicks, needed for MacOS. */ void doubleClick(MMMouseButton button){ #if defined(IS_MACOSX) /* Double click for Mac. */ diff --git a/robotgo.go b/robotgo.go index 420c22cc..e9d6efd2 100644 --- a/robotgo.go +++ b/robotgo.go @@ -9,20 +9,22 @@ // except according to those terms. /* - Package robotgo Go native cross-platform system automation. Please make sure Golang, GCC is installed correctly before installing RobotGo; See Requirements: + https://github.com/go-vgo/robotgo#requirements Installation: With Go module support (Go 1.11+), just import: + import "github.com/go-vgo/robotgo" Otherwise, to install the robotgo package, run the command: + go get -u github.com/go-vgo/robotgo */ package robotgo @@ -236,8 +238,8 @@ func getNumDisplays() int { return int(C.get_num_displays()) } -// GetHwndByPId get the hwnd by pid -func GetHwndByPId(pid int) int { +// GetHWNDByPid get the hwnd by pid +func GetHWNDByPid(pid int) int { return int(C.get_hwnd_by_pid(C.uintptr(pid))) } @@ -513,8 +515,9 @@ func MoveMouse(x, y int) { // Move move the mouse to (x, y) // // Examples: -// robotgo.MouseSleep = 100 // 100 millisecond -// robotgo.Move(10, 10) +// +// robotgo.MouseSleep = 100 // 100 millisecond +// robotgo.Move(10, 10) func Move(x, y int) { // if runtime.GOOS == "windows" { // f := ScaleF() @@ -560,6 +563,7 @@ func Drag(x, y int, args ...string) { // DragSmooth drag the mouse like smooth to (x, y) // // Examples: +// // robotgo.DragSmooth(10, 10) func DragSmooth(x, y int, args ...interface{}) { Toggle("left") @@ -582,6 +586,7 @@ func MoveMouseSmooth(x, y int, args ...interface{}) bool { // robotgo.MoveSmooth(x, y int, low, high float64, mouseDelay int) // // Examples: +// // robotgo.MoveSmooth(10, 10) // robotgo.MoveSmooth(10, 10, 1.0, 2.0) func MoveSmooth(x, y int, args ...interface{}) bool { @@ -648,7 +653,7 @@ func GetMousePos() (int, int) { // Deprecated: use the Click(), // -// MouseClick click the mouse +// # MouseClick click the mouse // // robotgo.MouseClick(button string, double bool) func MouseClick(args ...interface{}) { @@ -660,7 +665,8 @@ func MouseClick(args ...interface{}) { // robotgo.Click(button string, double bool) // // Examples: -// robotgo.Click() // default is left button +// +// robotgo.Click() // default is left button // robotgo.Click("right") // robotgo.Click("wheelLeft") func Click(args ...interface{}) { @@ -691,6 +697,7 @@ func Click(args ...interface{}) { // robotgo.MoveClick(x, y int, button string, double bool) // // Examples: +// // robotgo.MouseSleep = 100 // robotgo.MoveClick(10, 10) func MoveClick(x, y int, args ...interface{}) { @@ -709,10 +716,12 @@ func MovesClick(x, y int, args ...interface{}) { } // Toggle toggle the mouse, support button: -// "left", "center", "right", -// "wheelDown", "wheelUp", "wheelLeft", "wheelRight" +// +// "left", "center", "right", +// "wheelDown", "wheelUp", "wheelLeft", "wheelRight" // // Examples: +// // robotgo.Toggle("left") // default is down // robotgo.Toggle("left", "up") func Toggle(key ...string) error { @@ -749,6 +758,7 @@ func MouseUp(key ...string) error { // robotgo.Scroll(x, y, msDelay int) // // Examples: +// // robotgo.Scroll(10, 10) func Scroll(x, y int, args ...int) { var msDelay = 10 @@ -767,6 +777,7 @@ func Scroll(x, y int, args ...int) { // supported: "up", "down", "left", "right" // // Examples: +// // robotgo.ScrollMouse(10, "down") // robotgo.ScrollMouse(10, "up") func ScrollMouse(x int, direction ...string) { @@ -797,6 +808,7 @@ func ScrollMouse(x int, direction ...string) { // robotgo.ScrollSmooth(toy, num, sleep, tox) // // Examples: +// // robotgo.ScrollSmooth(-10) // robotgo.ScrollSmooth(-10, 6, 200, -10) func ScrollSmooth(to int, args ...int) { @@ -828,6 +840,7 @@ func ScrollSmooth(to int, args ...int) { // ScrollRelative scroll mouse with relative // // Examples: +// // robotgo.ScrollRelative(10, 10) func ScrollRelative(x, y int, args ...int) { mx, my := MoveArgs(x, y) @@ -987,7 +1000,7 @@ func GetHandle() int { // Deprecated: use the GetHandle(), // -// GetBHandle get the window handle, Wno-deprecated +// # GetBHandle get the window handle, Wno-deprecated // // This function will be removed in version v1.0.0 func GetBHandle() int { @@ -1008,6 +1021,7 @@ func cgetTitle(hwnd, isHwnd int32) string { // GetTitle get the window title return string // // Examples: +// // fmt.Println(robotgo.GetTitle()) // // ids, _ := robotgo.FindIds() @@ -1026,8 +1040,8 @@ func GetTitle(args ...int32) string { return internalGetTitle(args[0]) } -// GetPID get the process id return int32 -func GetPID() int32 { +// GetPid get the process id return int32 +func GetPid() int32 { pid := C.get_PID() return int32(pid) } @@ -1054,9 +1068,9 @@ func internalActive(pid int32, hwnd int) { C.active_PID(C.uintptr(pid), C.uintptr(hwnd)) } -// ActivePID active the window by PID, +// ActivePid active the window by Pid, // If args[0] > 0 on the Windows platform via a window handle to active -// func ActivePID(pid int32, args ...int) { +// func ActivePid(pid int32, args ...int) { // var hwnd int // if len(args) > 0 { // hwnd = args[0] @@ -1068,11 +1082,12 @@ func internalActive(pid int32, hwnd int) { // ActiveName active the window by name // // Examples: -// robotgo.ActiveName("chrome") +// +// robotgo.ActiveName("chrome") func ActiveName(name string) error { pids, err := FindIds(name) if err == nil && len(pids) > 0 { - return ActivePID(pids[0]) + return ActivePid(pids[0]) } return err diff --git a/robotgo_mac.go b/robotgo_mac.go index 0f9ce4a0..0d8ac311 100644 --- a/robotgo_mac.go +++ b/robotgo_mac.go @@ -18,7 +18,7 @@ package robotgo */ import "C" -// GetMianId get the main display id +// GetMainId get the main display id func GetMainId() int { return int(C.CGMainDisplayID()) } diff --git a/robotgo_mac_win.go b/robotgo_mac_win.go index 88c1bb96..798ea065 100644 --- a/robotgo_mac_win.go +++ b/robotgo_mac_win.go @@ -44,14 +44,15 @@ func internalGetTitle(pid int32, args ...int32) string { return gtitle } -// ActivePID active the window by PID, +// ActivePid active the window by PID, // // If args[0] > 0 on the Windows platform via a window handle to active // // Examples: +// // ids, _ := robotgo.FindIds() -// robotgo.ActivePID(ids[0]) -func ActivePID(pid int32, args ...int) error { +// robotgo.ActivePid(ids[0]) +func ActivePid(pid int32, args ...int) error { var hwnd int if len(args) > 0 { hwnd = args[0] @@ -71,6 +72,7 @@ func DisplaysNum() int { // If cancel button is not given, only the default button is displayed // // Examples: +// // robotgo.Alert("hi", "window", "ok", "cancel") func Alert(title, msg string, args ...string) bool { return showAlert(title, msg, args...) diff --git a/robotgo_win.go b/robotgo_win.go index e8aced33..2d05078f 100644 --- a/robotgo_win.go +++ b/robotgo_win.go @@ -57,7 +57,7 @@ func GetMain() win.HWND { return win.GetActiveWindow() } -// GetMianId get the main display id +// GetMainId get the main display id func GetMainId() int { return int(GetMain()) } diff --git a/robotgo_x11.go b/robotgo_x11.go index cc4dbc53..c6445f83 100644 --- a/robotgo_x11.go +++ b/robotgo_x11.go @@ -34,7 +34,7 @@ func GetBounds(pid int32, args ...int) (int, int, int, int) { return internalGetBounds(pid, hwnd) } - xid, err := GetXId(xu, pid) + xid, err := GetXid(xu, pid) if err != nil { log.Println("Get Xid from Pid errors is: ", err) return 0, 0, 0, 0 @@ -51,7 +51,7 @@ func GetClient(pid int32, args ...int) (int, int, int, int) { return internalGetClient(pid, hwnd) } - xid, err := GetXId(xu, pid) + xid, err := GetXid(xu, pid) if err != nil { log.Println("Get Xid from Pid errors is: ", err) return 0, 0, 0, 0 @@ -68,7 +68,7 @@ func internalGetTitle(pid int32, args ...int32) string { return cgetTitle(pid, hwnd) } - xid, err := GetXId(xu, pid) + xid, err := GetXid(xu, pid) if err != nil { log.Println("Get Xid from Pid errors is: ", err) return "" @@ -77,9 +77,9 @@ func internalGetTitle(pid int32, args ...int32) string { return cgetTitle(int32(xid), hwnd) } -// ActivePIDC active the window by PID, +// ActivePidC active the window by Pid, // If args[0] > 0 on the unix platform via a xid to active -func ActivePIDC(pid int32, args ...int) error { +func ActivePidC(pid int32, args ...int) error { var hwnd int if len(args) > 0 { hwnd = args[0] @@ -87,7 +87,7 @@ func ActivePIDC(pid int32, args ...int) error { return nil } - xid, err := GetXId(xu, pid) + xid, err := GetXid(xu, pid) if err != nil { log.Println("Get Xid from Pid errors is: ", err) return err @@ -97,11 +97,11 @@ func ActivePIDC(pid int32, args ...int) error { return nil } -// ActivePID active the window by PID, +// ActivePid active the window by Pid, // // If args[0] > 0 on the Windows platform via a window handle to active, // If args[0] > 0 on the unix platform via a xid to active -func ActivePID(pid int32, args ...int) error { +func ActivePid(pid int32, args ...int) error { if xu == nil { var err error xu, err = xgbutil.NewConn() @@ -133,8 +133,8 @@ func ActivePID(pid int32, args ...int) error { return nil } -// GetXId get the xid return window and error -func GetXId(xu *xgbutil.XUtil, pid int32) (xproto.Window, error) { +// GetXid get the xid return window and error +func GetXid(xu *xgbutil.XUtil, pid int32) (xproto.Window, error) { if xu == nil { var err error xu, err = xgbutil.NewConn() @@ -148,7 +148,7 @@ func GetXId(xu *xgbutil.XUtil, pid int32) (xproto.Window, error) { return xid, err } -// GetXidFromPid get the xide from pid +// GetXidFromPid get the xid from pid func GetXidFromPid(xu *xgbutil.XUtil, pid int32) (xproto.Window, error) { windows, err := ewmh.ClientListGet(xu) if err != nil { @@ -214,6 +214,7 @@ func GetMainId() int { // If cancel button is not given, only the default button is displayed // // Examples: +// // robotgo.Alert("hi", "window", "ok", "cancel") func Alert(title, msg string, args ...string) bool { defaultBtn, cancelBtn := alertArgs(args...) diff --git a/screen/goScreen.h b/screen/goScreen.h index b9c0a162..e990d3eb 100644 --- a/screen/goScreen.h +++ b/screen/goScreen.h @@ -99,7 +99,7 @@ uint32_t get_num_displays() { uintptr get_hwnd_by_pid(uintptr pid) { #if defined(IS_WINDOWS) - HWND hwnd = GetHwndByPId(pid); + HWND hwnd = GetHwndByPid(pid); return (uintptr)hwnd; #else return 0; diff --git a/window/goWindow.h b/window/goWindow.h index 7ab510e1..e73300b9 100644 --- a/window/goWindow.h +++ b/window/goWindow.h @@ -24,7 +24,7 @@ void min_window(uintptr pid, bool state, uintptr isHwnd){ // SetState((Window)pid, STATE_MINIMIZE, state); #elif defined(IS_WINDOWS) if (isHwnd == 0) { - HWND hwnd = GetHwndByPId(pid); + HWND hwnd = GetHwndByPid(pid); win_min(hwnd, state); } else { win_min((HWND)pid, state); @@ -41,7 +41,7 @@ void max_window(uintptr pid, bool state, uintptr isHwnd){ // SetState((Window)pid, STATE_MAXIMIZE, state); #elif defined(IS_WINDOWS) if (isHwnd == 0) { - HWND hwnd = GetHwndByPId(pid); + HWND hwnd = GetHwndByPid(pid); win_max(hwnd, state); } else { win_max((HWND)pid, state); diff --git a/window/win_sys.h b/window/win_sys.h index 9a800608..89e643d1 100644 --- a/window/win_sys.h +++ b/window/win_sys.h @@ -130,7 +130,7 @@ Bounds get_bounds(uintptr pid, uintptr isHwnd){ #elif defined(IS_WINDOWS) HWND hwnd; if (isHwnd == 0) { - hwnd= GetHwndByPId(pid); + hwnd= GetHwndByPid(pid); } else { hwnd = (HWND)pid; } @@ -195,7 +195,7 @@ Bounds get_client(uintptr pid, uintptr isHwnd) { #elif defined(IS_WINDOWS) HWND hwnd; if (isHwnd == 0) { - hwnd = GetHwndByPId(pid); + hwnd = GetHwndByPid(pid); } else { hwnd = (HWND)pid; } diff --git a/window/window.h b/window/window.h index f25c60cb..b4a861f9 100644 --- a/window/window.h +++ b/window/window.h @@ -60,7 +60,7 @@ MData set_handle_pid(uintptr pid, uintptr isHwnd){ #elif defined(IS_WINDOWS) // win.HWnd = (HWND)pid; // Handle to a window HWND if (isHwnd == 0) { - win.HWnd = GetHwndByPId(pid); + win.HWnd = GetHwndByPid(pid); } else { win.HWnd = (HWND)pid; } From c3cda41c2d55f17ccfd3d6db0ac52f07e3d7b182 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 14 Sep 2022 15:23:09 -0700 Subject: [PATCH 240/327] Update: update godoc and fixed typo --- README.md | 4 ++-- key.go | 28 +++++++++++++++------------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index a375d6f9..56e36181 100644 --- a/README.md +++ b/README.md @@ -519,9 +519,9 @@ Some discussions and questions, please see [issues/228](https://github.com/go-vg ## Plans - Refactor some C code to Go (such as x11, windows) - Better multiscreen support -- Waylad supports +- Wayland support - Update Window Handle -- Try support Android and IOS +- Try to support Android and IOS ## Contributors diff --git a/key.go b/key.go index 190270aa..c2e05a72 100644 --- a/key.go +++ b/key.go @@ -201,7 +201,7 @@ const ( LightsKbdDown = "lights_kbd_down" ) -// keyNames define MMKeyCode map +// keyNames define a map of key names to MMKeyCode var keyNames = map[string]C.MMKeyCode{ "backspace": C.K_BACKSPACE, "delete": C.K_DELETE, @@ -441,7 +441,7 @@ func keyToggles(k string, keyArr []string, pid int) error { */ -// ToInterfaces []string to []interface{} +// ToInterfaces convert []string to []interface{} func ToInterfaces(fields []string) []interface{} { res := make([]interface{}, 0, len(fields)) for _, s := range fields { @@ -450,7 +450,7 @@ func ToInterfaces(fields []string) []interface{} { return res } -// ToStrings []interface{} to []string +// ToStrings convert []interface{} to []string func ToStrings(fields []interface{}) []string { res := make([]string, 0, len(fields)) for _, s := range fields { @@ -467,19 +467,20 @@ func toErr(str *C.char) error { return errors.New(gstr) } -// KeyTap tap the keyboard code; +// KeyTap taps the keyboard code; // // See keys: +// // https://github.com/go-vgo/robotgo/blob/master/docs/keys.md // // Examples: +// // robotgo.KeySleep = 100 // 100 millisecond // robotgo.KeyTap("a") // robotgo.KeyTap("i", "alt", "command") // // arr := []string{"alt", "command"} // robotgo.KeyTap("i", arr) -// func KeyTap(key string, args ...interface{}) error { var keyArr []string @@ -512,17 +513,18 @@ func KeyTap(key string, args ...interface{}) error { return keyTaps(key, keyArr, pid) } -// KeyToggle toggle the keyboard, if there not have args default is "down" +// KeyToggle toggles the keyboard, if there not have args default is "down" // // See keys: +// // https://github.com/go-vgo/robotgo/blob/master/docs/keys.md // // Examples: +// // robotgo.KeyToggle("a") // robotgo.KeyToggle("a", "up") // // robotgo.KeyToggle("a", "up", "alt", "cmd") -// func KeyToggle(key string, args ...interface{}) error { if len(key) > 0 && unicode.IsUpper([]rune(key)[0]) { @@ -633,13 +635,13 @@ func inputUTF(str string) { C.free(unsafe.Pointer(cstr)) } -// TypeStr send a string, supported UTF-8 +// TypeStr send a string (supported UTF-8) // // robotgo.TypeStr(string: "The string to send", int: pid, "milli_sleep time", "x11 option") // // Examples: -// robotgo.TypeStr("abc@123, Hi galaxy, こんにちは") // +// robotgo.TypeStr("abc@123, Hi galaxy, こんにちは") func TypeStr(str string, args ...int) { var tm, tm1 = 0, 7 @@ -681,7 +683,7 @@ func TypeStr(str string, args ...int) { MilliSleep(KeySleep) } -// PasteStr paste a string, support UTF-8, +// PasteStr paste a string (support UTF-8), // write the string to clipboard and tap `cmd + v` func PasteStr(str string) error { err := clipboard.WriteAll(str) @@ -696,7 +698,7 @@ func PasteStr(str string) error { return KeyTap("v", "control") } -// TypeStrDelay type string delayed +// TypeStrDelay type string with delayed func TypeStrDelay(str string, delay int) { TypeStr(str) MilliSleep(delay) @@ -704,7 +706,7 @@ func TypeStrDelay(str string, delay int) { // Deprecated: use the TypeStr(), // -// TypeStringDelayed type string delayed, Wno-deprecated +// # TypeStringDelayed type string delayed, Wno-deprecated // // This function will be removed in version v1.0.0 func TypeStringDelayed(str string, delay int) { @@ -712,7 +714,7 @@ func TypeStringDelayed(str string, delay int) { TypeStrDelay(str, delay) } -// SetDelay set the key and mouse delay +// SetDelay sets the key and mouse delay func SetDelay(d ...int) { v := 10 if len(d) > 0 { From 4bf054f47a4e732f8510c80b69bc8129e5dd399d Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 1 Nov 2022 10:28:00 -0700 Subject: [PATCH 241/327] Unifed and rename some function for Pad --- examples/mouse/main.go | 6 +++--- robot_info_test.go | 3 +++ robotgo.go | 19 +++++++++++++------ robotgo_test.go | 4 ++-- 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/examples/mouse/main.go b/examples/mouse/main.go index b49806c6..d9ef7e32 100644 --- a/examples/mouse/main.go +++ b/examples/mouse/main.go @@ -55,7 +55,7 @@ func click() { func get() { // gets the mouse coordinates - x, y := robotgo.GetMousePos() + x, y := robotgo.Location() fmt.Println("pos:", x, y) if x == 456 && y == 586 { fmt.Println("mouse...", "586") @@ -66,8 +66,8 @@ func get() { func toggleAndScroll() { // scrolls the mouse either up - robotgo.ScrollMouse(10, "up") - robotgo.ScrollMouse(10, "right") + robotgo.ScrollDir(10, "up") + robotgo.ScrollDir(10, "right") robotgo.Scroll(100, 10) robotgo.Scroll(0, -10) diff --git a/robot_info_test.go b/robot_info_test.go index 0ce128d3..81a244c3 100644 --- a/robot_info_test.go +++ b/robot_info_test.go @@ -33,6 +33,9 @@ func TestGetScreenSize(t *testing.T) { rect := robotgo.GetScreenRect() fmt.Println("Get screen rect: ", rect) + + x, y = robotgo.Location() + fmt.Println("Get location: ", x, y) } func TestGetSysScale(t *testing.T) { diff --git a/robotgo.go b/robotgo.go index e9d6efd2..91faeb95 100644 --- a/robotgo.go +++ b/robotgo.go @@ -624,7 +624,7 @@ func MoveSmooth(x, y int, args ...interface{}) bool { // MoveArgs get the mouse relative args func MoveArgs(x, y int) (int, int) { - mx, my := GetMousePos() + mx, my := Location() mx = mx + x my = my + y @@ -642,8 +642,15 @@ func MoveSmoothRelative(x, y int, args ...interface{}) { MoveSmooth(mx, my, args...) } +// Deprecated: use the function Location() +// // GetMousePos get the mouse's position return x, y func GetMousePos() (int, int) { + return Location() +} + +// Location get the mouse location position return x, y +func Location() (int, int) { pos := C.getMousePos() x := int(pos.x) y := int(pos.y) @@ -773,17 +780,17 @@ func Scroll(x, y int, args ...int) { MilliSleep(MouseSleep + msDelay) } -// ScrollMouse scroll the mouse to (x, "up") +// ScrollDir scroll the mouse with direction to (x, "up") // supported: "up", "down", "left", "right" // // Examples: // -// robotgo.ScrollMouse(10, "down") -// robotgo.ScrollMouse(10, "up") -func ScrollMouse(x int, direction ...string) { +// robotgo.ScrollDir(10, "down") +// robotgo.ScrollDir(10, "up") +func ScrollDir(x int, direction ...interface{}) { d := "down" if len(direction) > 0 { - d = direction[0] + d = direction[0].(string) } if d == "down" { diff --git a/robotgo_test.go b/robotgo_test.go index bf3d54b3..c3aed911 100644 --- a/robotgo_test.go +++ b/robotgo_test.go @@ -68,8 +68,8 @@ func TestDragMouse(t *testing.T) { } func TestScrollMouse(t *testing.T) { - ScrollMouse(120, "up") - ScrollMouse(100, "right") + ScrollDir(120, "up") + ScrollDir(100, "right") Scroll(0, 120) MilliSleep(100) From 0293ab5d0c63911c604821bcb8c2b2555a6b62bb Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 1 Nov 2022 10:39:48 -0700 Subject: [PATCH 242/327] Add: add win32 send key event by pid support --- key/keypress.h | 2 +- key/keypress_c.h | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/key/keypress.h b/key/keypress.h index 6e69c710..779fab8e 100644 --- a/key/keypress.h +++ b/key/keypress.h @@ -40,7 +40,7 @@ #if defined(IS_WINDOWS) /* Send win32 key event for given key. */ - void win32KeyEvent(int key, MMKeyFlags flags, int32_t pid); + void win32KeyEvent(int key, MMKeyFlags flags, int32_t pid, int32_t isPid); #endif #endif /* KEYPRESS_H */ diff --git a/key/keypress_c.h b/key/keypress_c.h index 4d4959f1..614cf37d 100644 --- a/key/keypress_c.h +++ b/key/keypress_c.h @@ -16,7 +16,7 @@ /* Convenience wrappers around ugly APIs. */ #if defined(IS_WINDOWS) void WIN32_KEY_EVENT_WAIT(MMKeyCode key, DWORD flags, int32_t pid) { - win32KeyEvent(key, flags, pid); + win32KeyEvent(key, flags, pid, 0); Sleep(DEADBEEF_RANDRANGE(0, 1)); } #elif defined(USE_X11) @@ -68,7 +68,7 @@ static io_connect_t _getAuxiliaryKeyDriver(void) { #endif #if defined(IS_WINDOWS) -void win32KeyEvent(int key, MMKeyFlags flags, int32_t pid) { +void win32KeyEvent(int key, MMKeyFlags flags, int32_t pid, int32_t isPid) { int scan = MapVirtualKey(key & 0xff, MAPVK_VK_TO_VSC); /* Set the scan code for extended keys */ @@ -111,6 +111,15 @@ void win32KeyEvent(int key, MMKeyFlags flags, int32_t pid) { } } + if (pid != 0) { + HWND hwnd = (HWND) pid; + if (isPid == 0) { + hwnd = GetHwndByPid(pid); + } + SendMessage(hwnd, flags == 0 ? WM_KEYDOWN : WM_KEYUP, key, 0); + return; + } + /* Set the scan code for keyup */ // if ( flags & KEYEVENTF_KEYUP ) { // scan |= 0x80; @@ -168,7 +177,7 @@ void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags, int32_t pi if (flags & MOD_CONTROL) { WIN32_KEY_EVENT_WAIT(K_CONTROL, dwFlags, pid); } if (flags & MOD_SHIFT) { WIN32_KEY_EVENT_WAIT(K_SHIFT, dwFlags, pid); } - win32KeyEvent(code, dwFlags, pid); + win32KeyEvent(code, dwFlags, pid, 0); #elif defined(USE_X11) Display *display = XGetMainDisplay(); const Bool is_press = down ? True : False; /* Just to be safe. */ From a8faa0e90649f8a4793be1835612709ca6d16a53 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 21 Nov 2022 10:29:09 -0800 Subject: [PATCH 243/327] Update README.md --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 56e36181..331fdb15 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ -> Golang Desktop Automation. Control the mouse, keyboard, bitmap and image, read the screen, process, Window Handle and global event listener. +> Golang Desktop Automation. Control the mouse, keyboard, read the screen, process, Window Handle, image and bitmap and global event listener. RobotGo supports Mac, Windows, and Linux(X11); and robotgo supports arm64 and x86-amd64. @@ -65,6 +65,10 @@ xcode-select --install [MinGW-w64](https://sourceforge.net/projects/mingw-w64/files) (Use recommended) +Download the Mingw, then set system environment variables `C:\mingw64\bin` to the Path. +[Set environment variables to run GCC from command line](https://www.youtube.com/watch?v=1kY5iTK4-H0). + + ``` Or the other GCC (But you should compile the "libpng" with yourself when use the bitmap.) ``` From 469cd4da5eea653d590ce2ae7567f66a5bea591f Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 27 Nov 2022 17:55:45 -0800 Subject: [PATCH 244/327] Update & Add: unified use the int to replace int32; unified name and add more func; Update gomod and CI --- .circleci/config.yml | 2 +- .circleci/images/primary/Dockerfile | 2 +- appveyor.yml | 2 +- examples/window/main.go | 2 +- go.mod | 18 ++++---- go.sum | 63 +++++++++++++++++--------- ps.go | 14 +++--- robotgo.go | 70 ++++++++++++++--------------- robotgo_mac_win.go | 32 ++++++------- robotgo_test.go | 5 +++ robotgo_win.go | 5 +++ robotgo_x11.go | 46 +++++++++---------- screen/goScreen.h | 2 +- window/goWindow.h | 12 ++--- window/win_sys.h | 14 +++--- window/window.h | 16 +++---- 16 files changed, 168 insertions(+), 137 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index dc9f59a9..55be1d92 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,7 +5,7 @@ jobs: docker: # using custom image, see .circleci/images/primary/Dockerfile # - image: govgo/robotgoci:1.10.3 - - image: golang:1.19.1 + - image: golang:1.19.3 working_directory: /gopath/src/github.com/go-vgo/robotgo steps: - checkout diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index d4649aa2..7b15f841 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.19.1-stretch AS build +FROM golang:1.19.3-stretch AS build # FROM govgo/go:1.11.1 RUN apt update && apt install -y --no-install-recommends \ diff --git a/appveyor.yml b/appveyor.yml index c5e38ea2..1e8bb1ca 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,7 +34,7 @@ environment: PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% # - COMPILER: MINGW_W64 # ARCHITECTURE: x64 - GOVERSION: 1.19.1 + GOVERSION: 1.19.3 # GOPATH: c:\gopath # scripts that run after cloning repository diff --git a/examples/window/main.go b/examples/window/main.go index 7e39b5ba..5d631456 100644 --- a/examples/window/main.go +++ b/examples/window/main.go @@ -56,7 +56,7 @@ func findIds() { if len(fpid) > 0 { robotgo.KeyTap("a", fpid[0]) - robotgo.TypeStr("Hi galaxy!", int(fpid[0])) + robotgo.TypeStr("Hi galaxy!", fpid[0]) robotgo.KeyToggle("a", fpid[0], "cmd") robotgo.KeyToggle("a", fpid[0], "cmd", "up") diff --git a/go.mod b/go.mod index 3a267796..6cd39bac 100644 --- a/go.mod +++ b/go.mod @@ -8,25 +8,23 @@ require ( // github.com/robotn/gohook v0.31.3 github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 - github.com/vcaesar/gops v0.23.0 + github.com/vcaesar/gops v0.30.0 github.com/vcaesar/imgo v0.30.1 github.com/vcaesar/keycode v0.10.0 github.com/vcaesar/tt v0.20.0 - golang.org/x/image v0.0.0-20211028202545-6944b10bf410 // indirect - golang.org/x/net v0.0.0-20201110031124-69a78807bb2b // indirect + golang.org/x/image v0.1.0 // indirect ) require ( - github.com/davecgh/go-spew v1.1.1 // indirect github.com/go-ole/go-ole v1.2.6 // indirect - github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect + github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c // indirect github.com/otiai10/mint v1.3.0 // indirect - github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect - github.com/shirou/gopsutil/v3 v3.22.4 // indirect - github.com/tklauser/go-sysconf v0.3.10 // indirect - github.com/tklauser/numcpus v0.4.0 // indirect + github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c // indirect + github.com/shirou/gopsutil/v3 v3.22.10 // indirect + github.com/tklauser/go-sysconf v0.3.11 // indirect + github.com/tklauser/numcpus v0.6.0 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect - golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27 // indirect + golang.org/x/sys v0.2.0 // indirect ) // replace golang.org/x/sys => github.com/golang/sys v0.0.0-20190109145017-48ac38b7c8cb diff --git a/go.sum b/go.sum index c661775c..c8c887a2 100644 --- a/go.sum +++ b/go.sum @@ -6,10 +6,11 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c h1:VtwQ41oftZwlMnOEbMWQtSEUgU64U4s+GHk7hZK+jtY= +github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE= github.com/lxn/win v0.0.0-20210218163916-a377121e959e h1:H+t6A/QJMbhCSEH5rAuRxh+CtW96g0Or0Fxa9IKr4uc= github.com/lxn/win v0.0.0-20210218163916-a377121e959e/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= @@ -19,51 +20,73 @@ github.com/otiai10/mint v1.3.0 h1:Ady6MKVezQwHBkGzLFbrsywyp09Ah7rkmfjV3Bcr5uc= github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c h1:NRoLoZvkBTKvR5gQLgA3e0hqjkY9u1wm+iOL45VN/qI= +github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 h1:2lhSR8N3T6I30q096DT7/5AKEIcf1vvnnWAmS0wfnNY= github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934/go.mod h1:SxQhJskUJ4rleVU44YvnrdvxQr0tKy5SRSigBrCgyyQ= github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 h1:2uX8QRLkkxn2EpAQ6I3KhA79BkdRZfvugJUzJadiJwk= github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770/go.mod h1:svkDXUDQjUiWzLrA0OZgHc4lbOts3C+uRfP6/yjwYnU= -github.com/shirou/gopsutil/v3 v3.22.4 h1:srAQaiX6jX/cYL6q29aE0m8lOskT9CurZ9N61YR3yoI= -github.com/shirou/gopsutil/v3 v3.22.4/go.mod h1:D01hZJ4pVHPpCTZ3m3T2+wDF2YAGfd+H4ifUguaQzHM= +github.com/shirou/gopsutil/v3 v3.22.10 h1:4KMHdfBRYXGF9skjDWiL4RA2N+E8dRdodU/bOZpPoVg= +github.com/shirou/gopsutil/v3 v3.22.10/go.mod h1:QNza6r4YQoydyCfo6rH0blGfKahgibh4dQmV5xdFkQk= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk= -github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o= +github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM= +github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI= github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ= -github.com/vcaesar/gops v0.23.0 h1:gY/E5UJfLpImJjE7tiTJIVRcKOWxi7YX1J/CUHK8gXk= -github.com/vcaesar/gops v0.23.0/go.mod h1:3IepRPE6qK9Wy8MGLJx2N3o77fuO1Ec7FvPHyEuou8I= +github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms= +github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4= +github.com/vcaesar/gops v0.30.0 h1:970FznFxZP8ku0zckJRO+pI2fFhg3uJ0z+sQS0NHP4o= +github.com/vcaesar/gops v0.30.0/go.mod h1:xV1wieUA4D9RaNQ8lf8AwPZ8bl+x/MM5w3SsMCr5KVs= github.com/vcaesar/imgo v0.30.1 h1:B7QMm2mZY+SGoEvvJwNi+eAv21ptvk2YT1IbP2OzyLE= github.com/vcaesar/imgo v0.30.1/go.mod h1:n4EluJIN/0UYYGPHBCY/BWlIjdRUdY5U6obtP2lrgdM= github.com/vcaesar/keycode v0.10.0 h1:Qx5QE8ZXHyRyjoA2QOxBp25OKMKB+zxMVqm0FWGV0d4= github.com/vcaesar/keycode v0.10.0/go.mod h1:JNlY7xbKsh+LAGfY2j4M3znVrGEm5W1R8s/Uv6BJcfQ= github.com/vcaesar/tt v0.20.0 h1:9t2Ycb9RNHcP0WgQgIaRKJBB+FrRdejuaL6uWIHuoBA= github.com/vcaesar/tt v0.20.0/go.mod h1:GHPxQYhn+7OgKakRusH7KJ0M5MhywoeLb8Fcffs/Gtg= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/image v0.0.0-20211028202545-6944b10bf410 h1:hTftEOvwiOq2+O8k2D5/Q7COC7k5Qcrgc2TFURJYnvQ= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/image v0.1.0 h1:r8Oj8ZA2Xy12/b5KZYj3tuv7NG/fBz3TwQVvpJ9l8Rk= +golang.org/x/image v0.1.0/go.mod h1:iyPr49SD/G/TBxYVB/9RRtGUT5eNbo2u4NamWeQcD5c= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27 h1:XDXtA5hveEEV8JB2l7nhMTp3t3cHp9ZpwcdjqyEWLlo= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/ps.go b/ps.go index 9a453866..cba6f1b6 100644 --- a/ps.go +++ b/ps.go @@ -14,17 +14,17 @@ import ps "github.com/vcaesar/gops" // Nps process struct type Nps struct { - Pid int32 + Pid int Name string } // Pids get the all process id -func Pids() ([]int32, error) { +func Pids() ([]int, error) { return ps.Pids() } // PidExists determine whether the process exists -func PidExists(pid int32) (bool, error) { +func PidExists(pid int) (bool, error) { return ps.PidExists(pid) } @@ -45,7 +45,7 @@ func Process() ([]Nps, error) { } // FindName find the process name by the process id -func FindName(pid int32) (string, error) { +func FindName(pid int) (string, error) { return ps.FindName(pid) } @@ -57,12 +57,12 @@ func FindNames() ([]string, error) { // FindIds finds the all processes named with a subset // of "name" (case insensitive), // return matched IDs. -func FindIds(name string) ([]int32, error) { +func FindIds(name string) ([]int, error) { return ps.FindIds(name) } // FindPath find the process path by the process pid -func FindPath(pid int32) (string, error) { +func FindPath(pid int) (string, error) { return ps.FindPath(pid) } @@ -72,6 +72,6 @@ func Run(path string) ([]byte, error) { } // Kill kill the process by PID -func Kill(pid int32) error { +func Kill(pid int) error { return ps.Kill(pid) } diff --git a/robotgo.go b/robotgo.go index 91faeb95..dd902a33 100644 --- a/robotgo.go +++ b/robotgo.go @@ -920,55 +920,55 @@ func GetActive() C.MData { } // MinWindow set the window min -func MinWindow(pid int32, args ...interface{}) { +func MinWindow(pid int, args ...interface{}) { var ( state = true - hwnd int + isPid int ) if len(args) > 0 { state = args[0].(bool) } if len(args) > 1 { - hwnd = args[1].(int) + isPid = args[1].(int) } - C.min_window(C.uintptr(pid), C.bool(state), C.uintptr(hwnd)) + C.min_window(C.uintptr(pid), C.bool(state), C.int8_t(isPid)) } // MaxWindow set the window max -func MaxWindow(pid int32, args ...interface{}) { +func MaxWindow(pid int, args ...interface{}) { var ( state = true - hwnd int + isPid int ) if len(args) > 0 { state = args[0].(bool) } if len(args) > 1 { - hwnd = args[1].(int) + isPid = args[1].(int) } - C.max_window(C.uintptr(pid), C.bool(state), C.uintptr(hwnd)) + C.max_window(C.uintptr(pid), C.bool(state), C.int8_t(isPid)) } // CloseWindow close the window -func CloseWindow(args ...int32) { +func CloseWindow(args ...int) { if len(args) <= 0 { C.close_main_window() return } - var hwnd, isHwnd int32 + var pid, isPid int if len(args) > 0 { - hwnd = args[0] + pid = args[0] } if len(args) > 1 { - isHwnd = args[1] + isPid = args[1] } - C.close_window_by_PId(C.uintptr(hwnd), C.uintptr(isHwnd)) + C.close_window_by_PId(C.uintptr(pid), C.int8_t(isPid)) } // SetHandle set the window handle @@ -978,23 +978,23 @@ func SetHandle(hwnd int) { } // SetHandlePid set the window handle by pid -func SetHandlePid(pid int32, args ...int32) { - var isHwnd int32 +func SetHandlePid(pid int, args ...int) { + var isPid int if len(args) > 0 { - isHwnd = args[0] + isPid = args[0] } - C.set_handle_pid_mData(C.uintptr(pid), C.uintptr(isHwnd)) + C.set_handle_pid_mData(C.uintptr(pid), C.int8_t(isPid)) } // GetHandPid get handle mdata by pid -func GetHandPid(pid int32, args ...int32) C.MData { - var isHwnd int32 +func GetHandPid(pid int, args ...int) C.MData { + var isPid int if len(args) > 0 { - isHwnd = args[0] + isPid = args[0] } - return C.set_handle_pid(C.uintptr(pid), C.uintptr(isHwnd)) + return C.set_handle_pid(C.uintptr(pid), C.int8_t(isPid)) } // GetHandle get the window handle @@ -1018,8 +1018,8 @@ func GetBHandle() int { return ghwnd } -func cgetTitle(hwnd, isHwnd int32) string { - title := C.get_title_by_pid(C.uintptr(hwnd), C.uintptr(isHwnd)) +func cgetTitle(pid, isPid int) string { + title := C.get_title_by_pid(C.uintptr(pid), C.int8_t(isPid)) gtitle := C.GoString(title) return gtitle @@ -1033,7 +1033,7 @@ func cgetTitle(hwnd, isHwnd int32) string { // // ids, _ := robotgo.FindIds() // robotgo.GetTitle(ids[0]) -func GetTitle(args ...int32) string { +func GetTitle(args ...int) string { if len(args) <= 0 { title := C.get_main_title() gtitle := C.GoString(title) @@ -1048,20 +1048,20 @@ func GetTitle(args ...int32) string { } // GetPid get the process id return int32 -func GetPid() int32 { +func GetPid() int { pid := C.get_PID() - return int32(pid) + return int(pid) } // internalGetBounds get the window bounds -func internalGetBounds(pid int32, hwnd int) (int, int, int, int) { - bounds := C.get_bounds(C.uintptr(pid), C.uintptr(hwnd)) +func internalGetBounds(pid, isPid int) (int, int, int, int) { + bounds := C.get_bounds(C.uintptr(pid), C.int8_t(isPid)) return int(bounds.X), int(bounds.Y), int(bounds.W), int(bounds.H) } // internalGetClient get the window client bounds -func internalGetClient(pid int32, hwnd int) (int, int, int, int) { - bounds := C.get_client(C.uintptr(pid), C.uintptr(hwnd)) +func internalGetClient(pid, isPid int) (int, int, int, int) { + bounds := C.get_client(C.uintptr(pid), C.int8_t(isPid)) return int(bounds.X), int(bounds.Y), int(bounds.W), int(bounds.H) } @@ -1071,19 +1071,19 @@ func Is64Bit() bool { return bool(b) } -func internalActive(pid int32, hwnd int) { - C.active_PID(C.uintptr(pid), C.uintptr(hwnd)) +func internalActive(pid, isPid int) { + C.active_PID(C.uintptr(pid), C.int8_t(isPid)) } // ActivePid active the window by Pid, // If args[0] > 0 on the Windows platform via a window handle to active // func ActivePid(pid int32, args ...int) { -// var hwnd int +// var isPid int // if len(args) > 0 { -// hwnd = args[0] +// isPid = args[0] // } -// C.active_PID(C.uintptr(pid), C.uintptr(hwnd)) +// C.active_PID(C.uintptr(pid), C.uintptr(isPid)) // } // ActiveName active the window by name diff --git a/robotgo_mac_win.go b/robotgo_mac_win.go index 798ea065..e1fe1673 100644 --- a/robotgo_mac_win.go +++ b/robotgo_mac_win.go @@ -14,32 +14,32 @@ package robotgo // GetBounds get the window bounds -func GetBounds(pid int32, args ...int) (int, int, int, int) { - var hwnd int +func GetBounds(pid int, args ...int) (int, int, int, int) { + var isPid int if len(args) > 0 { - hwnd = args[0] + isPid = args[0] } - return internalGetBounds(pid, hwnd) + return internalGetBounds(pid, isPid) } // GetClient get the window client bounds -func GetClient(pid int32, args ...int) (int, int, int, int) { - var hwnd int +func GetClient(pid int, args ...int) (int, int, int, int) { + var isPid int if len(args) > 0 { - hwnd = args[0] + isPid = args[0] } - return internalGetClient(pid, hwnd) + return internalGetClient(pid, isPid) } // internalGetTitle get the window title -func internalGetTitle(pid int32, args ...int32) string { - var isHwnd int32 +func internalGetTitle(pid int, args ...int) string { + var isPid int if len(args) > 0 { - isHwnd = args[0] + isPid = args[0] } - gtitle := cgetTitle(pid, isHwnd) + gtitle := cgetTitle(pid, isPid) return gtitle } @@ -52,13 +52,13 @@ func internalGetTitle(pid int32, args ...int32) string { // // ids, _ := robotgo.FindIds() // robotgo.ActivePid(ids[0]) -func ActivePid(pid int32, args ...int) error { - var hwnd int +func ActivePid(pid int, args ...int) error { + var isPid int if len(args) > 0 { - hwnd = args[0] + isPid = args[0] } - internalActive(pid, hwnd) + internalActive(pid, isPid) return nil } diff --git a/robotgo_test.go b/robotgo_test.go index c3aed911..31d14b1a 100644 --- a/robotgo_test.go +++ b/robotgo_test.go @@ -220,6 +220,11 @@ func TestPs(t *testing.T) { tt.IsType(t, "[]int32", id) tt.Nil(t, err) + if len(id) > 0 { + e := KeyTap("v", id[0], "cmd") + tt.Nil(t, e) + } + // n, e = FindPath(id[0]) // tt.NotEmpty(t, n) // tt.Nil(t, e) diff --git a/robotgo_win.go b/robotgo_win.go index 2d05078f..1f9c6e64 100644 --- a/robotgo_win.go +++ b/robotgo_win.go @@ -52,6 +52,11 @@ func SetFocus(hwnd win.HWND) win.HWND { return win.SetFocus(hwnd) } +// SetForeg set the window into the foreground by hwnd +func SetForeg(hwnd win.HWND) bool { + return win.SetForegroundWindow(hwnd) +} + // GetMian get the main display hwnd func GetMain() win.HWND { return win.GetActiveWindow() diff --git a/robotgo_x11.go b/robotgo_x11.go index c6445f83..f8fdc00b 100644 --- a/robotgo_x11.go +++ b/robotgo_x11.go @@ -27,11 +27,11 @@ import ( var xu *xgbutil.XUtil // GetBounds get the window bounds -func GetBounds(pid int32, args ...int) (int, int, int, int) { - var hwnd int +func GetBounds(pid int, args ...int) (int, int, int, int) { + var isPid int if len(args) > 0 { - hwnd = args[0] - return internalGetBounds(pid, hwnd) + isPid = args[0] + return internalGetBounds(pid, isPid) } xid, err := GetXid(xu, pid) @@ -40,15 +40,15 @@ func GetBounds(pid int32, args ...int) (int, int, int, int) { return 0, 0, 0, 0 } - return internalGetBounds(int32(xid), hwnd) + return internalGetBounds(xid, isPid) } // GetClient get the window client bounds -func GetClient(pid int32, args ...int) (int, int, int, int) { - var hwnd int +func GetClient(pid int, args ...int) (int, int, int, int) { + var isPid int if len(args) > 0 { - hwnd = args[0] - return internalGetClient(pid, hwnd) + isPid = args[0] + return internalGetClient(pid, isPid) } xid, err := GetXid(xu, pid) @@ -57,15 +57,15 @@ func GetClient(pid int32, args ...int) (int, int, int, int) { return 0, 0, 0, 0 } - return internalGetClient(int32(xid), hwnd) + return internalGetClient(xid, isPid) } // internalGetTitle get the window title -func internalGetTitle(pid int32, args ...int32) string { - var hwnd int32 +func internalGetTitle(pid int, args ...int) string { + var isPid int if len(args) > 0 { - hwnd = args[0] - return cgetTitle(pid, hwnd) + isPid = args[0] + return cgetTitle(pid, isPid) } xid, err := GetXid(xu, pid) @@ -74,16 +74,16 @@ func internalGetTitle(pid int32, args ...int32) string { return "" } - return cgetTitle(int32(xid), hwnd) + return cgetTitle(xid, isPid) } // ActivePidC active the window by Pid, // If args[0] > 0 on the unix platform via a xid to active -func ActivePidC(pid int32, args ...int) error { - var hwnd int +func ActivePidC(pid int, args ...int) error { + var isPid int if len(args) > 0 { - hwnd = args[0] - internalActive(pid, hwnd) + isPid = args[0] + internalActive(pid, isPid) return nil } @@ -93,7 +93,7 @@ func ActivePidC(pid int32, args ...int) error { return err } - internalActive(int32(xid), hwnd) + internalActive(xid, isPid) return nil } @@ -101,7 +101,7 @@ func ActivePidC(pid int32, args ...int) error { // // If args[0] > 0 on the Windows platform via a window handle to active, // If args[0] > 0 on the unix platform via a xid to active -func ActivePid(pid int32, args ...int) error { +func ActivePid(pid int, args ...int) error { if xu == nil { var err error xu, err = xgbutil.NewConn() @@ -134,7 +134,7 @@ func ActivePid(pid int32, args ...int) error { } // GetXid get the xid return window and error -func GetXid(xu *xgbutil.XUtil, pid int32) (xproto.Window, error) { +func GetXid(xu *xgbutil.XUtil, pid int) (xproto.Window, error) { if xu == nil { var err error xu, err = xgbutil.NewConn() @@ -149,7 +149,7 @@ func GetXid(xu *xgbutil.XUtil, pid int32) (xproto.Window, error) { } // GetXidFromPid get the xid from pid -func GetXidFromPid(xu *xgbutil.XUtil, pid int32) (xproto.Window, error) { +func GetXidFromPid(xu *xgbutil.XUtil, pid int) (xproto.Window, error) { windows, err := ewmh.ClientListGet(xu) if err != nil { return 0, err diff --git a/screen/goScreen.h b/screen/goScreen.h index e990d3eb..c093d065 100644 --- a/screen/goScreen.h +++ b/screen/goScreen.h @@ -9,8 +9,8 @@ // except according to those terms. #include "../base/types.h" -#include "../base/rgb.h" #include "../base/pubs.h" +#include "../base/rgb.h" #include "screengrab_c.h" #include "screen_c.h" #include diff --git a/window/goWindow.h b/window/goWindow.h index e73300b9..6b69130e 100644 --- a/window/goWindow.h +++ b/window/goWindow.h @@ -12,7 +12,7 @@ #include "window.h" #include "win_sys.h" -void min_window(uintptr pid, bool state, uintptr isHwnd){ +void min_window(uintptr pid, bool state, int8_t isPid){ #if defined(IS_MACOSX) // return 0; AXUIElementRef axID = AXUIElementCreateApplication(pid); @@ -23,7 +23,7 @@ void min_window(uintptr pid, bool state, uintptr isHwnd){ XDismissErrors(); // SetState((Window)pid, STATE_MINIMIZE, state); #elif defined(IS_WINDOWS) - if (isHwnd == 0) { + if (isPid == 0) { HWND hwnd = GetHwndByPid(pid); win_min(hwnd, state); } else { @@ -32,7 +32,7 @@ void min_window(uintptr pid, bool state, uintptr isHwnd){ #endif } -void max_window(uintptr pid, bool state, uintptr isHwnd){ +void max_window(uintptr pid, bool state, int8_t isPid){ #if defined(IS_MACOSX) // return 0; #elif defined(USE_X11) @@ -40,7 +40,7 @@ void max_window(uintptr pid, bool state, uintptr isHwnd){ // SetState((Window)pid, STATE_MINIMIZE, false); // SetState((Window)pid, STATE_MAXIMIZE, state); #elif defined(IS_WINDOWS) - if (isHwnd == 0) { + if (isPid == 0) { HWND hwnd = GetHwndByPid(pid); win_max(hwnd, state); } else { @@ -71,7 +71,7 @@ uintptr b_get_handle() { #endif } -void active_PID(uintptr pid, uintptr isHwnd){ - MData win = set_handle_pid(pid, isHwnd); +void active_PID(uintptr pid, int8_t isPid){ + MData win = set_handle_pid(pid, isPid); set_active(win); } diff --git a/window/win_sys.h b/window/win_sys.h index 89e643d1..01edf012 100644 --- a/window/win_sys.h +++ b/window/win_sys.h @@ -12,7 +12,7 @@ #include #endif -Bounds get_client(uintptr pid, uintptr isHwnd); +Bounds get_client(uintptr pid, int8_t isPid); intptr scaleX(); double sys_scale(int32_t display_id) { @@ -73,7 +73,7 @@ intptr scaleX(){ #endif } -Bounds get_bounds(uintptr pid, uintptr isHwnd){ +Bounds get_bounds(uintptr pid, int8_t isPid){ // Check if the window is valid Bounds bounds; if (!is_valid()) { return bounds; } @@ -118,7 +118,7 @@ Bounds get_bounds(uintptr pid, uintptr isHwnd){ MData win; win.XWin = (Window)pid; - Bounds client = get_client(pid, isHwnd); + Bounds client = get_client(pid, isPid); Bounds frame = GetFrame(win); bounds.X = client.X - frame.X; @@ -129,7 +129,7 @@ Bounds get_bounds(uintptr pid, uintptr isHwnd){ return bounds; #elif defined(IS_WINDOWS) HWND hwnd; - if (isHwnd == 0) { + if (isPid == 0) { hwnd= GetHwndByPid(pid); } else { hwnd = (HWND)pid; @@ -147,13 +147,13 @@ Bounds get_bounds(uintptr pid, uintptr isHwnd){ #endif } -Bounds get_client(uintptr pid, uintptr isHwnd) { +Bounds get_client(uintptr pid, int8_t isPid) { // Check if the window is valid Bounds bounds; if (!is_valid()) { return bounds; } #if defined(IS_MACOSX) - return get_bounds(pid, isHwnd); + return get_bounds(pid, isPid); #elif defined(USE_X11) Display *rDisplay = XOpenDisplay(NULL); @@ -194,7 +194,7 @@ Bounds get_client(uintptr pid, uintptr isHwnd) { return bounds; #elif defined(IS_WINDOWS) HWND hwnd; - if (isHwnd == 0) { + if (isPid == 0) { hwnd = GetHwndByPid(pid); } else { hwnd = (HWND)pid; diff --git a/window/window.h b/window/window.h index b4a861f9..301129a8 100644 --- a/window/window.h +++ b/window/window.h @@ -50,7 +50,7 @@ bool Is64Bit() { return false; } -MData set_handle_pid(uintptr pid, uintptr isHwnd){ +MData set_handle_pid(uintptr pid, int8_t isPid){ MData win; #if defined(IS_MACOSX) // Handle to a AXUIElementRef @@ -59,7 +59,7 @@ MData set_handle_pid(uintptr pid, uintptr isHwnd){ win.XWin = (Window)pid; // Handle to an X11 window #elif defined(IS_WINDOWS) // win.HWnd = (HWND)pid; // Handle to a window HWND - if (isHwnd == 0) { + if (isPid == 0) { win.HWnd = GetHwndByPid(pid); } else { win.HWnd = (HWND)pid; @@ -69,8 +69,8 @@ MData set_handle_pid(uintptr pid, uintptr isHwnd){ return win; } -void set_handle_pid_mData(uintptr pid, uintptr isHwnd){ - MData win = set_handle_pid(pid, isHwnd); +void set_handle_pid_mData(uintptr pid, int8_t isPid){ + MData win = set_handle_pid(pid, isPid); mData = win; } @@ -464,8 +464,8 @@ void close_main_window () { close_window_by_Id(mData); } -void close_window_by_PId(uintptr pid, uintptr isHwnd){ - MData win = set_handle_pid(pid, isHwnd); +void close_window_by_PId(uintptr pid, int8_t isPid){ + MData win = set_handle_pid(pid, isPid); close_window_by_Id(win); } @@ -502,8 +502,8 @@ char* get_main_title(){ return get_title_by_hand(mData); } -char* get_title_by_pid(uintptr pid, uintptr isHwnd){ - MData win = set_handle_pid(pid, isHwnd); +char* get_title_by_pid(uintptr pid, int8_t isPid){ + MData win = set_handle_pid(pid, isPid); return get_title_by_hand(win); } From 5079db2df75905a6d967b134bf3d78ede8d8a4ff Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 27 Nov 2022 18:06:14 -0800 Subject: [PATCH 245/327] Fixed: fixed x11 type convert --- robotgo_x11.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/robotgo_x11.go b/robotgo_x11.go index f8fdc00b..4aba5a31 100644 --- a/robotgo_x11.go +++ b/robotgo_x11.go @@ -40,7 +40,7 @@ func GetBounds(pid int, args ...int) (int, int, int, int) { return 0, 0, 0, 0 } - return internalGetBounds(xid, isPid) + return internalGetBounds(int(xid), isPid) } // GetClient get the window client bounds @@ -57,7 +57,7 @@ func GetClient(pid int, args ...int) (int, int, int, int) { return 0, 0, 0, 0 } - return internalGetClient(xid, isPid) + return internalGetClient(int(xid), isPid) } // internalGetTitle get the window title @@ -74,7 +74,7 @@ func internalGetTitle(pid int, args ...int) string { return "" } - return cgetTitle(xid, isPid) + return cgetTitle(int(xid), isPid) } // ActivePidC active the window by Pid, @@ -93,7 +93,7 @@ func ActivePidC(pid int, args ...int) error { return err } - internalActive(xid, isPid) + internalActive(int(xid), isPid) return nil } From 2f2ed595f62511604c456fa73bd052c46b5c2861 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 27 Nov 2022 18:08:51 -0800 Subject: [PATCH 246/327] Fixed: fixed test --- robotgo_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/robotgo_test.go b/robotgo_test.go index 31d14b1a..f5ff861f 100644 --- a/robotgo_test.go +++ b/robotgo_test.go @@ -194,7 +194,7 @@ func TestImage(t *testing.T) { func TestPs(t *testing.T) { id, err := Pids() tt.Not(t, "[]", id) - tt.IsType(t, "[]int32", id) + tt.IsType(t, "[]int", id) tt.Nil(t, err) ps, e := Process() @@ -217,7 +217,7 @@ func TestPs(t *testing.T) { id, err = FindIds(n1[0]) tt.Not(t, "[]", id) - tt.IsType(t, "[]int32", id) + tt.IsType(t, "[]int", id) tt.Nil(t, err) if len(id) > 0 { From bb90d71b5f5c7375fc780a7a99e8fd1fc692bb88 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 27 Nov 2022 18:30:05 -0800 Subject: [PATCH 247/327] Add: add windows key tap and type by pid support --- key.go | 14 ++++++++++---- key/keypress.h | 2 +- key/keypress_c.h | 28 ++++++++++++++++++++++------ 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/key.go b/key.go index c2e05a72..e59e1cf4 100644 --- a/key.go +++ b/key.go @@ -321,7 +321,7 @@ var keyNames = map[string]C.MMKeyCode{ // { NULL: C.K_NOT_A_KEY } } -func tapKeyCode(code C.MMKeyCode, flags C.MMKeyFlags, pid C.int32_t) { +func tapKeyCode(code C.MMKeyCode, flags C.MMKeyFlags, pid C.uintptr) { C.toggleKeyCode(code, true, flags, pid) MilliSleep(3) C.toggleKeyCode(code, false, flags, pid) @@ -401,7 +401,7 @@ func keyTaps(k string, keyArr []string, pid int) error { return err } - tapKeyCode(key, flags, C.int32_t(pid)) + tapKeyCode(key, flags, C.uintptr(pid)) MilliSleep(KeySleep) return nil } @@ -426,7 +426,7 @@ func keyToggles(k string, keyArr []string, pid int) error { return err } - C.toggleKeyCode(key, C.bool(down), flags, C.int32_t(pid)) + C.toggleKeyCode(key, C.bool(down), flags, C.uintptr(pid)) MilliSleep(KeySleep) return nil } @@ -604,7 +604,13 @@ func UnicodeType(str uint32, args ...int) { if len(args) > 0 { pid = args[0] } - C.unicodeType(cstr, C.int32_t(pid)) + + isPid := 0 + if len(args) > 1 { + isPid = args[1] + } + + C.unicodeType(cstr, C.uintptr(pid), C.int8_t(isPid)) } // ToUC trans string to unicode []string diff --git a/key/keypress.h b/key/keypress.h index 779fab8e..3079d294 100644 --- a/key/keypress.h +++ b/key/keypress.h @@ -40,7 +40,7 @@ #if defined(IS_WINDOWS) /* Send win32 key event for given key. */ - void win32KeyEvent(int key, MMKeyFlags flags, int32_t pid, int32_t isPid); + void win32KeyEvent(int key, MMKeyFlags flags, uintptr pid, int8_t isPid); #endif #endif /* KEYPRESS_H */ diff --git a/key/keypress_c.h b/key/keypress_c.h index 614cf37d..32e8daee 100644 --- a/key/keypress_c.h +++ b/key/keypress_c.h @@ -15,6 +15,8 @@ /* Convenience wrappers around ugly APIs. */ #if defined(IS_WINDOWS) + HWND GetHwndByPid(DWORD dwProcessId); + void WIN32_KEY_EVENT_WAIT(MMKeyCode key, DWORD flags, int32_t pid) { win32KeyEvent(key, flags, pid, 0); Sleep(DEADBEEF_RANDRANGE(0, 1)); @@ -34,7 +36,7 @@ #endif #if defined(IS_MACOSX) - int SendTo(int32_t pid, CGEventRef event) { + int SendTo(uintptr pid, CGEventRef event) { if (pid != 0) { CGEventPostToPid(pid, event); } else { @@ -111,12 +113,15 @@ void win32KeyEvent(int key, MMKeyFlags flags, int32_t pid, int32_t isPid) { } } + // todo: test this if (pid != 0) { HWND hwnd = (HWND) pid; if (isPid == 0) { hwnd = GetHwndByPid(pid); } - SendMessage(hwnd, flags == 0 ? WM_KEYDOWN : WM_KEYUP, key, 0); + int down = (flags == 0 ? WM_KEYDOWN : WM_KEYUP); + // SendMessage(hwnd, down, key, 0); + PostMessageW(hwnd, down, key, 0); return; } @@ -138,7 +143,7 @@ void win32KeyEvent(int key, MMKeyFlags flags, int32_t pid, int32_t isPid) { } #endif -void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags, int32_t pid) { +void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags, uintptr pid) { #if defined(IS_MACOSX) /* The media keys all have 1000 added to them to help us detect them. */ if (code >= 1000) { @@ -215,7 +220,7 @@ void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags, int32_t pi } #endif -void toggleKey(char c, const bool down, MMKeyFlags flags, int32_t pid) { +void toggleKey(char c, const bool down, MMKeyFlags flags, uintptr pid) { MMKeyCode keyCode = keyCodeForChar(c); //Prevent unused variable warning for Mac and Linux. @@ -251,7 +256,7 @@ void toggleKey(char c, const bool down, MMKeyFlags flags, int32_t pid) { // } #if defined(IS_MACOSX) -void toggleUnicode(UniChar ch, const bool down, int32_t pid) { +void toggleUnicode(UniChar ch, const bool down, uintptr pid) { /* This function relies on the convenient CGEventKeyboardSetUnicodeString(), convert characters to a keycode, but does not support adding modifier flags. It is only used in typeString(). @@ -302,7 +307,7 @@ void toggleUnicode(UniChar ch, const bool down, int32_t pid) { #endif // unicode type -void unicodeType(const unsigned value, int32_t pid){ +void unicodeType(const unsigned value, uintptr pid, int8_t isPid){ #if defined(IS_MACOSX) UniChar ch = (UniChar)value; // Convert to unsigned char @@ -310,6 +315,17 @@ void unicodeType(const unsigned value, int32_t pid){ microsleep(5.0); toggleUnicode(ch, false, pid); #elif defined(IS_WINDOWS) + if (pid != 0) { + HWND hwnd = (HWND) pid; + if (isPid == 0) { + hwnd = GetHwndByPid(pid); + } + + // SendMessage(hwnd, down, value, 0); + PostMessageW(hwnd, WM_CHAR, value, 0); + return; + } + INPUT input[2]; memset(input, 0, sizeof(input)); From 7103f6b89113282d7c15bb2dcb2b177e1bda913f Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 27 Nov 2022 18:33:32 -0800 Subject: [PATCH 248/327] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 331fdb15..03f44c4d 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ xcode-select --install [MinGW-w64](https://sourceforge.net/projects/mingw-w64/files) (Use recommended) Download the Mingw, then set system environment variables `C:\mingw64\bin` to the Path. -[Set environment variables to run GCC from command line](https://www.youtube.com/watch?v=1kY5iTK4-H0). +[Set environment variables to run GCC from command line](https://www.youtube.com/results?search_query=Set+environment+variables+to+run+GCC+from+command+line). ``` @@ -453,7 +453,7 @@ func main() { fmt.Println("pids... ", fpid) if len(fpid) > 0 { - robotgo.TypeStr("Hi galaxy!", int(fpid[0])) + robotgo.TypeStr("Hi galaxy!", fpid[0]) robotgo.KeyTap("a", fpid[0], "cmd") robotgo.KeyToggle("a", fpid[0]) From 4eea01b88d4c16bd591ee09cf74dafba357ede1e Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 27 Nov 2022 18:38:05 -0800 Subject: [PATCH 249/327] Fixed: fixed windows int type --- key/keypress_c.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/key/keypress_c.h b/key/keypress_c.h index 32e8daee..dd0134f7 100644 --- a/key/keypress_c.h +++ b/key/keypress_c.h @@ -17,7 +17,7 @@ #if defined(IS_WINDOWS) HWND GetHwndByPid(DWORD dwProcessId); - void WIN32_KEY_EVENT_WAIT(MMKeyCode key, DWORD flags, int32_t pid) { + void WIN32_KEY_EVENT_WAIT(MMKeyCode key, DWORD flags, uiprint pid) { win32KeyEvent(key, flags, pid, 0); Sleep(DEADBEEF_RANDRANGE(0, 1)); } @@ -70,7 +70,7 @@ static io_connect_t _getAuxiliaryKeyDriver(void) { #endif #if defined(IS_WINDOWS) -void win32KeyEvent(int key, MMKeyFlags flags, int32_t pid, int32_t isPid) { +void win32KeyEvent(int key, MMKeyFlags flags, uintptr pid, int8_t isPid) { int scan = MapVirtualKey(key & 0xff, MAPVK_VK_TO_VSC); /* Set the scan code for extended keys */ From 7aa5beb8f7e6c3dc59b1e99079681d8a25bafc2e Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 27 Nov 2022 18:40:51 -0800 Subject: [PATCH 250/327] Fixed: fixed typo --- key/keypress_c.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/key/keypress_c.h b/key/keypress_c.h index dd0134f7..53dd3047 100644 --- a/key/keypress_c.h +++ b/key/keypress_c.h @@ -17,7 +17,7 @@ #if defined(IS_WINDOWS) HWND GetHwndByPid(DWORD dwProcessId); - void WIN32_KEY_EVENT_WAIT(MMKeyCode key, DWORD flags, uiprint pid) { + void WIN32_KEY_EVENT_WAIT(MMKeyCode key, DWORD flags, uintptr pid) { win32KeyEvent(key, flags, pid, 0); Sleep(DEADBEEF_RANDRANGE(0, 1)); } From f911550742faa5b34c3e203b1364a0084b386c57 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 28 Nov 2022 13:40:01 -0800 Subject: [PATCH 251/327] Update: Update README.md and godoc --- README.md | 5 ++--- doc.go | 2 +- key.go | 7 +++++++ 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 03f44c4d..9223dc8c 100644 --- a/README.md +++ b/README.md @@ -68,10 +68,9 @@ xcode-select --install Download the Mingw, then set system environment variables `C:\mingw64\bin` to the Path. [Set environment variables to run GCC from command line](https://www.youtube.com/results?search_query=Set+environment+variables+to+run+GCC+from+command+line). - -``` +` Or the other GCC (But you should compile the "libpng" with yourself when use the bitmap.) -``` +` #### For everything else: diff --git a/doc.go b/doc.go index d668b874..b28cde23 100644 --- a/doc.go +++ b/doc.go @@ -54,7 +54,7 @@ Keys are supported: "f23" "f24" - "cmd" is the "win" key for windows + "cmd" this is the "win" key for windows "lcmd" left command "rcmd" right command // "command" diff --git a/key.go b/key.go index e59e1cf4..f0b37a80 100644 --- a/key.go +++ b/key.go @@ -30,6 +30,7 @@ import ( "github.com/vcaesar/tt" ) +// Defining a bunch of constants. const ( // KeyA define key "a" KeyA = "a" @@ -321,6 +322,7 @@ var keyNames = map[string]C.MMKeyCode{ // { NULL: C.K_NOT_A_KEY } } +// It sends a key press and release to the active application func tapKeyCode(code C.MMKeyCode, flags C.MMKeyFlags, pid C.uintptr) { C.toggleKeyCode(code, true, flags, pid) MilliSleep(3) @@ -459,6 +461,7 @@ func ToStrings(fields []interface{}) []string { return res } +// toErr it converts a C string to a Go error func toErr(str *C.char) error { gstr := C.GoString(str) if gstr == "" { @@ -481,6 +484,8 @@ func toErr(str *C.char) error { // // arr := []string{"alt", "command"} // robotgo.KeyTap("i", arr) +// +// robotgo.KeyTap("k", pid int) func KeyTap(key string, args ...interface{}) error { var keyArr []string @@ -525,6 +530,7 @@ func KeyTap(key string, args ...interface{}) error { // robotgo.KeyToggle("a", "up") // // robotgo.KeyToggle("a", "up", "alt", "cmd") +// robotgo.KeyToggle("k", pid int) func KeyToggle(key string, args ...interface{}) error { if len(key) > 0 && unicode.IsUpper([]rune(key)[0]) { @@ -648,6 +654,7 @@ func inputUTF(str string) { // Examples: // // robotgo.TypeStr("abc@123, Hi galaxy, こんにちは") +// robotgo.TypeStr("To be or not to be, this is questions.", pid int) func TypeStr(str string, args ...int) { var tm, tm1 = 0, 7 From 6313e521565c7b2a337964cfd1e8d8f56da945b6 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 28 Nov 2022 14:21:03 -0800 Subject: [PATCH 252/327] Update: Optimize window hand code --- key/keypress_c.h | 31 ++++++++++++++++++++++--------- window/alert_c.h | 1 + window/goWindow.h | 16 ++++------------ window/pub.h | 2 ++ window/win_sys.h | 14 ++------------ window/window.h | 6 +----- 6 files changed, 32 insertions(+), 38 deletions(-) diff --git a/key/keypress_c.h b/key/keypress_c.h index 53dd3047..35c6d548 100644 --- a/key/keypress_c.h +++ b/key/keypress_c.h @@ -1,6 +1,16 @@ -#include "keypress.h" +// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// https://github.com/go-vgo/robotgo/blob/master/LICENSE +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + #include "../base/deadbeef_rand_c.h" #include "../base/microsleep.h" +#include "keypress.h" #include "keycode_c.h" #include /* For isupper() */ @@ -17,6 +27,14 @@ #if defined(IS_WINDOWS) HWND GetHwndByPid(DWORD dwProcessId); + HWND getHwnd(uintptr pid, int8_t isPid) { + HWND hwnd = (HWND) pid; + if (isPid == 0) { + hwnd = GetHwndByPid(pid); + } + return hwnd; + } + void WIN32_KEY_EVENT_WAIT(MMKeyCode key, DWORD flags, uintptr pid) { win32KeyEvent(key, flags, pid, 0); Sleep(DEADBEEF_RANDRANGE(0, 1)); @@ -115,10 +133,8 @@ void win32KeyEvent(int key, MMKeyFlags flags, uintptr pid, int8_t isPid) { // todo: test this if (pid != 0) { - HWND hwnd = (HWND) pid; - if (isPid == 0) { - hwnd = GetHwndByPid(pid); - } + HWND hwnd = getHwnd(pid, isPid); + int down = (flags == 0 ? WM_KEYDOWN : WM_KEYUP); // SendMessage(hwnd, down, key, 0); PostMessageW(hwnd, down, key, 0); @@ -316,10 +332,7 @@ void unicodeType(const unsigned value, uintptr pid, int8_t isPid){ toggleUnicode(ch, false, pid); #elif defined(IS_WINDOWS) if (pid != 0) { - HWND hwnd = (HWND) pid; - if (isPid == 0) { - hwnd = GetHwndByPid(pid); - } + HWND hwnd = getHwnd(pid, isPid); // SendMessage(hwnd, down, value, 0); PostMessageW(hwnd, WM_CHAR, value, 0); diff --git a/window/alert_c.h b/window/alert_c.h index d5ed2bae..290786d4 100644 --- a/window/alert_c.h +++ b/window/alert_c.h @@ -18,6 +18,7 @@ int showAlert(const char *title, const char *msg, CFStringRef defaultButtonTitle = CFStringCreateWithUTF8String(defaultButton); CFStringRef cancelButtonTitle = CFStringCreateWithUTF8String(cancelButton); CFOptionFlags responseFlags; + SInt32 err = CFUserNotificationDisplayAlert( 0.0, kCFUserNotificationNoteAlertLevel, NULL, NULL, NULL, alertHeader, alertMessage, defaultButtonTitle, cancelButtonTitle, NULL, &responseFlags); diff --git a/window/goWindow.h b/window/goWindow.h index 6b69130e..cee4ed30 100644 --- a/window/goWindow.h +++ b/window/goWindow.h @@ -23,12 +23,8 @@ void min_window(uintptr pid, bool state, int8_t isPid){ XDismissErrors(); // SetState((Window)pid, STATE_MINIMIZE, state); #elif defined(IS_WINDOWS) - if (isPid == 0) { - HWND hwnd = GetHwndByPid(pid); - win_min(hwnd, state); - } else { - win_min((HWND)pid, state); - } + HWND hwnd = getHwnd(pid, isPid); + win_min(hwnd, state); #endif } @@ -40,12 +36,8 @@ void max_window(uintptr pid, bool state, int8_t isPid){ // SetState((Window)pid, STATE_MINIMIZE, false); // SetState((Window)pid, STATE_MAXIMIZE, state); #elif defined(IS_WINDOWS) - if (isPid == 0) { - HWND hwnd = GetHwndByPid(pid); - win_max(hwnd, state); - } else { - win_max((HWND)pid, state); - } + HWND hwnd = getHwnd(pid, isPid); + win_max(hwnd, state); #endif } diff --git a/window/pub.h b/window/pub.h index f38d4d44..2ab44625 100644 --- a/window/pub.h +++ b/window/pub.h @@ -267,6 +267,8 @@ typedef struct _Bounds Bounds; #elif defined(IS_WINDOWS) + HWND getHwnd(uintptr pid, int8_t isPid); + void win_min(HWND hwnd, bool state){ if (state) { ShowWindow(hwnd, SW_MINIMIZE); diff --git a/window/win_sys.h b/window/win_sys.h index 01edf012..776899b3 100644 --- a/window/win_sys.h +++ b/window/win_sys.h @@ -128,12 +128,7 @@ Bounds get_bounds(uintptr pid, int8_t isPid){ return bounds; #elif defined(IS_WINDOWS) - HWND hwnd; - if (isPid == 0) { - hwnd= GetHwndByPid(pid); - } else { - hwnd = (HWND)pid; - } + HWND hwnd = getHwnd(pid, isPid); RECT rect = { 0 }; GetWindowRect(hwnd, &rect); @@ -193,12 +188,7 @@ Bounds get_client(uintptr pid, int8_t isPid) { return bounds; #elif defined(IS_WINDOWS) - HWND hwnd; - if (isPid == 0) { - hwnd = GetHwndByPid(pid); - } else { - hwnd = (HWND)pid; - } + HWND hwnd = getHwnd(pid, isPid); RECT rect = { 0 }; GetClientRect(hwnd, &rect); diff --git a/window/window.h b/window/window.h index 301129a8..35eaef5c 100644 --- a/window/window.h +++ b/window/window.h @@ -59,11 +59,7 @@ MData set_handle_pid(uintptr pid, int8_t isPid){ win.XWin = (Window)pid; // Handle to an X11 window #elif defined(IS_WINDOWS) // win.HWnd = (HWND)pid; // Handle to a window HWND - if (isPid == 0) { - win.HWnd = GetHwndByPid(pid); - } else { - win.HWnd = (HWND)pid; - } + win.HWnd = getHwnd(pid, isPid); #endif return win; From f4f4a3d319056902802de6d65449f095f6432244 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sat, 10 Dec 2022 15:50:41 -0800 Subject: [PATCH 253/327] Update: Update CI --- .circleci/config.yml | 2 +- .circleci/images/primary/Dockerfile | 2 +- appveyor.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 55be1d92..6bf42fea 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,7 +5,7 @@ jobs: docker: # using custom image, see .circleci/images/primary/Dockerfile # - image: govgo/robotgoci:1.10.3 - - image: golang:1.19.3 + - image: golang:1.19.4 working_directory: /gopath/src/github.com/go-vgo/robotgo steps: - checkout diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index 7b15f841..01b48c93 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.19.3-stretch AS build +FROM golang:1.19.4-stretch AS build # FROM govgo/go:1.11.1 RUN apt update && apt install -y --no-install-recommends \ diff --git a/appveyor.yml b/appveyor.yml index 1e8bb1ca..c667add4 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,7 +34,7 @@ environment: PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% # - COMPILER: MINGW_W64 # ARCHITECTURE: x64 - GOVERSION: 1.19.3 + GOVERSION: 1.19.4 # GOPATH: c:\gopath # scripts that run after cloning repository From e8b397520516585ce04bc17279a6370a048de24d Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 15 Dec 2022 08:58:17 -0800 Subject: [PATCH 254/327] Add: add cmd to the ctrl supported --- clipboard/cmd/gocopy/gocopy.go | 4 ++-- key.go | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/clipboard/cmd/gocopy/gocopy.go b/clipboard/cmd/gocopy/gocopy.go index 115672af..aaa9c30b 100644 --- a/clipboard/cmd/gocopy/gocopy.go +++ b/clipboard/cmd/gocopy/gocopy.go @@ -1,14 +1,14 @@ package main import ( - "io/ioutil" + "io" "os" "github.com/go-vgo/robotgo/clipboard" ) func main() { - out, err := ioutil.ReadAll(os.Stdin) + out, err := io.ReadAll(os.Stdin) if err != nil { panic(err) } diff --git a/key.go b/key.go index f0b37a80..998452e5 100644 --- a/key.go +++ b/key.go @@ -322,6 +322,15 @@ var keyNames = map[string]C.MMKeyCode{ // { NULL: C.K_NOT_A_KEY } } +// CmdCtrl If the operating system is macOS, return the key string "cmd", +// otherwise return the key string "ctrl +func CmdCtrl() string { + if runtime.GOOS == "darwin" { + return "cmd" + } + return "ctrl" +} + // It sends a key press and release to the active application func tapKeyCode(code C.MMKeyCode, flags C.MMKeyFlags, pid C.uintptr) { C.toggleKeyCode(code, true, flags, pid) From bdae1a7759ba826a70227d5fed16e4c5e8bfec9c Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 11 Jan 2023 16:08:24 -0800 Subject: [PATCH 255/327] Fix: fixed mac multi screen capture --- screen/screengrab_c.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/screen/screengrab_c.h b/screen/screengrab_c.h index 1118391d..59900130 100644 --- a/screen/screengrab_c.h +++ b/screen/screengrab_c.h @@ -20,7 +20,7 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id) size_t bufferSize = 0; CGDirectDisplayID displayID = (CGDirectDisplayID) display_id; - if (displayID == -1) { + if (displayID == -1 || displayID == 0) { displayID = CGMainDisplayID(); } @@ -94,11 +94,13 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id) } if (screen == NULL) { return NULL; } + // Todo: + screenMem = CreateCompatibleDC(screen); /* Get screen data in display device context. */ dib = CreateDIBSection(screen, &bi, DIB_RGB_COLORS, &data, NULL, 0); /* Copy the data into a bitmap struct. */ - BOOL b = (screenMem = CreateCompatibleDC(screen)) == NULL || + BOOL b = (screenMem == NULL) || SelectObject(screenMem, dib) == NULL || !BitBlt(screenMem, (int)0, (int)0, (int)rect.size.w, (int)rect.size.h, screen, rect.origin.x, rect.origin.y, SRCCOPY); From 95be5f752fe2228d4b37febdbf3c9eaef7425534 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 15 Jan 2023 09:12:40 -0800 Subject: [PATCH 256/327] Fixed: fixed mac key release and remove the toggle defaut sleep --- README.md | 31 ++++++++++++++++++++----------- examples/README.md | 2 +- examples/scale/main.go | 2 +- key.go | 6 ++++-- key/keypress_c.h | 12 ++++-------- mouse/mouse_c.h | 8 ++++---- robotgo.go | 22 ++++++++++++---------- robotgo_test.go | 10 +++++----- 8 files changed, 51 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index 9223dc8c..b7319a99 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ + [![Build Status](https://github.com/go-vgo/robotgo/workflows/Go/badge.svg)](https://github.com/go-vgo/robotgo/commits/master) [![CircleCI Status](https://circleci.com/gh/go-vgo/robotgo.svg?style=shield)](https://circleci.com/gh/go-vgo/robotgo) [![Build Status](https://travis-ci.org/go-vgo/robotgo.svg)](https://travis-ci.org/go-vgo/robotgo) @@ -12,6 +13,7 @@ [![GoDoc](https://godoc.org/github.com/go-vgo/robotgo?status.svg)](https://godoc.org/github.com/go-vgo/robotgo) [![GitHub release](https://img.shields.io/github/release/go-vgo/robotgo.svg)](https://github.com/go-vgo/robotgo/releases/latest) [![Join the chat at https://gitter.im/go-vgo/robotgo](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/go-vgo/robotgo?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + @@ -20,6 +22,7 @@ RobotGo supports Mac, Windows, and Linux(X11); and robotgo supports arm64 and x86-amd64. ## Contents + - [Docs](#docs) - [Binding](#binding) - [Requirements](#requirements) @@ -34,10 +37,12 @@ RobotGo supports Mac, Windows, and Linux(X11); and robotgo supports arm64 and x8 - [License](#license) ## Docs - - [GoDoc](https://godoc.org/github.com/go-vgo/robotgo)
- - [API Docs](https://github.com/go-vgo/robotgo/blob/master/docs/doc.md) (Deprecated, no updated) + +- [GoDoc](https://godoc.org/github.com/go-vgo/robotgo)
+- [API Docs](https://github.com/go-vgo/robotgo/blob/master/docs/doc.md) (Deprecated, no updated) ## Binding: + [ADB](https://github.com/vcaesar/adb), packaging android adb API. [Robotn](https://github.com/vcaesar/robotn), binding JavaScript and other, support more language. @@ -47,6 +52,7 @@ RobotGo supports Mac, Windows, and Linux(X11); and robotgo supports arm64 and x8 Now, Please make sure `Golang, GCC` is installed correctly before installing RobotGo. ### ALL: + ``` Golang @@ -63,14 +69,12 @@ xcode-select --install #### For Windows: -[MinGW-w64](https://sourceforge.net/projects/mingw-w64/files) (Use recommended) +[MinGW-w64](https://sourceforge.net/projects/mingw-w64/files) (Use recommended) Download the Mingw, then set system environment variables `C:\mingw64\bin` to the Path. [Set environment variables to run GCC from command line](https://www.youtube.com/results?search_query=Set+environment+variables+to+run+GCC+from+command+line). -` -Or the other GCC (But you should compile the "libpng" with yourself when use the bitmap.) -` +`Or the other GCC (But you should compile the "libpng" with yourself when use the bitmap.)` #### For everything else: @@ -115,7 +119,7 @@ sudo apt install xsel xclip ##### Fedora: ```yml -sudo dnf install libXtst-devel +sudo dnf install libXtst-devel # Bitmap sudo dnf install libpng-devel @@ -144,6 +148,7 @@ go get github.com/go-vgo/robotgo png.h: No such file or directory? Please see [issues/47](https://github.com/go-vgo/robotgo/issues/47). ## Update: + ``` go get -u github.com/go-vgo/robotgo ``` @@ -151,7 +156,6 @@ go get -u github.com/go-vgo/robotgo Note go1.10.x C file compilation cache problem, [golang #24355](https://github.com/golang/go/issues/24355). `go mod vendor` problem, [golang #26366](https://github.com/golang/go/issues/26366). - ## [Examples:](https://github.com/go-vgo/robotgo/blob/master/examples) #### [Mouse](https://github.com/go-vgo/robotgo/blob/master/examples/mouse/main.go) @@ -486,6 +490,7 @@ func main() { ## CrossCompiling ##### Windows64 to windows32 + ```Go SET CGO_ENABLED=1 SET GOARCH=386 @@ -495,6 +500,7 @@ go build main.go #### Other to windows Install Requirements (Ubuntu, Just used by bitmap.): + ```bash sudo apt install gcc-multilib sudo apt install gcc-mingw-w64 @@ -503,6 +509,7 @@ sudo apt install libz-mingw-w64-dev ``` Build the binary: + ```Go GOOS=windows GOARCH=amd64 CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ go build -x ./ ``` @@ -515,11 +522,13 @@ GOOS=windows GOARCH=amd64 CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64 Some discussions and questions, please see [issues/228](https://github.com/go-vgo/robotgo/issues/228), [issues/143](https://github.com/go-vgo/robotgo/issues/143). ## Authors -* [The author is vz](https://github.com/vcaesar) -* [Maintainers](https://github.com/orgs/go-vgo/people) -* [Contributors](https://github.com/go-vgo/robotgo/graphs/contributors) + +- [The author is vz](https://github.com/vcaesar) +- [Maintainers](https://github.com/orgs/go-vgo/people) +- [Contributors](https://github.com/go-vgo/robotgo/graphs/contributors) ## Plans + - Refactor some C code to Go (such as x11, windows) - Better multiscreen support - Wayland support diff --git a/examples/README.md b/examples/README.md index af5c8ab3..e7188e89 100644 --- a/examples/README.md +++ b/examples/README.md @@ -68,7 +68,7 @@ import ( ) func main() { - x, y := robotgo.GetMousePos() + x, y := robotgo.Location() fmt.Println("pos:", x, y) color := robotgo.GetPixelColor(100, 200) fmt.Println("color----", color) diff --git a/examples/scale/main.go b/examples/scale/main.go index 71e7371d..d2baae48 100644 --- a/examples/scale/main.go +++ b/examples/scale/main.go @@ -22,7 +22,7 @@ func main() { robotx, roboty := 35*s/100, 25*s/100 fmt.Println("scale: ", sx, s, " pos: ", robotx, roboty) - mx, my := robotgo.GetMousePos() + mx, my := robotgo.Location() sx, sy := mx*s/100, my*s/100 rx, ry, rw, rh := sx, sy, robotx, roboty diff --git a/key.go b/key.go index 998452e5..4f9b6dc1 100644 --- a/key.go +++ b/key.go @@ -417,7 +417,7 @@ func keyTaps(k string, keyArr []string, pid int) error { return nil } -func keyToggles(k string, keyArr []string, pid int) error { +func keyToggles(k string, keyArr []string, pid int, args ...interface{}) error { if len(keyArr) <= 0 { keyArr = append(keyArr, "down") } @@ -438,7 +438,9 @@ func keyToggles(k string, keyArr []string, pid int) error { } C.toggleKeyCode(key, C.bool(down), flags, C.uintptr(pid)) - MilliSleep(KeySleep) + if len(args) > 0 { + MilliSleep(KeySleep) + } return nil } diff --git a/key/keypress_c.h b/key/keypress_c.h index 35c6d548..6064b4a3 100644 --- a/key/keypress_c.h +++ b/key/keypress_c.h @@ -60,6 +60,8 @@ } else { CGEventPost(kCGSessionEventTap, event); } + + CFRelease(event); return 0; } @@ -187,7 +189,6 @@ void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags, uintptr pi } SendTo(pid, keyEvent); - CFRelease(keyEvent); } #elif defined(IS_WINDOWS) const DWORD dwFlags = down ? 0 : KEYEVENTF_KEYUP; @@ -239,11 +240,6 @@ void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags, uintptr pi void toggleKey(char c, const bool down, MMKeyFlags flags, uintptr pid) { MMKeyCode keyCode = keyCodeForChar(c); - //Prevent unused variable warning for Mac and Linux. - #if defined(IS_WINDOWS) - int modifiers; - #endif - #if defined(USE_X11) if (toUpper(c) && !(flags & MOD_SHIFT)) { flags |= MOD_SHIFT; /* Not sure if this is safe for all layouts. */ @@ -255,7 +251,8 @@ void toggleKey(char c, const bool down, MMKeyFlags flags, uintptr pid) { #endif #if defined(IS_WINDOWS) - modifiers = keyCode >> 8; // Pull out modifers. + int modifiers = keyCode >> 8; // Pull out modifers. + if ((modifiers & 1) != 0) { flags |= MOD_SHIFT; } // Uptdate flags from keycode modifiers. if ((modifiers & 2) != 0) { flags |= MOD_CONTROL; } if ((modifiers & 4) != 0) { flags |= MOD_ALT; } @@ -286,7 +283,6 @@ void toggleUnicode(UniChar ch, const bool down, uintptr pid) { CGEventKeyboardSetUnicodeString(keyEvent, 1, &ch); SendTo(pid, keyEvent); - CFRelease(keyEvent); } #endif diff --git a/mouse/mouse_c.h b/mouse/mouse_c.h index a53bdf5f..f273fbd9 100644 --- a/mouse/mouse_c.h +++ b/mouse/mouse_c.h @@ -133,7 +133,7 @@ void dragMouse(MMPointInt32 point, const MMMouseButton button){ #endif } -MMPointInt32 getMousePos() { +MMPointInt32 location() { #if defined(IS_MACOSX) CGEventRef event = CGEventCreate(NULL); CGPoint point = CGEventGetLocation(event); @@ -161,7 +161,7 @@ MMPointInt32 getMousePos() { /* Press down a button, or release it. */ void toggleMouse(bool down, MMMouseButton button) { #if defined(IS_MACOSX) - const CGPoint currentPos = CGPointFromMMPointInt32(getMousePos()); + const CGPoint currentPos = CGPointFromMMPointInt32(location()); const CGEventType mouseType = MMMouseToCGEventType(down, button); CGEventRef event = CGEventCreateMouseEvent(NULL, mouseType, currentPos, (CGMouseButton)button); @@ -196,7 +196,7 @@ void clickMouse(MMMouseButton button){ void doubleClick(MMMouseButton button){ #if defined(IS_MACOSX) /* Double click for Mac. */ - const CGPoint currentPos = CGPointFromMMPointInt32(getMousePos()); + const CGPoint currentPos = CGPointFromMMPointInt32(location()); const CGEventType mouseTypeDown = MMMouseToCGEventType(true, button); const CGEventType mouseTypeUP = MMMouseToCGEventType(false, button); @@ -298,7 +298,7 @@ static double crude_hypot(double x, double y){ } bool smoothlyMoveMouse(MMPointInt32 endPoint, double lowSpeed, double highSpeed){ - MMPointInt32 pos = getMousePos(); + MMPointInt32 pos = location(); MMSizeInt32 screenSize = getMainDisplaySize(); double velo_x = 0.0, velo_y = 0.0; double distance; diff --git a/robotgo.go b/robotgo.go index dd902a33..06329969 100644 --- a/robotgo.go +++ b/robotgo.go @@ -211,9 +211,9 @@ func GetPixelColor(x, y int, displayId ...int) string { return PadHex(GetPxColor(x, y, displayId...)) } -// GetMouseColor get the mouse pos's color -func GetMouseColor(displayId ...int) string { - x, y := GetMousePos() +// GetLocationColor get the location pos's color +func GetLocationColor(displayId ...int) string { + x, y := Location() return GetPixelColor(x, y, displayId...) } @@ -651,7 +651,7 @@ func GetMousePos() (int, int) { // Location get the mouse location position return x, y func Location() (int, int) { - pos := C.getMousePos() + pos := C.location() x := int(pos.x) y := int(pos.y) @@ -731,29 +731,31 @@ func MovesClick(x, y int, args ...interface{}) { // // robotgo.Toggle("left") // default is down // robotgo.Toggle("left", "up") -func Toggle(key ...string) error { +func Toggle(key ...interface{}) error { var button C.MMMouseButton = C.LEFT_BUTTON if len(key) > 0 { - button = CheckMouse(key[0]) + button = CheckMouse(key[0].(string)) } down := true - if len(key) > 1 && key[1] == "up" { + if len(key) > 1 && key[1].(string) == "up" { down = false } C.toggleMouse(C.bool(down), button) - MilliSleep(MouseSleep) + if len(key) > 2 { + MilliSleep(MouseSleep) + } return nil } // MouseDown send mouse down event -func MouseDown(key ...string) error { +func MouseDown(key ...interface{}) error { return Toggle(key...) } // MouseUp send mouse up event -func MouseUp(key ...string) error { +func MouseUp(key ...interface{}) error { if len(key) <= 0 { key = append(key, "left") } diff --git a/robotgo_test.go b/robotgo_test.go index f5ff861f..82d0e9e0 100644 --- a/robotgo_test.go +++ b/robotgo_test.go @@ -42,7 +42,7 @@ func TestSize(t *testing.T) { func TestMoveMouse(t *testing.T) { Move(20, 20) MilliSleep(50) - x, y := GetMousePos() + x, y := Location() tt.Equal(t, 20, x) tt.Equal(t, 20, y) @@ -51,7 +51,7 @@ func TestMoveMouse(t *testing.T) { func TestMoveMouseSmooth(t *testing.T) { b := MoveSmooth(100, 100) MilliSleep(50) - x, y := GetMousePos() + x, y := Location() tt.True(t, b) tt.Equal(t, 100, x) @@ -61,7 +61,7 @@ func TestMoveMouseSmooth(t *testing.T) { func TestDragMouse(t *testing.T) { DragSmooth(500, 500) MilliSleep(50) - x, y := GetMousePos() + x, y := Location() tt.Equal(t, 500, x) tt.Equal(t, 500, y) @@ -85,7 +85,7 @@ func TestMoveRelative(t *testing.T) { MoveRelative(10, -10) MilliSleep(50) - x, y := GetMousePos() + x, y := Location() tt.Equal(t, 210, x) tt.Equal(t, 190, y) } @@ -97,7 +97,7 @@ func TestMoveSmoothRelative(t *testing.T) { MoveSmoothRelative(10, -10) MilliSleep(50) - x, y := GetMousePos() + x, y := Location() tt.Equal(t, 210, x) tt.Equal(t, 190, y) } From 736fa1cc261802abe11d9c2f8fa13b4711854b04 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 18 Jan 2023 11:45:18 -0800 Subject: [PATCH 257/327] Add: add windows capture multi screen support --- screen/screengrab_c.h | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/screen/screengrab_c.h b/screen/screengrab_c.h index 59900130..c390fe51 100644 --- a/screen/screengrab_c.h +++ b/screen/screengrab_c.h @@ -72,14 +72,17 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id) HBITMAP dib; BITMAPINFO bi; + int32_t x = rect.origin.x, y = rect.origin.y; + int32_t w = rect.size.w, h = rect.size.h; + /* Initialize bitmap info. */ bi.bmiHeader.biSize = sizeof(bi.bmiHeader); - bi.bmiHeader.biWidth = (long)rect.size.w; - bi.bmiHeader.biHeight = -(long)rect.size.h; /* Non-cartesian, please */ + bi.bmiHeader.biWidth = (long) w; + bi.bmiHeader.biHeight = -(long) h; /* Non-cartesian, please */ bi.bmiHeader.biPlanes = 1; bi.bmiHeader.biBitCount = 32; bi.bmiHeader.biCompression = BI_RGB; - bi.bmiHeader.biSizeImage = (DWORD)(4 * rect.size.w * rect.size.h); + bi.bmiHeader.biSizeImage = (DWORD)(4 * w * h); bi.bmiHeader.biXPelsPerMeter = 0; bi.bmiHeader.biYPelsPerMeter = 0; bi.bmiHeader.biClrUsed = 0; @@ -102,8 +105,7 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id) /* Copy the data into a bitmap struct. */ BOOL b = (screenMem == NULL) || SelectObject(screenMem, dib) == NULL || - !BitBlt(screenMem, (int)0, (int)0, (int)rect.size.w, (int)rect.size.h, - screen, rect.origin.x, rect.origin.y, SRCCOPY); + !BitBlt(screenMem, (int)0, (int)0, (int)w, (int)h, screen, x, y, SRCCOPY); if (b) { /* Error copying data. */ ReleaseDC(hwnd, screen); @@ -113,8 +115,7 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id) return NULL; } - bitmap = createMMBitmap_c(NULL, rect.size.w, rect.size.h, 4 * rect.size.w, - (uint8_t)bi.bmiHeader.biBitCount, 4); + bitmap = createMMBitmap_c(NULL, w, h, 4 * w, (uint8_t)bi.bmiHeader.biBitCount, 4); /* Copy the data to our pixel buffer. */ if (bitmap != NULL) { From f830c8ed13ade08e86f01f013cc63ab7cd7325a2 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 19 Jan 2023 10:06:56 -0800 Subject: [PATCH 258/327] Add: add capture multi screen default support --- robotgo.go | 9 ++++++++- screen/goScreen.h | 6 +++--- screen/screengrab_c.h | 22 ++++++++++++---------- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/robotgo.go b/robotgo.go index 06329969..4acce50e 100644 --- a/robotgo.go +++ b/robotgo.go @@ -72,6 +72,9 @@ var ( // DisplayID set the screen display id DisplayID = -1 + + // NotPid used the hwnd not pid in windows + NotPid bool ) type ( @@ -324,7 +327,11 @@ func CaptureScreen(args ...int) CBitmap { h = C.int32_t(rect.H) } - bit := C.capture_screen(x, y, w, h, C.int32_t(displayId)) + isPid := 0 + if NotPid || len(args) > 5 { + isPid = 1 + } + bit := C.capture_screen(x, y, w, h, C.int32_t(displayId), C.int8_t(isPid)) return CBitmap(bit) } diff --git a/screen/goScreen.h b/screen/goScreen.h index c093d065..24321bf6 100644 --- a/screen/goScreen.h +++ b/screen/goScreen.h @@ -51,7 +51,7 @@ MMRGBHex get_px_color(int32_t x, int32_t y, int32_t display_id) { return color; } - bitmap = copyMMBitmapFromDisplayInRect(MMRectInt32Make(x, y, 1, 1), display_id); + bitmap = copyMMBitmapFromDisplayInRect(MMRectInt32Make(x, y, 1, 1), display_id, 0); color = MMRGBHexAtPoint(bitmap, 0, 0); destroyMMBitmap(bitmap); @@ -114,8 +114,8 @@ void bitmap_dealloc(MMBitmapRef bitmap) { } // capture_screen capture screen -MMBitmapRef capture_screen(int32_t x, int32_t y, int32_t w, int32_t h, int32_t display_id) { - MMBitmapRef bitmap = copyMMBitmapFromDisplayInRect(MMRectInt32Make(x, y, w, h), display_id); +MMBitmapRef capture_screen(int32_t x, int32_t y, int32_t w, int32_t h, int32_t display_id, int8_t isPid) { + MMBitmapRef bitmap = copyMMBitmapFromDisplayInRect(MMRectInt32Make(x, y, w, h), display_id, isPid); return bitmap; } diff --git a/screen/screengrab_c.h b/screen/screengrab_c.h index c390fe51..49852d0e 100644 --- a/screen/screengrab_c.h +++ b/screen/screengrab_c.h @@ -13,7 +13,7 @@ #include #endif -MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id) { +MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id, int8_t isPid) { #if defined(IS_MACOSX) MMBitmapRef bitmap = NULL; uint8_t *buffer = NULL; @@ -24,8 +24,8 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id) displayID = CGMainDisplayID(); } - CGImageRef image = CGDisplayCreateImageForRect(displayID, - CGRectMake(rect.origin.x, rect.origin.y, rect.size.w, rect.size.h)); + MMPointInt32 o = rect.origin; MMSizeInt32 s = rect.size; + CGImageRef image = CGDisplayCreateImageForRect(displayID, CGRectMake(o.x, o.y, s.w, s.h)); if (!image) { return NULL; } CFDataRef imageData = CGDataProviderCopyData(CGImageGetDataProvider(image)); @@ -52,14 +52,14 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id) display = XGetMainDisplay(); } + MMPointInt32 o = rect.origin; MMSizeInt32 s = rect.size; XImage *image = XGetImage(display, XDefaultRootWindow(display), - (int)rect.origin.x, (int)rect.origin.y, - (unsigned int)rect.size.w, (unsigned int)rect.size.h, AllPlanes, ZPixmap); + (int)o.x, (int)o.y, (unsigned int)s.w, (unsigned int)s.h, AllPlanes, ZPixmap); XCloseDisplay(display); if (image == NULL) { return NULL; } bitmap = createMMBitmap_c((uint8_t *)image->data, - rect.size.w, rect.size.h, (size_t)image->bytes_per_line, + s.w, s.h, (size_t)image->bytes_per_line, (uint8_t)image->bits_per_pixel, (uint8_t)image->bits_per_pixel / 8); image->data = NULL; /* Steal ownership of bitmap data so we don't have to copy it. */ XDestroyImage(image); @@ -89,15 +89,17 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id) bi.bmiHeader.biClrImportant = 0; HWND hwnd; - if (display_id == -1) { - screen = GetDC(NULL); /* Get entire screen */ + if (display_id == -1 || isPid == 0) { + // screen = GetDC(NULL); /* Get entire screen */ + hwnd = GetDesktopWindow(); } else { hwnd = (HWND) (uintptr) display_id; - screen = GetDC(hwnd); } + screen = GetDC(hwnd); + if (screen == NULL) { return NULL; } - // Todo: + // Todo: Use DXGI screenMem = CreateCompatibleDC(screen); /* Get screen data in display device context. */ dib = CreateDIBSection(screen, &bi, DIB_RGB_COLORS, &data, NULL, 0); From df1617d8942b033d5990ba4b0fb35e212f261eee Mon Sep 17 00:00:00 2001 From: vcaesar Date: Fri, 20 Jan 2023 13:53:06 -0800 Subject: [PATCH 259/327] Update: used NotPid option args and move Deprecated func to v1 --- key.go | 13 +----- robotgo.go | 103 +++++---------------------------------------- robotgo_fn_v1.go | 95 +++++++++++++++++++++++++++++++++++++++++ robotgo_mac_win.go | 16 +++---- robotgo_x11.go | 16 +++---- 5 files changed, 124 insertions(+), 119 deletions(-) create mode 100644 robotgo_fn_v1.go diff --git a/key.go b/key.go index 4f9b6dc1..3cfd588a 100644 --- a/key.go +++ b/key.go @@ -27,7 +27,6 @@ import ( "unsafe" "github.com/go-vgo/robotgo/clipboard" - "github.com/vcaesar/tt" ) // Defining a bunch of constants. @@ -723,22 +722,14 @@ func PasteStr(str string) error { } // TypeStrDelay type string with delayed +// And you can use robotgo.KeySleep = 100 to delayed not this function func TypeStrDelay(str string, delay int) { TypeStr(str) MilliSleep(delay) } -// Deprecated: use the TypeStr(), -// -// # TypeStringDelayed type string delayed, Wno-deprecated -// -// This function will be removed in version v1.0.0 -func TypeStringDelayed(str string, delay int) { - tt.Drop("TypeStringDelayed", "TypeStrDelay") - TypeStrDelay(str, delay) -} - // SetDelay sets the key and mouse delay +// robotgo.SetDelay(100) option the robotgo.KeySleep and robotgo.MouseSleep = d func SetDelay(d ...int) { v := 10 if len(d) > 0 { diff --git a/robotgo.go b/robotgo.go index 4acce50e..05d569db 100644 --- a/robotgo.go +++ b/robotgo.go @@ -331,6 +331,7 @@ func CaptureScreen(args ...int) CBitmap { if NotPid || len(args) > 5 { isPid = 1 } + bit := C.capture_screen(x, y, w, h, C.int32_t(displayId), C.int8_t(isPid)) return CBitmap(bit) } @@ -444,45 +445,6 @@ func ScaleX() int { return int(C.scaleX()) } -// Deprecated: use the ScaledF(), -// -// Scale get the screen scale (only windows old), drop -func Scale() int { - dpi := map[int]int{ - 0: 100, - // DPI Scaling Level - 96: 100, - 120: 125, - 144: 150, - 168: 175, - 192: 200, - 216: 225, - // Custom DPI - 240: 250, - 288: 300, - 384: 400, - 480: 500, - } - - x := ScaleX() - return dpi[x] -} - -// Deprecated: use the ScaledF(), -// -// Scale0 return ScaleX() / 0.96, drop -func Scale0() int { - return int(float64(ScaleX()) / 0.96) -} - -// Deprecated: use the ScaledF(), -// -// Mul mul the scale, drop -func Mul(x int) int { - s := Scale() - return x * s / 100 -} - /* .___ ___. ______ __ __ _______. _______ | \/ | / __ \ | | | | / || ____| @@ -512,13 +474,6 @@ func CheckMouse(btn string) C.MMMouseButton { return C.LEFT_BUTTON } -// Deprecated: use the Move(), -// -// MoveMouse move the mouse -func MoveMouse(x, y int) { - Move(x, y) -} - // Move move the mouse to (x, y) // // Examples: @@ -538,18 +493,6 @@ func Move(x, y int) { MilliSleep(MouseSleep) } -// Deprecated: use the DragSmooth(), -// -// DragMouse drag the mouse to (x, y), -// It's same with the DragSmooth() now -func DragMouse(x, y int, args ...interface{}) { - Toggle("left") - MilliSleep(50) - // Drag(x, y, args...) - MoveSmooth(x, y, args...) - Toggle("left", "up") -} - // Deprecated: use the DragSmooth(), // // Drag drag the mouse to (x, y), @@ -579,14 +522,6 @@ func DragSmooth(x, y int, args ...interface{}) { Toggle("left", "up") } -// Deprecated: use the MoveSmooth(), -// -// MoveMouseSmooth move the mouse smooth, -// moves mouse to x, y human like, with the mouse button up. -func MoveMouseSmooth(x, y int, args ...interface{}) bool { - return MoveSmooth(x, y, args...) -} - // MoveSmooth move the mouse smooth, // moves mouse to x, y human like, with the mouse button up. // @@ -649,13 +584,6 @@ func MoveSmoothRelative(x, y int, args ...interface{}) { MoveSmooth(mx, my, args...) } -// Deprecated: use the function Location() -// -// GetMousePos get the mouse's position return x, y -func GetMousePos() (int, int) { - return Location() -} - // Location get the mouse location position return x, y func Location() (int, int) { pos := C.location() @@ -665,15 +593,6 @@ func Location() (int, int) { return x, y } -// Deprecated: use the Click(), -// -// # MouseClick click the mouse -// -// robotgo.MouseClick(button string, double bool) -func MouseClick(args ...interface{}) { - Click(args...) -} - // Click click the mouse button // // robotgo.Click(button string, double bool) @@ -938,8 +857,8 @@ func MinWindow(pid int, args ...interface{}) { if len(args) > 0 { state = args[0].(bool) } - if len(args) > 1 { - isPid = args[1].(int) + if len(args) > 1 || NotPid { + isPid = 1 } C.min_window(C.uintptr(pid), C.bool(state), C.int8_t(isPid)) @@ -955,8 +874,8 @@ func MaxWindow(pid int, args ...interface{}) { if len(args) > 0 { state = args[0].(bool) } - if len(args) > 1 { - isPid = args[1].(int) + if len(args) > 1 || NotPid { + isPid = 1 } C.max_window(C.uintptr(pid), C.bool(state), C.int8_t(isPid)) @@ -973,8 +892,8 @@ func CloseWindow(args ...int) { if len(args) > 0 { pid = args[0] } - if len(args) > 1 { - isPid = args[1] + if len(args) > 1 || NotPid { + isPid = 1 } C.close_window_by_PId(C.uintptr(pid), C.int8_t(isPid)) @@ -989,8 +908,8 @@ func SetHandle(hwnd int) { // SetHandlePid set the window handle by pid func SetHandlePid(pid int, args ...int) { var isPid int - if len(args) > 0 { - isPid = args[0] + if len(args) > 0 || NotPid { + isPid = 1 } C.set_handle_pid_mData(C.uintptr(pid), C.int8_t(isPid)) @@ -999,8 +918,8 @@ func SetHandlePid(pid int, args ...int) { // GetHandPid get handle mdata by pid func GetHandPid(pid int, args ...int) C.MData { var isPid int - if len(args) > 0 { - isPid = args[0] + if len(args) > 0 || NotPid { + isPid = 1 } return C.set_handle_pid(C.uintptr(pid), C.int8_t(isPid)) diff --git a/robotgo_fn_v1.go b/robotgo_fn_v1.go new file mode 100644 index 00000000..0132aef2 --- /dev/null +++ b/robotgo_fn_v1.go @@ -0,0 +1,95 @@ +package robotgo + +import "github.com/vcaesar/tt" + +// Deprecated: use the Move(), +// +// MoveMouse move the mouse +func MoveMouse(x, y int) { + Move(x, y) +} + +// Deprecated: use the DragSmooth(), +// +// DragMouse drag the mouse to (x, y), +// It's same with the DragSmooth() now +func DragMouse(x, y int, args ...interface{}) { + Toggle("left") + MilliSleep(50) + // Drag(x, y, args...) + MoveSmooth(x, y, args...) + Toggle("left", "up") +} + +// Deprecated: use the MoveSmooth(), +// +// MoveMouseSmooth move the mouse smooth, +// moves mouse to x, y human like, with the mouse button up. +func MoveMouseSmooth(x, y int, args ...interface{}) bool { + return MoveSmooth(x, y, args...) +} + +// Deprecated: use the function Location() +// +// GetMousePos get the mouse's position return x, y +func GetMousePos() (int, int) { + return Location() +} + +// Deprecated: use the Click(), +// +// # MouseClick click the mouse +// +// robotgo.MouseClick(button string, double bool) +func MouseClick(args ...interface{}) { + Click(args...) +} + +// Deprecated: use the TypeStr(), +// +// # TypeStringDelayed type string delayed, Wno-deprecated +// +// This function will be removed in version v1.0.0 +func TypeStringDelayed(str string, delay int) { + tt.Drop("TypeStringDelayed", "TypeStrDelay") + TypeStrDelay(str, delay) +} + +// Deprecated: use the ScaledF(), +// +// Scale get the screen scale (only windows old), drop +func Scale() int { + dpi := map[int]int{ + 0: 100, + // DPI Scaling Level + 96: 100, + 120: 125, + 144: 150, + 168: 175, + 192: 200, + 216: 225, + // Custom DPI + 240: 250, + 288: 300, + 384: 400, + 480: 500, + } + + x := ScaleX() + return dpi[x] +} + +// Deprecated: use the ScaledF(), +// +// Scale0 return ScaleX() / 0.96, drop +func Scale0() int { + return int(float64(ScaleX()) / 0.96) +} + +// Deprecated: use the ScaledF(), +// +// Mul mul the scale, drop +func Mul(x int) int { + s := Scale() + return x * s / 100 +} diff --git a/robotgo_mac_win.go b/robotgo_mac_win.go index e1fe1673..ec31e581 100644 --- a/robotgo_mac_win.go +++ b/robotgo_mac_win.go @@ -16,8 +16,8 @@ package robotgo // GetBounds get the window bounds func GetBounds(pid int, args ...int) (int, int, int, int) { var isPid int - if len(args) > 0 { - isPid = args[0] + if len(args) > 0 || NotPid { + isPid = 1 } return internalGetBounds(pid, isPid) @@ -26,8 +26,8 @@ func GetBounds(pid int, args ...int) (int, int, int, int) { // GetClient get the window client bounds func GetClient(pid int, args ...int) (int, int, int, int) { var isPid int - if len(args) > 0 { - isPid = args[0] + if len(args) > 0 || NotPid { + isPid = 1 } return internalGetClient(pid, isPid) @@ -36,8 +36,8 @@ func GetClient(pid int, args ...int) (int, int, int, int) { // internalGetTitle get the window title func internalGetTitle(pid int, args ...int) string { var isPid int - if len(args) > 0 { - isPid = args[0] + if len(args) > 0 || NotPid { + isPid = 1 } gtitle := cgetTitle(pid, isPid) @@ -54,8 +54,8 @@ func internalGetTitle(pid int, args ...int) string { // robotgo.ActivePid(ids[0]) func ActivePid(pid int, args ...int) error { var isPid int - if len(args) > 0 { - isPid = args[0] + if len(args) > 0 || NotPid { + isPid = 1 } internalActive(pid, isPid) diff --git a/robotgo_x11.go b/robotgo_x11.go index 4aba5a31..26355a18 100644 --- a/robotgo_x11.go +++ b/robotgo_x11.go @@ -29,8 +29,8 @@ var xu *xgbutil.XUtil // GetBounds get the window bounds func GetBounds(pid int, args ...int) (int, int, int, int) { var isPid int - if len(args) > 0 { - isPid = args[0] + if len(args) > 0 || NotPid { + isPid = 1 return internalGetBounds(pid, isPid) } @@ -46,8 +46,8 @@ func GetBounds(pid int, args ...int) (int, int, int, int) { // GetClient get the window client bounds func GetClient(pid int, args ...int) (int, int, int, int) { var isPid int - if len(args) > 0 { - isPid = args[0] + if len(args) > 0 || NotPid { + isPid = 1 return internalGetClient(pid, isPid) } @@ -63,8 +63,8 @@ func GetClient(pid int, args ...int) (int, int, int, int) { // internalGetTitle get the window title func internalGetTitle(pid int, args ...int) string { var isPid int - if len(args) > 0 { - isPid = args[0] + if len(args) > 0 || NotPid { + isPid = 1 return cgetTitle(pid, isPid) } @@ -81,8 +81,8 @@ func internalGetTitle(pid int, args ...int) string { // If args[0] > 0 on the unix platform via a xid to active func ActivePidC(pid int, args ...int) error { var isPid int - if len(args) > 0 { - isPid = args[0] + if len(args) > 0 || NotPid { + isPid = 1 internalActive(pid, isPid) return nil } From bb76af18f092c116a773f7cc866666f9dd7c2efd Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 22 Jan 2023 18:34:03 -0800 Subject: [PATCH 260/327] Add: add mouse of scale support and optimize the multi screen --- mouse/mouse_c.h | 22 +++++++++------------- robotgo.go | 29 ++++++++++++++++++++++------- robotgo_fn_v1.go | 6 +++--- screen/screen_c.h | 17 +++++++++-------- 4 files changed, 43 insertions(+), 31 deletions(-) diff --git a/mouse/mouse_c.h b/mouse/mouse_c.h index f273fbd9..d7d11b07 100644 --- a/mouse/mouse_c.h +++ b/mouse/mouse_c.h @@ -101,7 +101,7 @@ void moveMouse(MMPointInt32 point){ #define MOUSE_COORD_TO_ABS(coord, width_or_height) ( \ ((65536 * coord) / width_or_height) + (coord < 0 ? -1 : 1)) - MMRectInt32 rect = getScreenRect(-1); + MMRectInt32 rect = getScreenRect(1); int32_t x = MOUSE_COORD_TO_ABS(point.x - rect.origin.x, rect.size.w); int32_t y = MOUSE_COORD_TO_ABS(point.y - rect.origin.y, rect.size.h); @@ -239,12 +239,8 @@ void scrollMouseXY(int x, int y) { int xdir = 6; Display *display = XGetMainDisplay(); - if (y < 0) { - ydir = 5; - } - if (x < 0) { - xdir = 7; - } + if (y < 0) { ydir = 5; } + if (x < 0) { xdir = 7; } int xi; int yi; for (xi = 0; xi < abs(x); xi++) { @@ -299,7 +295,7 @@ static double crude_hypot(double x, double y){ bool smoothlyMoveMouse(MMPointInt32 endPoint, double lowSpeed, double highSpeed){ MMPointInt32 pos = location(); - MMSizeInt32 screenSize = getMainDisplaySize(); + // MMSizeInt32 screenSize = getMainDisplaySize(); double velo_x = 0.0, velo_y = 0.0; double distance; @@ -315,13 +311,13 @@ bool smoothlyMoveMouse(MMPointInt32 endPoint, double lowSpeed, double highSpeed) velo_x /= veloDistance; velo_y /= veloDistance; - pos.x += floor(velo_x + 0.5); - pos.y += floor(velo_y + 0.5); + pos.x += floor(velo_x + 0.8); + pos.y += floor(velo_y + 0.8); /* Make sure we are in the screen boundaries! (Strange things will happen if we are not.) */ - if (pos.x >= screenSize.w || pos.y >= screenSize.h) { - return false; - } + // if (pos.x >= screenSize.w || pos.y >= screenSize.h) { + // return false; + // } moveMouse(pos); /* Wait 1 - 3 milliseconds. */ diff --git a/robotgo.go b/robotgo.go index 05d569db..cbd143da 100644 --- a/robotgo.go +++ b/robotgo.go @@ -75,6 +75,8 @@ var ( // NotPid used the hwnd not pid in windows NotPid bool + // Scale option the os screen scale + Scale bool ) type ( @@ -253,7 +255,7 @@ func SysScale(displayId ...int) float64 { return float64(s) } -// Scaled get the screen scaled size +// Scaled get the screen scaled return scale size func Scaled(x int, displayId ...int) int { f := ScaleF(displayId...) return Scaled0(x, f) @@ -282,7 +284,8 @@ func GetScreenRect(displayId ...int) Rect { int(rect.size.w), int(rect.size.h) if runtime.GOOS == "windows" { - f := ScaleF(displayId...) + // f := ScaleF(displayId...) + f := ScaleF() x, y, w, h = Scaled0(x, f), Scaled0(y, f), Scaled0(w, f), Scaled0(h, f) } return Rect{ @@ -474,17 +477,24 @@ func CheckMouse(btn string) C.MMMouseButton { return C.LEFT_BUTTON } +// MoveScale calculate the os scale factor x, y +func MoveScale(x, y int, displayId ...int) (int, int) { + if Scale && runtime.GOOS == "windows" { + f := ScaleF() + x, y = Scaled0(x, f), Scaled0(y, f) + } + + return x, y +} + // Move move the mouse to (x, y) // // Examples: // // robotgo.MouseSleep = 100 // 100 millisecond // robotgo.Move(10, 10) -func Move(x, y int) { - // if runtime.GOOS == "windows" { - // f := ScaleF() - // x, y = Scaled0(x, f), Scaled0(y, f) - // } +func Move(x, y int, displayId ...int) { + x, y = MoveScale(x, y, displayId...) cx := C.int32_t(x) cy := C.int32_t(y) @@ -498,6 +508,8 @@ func Move(x, y int) { // Drag drag the mouse to (x, y), // It's not valid now, use the DragSmooth() func Drag(x, y int, args ...string) { + x, y = MoveScale(x, y) + var button C.MMMouseButton = C.LEFT_BUTTON cx := C.int32_t(x) cy := C.int32_t(y) @@ -516,6 +528,8 @@ func Drag(x, y int, args ...string) { // // robotgo.DragSmooth(10, 10) func DragSmooth(x, y int, args ...interface{}) { + x, y = MoveScale(x, y) + Toggle("left") MilliSleep(50) MoveSmooth(x, y, args...) @@ -536,6 +550,7 @@ func MoveSmooth(x, y int, args ...interface{}) bool { // f := ScaleF() // x, y = Scaled0(x, f), Scaled0(y, f) // } + x, y = MoveScale(x, y) cx := C.int32_t(x) cy := C.int32_t(y) diff --git a/robotgo_fn_v1.go b/robotgo_fn_v1.go index 0132aef2..89cacf9d 100644 --- a/robotgo_fn_v1.go +++ b/robotgo_fn_v1.go @@ -57,8 +57,8 @@ func TypeStringDelayed(str string, delay int) { // Deprecated: use the ScaledF(), // -// Scale get the screen scale (only windows old), drop -func Scale() int { +// Scale1 get the screen scale (only windows old), drop +func Scale1() int { dpi := map[int]int{ 0: 100, // DPI Scaling Level @@ -90,6 +90,6 @@ func Scale0() int { // // Mul mul the scale, drop func Mul(x int) int { - s := Scale() + s := Scale1() return x * s / 100 } diff --git a/screen/screen_c.h b/screen/screen_c.h index bc7fba56..88dcd834 100644 --- a/screen/screen_c.h +++ b/screen/screen_c.h @@ -50,19 +50,20 @@ MMRectInt32 getScreenRect(int32_t display_id) { (int32_t)DisplayWidth(display, screen), (int32_t)DisplayHeight(display, screen)); #elif defined(IS_WINDOWS) - // if (GetSystemMetrics(SM_CMONITORS) == 1) { + if (GetSystemMetrics(SM_CMONITORS) == 1 + || display_id == -1 || display_id == 0) { return MMRectInt32Make( (int32_t)0, (int32_t)0, (int32_t)GetSystemMetrics(SM_CXSCREEN), (int32_t)GetSystemMetrics(SM_CYSCREEN)); - // } else { - // return MMRectInt32Make( - // (int32_t)GetSystemMetrics(SM_XVIRTUALSCREEN), - // (int32_t)GetSystemMetrics(SM_YVIRTUALSCREEN), - // (int32_t)GetSystemMetrics(SM_CXVIRTUALSCREEN), - // (int32_t)GetSystemMetrics(SM_CYVIRTUALSCREEN)); - // } + } else { + return MMRectInt32Make( + (int32_t)GetSystemMetrics(SM_XVIRTUALSCREEN), + (int32_t)GetSystemMetrics(SM_YVIRTUALSCREEN), + (int32_t)GetSystemMetrics(SM_CXVIRTUALSCREEN), + (int32_t)GetSystemMetrics(SM_CYVIRTUALSCREEN)); + } #endif } From 23d3df9027e92444e350cacf908993ae9ed703e3 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 22 Jan 2023 18:38:28 -0800 Subject: [PATCH 261/327] Update: update examples --- examples/scale/main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/scale/main.go b/examples/scale/main.go index d2baae48..458dc43d 100644 --- a/examples/scale/main.go +++ b/examples/scale/main.go @@ -17,8 +17,8 @@ func main() { // robotgo.SaveBitmap(bitmap, "test.png") robotgo.Save(robotgo.ToImage(bitmap), "test.png") - sx := robotgo.ScaleX() - s := robotgo.Scale() + sx := robotgo.ScaleX() // Deprecated + s := robotgo.Scale1() // Deprecated, use the ScaleF() function robotx, roboty := 35*s/100, 25*s/100 fmt.Println("scale: ", sx, s, " pos: ", robotx, roboty) From 73a40e786170e7ed1da3896185f14b475daf958d Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 23 Jan 2023 18:14:28 -0800 Subject: [PATCH 262/327] Add: add more capture screens hot support and fixed bug --- go.mod | 3 +++ go.sum | 6 ++++++ mouse/mouse_c.h | 4 ++-- robotgo.go | 6 ++++-- screen.go | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 67 insertions(+), 4 deletions(-) create mode 100644 screen.go diff --git a/go.mod b/go.mod index 6cd39bac..aaa74616 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/go-vgo/robotgo go 1.17 require ( + github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329 github.com/lxn/win v0.0.0-20210218163916-a377121e959e github.com/otiai10/gosseract v2.2.1+incompatible // github.com/robotn/gohook v0.31.3 @@ -16,7 +17,9 @@ require ( ) require ( + github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5 // indirect github.com/go-ole/go-ole v1.2.6 // indirect + github.com/jezek/xgb v0.0.0-20210312150743-0e0f116e1240 // indirect github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c // indirect github.com/otiai10/mint v1.3.0 // indirect github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c // indirect diff --git a/go.sum b/go.sum index c8c887a2..13abb3b5 100644 --- a/go.sum +++ b/go.sum @@ -3,11 +3,17 @@ github.com/BurntSushi/graphics-go v0.0.0-20160129215708-b43f31a4a966/go.mod h1:M github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5 h1:Y5Q2mEwfzjMt5+3u70Gtw93ZOu2UuPeeeTBDntF7FoY= +github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5/go.mod h1:uF6rMu/1nvu+5DpiRLwusA6xB8zlkNoGzKn8lmYONUo= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/jezek/xgb v0.0.0-20210312150743-0e0f116e1240 h1:dy+DS31tGEGCsZzB45HmJJNHjur8GDgtRNX9U7HnSX4= +github.com/jezek/xgb v0.0.0-20210312150743-0e0f116e1240/go.mod h1:3P4UH/k22rXyHIJD2w4h2XMqPX4Of/eySEZq9L6wqc4= +github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329 h1:qq2nCpSrXrmvDGRxW0ruW9BVEV1CN2a9YDOExdt+U0o= +github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329/go.mod h1:2VPVQDR4wO7KXHwP+DAypEy67rXf+okUx2zjgpCxZw4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c h1:VtwQ41oftZwlMnOEbMWQtSEUgU64U4s+GHk7hZK+jtY= github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE= diff --git a/mouse/mouse_c.h b/mouse/mouse_c.h index d7d11b07..c46b1c35 100644 --- a/mouse/mouse_c.h +++ b/mouse/mouse_c.h @@ -311,8 +311,8 @@ bool smoothlyMoveMouse(MMPointInt32 endPoint, double lowSpeed, double highSpeed) velo_x /= veloDistance; velo_y /= veloDistance; - pos.x += floor(velo_x + 0.8); - pos.y += floor(velo_y + 0.8); + pos.x += floor(velo_x + 0.5); + pos.y += floor(velo_y + 0.5); /* Make sure we are in the screen boundaries! (Strange things will happen if we are not.) */ // if (pos.x >= screenSize.w || pos.y >= screenSize.h) { diff --git a/robotgo.go b/robotgo.go index cbd143da..505ee6f8 100644 --- a/robotgo.go +++ b/robotgo.go @@ -324,8 +324,10 @@ func CaptureScreen(args ...int) CBitmap { } else { // Get the main screen rect. rect := GetScreenRect(displayId) - // x = C.int32_t(rect.X) - // y = C.int32_t(rect.Y) + if runtime.GOOS == "windows" { + x = C.int32_t(rect.X) + y = C.int32_t(rect.Y) + } w = C.int32_t(rect.W) h = C.int32_t(rect.H) } diff --git a/screen.go b/screen.go new file mode 100644 index 00000000..e0eca41e --- /dev/null +++ b/screen.go @@ -0,0 +1,52 @@ +// Copyright 2016 The go-vgo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// https://github.com/go-vgo/robotgo/blob/master/LICENSE +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +package robotgo + +import ( + "image" + + "github.com/kbinani/screenshot" +) + +// GetScreenBound gets the display screen bounds +func GetDisplayBounds(i int) (x, y, w, h int) { + bs := screenshot.GetDisplayBounds(i) + return bs.Min.X, bs.Min.Y, bs.Dx(), bs.Dy() +} + +// GetDisplayBounds gets the display rect +func GetDisplayRect(i int) Rect { + x, y, w, h := GetDisplayBounds(i) + return Rect{ + Point{X: x, Y: y}, + Size{W: w, H: h}} +} + +// Capture capture the screenshot +func Capture(args ...int) (*image.RGBA, error) { + displayId := 0 + if DisplayID != -1 { + displayId = DisplayID + } + + if len(args) > 4 { + displayId = args[4] + } + + var x, y, w, h int + if len(args) > 3 { + x, y, w, h = args[0], args[1], args[2], args[3] + } else { + x, y, w, h = GetDisplayBounds(displayId) + } + + return screenshot.Capture(x, y, w, h) +} From dd149367b3a26bf89adabd56311e5d02224bd1f9 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 1 Feb 2023 10:25:11 -0800 Subject: [PATCH 263/327] Update: update and add more examples --- examples/scale/main.go | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/examples/scale/main.go b/examples/scale/main.go index 458dc43d..704c75b8 100644 --- a/examples/scale/main.go +++ b/examples/scale/main.go @@ -7,16 +7,30 @@ import ( ) func main() { - // // syscall.NewLazyDLL("user32.dll").NewProc("SetProcessDPIAware").Call() width, height := robotgo.GetScaleSize() fmt.Println("get scale screen size: ", width, height) bitmap := robotgo.CaptureScreen(0, 0, width, height) - // robotgo.SaveBitmap(bitmap, "test.png") + defer robotgo.FreeBitmap(bitmap) + // bitmap.Save(bitmap, "test.png") robotgo.Save(robotgo.ToImage(bitmap), "test.png") + robotgo.Scale = true + robotgo.Move(10, 10) + robotgo.MoveSmooth(100, 100) + + fmt.Println(robotgo.Location()) + + num := robotgo.DisplaysNum() + for i := 0; i < num; i++ { + rect := robotgo.GetScreenRect(i) + fmt.Println("rect: ", rect) + } +} + +func old() { sx := robotgo.ScaleX() // Deprecated s := robotgo.Scale1() // Deprecated, use the ScaleF() function robotx, roboty := 35*s/100, 25*s/100 @@ -28,7 +42,8 @@ func main() { rx, ry, rw, rh := sx, sy, robotx, roboty // bit1 := robotgo.CaptureScreen(10, 20, robotw, roboth) bit1 := robotgo.CaptureScreen(rx, ry, rw, rh) - // robotgo.SaveBitmap(bit1, "test2.png") + defer robotgo.FreeBitmap(bit1) + // bitmap.Save(bit1, "test2.png") robotgo.Save(robotgo.ToImage(bit1), "test2.png") clo := robotgo.GetPixelColor(robotx, roboty) From f47571eaae3f493b324f5b0bebbe625fc38ecf23 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 1 Feb 2023 10:28:17 -0800 Subject: [PATCH 264/327] Update: update examples --- examples/screen/main.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/screen/main.go b/examples/screen/main.go index aaa04afa..4bffafe9 100644 --- a/examples/screen/main.go +++ b/examples/screen/main.go @@ -20,7 +20,9 @@ import ( func bitmap() { bit := robotgo.CaptureScreen() + defer robotgo.FreeBitmap(bit) fmt.Println("abitMap...", bit) + gbit := robotgo.ToBitmap(bit) fmt.Println("bitmap...", gbit.Width) From c8d35acd249f00c180ea00cecddb8d346f0c012e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Feb 2023 14:43:17 +0000 Subject: [PATCH 265/327] Bump golang.org/x/image from 0.1.0 to 0.5.0 Bumps [golang.org/x/image](https://github.com/golang/image) from 0.1.0 to 0.5.0. - [Release notes](https://github.com/golang/image/releases) - [Commits](https://github.com/golang/image/compare/v0.1.0...v0.5.0) --- updated-dependencies: - dependency-name: golang.org/x/image dependency-type: indirect ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index aaa74616..8b61f8c7 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/vcaesar/imgo v0.30.1 github.com/vcaesar/keycode v0.10.0 github.com/vcaesar/tt v0.20.0 - golang.org/x/image v0.1.0 // indirect + golang.org/x/image v0.5.0 // indirect ) require ( diff --git a/go.sum b/go.sum index 13abb3b5..4602dd6c 100644 --- a/go.sum +++ b/go.sum @@ -62,8 +62,8 @@ github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/image v0.1.0 h1:r8Oj8ZA2Xy12/b5KZYj3tuv7NG/fBz3TwQVvpJ9l8Rk= -golang.org/x/image v0.1.0/go.mod h1:iyPr49SD/G/TBxYVB/9RRtGUT5eNbo2u4NamWeQcD5c= +golang.org/x/image v0.5.0 h1:5JMiNunQeQw++mMOz48/ISeNu3Iweh/JaZU8ZLqHRrI= +golang.org/x/image v0.5.0/go.mod h1:FVC7BI/5Ym8R25iw5OLsgshdUBbT1h5jZTpA+mvAdZ4= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= @@ -88,7 +88,7 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= From cc6f1934f9594d776d4ec976b92069db0b47bc04 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sat, 18 Feb 2023 09:28:58 -0800 Subject: [PATCH 266/327] Update: bump go CI to 1.20.x --- .circleci/config.yml | 2 +- .github/workflows/go.yml | 4 ++-- appveyor.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6bf42fea..068162c5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,7 +5,7 @@ jobs: docker: # using custom image, see .circleci/images/primary/Dockerfile # - image: govgo/robotgoci:1.10.3 - - image: golang:1.19.4 + - image: golang:1.20.1 working_directory: /gopath/src/github.com/go-vgo/robotgo steps: - checkout diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index dd31edad..e9ecb352 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -10,10 +10,10 @@ jobs: runs-on: ${{ matrix.os }} steps: - - name: Set up Go 1.19 + - name: Set up Go 1.20 uses: actions/setup-go@v1 with: - go-version: 1.19 + go-version: 1.20 id: go - name: Check out code into the Go module directory diff --git a/appveyor.yml b/appveyor.yml index c667add4..9f467456 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,7 +34,7 @@ environment: PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% # - COMPILER: MINGW_W64 # ARCHITECTURE: x64 - GOVERSION: 1.19.4 + GOVERSION: 1.20.1 # GOPATH: c:\gopath # scripts that run after cloning repository From 6a2ffab6258a51ba691edb81002a52f86a8dbe44 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 22 Feb 2023 09:59:50 -0800 Subject: [PATCH 267/327] Update: update go mod --- go.mod | 18 +++++++++--------- go.sum | 25 +++++++++++++++---------- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/go.mod b/go.mod index 8b61f8c7..2b63feb0 100644 --- a/go.mod +++ b/go.mod @@ -3,31 +3,31 @@ module github.com/go-vgo/robotgo go 1.17 require ( - github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329 github.com/lxn/win v0.0.0-20210218163916-a377121e959e github.com/otiai10/gosseract v2.2.1+incompatible // github.com/robotn/gohook v0.31.3 github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 github.com/vcaesar/gops v0.30.0 - github.com/vcaesar/imgo v0.30.1 + github.com/vcaesar/imgo v0.30.2 github.com/vcaesar/keycode v0.10.0 github.com/vcaesar/tt v0.20.0 - golang.org/x/image v0.5.0 // indirect ) require ( - github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5 // indirect + github.com/gen2brain/shm v0.0.0-20221026125803-c33c9e32b1c8 // indirect github.com/go-ole/go-ole v1.2.6 // indirect - github.com/jezek/xgb v0.0.0-20210312150743-0e0f116e1240 // indirect - github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c // indirect + github.com/jezek/xgb v1.1.0 // indirect + github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329 + github.com/lufia/plan9stats v0.0.0-20230110061619-bbe2e5e100de // indirect github.com/otiai10/mint v1.3.0 // indirect - github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c // indirect - github.com/shirou/gopsutil/v3 v3.22.10 // indirect + github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect + github.com/shirou/gopsutil/v3 v3.23.1 // indirect github.com/tklauser/go-sysconf v0.3.11 // indirect github.com/tklauser/numcpus v0.6.0 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect - golang.org/x/sys v0.2.0 // indirect + golang.org/x/image v0.5.0 // indirect + golang.org/x/sys v0.5.0 // indirect ) // replace golang.org/x/sys => github.com/golang/sys v0.0.0-20190109145017-48ac38b7c8cb diff --git a/go.sum b/go.sum index 4602dd6c..08c84a63 100644 --- a/go.sum +++ b/go.sum @@ -3,20 +3,23 @@ github.com/BurntSushi/graphics-go v0.0.0-20160129215708-b43f31a4a966/go.mod h1:M github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5 h1:Y5Q2mEwfzjMt5+3u70Gtw93ZOu2UuPeeeTBDntF7FoY= github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5/go.mod h1:uF6rMu/1nvu+5DpiRLwusA6xB8zlkNoGzKn8lmYONUo= +github.com/gen2brain/shm v0.0.0-20221026125803-c33c9e32b1c8 h1:u4/UVF0sNxlqDwCptjIUTUkZW4UoZDrcHzvd2kNnF/k= +github.com/gen2brain/shm v0.0.0-20221026125803-c33c9e32b1c8/go.mod h1:uF6rMu/1nvu+5DpiRLwusA6xB8zlkNoGzKn8lmYONUo= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/jezek/xgb v0.0.0-20210312150743-0e0f116e1240 h1:dy+DS31tGEGCsZzB45HmJJNHjur8GDgtRNX9U7HnSX4= github.com/jezek/xgb v0.0.0-20210312150743-0e0f116e1240/go.mod h1:3P4UH/k22rXyHIJD2w4h2XMqPX4Of/eySEZq9L6wqc4= +github.com/jezek/xgb v1.1.0 h1:wnpxJzP1+rkbGclEkmwpVFQWpuE2PUGNUzP8SbfFobk= +github.com/jezek/xgb v1.1.0/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk= github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329 h1:qq2nCpSrXrmvDGRxW0ruW9BVEV1CN2a9YDOExdt+U0o= github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329/go.mod h1:2VPVQDR4wO7KXHwP+DAypEy67rXf+okUx2zjgpCxZw4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= -github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c h1:VtwQ41oftZwlMnOEbMWQtSEUgU64U4s+GHk7hZK+jtY= github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE= +github.com/lufia/plan9stats v0.0.0-20230110061619-bbe2e5e100de h1:V53FWzU6KAZVi1tPp5UIsMoUWJ2/PNwYIDXnu7QuBCE= +github.com/lufia/plan9stats v0.0.0-20230110061619-bbe2e5e100de/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE= github.com/lxn/win v0.0.0-20210218163916-a377121e959e h1:H+t6A/QJMbhCSEH5rAuRxh+CtW96g0Or0Fxa9IKr4uc= github.com/lxn/win v0.0.0-20210218163916-a377121e959e/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= @@ -27,14 +30,16 @@ github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT9 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= -github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c h1:NRoLoZvkBTKvR5gQLgA3e0hqjkY9u1wm+iOL45VN/qI= github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b h1:0LFwY6Q3gMACTjAbMZBjXAqTOzOwFaj2Ld6cjeQ7Rig= +github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 h1:2lhSR8N3T6I30q096DT7/5AKEIcf1vvnnWAmS0wfnNY= github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934/go.mod h1:SxQhJskUJ4rleVU44YvnrdvxQr0tKy5SRSigBrCgyyQ= github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 h1:2uX8QRLkkxn2EpAQ6I3KhA79BkdRZfvugJUzJadiJwk= github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770/go.mod h1:svkDXUDQjUiWzLrA0OZgHc4lbOts3C+uRfP6/yjwYnU= -github.com/shirou/gopsutil/v3 v3.22.10 h1:4KMHdfBRYXGF9skjDWiL4RA2N+E8dRdodU/bOZpPoVg= github.com/shirou/gopsutil/v3 v3.22.10/go.mod h1:QNza6r4YQoydyCfo6rH0blGfKahgibh4dQmV5xdFkQk= +github.com/shirou/gopsutil/v3 v3.23.1 h1:a9KKO+kGLKEvcPIs4W62v0nu3sciVDOOOPUD0Hz7z/4= +github.com/shirou/gopsutil/v3 v3.23.1/go.mod h1:NN6mnm5/0k8jw4cBfCnJtr5L7ErOTg18tMNpgFkn0hA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -50,8 +55,8 @@ github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYm github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4= github.com/vcaesar/gops v0.30.0 h1:970FznFxZP8ku0zckJRO+pI2fFhg3uJ0z+sQS0NHP4o= github.com/vcaesar/gops v0.30.0/go.mod h1:xV1wieUA4D9RaNQ8lf8AwPZ8bl+x/MM5w3SsMCr5KVs= -github.com/vcaesar/imgo v0.30.1 h1:B7QMm2mZY+SGoEvvJwNi+eAv21ptvk2YT1IbP2OzyLE= -github.com/vcaesar/imgo v0.30.1/go.mod h1:n4EluJIN/0UYYGPHBCY/BWlIjdRUdY5U6obtP2lrgdM= +github.com/vcaesar/imgo v0.30.2 h1:JUTKt9Og95RJ7ANjNtjW1NSO0jWMWxHCbryriNYooQE= +github.com/vcaesar/imgo v0.30.2/go.mod h1:8mJleCPHDTqMmyRHFFim+S+B+1ighHqAETvuf7WCnZI= github.com/vcaesar/keycode v0.10.0 h1:Qx5QE8ZXHyRyjoA2QOxBp25OKMKB+zxMVqm0FWGV0d4= github.com/vcaesar/keycode v0.10.0/go.mod h1:JNlY7xbKsh+LAGfY2j4M3znVrGEm5W1R8s/Uv6BJcfQ= github.com/vcaesar/tt v0.20.0 h1:9t2Ycb9RNHcP0WgQgIaRKJBB+FrRdejuaL6uWIHuoBA= @@ -61,7 +66,6 @@ github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPR github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= golang.org/x/image v0.5.0 h1:5JMiNunQeQw++mMOz48/ISeNu3Iweh/JaZU8ZLqHRrI= golang.org/x/image v0.5.0/go.mod h1:FVC7BI/5Ym8R25iw5OLsgshdUBbT1h5jZTpA+mvAdZ4= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -80,13 +84,14 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From e0583e83ec16b04088379cb8cec5978fc8d5443d Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 23 Feb 2023 09:54:44 -0800 Subject: [PATCH 268/327] Update: update gops mod --- go.mod | 2 +- go.sum | 10 ++-------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 2b63feb0..b32d6e3b 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( // github.com/robotn/gohook v0.31.3 github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 - github.com/vcaesar/gops v0.30.0 + github.com/vcaesar/gops v0.30.1 github.com/vcaesar/imgo v0.30.2 github.com/vcaesar/keycode v0.10.0 github.com/vcaesar/tt v0.20.0 diff --git a/go.sum b/go.sum index 08c84a63..42873fcf 100644 --- a/go.sum +++ b/go.sum @@ -17,7 +17,6 @@ github.com/jezek/xgb v1.1.0/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFl github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329 h1:qq2nCpSrXrmvDGRxW0ruW9BVEV1CN2a9YDOExdt+U0o= github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329/go.mod h1:2VPVQDR4wO7KXHwP+DAypEy67rXf+okUx2zjgpCxZw4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= -github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE= github.com/lufia/plan9stats v0.0.0-20230110061619-bbe2e5e100de h1:V53FWzU6KAZVi1tPp5UIsMoUWJ2/PNwYIDXnu7QuBCE= github.com/lufia/plan9stats v0.0.0-20230110061619-bbe2e5e100de/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE= github.com/lxn/win v0.0.0-20210218163916-a377121e959e h1:H+t6A/QJMbhCSEH5rAuRxh+CtW96g0Or0Fxa9IKr4uc= @@ -30,14 +29,12 @@ github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT9 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= -github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b h1:0LFwY6Q3gMACTjAbMZBjXAqTOzOwFaj2Ld6cjeQ7Rig= github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 h1:2lhSR8N3T6I30q096DT7/5AKEIcf1vvnnWAmS0wfnNY= github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934/go.mod h1:SxQhJskUJ4rleVU44YvnrdvxQr0tKy5SRSigBrCgyyQ= github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 h1:2uX8QRLkkxn2EpAQ6I3KhA79BkdRZfvugJUzJadiJwk= github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770/go.mod h1:svkDXUDQjUiWzLrA0OZgHc4lbOts3C+uRfP6/yjwYnU= -github.com/shirou/gopsutil/v3 v3.22.10/go.mod h1:QNza6r4YQoydyCfo6rH0blGfKahgibh4dQmV5xdFkQk= github.com/shirou/gopsutil/v3 v3.23.1 h1:a9KKO+kGLKEvcPIs4W62v0nu3sciVDOOOPUD0Hz7z/4= github.com/shirou/gopsutil/v3 v3.23.1/go.mod h1:NN6mnm5/0k8jw4cBfCnJtr5L7ErOTg18tMNpgFkn0hA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -47,14 +44,12 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk= github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM= github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI= -github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ= github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms= github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4= -github.com/vcaesar/gops v0.30.0 h1:970FznFxZP8ku0zckJRO+pI2fFhg3uJ0z+sQS0NHP4o= -github.com/vcaesar/gops v0.30.0/go.mod h1:xV1wieUA4D9RaNQ8lf8AwPZ8bl+x/MM5w3SsMCr5KVs= +github.com/vcaesar/gops v0.30.1 h1:MmTJhcCz0xTLSxOv4bmqbXQBPYVZpFLDzwN9Jdp/FR0= +github.com/vcaesar/gops v0.30.1/go.mod h1:F/8aazx2wGZ69ruziZcNGnlq/rehITYTqZ6ewVLDiyk= github.com/vcaesar/imgo v0.30.2 h1:JUTKt9Og95RJ7ANjNtjW1NSO0jWMWxHCbryriNYooQE= github.com/vcaesar/imgo v0.30.2/go.mod h1:8mJleCPHDTqMmyRHFFim+S+B+1ighHqAETvuf7WCnZI= github.com/vcaesar/keycode v0.10.0 h1:Qx5QE8ZXHyRyjoA2QOxBp25OKMKB+zxMVqm0FWGV0d4= @@ -81,7 +76,6 @@ golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= From 9afa31112114a64953e99d393ddf4f30c6bc1da5 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 27 Feb 2023 09:35:35 -0800 Subject: [PATCH 269/327] Add: add the GetDesktopWindow and scale support --- robotgo_win.go | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/robotgo_win.go b/robotgo_win.go index 1f9c6e64..b8031450 100644 --- a/robotgo_win.go +++ b/robotgo_win.go @@ -67,20 +67,31 @@ func GetMainId() int { return int(GetMain()) } -// ScaleF get the system scale val +// ScaleF get the system scale value +// if "displayId == -2" this function will get the desktop scale value func ScaleF(displayId ...int) (f float64) { if len(displayId) > 0 && displayId[0] != -1 { dpi := GetDPI(win.HWND(displayId[0])) f = float64(dpi) / 96.0 } else { - f = float64(GetMainDPI()) / 96.0 + if displayId == -2 { + f = float64(GetDPI(GetDesktopWindow())) / 96.0 + } else { + f = float64(GetMainDPI()) / 96.0 + } } + if f == 0.0 { f = 1.0 } return f } +// GetDesktopWindow get the desktop window hwnd id +func GetDesktopWindow() win.HWND { + return win.GetDesktopWindow() +} + // GetMainDPI get the display dpi func GetMainDPI() int { return int(GetDPI(GetHWND())) From 01212c568407d752c42443c582914bb6dbab856c Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 27 Feb 2023 09:49:26 -0800 Subject: [PATCH 270/327] Fixed: fixed code and CI --- robotgo_win.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/robotgo_win.go b/robotgo_win.go index b8031450..d2208bca 100644 --- a/robotgo_win.go +++ b/robotgo_win.go @@ -71,14 +71,16 @@ func GetMainId() int { // if "displayId == -2" this function will get the desktop scale value func ScaleF(displayId ...int) (f float64) { if len(displayId) > 0 && displayId[0] != -1 { - dpi := GetDPI(win.HWND(displayId[0])) - f = float64(dpi) / 96.0 - } else { - if displayId == -2 { + if displayId[0] >= 0 { + dpi := GetDPI(win.HWND(displayId[0])) + f = float64(dpi) / 96.0 + } + + if displayId[0] == -2 { f = float64(GetDPI(GetDesktopWindow())) / 96.0 - } else { - f = float64(GetMainDPI()) / 96.0 } + } else { + f = float64(GetMainDPI()) / 96.0 } if f == 0.0 { From 4140463ed108842cc1b42b4bb8a3902d9f50b56d Mon Sep 17 00:00:00 2001 From: Weilong Wang Date: Fri, 10 Mar 2023 15:12:21 +0800 Subject: [PATCH 271/327] Update README.md, add type conversion list. --- README.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/README.md b/README.md index b7319a99..ce14fb11 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ RobotGo supports Mac, Windows, and Linux(X11); and robotgo supports arm64 and x8 - [Installation](#installation) - [Update](#update) - [Examples](#examples) +- [Type Conversion](#type-conversion) - [Cross-Compiling](#crosscompiling) - [Authors](#authors) - [Plans](#plans) @@ -487,6 +488,28 @@ func main() { } ``` +## Type Conversion + +| | type conversion | func +|-----|---------------------|---------------------- +| * | robotgo.Bitmap -> robotgo.CBitmap | robotgo.ToCBitmap() +| | robotgo.Bitmap -> *image.RGBA | robotgo.ToRGBAGo() +| * | robotgo.CBitmap -> C.MMBitmapRef | robotgo.ToMMBitmapRef() +| | robotgo.CBitmap -> robotgo.Bitmap | robotgo.ToBitmap() +| | robotgo.CBitmap -> image.Image | robotgo.ToImage() +| | robotgo.CBitmap -> *image.RGBA | robotgo.ToRGBA() +| * | C.MMBitmapRef -> robotgo.CBitmap | robotgo.CBitmap() +| * | image.Image -> robotgo.Bitmap | robotgo.ImgToBitmap() +| | image.Image -> robotgo.CBitmap | robotgo.ImgToCBitmap() +| | image.Image -> []byte | robotgo.ToByteImg() +| | image.Image -> string | robotgo.ToStringImg() +| * | *image.RGBA -> robotgo.Bitmap | robotgo.RGBAToBitmap() +| * | []byte -> image.Image | robotgo.ByteToImg() +| | []byte-> robotgo.CBitmap | robotgo.ByteToCBitmap() +| | []byte -> string | string() +| * | string -> image.Image | robotgo.StrToImg() +| | string -> byte | []byte() + ## CrossCompiling ##### Windows64 to windows32 From cbca6d08c719a7466756b40c220edf0132025f50 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sat, 11 Mar 2023 08:51:29 -0800 Subject: [PATCH 272/327] Update: move type conversion to key.md and update godoc --- README.md | 24 +----------------------- docs/keys.md | 24 +++++++++++++++++++++++- key.go | 4 ++-- robotgo.go | 6 +++++- 4 files changed, 31 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index ce14fb11..d608c4ed 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ RobotGo supports Mac, Windows, and Linux(X11); and robotgo supports arm64 and x8 - [Installation](#installation) - [Update](#update) - [Examples](#examples) -- [Type Conversion](#type-conversion) +- [Type Conversion and keys](https://github.com/go-vgo/robotgo/blob/master/docs/keys.md) - [Cross-Compiling](#crosscompiling) - [Authors](#authors) - [Plans](#plans) @@ -488,28 +488,6 @@ func main() { } ``` -## Type Conversion - -| | type conversion | func -|-----|---------------------|---------------------- -| * | robotgo.Bitmap -> robotgo.CBitmap | robotgo.ToCBitmap() -| | robotgo.Bitmap -> *image.RGBA | robotgo.ToRGBAGo() -| * | robotgo.CBitmap -> C.MMBitmapRef | robotgo.ToMMBitmapRef() -| | robotgo.CBitmap -> robotgo.Bitmap | robotgo.ToBitmap() -| | robotgo.CBitmap -> image.Image | robotgo.ToImage() -| | robotgo.CBitmap -> *image.RGBA | robotgo.ToRGBA() -| * | C.MMBitmapRef -> robotgo.CBitmap | robotgo.CBitmap() -| * | image.Image -> robotgo.Bitmap | robotgo.ImgToBitmap() -| | image.Image -> robotgo.CBitmap | robotgo.ImgToCBitmap() -| | image.Image -> []byte | robotgo.ToByteImg() -| | image.Image -> string | robotgo.ToStringImg() -| * | *image.RGBA -> robotgo.Bitmap | robotgo.RGBAToBitmap() -| * | []byte -> image.Image | robotgo.ByteToImg() -| | []byte-> robotgo.CBitmap | robotgo.ByteToCBitmap() -| | []byte -> string | string() -| * | string -> image.Image | robotgo.StrToImg() -| | string -> byte | []byte() - ## CrossCompiling ##### Windows64 to windows32 diff --git a/docs/keys.md b/docs/keys.md index dff9e228..cedc4fdf 100644 --- a/docs/keys.md +++ b/docs/keys.md @@ -1,3 +1,25 @@ +## Type Conversion + +| | type conversion | func | +| --- | --------------------------------- | ----------------------- | +| \* | robotgo.Bitmap -> robotgo.CBitmap | robotgo.ToCBitmap() | +| | robotgo.Bitmap -> \*image.RGBA | robotgo.ToRGBAGo() | +| \* | robotgo.CBitmap -> C.MMBitmapRef | robotgo.ToMMBitmapRef() | +| | robotgo.CBitmap -> robotgo.Bitmap | robotgo.ToBitmap() | +| | robotgo.CBitmap -> image.Image | robotgo.ToImage() | +| | robotgo.CBitmap -> \*image.RGBA | robotgo.ToRGBA() | +| \* | C.MMBitmapRef -> robotgo.CBitmap | robotgo.CBitmap() | +| \* | image.Image -> robotgo.Bitmap | robotgo.ImgToBitmap() | +| | image.Image -> robotgo.CBitmap | robotgo.ImgToCBitmap() | +| | image.Image -> []byte | robotgo.ToByteImg() | +| | image.Image -> string | robotgo.ToStringImg() | +| \* | \*image.RGBA -> robotgo.Bitmap | robotgo.RGBAToBitmap() | +| \* | []byte -> image.Image | robotgo.ByteToImg() | +| | []byte-> robotgo.CBitmap | robotgo.ByteToCBitmap() | +| | []byte -> string | string() | +| \* | string -> image.Image | robotgo.StrToImg() | +| | string -> byte | []byte() | + # Keys ```Go @@ -118,4 +140,4 @@ "lights_kbd_toggle" Toggle keyboard backlight on/off No Windows support "lights_kbd_up" Turn up keyboard backlight brightness No Windows support "lights_kbd_down" Turn down keyboard backlight brightness No Windows support -``` \ No newline at end of file +``` diff --git a/key.go b/key.go index 3cfd588a..15e85e6c 100644 --- a/key.go +++ b/key.go @@ -482,7 +482,7 @@ func toErr(str *C.char) error { // KeyTap taps the keyboard code; // -// See keys: +// See keys supported: // // https://github.com/go-vgo/robotgo/blob/master/docs/keys.md // @@ -613,7 +613,7 @@ func CharCodeAt(s string, n int) rune { return 0 } -// UnicodeType tap uint32 unicode +// UnicodeType tap the uint32 unicode func UnicodeType(str uint32, args ...int) { cstr := C.uint(str) pid := 0 diff --git a/robotgo.go b/robotgo.go index 505ee6f8..4c97069a 100644 --- a/robotgo.go +++ b/robotgo.go @@ -88,7 +88,11 @@ type ( CBitmap C.MMBitmapRef ) -// Bitmap is Bitmap struct +// Bitmap define the go Bitmap struct +// +// The common type conversion of bitmap: +// +// https://github.com/go-vgo/robotgo/blob/master/docs/keys.md type Bitmap struct { ImgBuf *uint8 Width, Height int From ffcf6b26cd3022da12ed16d991de7173dc7dfd80 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 13 Mar 2023 11:07:26 -0700 Subject: [PATCH 273/327] Update: fixed windows scale move and Location(), update godoc --- key.go | 4 ++-- robotgo.go | 15 +++++++++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/key.go b/key.go index 15e85e6c..98c53425 100644 --- a/key.go +++ b/key.go @@ -484,7 +484,7 @@ func toErr(str *C.char) error { // // See keys supported: // -// https://github.com/go-vgo/robotgo/blob/master/docs/keys.md +// https://github.com/go-vgo/robotgo/blob/master/docs/keys.md#keys // // Examples: // @@ -532,7 +532,7 @@ func KeyTap(key string, args ...interface{}) error { // // See keys: // -// https://github.com/go-vgo/robotgo/blob/master/docs/keys.md +// https://github.com/go-vgo/robotgo/blob/master/docs/keys.md#keys // // Examples: // diff --git a/robotgo.go b/robotgo.go index 4c97069a..b445a8fd 100644 --- a/robotgo.go +++ b/robotgo.go @@ -92,7 +92,7 @@ type ( // // The common type conversion of bitmap: // -// https://github.com/go-vgo/robotgo/blob/master/docs/keys.md +// https://github.com/go-vgo/robotgo/blob/master/docs/keys.md#type-conversion type Bitmap struct { ImgBuf *uint8 Width, Height int @@ -270,6 +270,11 @@ func Scaled0(x int, f float64) int { return int(float64(x) * f) } +// Scaled1 return int(x / f) +func Scaled1(x int, f float64) int { + return int(float64(x) / f) +} + // GetScreenSize get the screen size func GetScreenSize() (int, int) { size := C.getMainDisplaySize() @@ -332,6 +337,7 @@ func CaptureScreen(args ...int) CBitmap { x = C.int32_t(rect.X) y = C.int32_t(rect.Y) } + w = C.int32_t(rect.W) h = C.int32_t(rect.H) } @@ -487,7 +493,7 @@ func CheckMouse(btn string) C.MMMouseButton { func MoveScale(x, y int, displayId ...int) (int, int) { if Scale && runtime.GOOS == "windows" { f := ScaleF() - x, y = Scaled0(x, f), Scaled0(y, f) + x, y = Scaled1(x, f), Scaled1(y, f) } return x, y @@ -611,6 +617,11 @@ func Location() (int, int) { x := int(pos.x) y := int(pos.y) + if runtime.GOOS == "windows" { + f := ScaleF() + x, y = Scaled0(x, f), Scaled0(y, f) + } + return x, y } From c62f7fd81ef137d446a1131db5484a77a273a144 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 9 Apr 2023 12:40:01 -0700 Subject: [PATCH 274/327] Update README.md and documents --- README.md | 60 +++++++++++-------------------------------------- docs/install.md | 33 +++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 47 deletions(-) create mode 100644 docs/install.md diff --git a/README.md b/README.md index d608c4ed..7dadb850 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ RobotGo supports Mac, Windows, and Linux(X11); and robotgo supports arm64 and x8 - [Update](#update) - [Examples](#examples) - [Type Conversion and keys](https://github.com/go-vgo/robotgo/blob/master/docs/keys.md) -- [Cross-Compiling](#crosscompiling) +- [Cross-Compiling](https://github.com/go-vgo/robotgo/blob/master/docs/install.md#crosscompiling) - [Authors](#authors) - [Plans](#plans) - [Donate](#donate) @@ -84,18 +84,13 @@ GCC X11 with the XTest extension (the Xtst library) +"Clipboard": xsel xclip -"Bitmap": -libpng (Just used by bitmap) +"Bitmap": libpng (Just used by the bitmap.) -"Event": +"Event": xcb, xkb, libxkbcommon (Just used by the hook.) -xcb, xkb, libxkbcommon - -"Clipboard": - -xsel xclip ``` ##### Ubuntu: @@ -107,29 +102,34 @@ sudo apt install gcc libc6-dev # x11 sudo apt install libx11-dev xorg-dev libxtst-dev +# Clipboard +sudo apt install xsel xclip + +# # Bitmap sudo apt install libpng++-dev # Hook sudo apt install xcb libxcb-xkb-dev x11-xkb-utils libx11-xcb-dev libxkbcommon-x11-dev libxkbcommon-dev -# Clipboard -sudo apt install xsel xclip ``` ##### Fedora: ```yml +# x11 sudo dnf install libXtst-devel +# Clipboard +sudo dnf install xsel xclip + +# # Bitmap sudo dnf install libpng-devel # Hook sudo dnf install libxkbcommon-devel libxkbcommon-x11-devel xorg-x11-xkb-utils-devel -# Clipboard -sudo dnf install xsel xclip ``` ## Installation: @@ -488,40 +488,6 @@ func main() { } ``` -## CrossCompiling - -##### Windows64 to windows32 - -```Go -SET CGO_ENABLED=1 -SET GOARCH=386 -go build main.go -``` - -#### Other to windows - -Install Requirements (Ubuntu, Just used by bitmap.): - -```bash -sudo apt install gcc-multilib -sudo apt install gcc-mingw-w64 -# fix err: zlib.h: No such file or directory -sudo apt install libz-mingw-w64-dev -``` - -Build the binary: - -```Go -GOOS=windows GOARCH=amd64 CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ go build -x ./ -``` - -``` -// CC=mingw-w64\x86_64-7.2.0-win32-seh-rt_v5-rev1\mingw64\bin\gcc.exe -// CXX=mingw-w64\x86_64-7.2.0-win32-seh-rt_v5-rev1\mingw64\bin\g++.exe -``` - -Some discussions and questions, please see [issues/228](https://github.com/go-vgo/robotgo/issues/228), [issues/143](https://github.com/go-vgo/robotgo/issues/143). - ## Authors - [The author is vz](https://github.com/vcaesar) diff --git a/docs/install.md b/docs/install.md new file mode 100644 index 00000000..47187071 --- /dev/null +++ b/docs/install.md @@ -0,0 +1,33 @@ +## CrossCompiling + +##### Windows64 to windows32 + +```Go +SET CGO_ENABLED=1 +SET GOARCH=386 +go build main.go +``` + +#### Other to windows + +Install Requirements (Ubuntu): + +```bash +sudo apt install gcc-multilib +sudo apt install gcc-mingw-w64 +# fix err: zlib.h: No such file or directory, Just used by bitmap. +sudo apt install libz-mingw-w64-dev +``` + +Build the binary: + +```Go +GOOS=windows GOARCH=amd64 CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ go build -x ./ +``` + +``` +// CC=mingw-w64\x86_64-7.2.0-win32-seh-rt_v5-rev1\mingw64\bin\gcc.exe +// CXX=mingw-w64\x86_64-7.2.0-win32-seh-rt_v5-rev1\mingw64\bin\g++.exe +``` + +Some discussions and questions, please see [issues/228](https://github.com/go-vgo/robotgo/issues/228), [issues/143](https://github.com/go-vgo/robotgo/issues/143). From 8ea126d35ba63cb2d484dd2b29a47f8ef054618c Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 9 Apr 2023 12:41:44 -0700 Subject: [PATCH 275/327] Update: Update dockerfile and CI --- .circleci/config.yml | 2 +- .circleci/images/primary/Dockerfile | 2 +- appveyor.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 068162c5..756e8d0a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,7 +5,7 @@ jobs: docker: # using custom image, see .circleci/images/primary/Dockerfile # - image: govgo/robotgoci:1.10.3 - - image: golang:1.20.1 + - image: golang:1.20.3 working_directory: /gopath/src/github.com/go-vgo/robotgo steps: - checkout diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index 01b48c93..bc83ff92 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.19.4-stretch AS build +FROM golang:1.20.3-stretch AS build # FROM govgo/go:1.11.1 RUN apt update && apt install -y --no-install-recommends \ diff --git a/appveyor.yml b/appveyor.yml index 9f467456..2c2bc645 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,7 +34,7 @@ environment: PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% # - COMPILER: MINGW_W64 # ARCHITECTURE: x64 - GOVERSION: 1.20.1 + GOVERSION: 1.20.3 # GOPATH: c:\gopath # scripts that run after cloning repository From 8e7a413ec6f8cad6b0e97810c6e006dd4920df72 Mon Sep 17 00:00:00 2001 From: Jean Raby Date: Sun, 11 Jun 2023 13:17:26 -0400 Subject: [PATCH 276/327] Fix x11 display leak (#590) * Call XCloseDisplay in all return paths Add test to confirm XOpenDisplay leak is plugged * whitespace --- robot_info_test.go | 10 +++++++++- window/pub.h | 1 + window/window.h | 10 +++++++--- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/robot_info_test.go b/robot_info_test.go index 81a244c3..93a9eb3c 100644 --- a/robot_info_test.go +++ b/robot_info_test.go @@ -43,5 +43,13 @@ func TestGetSysScale(t *testing.T) { log.Println("SysScale: ", s) f := robotgo.ScaleF() - log.Println("sclae: ", f) + log.Println("scale: ", f) +} + +func TestGetTitle(t *testing.T) { + // just exercise the function, it used to crash with a segfault + "Maximum + // number of clients reached" + for i := 0; i < 128; i++ { + robotgo.GetTitle() + } } diff --git a/window/pub.h b/window/pub.h index 2ab44625..af1158b8 100644 --- a/window/pub.h +++ b/window/pub.h @@ -191,6 +191,7 @@ typedef struct _Bounds Bounds; if (items != NULL) { *items = (uint32_t) nItems; } + XCloseDisplay(rDisplay); return result; } } diff --git a/window/window.h b/window/window.h index 35eaef5c..8e0ff69f 100644 --- a/window/window.h +++ b/window/window.h @@ -104,7 +104,10 @@ bool is_valid() { // Get the window PID property void* result = GetWindowProperty(mData, WM_PID,NULL); - if (result == NULL) { return false; } + if (result == NULL) { + XCloseDisplay(rDisplay); + return false; + } // Free result and return true XFree(result); @@ -405,6 +408,7 @@ MData get_active(void) { if (window != 0) { // Set and return the foreground window result.XWin = (Window)window; + XCloseDisplay(rDisplay); return result; } } @@ -494,13 +498,13 @@ void close_window_by_Id(MData m_data){ char* get_main_title(){ // Check if the window is valid if (!is_valid()) { return "is_valid failed."; } - + return get_title_by_hand(mData); } char* get_title_by_pid(uintptr pid, int8_t isPid){ MData win = set_handle_pid(pid, isPid); - return get_title_by_hand(win); + return get_title_by_hand(win); } char* named(void *result) { From 6fa2f418fa315a6b6fd5137ebc75a9bf56d2f854 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 5 Jul 2023 11:02:55 -0700 Subject: [PATCH 277/327] Fix: fixed typo --- examples/screen/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/screen/main.go b/examples/screen/main.go index 4bffafe9..6ea37f89 100644 --- a/examples/screen/main.go +++ b/examples/screen/main.go @@ -88,7 +88,7 @@ func screen() { fmt.Println("ScaleF: ", s1) } sx, sy = robotgo.GetScaleSize() - fmt.Println("get screen sclae size: ", sx, sy) + fmt.Println("get screen scale size: ", sx, sy) color() } From 5c3cbd6e1715d5d39ea6014a2b252d100dd99865 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 6 Jul 2023 10:14:42 -0700 Subject: [PATCH 278/327] Update: update and remove some old code --- key/keypress_c.h | 260 +++++++++++++++++++++--------------------- mouse/mouse_c.h | 96 ++++++++-------- screen/screengrab_c.h | 3 +- 3 files changed, 179 insertions(+), 180 deletions(-) diff --git a/key/keypress_c.h b/key/keypress_c.h index 6064b4a3..a606f044 100644 --- a/key/keypress_c.h +++ b/key/keypress_c.h @@ -65,100 +65,99 @@ return 0; } -static io_connect_t _getAuxiliaryKeyDriver(void) { - static mach_port_t sEventDrvrRef = 0; - mach_port_t masterPort, service, iter; - kern_return_t kr; + static io_connect_t _getAuxiliaryKeyDriver(void) { + static mach_port_t sEventDrvrRef = 0; + mach_port_t masterPort, service, iter; + kern_return_t kr; - if (!sEventDrvrRef) { - kr = IOMasterPort(bootstrap_port, &masterPort); - assert(KERN_SUCCESS == kr); - kr = IOServiceGetMatchingServices(masterPort, IOServiceMatching(kIOHIDSystemClass), &iter); - assert(KERN_SUCCESS == kr); + if (!sEventDrvrRef) { + kr = IOMasterPort(bootstrap_port, &masterPort); + assert(KERN_SUCCESS == kr); + kr = IOServiceGetMatchingServices(masterPort, IOServiceMatching(kIOHIDSystemClass), &iter); + assert(KERN_SUCCESS == kr); - service = IOIteratorNext(iter); - assert(service); - - kr = IOServiceOpen(service, mach_task_self(), kIOHIDParamConnectType, &sEventDrvrRef); - assert(KERN_SUCCESS == kr); + service = IOIteratorNext(iter); + assert(service); - IOObjectRelease(service); - IOObjectRelease(iter); - } - return sEventDrvrRef; -} -#endif + kr = IOServiceOpen(service, mach_task_self(), kIOHIDParamConnectType, &sEventDrvrRef); + assert(KERN_SUCCESS == kr); -#if defined(IS_WINDOWS) -void win32KeyEvent(int key, MMKeyFlags flags, uintptr pid, int8_t isPid) { - int scan = MapVirtualKey(key & 0xff, MAPVK_VK_TO_VSC); - - /* Set the scan code for extended keys */ - switch (key){ - case VK_RCONTROL: - case VK_SNAPSHOT: /* Print Screen */ - case VK_RMENU: /* Right Alt / Alt Gr */ - case VK_PAUSE: /* Pause / Break */ - case VK_HOME: - case VK_UP: - case VK_PRIOR: /* Page up */ - case VK_LEFT: - case VK_RIGHT: - case VK_END: - case VK_DOWN: - case VK_NEXT: /* 'Page Down' */ - case VK_INSERT: - case VK_DELETE: - case VK_LWIN: - case VK_RWIN: - case VK_APPS: /* Application */ - case VK_VOLUME_MUTE: - case VK_VOLUME_DOWN: - case VK_VOLUME_UP: - case VK_MEDIA_NEXT_TRACK: - case VK_MEDIA_PREV_TRACK: - case VK_MEDIA_STOP: - case VK_MEDIA_PLAY_PAUSE: - case VK_BROWSER_BACK: - case VK_BROWSER_FORWARD: - case VK_BROWSER_REFRESH: - case VK_BROWSER_STOP: - case VK_BROWSER_SEARCH: - case VK_BROWSER_FAVORITES: - case VK_BROWSER_HOME: - case VK_LAUNCH_MAIL: - { - flags |= KEYEVENTF_EXTENDEDKEY; - break; + IOObjectRelease(service); + IOObjectRelease(iter); } + return sEventDrvrRef; } +#elif defined(IS_WINDOWS) + + void win32KeyEvent(int key, MMKeyFlags flags, uintptr pid, int8_t isPid) { + int scan = MapVirtualKey(key & 0xff, MAPVK_VK_TO_VSC); + + /* Set the scan code for extended keys */ + switch (key){ + case VK_RCONTROL: + case VK_SNAPSHOT: /* Print Screen */ + case VK_RMENU: /* Right Alt / Alt Gr */ + case VK_PAUSE: /* Pause / Break */ + case VK_HOME: + case VK_UP: + case VK_PRIOR: /* Page up */ + case VK_LEFT: + case VK_RIGHT: + case VK_END: + case VK_DOWN: + case VK_NEXT: /* 'Page Down' */ + case VK_INSERT: + case VK_DELETE: + case VK_LWIN: + case VK_RWIN: + case VK_APPS: /* Application */ + case VK_VOLUME_MUTE: + case VK_VOLUME_DOWN: + case VK_VOLUME_UP: + case VK_MEDIA_NEXT_TRACK: + case VK_MEDIA_PREV_TRACK: + case VK_MEDIA_STOP: + case VK_MEDIA_PLAY_PAUSE: + case VK_BROWSER_BACK: + case VK_BROWSER_FORWARD: + case VK_BROWSER_REFRESH: + case VK_BROWSER_STOP: + case VK_BROWSER_SEARCH: + case VK_BROWSER_FAVORITES: + case VK_BROWSER_HOME: + case VK_LAUNCH_MAIL: + { + flags |= KEYEVENTF_EXTENDEDKEY; + break; + } + } - // todo: test this - if (pid != 0) { - HWND hwnd = getHwnd(pid, isPid); + // todo: test this + if (pid != 0) { + HWND hwnd = getHwnd(pid, isPid); - int down = (flags == 0 ? WM_KEYDOWN : WM_KEYUP); - // SendMessage(hwnd, down, key, 0); - PostMessageW(hwnd, down, key, 0); - return; - } + int down = (flags == 0 ? WM_KEYDOWN : WM_KEYUP); + // SendMessage(hwnd, down, key, 0); + PostMessageW(hwnd, down, key, 0); + return; + } - /* Set the scan code for keyup */ - // if ( flags & KEYEVENTF_KEYUP ) { - // scan |= 0x80; - // } - // keybd_event(key, scan, flags, 0); - - INPUT keyInput; - - keyInput.type = INPUT_KEYBOARD; - keyInput.ki.wVk = key; - keyInput.ki.wScan = scan; - keyInput.ki.dwFlags = flags; - keyInput.ki.time = 0; - keyInput.ki.dwExtraInfo = 0; - SendInput(1, &keyInput, sizeof(keyInput)); -} + /* Set the scan code for keyup */ + // if ( flags & KEYEVENTF_KEYUP ) { + // scan |= 0x80; + // } + // keybd_event(key, scan, flags, 0); + + INPUT keyInput; + + keyInput.type = INPUT_KEYBOARD; + keyInput.ki.wVk = key; + keyInput.ki.wScan = scan; + keyInput.ki.dwFlags = flags; + keyInput.ki.time = 0; + keyInput.ki.dwExtraInfo = 0; + SendInput(1, &keyInput, sizeof(keyInput)); + } #endif void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags, uintptr pid) { @@ -269,57 +268,27 @@ void toggleKey(char c, const bool down, MMKeyFlags flags, uintptr pid) { // } #if defined(IS_MACOSX) -void toggleUnicode(UniChar ch, const bool down, uintptr pid) { - /* This function relies on the convenient CGEventKeyboardSetUnicodeString(), - convert characters to a keycode, but does not support adding modifier flags. - It is only used in typeString(). - -- if you need modifier keys, use the above functions instead. */ - CGEventRef keyEvent = CGEventCreateKeyboardEvent(NULL, 0, down); - if (keyEvent == NULL) { - fputs("Could not create keyboard event.\n", stderr); - return; - } - - CGEventKeyboardSetUnicodeString(keyEvent, 1, &ch); - - SendTo(pid, keyEvent); -} -#endif - -#if defined(USE_X11) - #define toggleUniKey(c, down) toggleKey(c, down, MOD_NONE, 0) - - int input_utf(const char *utf) { - Display *dpy = XOpenDisplay(NULL); - KeySym sym = XStringToKeysym(utf); - // KeySym sym = XKeycodeToKeysym(dpy, utf); - - int min, max, numcodes; - XDisplayKeycodes(dpy, &min, &max); - KeySym *keysym; - keysym = XGetKeyboardMapping(dpy, min, max-min+1, &numcodes); - keysym[(max-min-1)*numcodes] = sym; - XChangeKeyboardMapping(dpy, min, numcodes, keysym, (max-min)); - XFree(keysym); - XFlush(dpy); + void toggleUnicode(UniChar ch, const bool down, uintptr pid) { + /* This function relies on the convenient CGEventKeyboardSetUnicodeString(), + convert characters to a keycode, but does not support adding modifier flags. + It is only used in typeString(). + -- if you need modifier keys, use the above functions instead. */ + CGEventRef keyEvent = CGEventCreateKeyboardEvent(NULL, 0, down); + if (keyEvent == NULL) { + fputs("Could not create keyboard event.\n", stderr); + return; + } - KeyCode code = XKeysymToKeycode(dpy, sym); - XTestFakeKeyEvent(dpy, code, True, 1); - XTestFakeKeyEvent(dpy, code, False, 1); + CGEventKeyboardSetUnicodeString(keyEvent, 1, &ch); - XFlush(dpy); - XCloseDisplay(dpy); - return 0; - } -#endif -#if !defined(USE_X11) - int input_utf(const char *utf){ - return 0; + SendTo(pid, keyEvent); } +#else + #define toggleUniKey(c, down) toggleKey(c, down, MOD_NONE, 0) #endif // unicode type -void unicodeType(const unsigned value, uintptr pid, int8_t isPid){ +void unicodeType(const unsigned value, uintptr pid, int8_t isPid) { #if defined(IS_MACOSX) UniChar ch = (UniChar)value; // Convert to unsigned char @@ -354,4 +323,33 @@ void unicodeType(const unsigned value, uintptr pid, int8_t isPid){ microsleep(5.0); toggleUniKey(value, false); #endif -} \ No newline at end of file +} + +#if defined(USE_X11) + int input_utf(const char *utf) { + Display *dpy = XOpenDisplay(NULL); + KeySym sym = XStringToKeysym(utf); + // KeySym sym = XKeycodeToKeysym(dpy, utf); + + int min, max, numcodes; + XDisplayKeycodes(dpy, &min, &max); + KeySym *keysym; + keysym = XGetKeyboardMapping(dpy, min, max-min+1, &numcodes); + keysym[(max-min-1)*numcodes] = sym; + XChangeKeyboardMapping(dpy, min, numcodes, keysym, (max-min)); + XFree(keysym); + XFlush(dpy); + + KeyCode code = XKeysymToKeycode(dpy, sym); + XTestFakeKeyEvent(dpy, code, True, 1); + XTestFakeKeyEvent(dpy, code, False, 1); + + XFlush(dpy); + XCloseDisplay(dpy); + return 0; + } +#else + int input_utf(const char *utf){ + return 0; + } +#endif \ No newline at end of file diff --git a/mouse/mouse_c.h b/mouse/mouse_c.h index c46b1c35..0f4ee863 100644 --- a/mouse/mouse_c.h +++ b/mouse/mouse_c.h @@ -15,69 +15,69 @@ /* Some convenience macros for converting our enums to the system API types. */ #if defined(IS_MACOSX) -CGEventType MMMouseDownToCGEventType(MMMouseButton button) { - if (button == LEFT_BUTTON) { - return kCGEventLeftMouseDown; + CGEventType MMMouseDownToCGEventType(MMMouseButton button) { + if (button == LEFT_BUTTON) { + return kCGEventLeftMouseDown; + } + if (button == RIGHT_BUTTON) { + return kCGEventRightMouseDown; + } + return kCGEventOtherMouseDown; } - if (button == RIGHT_BUTTON) { - return kCGEventRightMouseDown; - } - return kCGEventOtherMouseDown; -} -CGEventType MMMouseUpToCGEventType(MMMouseButton button) { - if (button == LEFT_BUTTON) { return kCGEventLeftMouseUp; } - if (button == RIGHT_BUTTON) { return kCGEventRightMouseUp; } - return kCGEventOtherMouseUp; -} + CGEventType MMMouseUpToCGEventType(MMMouseButton button) { + if (button == LEFT_BUTTON) { return kCGEventLeftMouseUp; } + if (button == RIGHT_BUTTON) { return kCGEventRightMouseUp; } + return kCGEventOtherMouseUp; + } -CGEventType MMMouseDragToCGEventType(MMMouseButton button) { - if (button == LEFT_BUTTON) { return kCGEventLeftMouseDragged; } - if (button == RIGHT_BUTTON) { return kCGEventRightMouseDragged; } - return kCGEventOtherMouseDragged; -} + CGEventType MMMouseDragToCGEventType(MMMouseButton button) { + if (button == LEFT_BUTTON) { return kCGEventLeftMouseDragged; } + if (button == RIGHT_BUTTON) { return kCGEventRightMouseDragged; } + return kCGEventOtherMouseDragged; + } -CGEventType MMMouseToCGEventType(bool down, MMMouseButton button) { - if (down) { return MMMouseDownToCGEventType(button); } - return MMMouseUpToCGEventType(button); -} + CGEventType MMMouseToCGEventType(bool down, MMMouseButton button) { + if (down) { return MMMouseDownToCGEventType(button); } + return MMMouseUpToCGEventType(button); + } #elif defined(IS_WINDOWS) -DWORD MMMouseUpToMEventF(MMMouseButton button) { - if (button == LEFT_BUTTON) { return MOUSEEVENTF_LEFTUP; } - if (button == RIGHT_BUTTON) { return MOUSEEVENTF_RIGHTUP; } - return MOUSEEVENTF_MIDDLEUP; -} + DWORD MMMouseUpToMEventF(MMMouseButton button) { + if (button == LEFT_BUTTON) { return MOUSEEVENTF_LEFTUP; } + if (button == RIGHT_BUTTON) { return MOUSEEVENTF_RIGHTUP; } + return MOUSEEVENTF_MIDDLEUP; + } -DWORD MMMouseDownToMEventF(MMMouseButton button) { - if (button == LEFT_BUTTON) { return MOUSEEVENTF_LEFTDOWN; } - if (button == RIGHT_BUTTON) { return MOUSEEVENTF_RIGHTDOWN; } - return MOUSEEVENTF_MIDDLEDOWN; -} + DWORD MMMouseDownToMEventF(MMMouseButton button) { + if (button == LEFT_BUTTON) { return MOUSEEVENTF_LEFTDOWN; } + if (button == RIGHT_BUTTON) { return MOUSEEVENTF_RIGHTDOWN; } + return MOUSEEVENTF_MIDDLEDOWN; + } -DWORD MMMouseToMEventF(bool down, MMMouseButton button) { - if (down) { return MMMouseDownToMEventF(button); } - return MMMouseUpToMEventF(button); -} + DWORD MMMouseToMEventF(bool down, MMMouseButton button) { + if (down) { return MMMouseDownToMEventF(button); } + return MMMouseUpToMEventF(button); + } #endif #if defined(IS_MACOSX) -/* Calculate the delta for a mouse move and add them to the event. */ -void calculateDeltas(CGEventRef *event, MMPointInt32 point){ - /* The next few lines are a workaround for games not detecting mouse moves. */ - CGEventRef get = CGEventCreate(NULL); - CGPoint mouse = CGEventGetLocation(get); + /* Calculate the delta for a mouse move and add them to the event. */ + void calculateDeltas(CGEventRef *event, MMPointInt32 point) { + /* The next few lines are a workaround for games not detecting mouse moves. */ + CGEventRef get = CGEventCreate(NULL); + CGPoint mouse = CGEventGetLocation(get); - // Calculate the deltas. - int64_t deltaX = point.x - mouse.x; - int64_t deltaY = point.y - mouse.y; + // Calculate the deltas. + int64_t deltaX = point.x - mouse.x; + int64_t deltaY = point.y - mouse.y; - CGEventSetIntegerValueField(*event, kCGMouseEventDeltaX, deltaX); - CGEventSetIntegerValueField(*event, kCGMouseEventDeltaY, deltaY); + CGEventSetIntegerValueField(*event, kCGMouseEventDeltaX, deltaX); + CGEventSetIntegerValueField(*event, kCGMouseEventDeltaY, deltaY); - CFRelease(get); -} + CFRelease(get); + } #endif /* Move the mouse to a specific point. */ diff --git a/screen/screengrab_c.h b/screen/screengrab_c.h index 49852d0e..9af73022 100644 --- a/screen/screengrab_c.h +++ b/screen/screengrab_c.h @@ -54,7 +54,8 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id, MMPointInt32 o = rect.origin; MMSizeInt32 s = rect.size; XImage *image = XGetImage(display, XDefaultRootWindow(display), - (int)o.x, (int)o.y, (unsigned int)s.w, (unsigned int)s.h, AllPlanes, ZPixmap); + (int)o.x, (int)o.y, (unsigned int)s.w, (unsigned int)s.h, + AllPlanes, ZPixmap); XCloseDisplay(display); if (image == NULL) { return NULL; } From 0c4055bfee26758c61a98b55aa63c67c5ac02435 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Fri, 18 Aug 2023 10:28:15 -0700 Subject: [PATCH 279/327] Update: bump CI --- .circleci/config.yml | 2 +- .github/workflows/go.yml | 4 ++-- appveyor.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 756e8d0a..5b490fa1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,7 +5,7 @@ jobs: docker: # using custom image, see .circleci/images/primary/Dockerfile # - image: govgo/robotgoci:1.10.3 - - image: golang:1.20.3 + - image: golang:1.21.0 working_directory: /gopath/src/github.com/go-vgo/robotgo steps: - checkout diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index e9ecb352..2e4ff929 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -10,10 +10,10 @@ jobs: runs-on: ${{ matrix.os }} steps: - - name: Set up Go 1.20 + - name: Set up Go 1.21.0 uses: actions/setup-go@v1 with: - go-version: 1.20 + go-version: 1.21.0 id: go - name: Check out code into the Go module directory diff --git a/appveyor.yml b/appveyor.yml index 2c2bc645..67a5d86a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,7 +34,7 @@ environment: PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% # - COMPILER: MINGW_W64 # ARCHITECTURE: x64 - GOVERSION: 1.20.3 + GOVERSION: 1.21.0 # GOPATH: c:\gopath # scripts that run after cloning repository From 5b0ac98ef392661055fd2d7c82b7f55883b87e18 Mon Sep 17 00:00:00 2001 From: guangwu Date: Sat, 26 Aug 2023 11:45:07 +0800 Subject: [PATCH 280/327] fix: continuous typo --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9e36d624..6c15d203 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -24,7 +24,7 @@ This process gives everyone a chance to validate the design, helps prevent dupli ## Testing redux -Before sending code out for review, run all the tests for the whole tree to make sure the changes don't break other usage and keep the compatibility on upgrade. You must be test on Mac, Windows, Linux and other. You should install the CLI for Circle CI, as we are using the server for continous testing. +Before sending code out for review, run all the tests for the whole tree to make sure the changes don't break other usage and keep the compatibility on upgrade. You must be test on Mac, Windows, Linux and other. You should install the CLI for Circle CI, as we are using the server for continuous testing. ## Code review From 90f41269dafef3f278153ae692d084eb96a592cf Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 3 Sep 2023 12:12:56 -0700 Subject: [PATCH 281/327] Update: update gomod and fixed warning --- go.mod | 27 +++++++++--------- go.sum | 73 ++++++++++++++++++++++++++++--------------------- img.go | 2 +- window/window.h | 2 +- 4 files changed, 58 insertions(+), 46 deletions(-) diff --git a/go.mod b/go.mod index b32d6e3b..b987153a 100644 --- a/go.mod +++ b/go.mod @@ -8,26 +8,27 @@ require ( // github.com/robotn/gohook v0.31.3 github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 - github.com/vcaesar/gops v0.30.1 - github.com/vcaesar/imgo v0.30.2 - github.com/vcaesar/keycode v0.10.0 + github.com/vcaesar/gops v0.30.2 + github.com/vcaesar/imgo v0.40.0 + github.com/vcaesar/keycode v0.10.1 github.com/vcaesar/tt v0.20.0 ) require ( - github.com/gen2brain/shm v0.0.0-20221026125803-c33c9e32b1c8 // indirect - github.com/go-ole/go-ole v1.2.6 // indirect + github.com/gen2brain/shm v0.0.0-20230802011745-f2460f5984f7 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect github.com/jezek/xgb v1.1.0 // indirect - github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329 - github.com/lufia/plan9stats v0.0.0-20230110061619-bbe2e5e100de // indirect + github.com/kbinani/screenshot v0.0.0-20230812210009-b87d31814237 + github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a // indirect github.com/otiai10/mint v1.3.0 // indirect github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect - github.com/shirou/gopsutil/v3 v3.23.1 // indirect - github.com/tklauser/go-sysconf v0.3.11 // indirect - github.com/tklauser/numcpus v0.6.0 // indirect - github.com/yusufpapurcu/wmi v1.2.2 // indirect - golang.org/x/image v0.5.0 // indirect - golang.org/x/sys v0.5.0 // indirect + github.com/shirou/gopsutil/v3 v3.23.8 // indirect + github.com/shoenig/go-m1cpu v0.1.6 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect + github.com/yusufpapurcu/wmi v1.2.3 // indirect + golang.org/x/image v0.12.0 // indirect + golang.org/x/sys v0.12.0 // indirect ) // replace golang.org/x/sys => github.com/golang/sys v0.0.0-20190109145017-48ac38b7c8cb diff --git a/go.sum b/go.sum index 42873fcf..3b660c78 100644 --- a/go.sum +++ b/go.sum @@ -3,22 +3,21 @@ github.com/BurntSushi/graphics-go v0.0.0-20160129215708-b43f31a4a966/go.mod h1:M github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5/go.mod h1:uF6rMu/1nvu+5DpiRLwusA6xB8zlkNoGzKn8lmYONUo= -github.com/gen2brain/shm v0.0.0-20221026125803-c33c9e32b1c8 h1:u4/UVF0sNxlqDwCptjIUTUkZW4UoZDrcHzvd2kNnF/k= -github.com/gen2brain/shm v0.0.0-20221026125803-c33c9e32b1c8/go.mod h1:uF6rMu/1nvu+5DpiRLwusA6xB8zlkNoGzKn8lmYONUo= -github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/gen2brain/shm v0.0.0-20230802011745-f2460f5984f7 h1:VLEKvjGJYAMCXw0/32r9io61tEXnMWDRxMk+peyRVFc= +github.com/gen2brain/shm v0.0.0-20230802011745-f2460f5984f7/go.mod h1:uF6rMu/1nvu+5DpiRLwusA6xB8zlkNoGzKn8lmYONUo= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/jezek/xgb v0.0.0-20210312150743-0e0f116e1240/go.mod h1:3P4UH/k22rXyHIJD2w4h2XMqPX4Of/eySEZq9L6wqc4= github.com/jezek/xgb v1.1.0 h1:wnpxJzP1+rkbGclEkmwpVFQWpuE2PUGNUzP8SbfFobk= github.com/jezek/xgb v1.1.0/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk= -github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329 h1:qq2nCpSrXrmvDGRxW0ruW9BVEV1CN2a9YDOExdt+U0o= -github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329/go.mod h1:2VPVQDR4wO7KXHwP+DAypEy67rXf+okUx2zjgpCxZw4= +github.com/kbinani/screenshot v0.0.0-20230812210009-b87d31814237 h1:YOp8St+CM/AQ9Vp4XYm4272E77MptJDHkwypQHIRl9Q= +github.com/kbinani/screenshot v0.0.0-20230812210009-b87d31814237/go.mod h1:e7qQlOY68wOz4b82D7n+DdaptZAi+SHW0+yKiWZzEYE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= -github.com/lufia/plan9stats v0.0.0-20230110061619-bbe2e5e100de h1:V53FWzU6KAZVi1tPp5UIsMoUWJ2/PNwYIDXnu7QuBCE= -github.com/lufia/plan9stats v0.0.0-20230110061619-bbe2e5e100de/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE= +github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a h1:N9zuLhTvBSRt0gWSiJswwQ2HqDmtX/ZCDJURnKUt1Ik= +github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE= github.com/lxn/win v0.0.0-20210218163916-a377121e959e h1:H+t6A/QJMbhCSEH5rAuRxh+CtW96g0Or0Fxa9IKr4uc= github.com/lxn/win v0.0.0-20210218163916-a377121e959e/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= @@ -35,41 +34,48 @@ github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 h1:2lhSR8N3T6I30q096DT7 github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934/go.mod h1:SxQhJskUJ4rleVU44YvnrdvxQr0tKy5SRSigBrCgyyQ= github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 h1:2uX8QRLkkxn2EpAQ6I3KhA79BkdRZfvugJUzJadiJwk= github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770/go.mod h1:svkDXUDQjUiWzLrA0OZgHc4lbOts3C+uRfP6/yjwYnU= -github.com/shirou/gopsutil/v3 v3.23.1 h1:a9KKO+kGLKEvcPIs4W62v0nu3sciVDOOOPUD0Hz7z/4= -github.com/shirou/gopsutil/v3 v3.23.1/go.mod h1:NN6mnm5/0k8jw4cBfCnJtr5L7ErOTg18tMNpgFkn0hA= +github.com/shirou/gopsutil/v3 v3.23.8 h1:xnATPiybo6GgdRoC4YoGnxXZFRc3dqQTGi73oLvvBrE= +github.com/shirou/gopsutil/v3 v3.23.8/go.mod h1:7hmCaBn+2ZwaZOr6jmPBZDfawwMGuo1id3C6aM8EDqQ= +github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= +github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= +github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= +github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM= -github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI= -github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms= -github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4= -github.com/vcaesar/gops v0.30.1 h1:MmTJhcCz0xTLSxOv4bmqbXQBPYVZpFLDzwN9Jdp/FR0= -github.com/vcaesar/gops v0.30.1/go.mod h1:F/8aazx2wGZ69ruziZcNGnlq/rehITYTqZ6ewVLDiyk= -github.com/vcaesar/imgo v0.30.2 h1:JUTKt9Og95RJ7ANjNtjW1NSO0jWMWxHCbryriNYooQE= -github.com/vcaesar/imgo v0.30.2/go.mod h1:8mJleCPHDTqMmyRHFFim+S+B+1ighHqAETvuf7WCnZI= -github.com/vcaesar/keycode v0.10.0 h1:Qx5QE8ZXHyRyjoA2QOxBp25OKMKB+zxMVqm0FWGV0d4= -github.com/vcaesar/keycode v0.10.0/go.mod h1:JNlY7xbKsh+LAGfY2j4M3znVrGEm5W1R8s/Uv6BJcfQ= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/vcaesar/gops v0.30.2 h1:fANyUGCjLkfcYmJRVnXv+QZhT8cL2e0GWpRFZe58p/4= +github.com/vcaesar/gops v0.30.2/go.mod h1:2NSA2Q9M1irGnGD9tWdo0Z+MwKjUj4Q4EgUDukN/Vsk= +github.com/vcaesar/imgo v0.40.0 h1:okI1eonRAfGLzjqgTIBkUwhm4j/rH19qGno4eFOBQsc= +github.com/vcaesar/imgo v0.40.0/go.mod h1:E5uI53XkEfbI20VvcIZ/19G2hHidPfH9h4NtQooEY+8= +github.com/vcaesar/keycode v0.10.1 h1:0DesGmMAPWpYTCYddOFiCMKCDKgNnwiQa2QXindVUHw= +github.com/vcaesar/keycode v0.10.1/go.mod h1:JNlY7xbKsh+LAGfY2j4M3znVrGEm5W1R8s/Uv6BJcfQ= github.com/vcaesar/tt v0.20.0 h1:9t2Ycb9RNHcP0WgQgIaRKJBB+FrRdejuaL6uWIHuoBA= github.com/vcaesar/tt v0.20.0/go.mod h1:GHPxQYhn+7OgKakRusH7KJ0M5MhywoeLb8Fcffs/Gtg= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= -github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= +github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/image v0.5.0 h1:5JMiNunQeQw++mMOz48/ISeNu3Iweh/JaZU8ZLqHRrI= -golang.org/x/image v0.5.0/go.mod h1:FVC7BI/5Ym8R25iw5OLsgshdUBbT1h5jZTpA+mvAdZ4= +golang.org/x/image v0.12.0 h1:w13vZbU4o5rKOFFR8y7M+c4A5jXDC0uXTdHYRP8X2DQ= +golang.org/x/image v0.12.0/go.mod h1:Lu90jvHG7GfemOIcldsh9A2hS01ocl6oNO7ype5mEnk= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0 h1:L4ZwwTvKW9gr0ZMS1yrHD9GZhIuVjOBBnaKH+SPQK0Q= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -78,19 +84,24 @@ golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/img.go b/img.go index edc32e6b..62ec5f60 100644 --- a/img.go +++ b/img.go @@ -55,7 +55,7 @@ func SaveJpeg(img image.Image, path string, quality ...int) error { // ToByteImg convert image.Image to []byte func ToByteImg(img image.Image, fm ...string) []byte { - return imgo.ToByteImg(img, fm...) + return imgo.ToByte(img, fm...) } // ToStringImg convert image.Image to string diff --git a/window/window.h b/window/window.h index 8e0ff69f..2b9698e6 100644 --- a/window/window.h +++ b/window/window.h @@ -15,7 +15,7 @@ bool is_valid(); bool IsAxEnabled(bool options); MData get_active(void); -void initWindow(); +void initWindow(uintptr handle); char* get_title_by_hand(MData m_data); void close_window_by_Id(MData m_data); From de675b4dd2dcc86d7b6036d6386bd9bb01c87aed Mon Sep 17 00:00:00 2001 From: Mokky Date: Thu, 7 Sep 2023 20:53:58 +0900 Subject: [PATCH 282/327] Update window.h Fix: error when current window is minimized --- window/window.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/window/window.h b/window/window.h index 2b9698e6..b206aa8c 100644 --- a/window/window.h +++ b/window/window.h @@ -367,11 +367,11 @@ MData get_active(void) { if (focused == NULL) { return result; } // Verify AXUIElementRef element; + CGWindowID win = 0; // Retrieve the currently focused window if (AXUIElementCopyAttributeValue(focused, kAXFocusedWindowAttribute, (CFTypeRef*) &element) == kAXErrorSuccess && element) { - CGWindowID win = 0; // Use undocumented API to get WID if (_AXUIElementGetWindow(element, &win) == kAXErrorSuccess && win) { // Manually set internals @@ -380,6 +380,9 @@ MData get_active(void) { } else { CFRelease(element); } + } else { + result.CgID = win; + result.AxID = element; } CFRelease(focused); From b8a6b1778e41a91a96ff006ec2f0b37e385ea157 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 30 Oct 2023 08:24:33 -0700 Subject: [PATCH 283/327] Update: gofmt the code --- clipboard/clipboard.go | 1 - 1 file changed, 1 deletion(-) diff --git a/clipboard/clipboard.go b/clipboard/clipboard.go index f1b21861..e0017f96 100644 --- a/clipboard/clipboard.go +++ b/clipboard/clipboard.go @@ -3,7 +3,6 @@ // license that can be found in the LICENSE file. /* - Package clipboard read/write on clipboard */ package clipboard From 722feb7ba3d0dd0e8e67ea06b6baa14d4826f166 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 13 Nov 2023 09:23:29 -0800 Subject: [PATCH 284/327] Update: update readme.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7dadb850..7f9c6cc7 100644 --- a/README.md +++ b/README.md @@ -70,12 +70,12 @@ xcode-select --install #### For Windows: -[MinGW-w64](https://sourceforge.net/projects/mingw-w64/files) (Use recommended) +[MinGW-w64](https://sourceforge.net/projects/mingw-w64/files) (Use recommended) or others Mingw [llvm-mingw](https://github.com/mstorsjo/llvm-mingw) Download the Mingw, then set system environment variables `C:\mingw64\bin` to the Path. [Set environment variables to run GCC from command line](https://www.youtube.com/results?search_query=Set+environment+variables+to+run+GCC+from+command+line). -`Or the other GCC (But you should compile the "libpng" with yourself when use the bitmap.)` +`Or the other GCC` (But you should compile the "libpng" with yourself when use the [bitmap](https://github.com/vcaesar/bitmap).) #### For everything else: From e2f5f54804441097eec769e124fb015f588d5dfd Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 13 Nov 2023 10:22:10 -0800 Subject: [PATCH 285/327] Update: update readme.md --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 7f9c6cc7..70a90089 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ [![Build Status](https://travis-ci.org/go-vgo/robotgo.svg)](https://travis-ci.org/go-vgo/robotgo) ![Appveyor](https://ci.appveyor.com/api/projects/status/github/go-vgo/robotgo?branch=master&svg=true) [![Go Report Card](https://goreportcard.com/badge/github.com/go-vgo/robotgo)](https://goreportcard.com/report/github.com/go-vgo/robotgo) -[![GoDoc](https://godoc.org/github.com/go-vgo/robotgo?status.svg)](https://godoc.org/github.com/go-vgo/robotgo) +[![GoDoc](https://pkg.go.dev/badge/github.com/go-vgo/robotgo?status.svg)](https://pkg.go.dev/github.com/go-vgo/robotgo?tab=doc) [![GitHub release](https://img.shields.io/github/release/go-vgo/robotgo.svg)](https://github.com/go-vgo/robotgo/releases/latest) [![Join the chat at https://gitter.im/go-vgo/robotgo](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/go-vgo/robotgo?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) @@ -62,7 +62,7 @@ GCC #### For MacOS: -Xcode Command Line Tools (And Privacy setting: [#277](https://github.com/go-vgo/robotgo/issues/277) ) +Xcode Command Line Tools (And Privacy setting: [#277](https://github.com/go-vgo/robotgo/issues/277)) ``` xcode-select --install @@ -70,7 +70,7 @@ xcode-select --install #### For Windows: -[MinGW-w64](https://sourceforge.net/projects/mingw-w64/files) (Use recommended) or others Mingw [llvm-mingw](https://github.com/mstorsjo/llvm-mingw) +[MinGW-w64](https://sourceforge.net/projects/mingw-w64/files) (Use recommended) or others Mingw [llvm-mingw](https://github.com/mstorsjo/llvm-mingw); Download the Mingw, then set system environment variables `C:\mingw64\bin` to the Path. [Set environment variables to run GCC from command line](https://www.youtube.com/results?search_query=Set+environment+variables+to+run+GCC+from+command+line). @@ -87,9 +87,9 @@ X11 with the XTest extension (the Xtst library) "Clipboard": xsel xclip -"Bitmap": libpng (Just used by the bitmap.) +"Bitmap": libpng (Just used by the "bitmap".) -"Event": xcb, xkb, libxkbcommon (Just used by the hook.) +"Event-Gohook": xcb, xkb, libxkbcommon (Just used by the "hook".) ``` @@ -109,7 +109,7 @@ sudo apt install xsel xclip # Bitmap sudo apt install libpng++-dev -# Hook +# GoHook sudo apt install xcb libxcb-xkb-dev x11-xkb-utils libx11-xcb-dev libxkbcommon-x11-dev libxkbcommon-dev ``` From 61b77ce3e12501317424b4dfabf07eaf3d9b8a94 Mon Sep 17 00:00:00 2001 From: sleep2144985 Date: Wed, 20 Dec 2023 17:35:11 +0800 Subject: [PATCH 286/327] fix: x11 capslock reference the wrong constant --- key/keycode.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/key/keycode.h b/key/keycode.h index 4a6771ac..d5577faa 100644 --- a/key/keycode.h +++ b/key/keycode.h @@ -179,7 +179,7 @@ enum _MMKeyCode { K_SHIFT = XK_Shift_L, K_LSHIFT = XK_Shift_L, K_RSHIFT = XK_Shift_R, - K_CAPSLOCK = XK_Shift_Lock, + K_CAPSLOCK = XK_Caps_Lock, K_SPACE = XK_space, K_INSERT = XK_Insert, K_PRINTSCREEN = XK_Print, From 39818d41fa898f2378d55099cbed12a627e6bbf3 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 20 Dec 2023 09:52:51 -0800 Subject: [PATCH 287/327] Add: add next Linux and Windows files --- .circleci/images/primary/Dockerfile | 2 +- README.md | 2 +- wayland_n.go | 2 ++ windows_n.go | 2 ++ 4 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 wayland_n.go create mode 100644 windows_n.go diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index bc83ff92..0cc660ac 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.20.3-stretch AS build +FROM golang:1.21.5-stretch AS build # FROM govgo/go:1.11.1 RUN apt update && apt install -y --no-install-recommends \ diff --git a/README.md b/README.md index 70a90089..763b6bb7 100644 --- a/README.md +++ b/README.md @@ -127,7 +127,7 @@ sudo dnf install xsel xclip # Bitmap sudo dnf install libpng-devel -# Hook +# GoHook sudo dnf install libxkbcommon-devel libxkbcommon-x11-devel xorg-x11-xkb-utils-devel ``` diff --git a/wayland_n.go b/wayland_n.go new file mode 100644 index 00000000..bc07c4d1 --- /dev/null +++ b/wayland_n.go @@ -0,0 +1,2 @@ +// +bulid linux,next +package robotgo diff --git a/windows_n.go b/windows_n.go new file mode 100644 index 00000000..613fb790 --- /dev/null +++ b/windows_n.go @@ -0,0 +1,2 @@ +// +bulid windows,next +package robotgo From e9421b58b67250feb987463bb115592921820f50 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Fri, 23 Feb 2024 08:47:11 -0800 Subject: [PATCH 288/327] Update: bump CI to newest --- .circleci/config.yml | 2 +- .circleci/images/primary/Dockerfile | 2 +- appveyor.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 5b490fa1..544556f8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,7 +5,7 @@ jobs: docker: # using custom image, see .circleci/images/primary/Dockerfile # - image: govgo/robotgoci:1.10.3 - - image: golang:1.21.0 + - image: golang:1.22.0 working_directory: /gopath/src/github.com/go-vgo/robotgo steps: - checkout diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index 0cc660ac..b9618cdb 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.21.5-stretch AS build +FROM golang:1.21.7-stretch AS build # FROM govgo/go:1.11.1 RUN apt update && apt install -y --no-install-recommends \ diff --git a/appveyor.yml b/appveyor.yml index 67a5d86a..ae1d56e9 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,7 +34,7 @@ environment: PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% # - COMPILER: MINGW_W64 # ARCHITECTURE: x64 - GOVERSION: 1.21.0 + GOVERSION: 1.22.0 # GOPATH: c:\gopath # scripts that run after cloning repository From 3171c5bdff584a84abde8fc4ea46d06b82a38bc3 Mon Sep 17 00:00:00 2001 From: nzlov Date: Sun, 7 Apr 2024 14:08:26 +0800 Subject: [PATCH 289/327] fix: DragSmooth Repeat Call MoveScale `DragSmooth` calls `MoveScale` followed by `MoveSmooth`, and `MoveSmooth` calls `MoveScale` within `MoveSmooth`, resulting in duplicate calls to `MoveScale`. --- robotgo.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/robotgo.go b/robotgo.go index b445a8fd..f4660ac8 100644 --- a/robotgo.go +++ b/robotgo.go @@ -540,8 +540,6 @@ func Drag(x, y int, args ...string) { // // robotgo.DragSmooth(10, 10) func DragSmooth(x, y int, args ...interface{}) { - x, y = MoveScale(x, y) - Toggle("left") MilliSleep(50) MoveSmooth(x, y, args...) From 05c54c6f259c2366673744796152396774597204 Mon Sep 17 00:00:00 2001 From: rustfix <771054535@qq.com> Date: Mon, 15 Apr 2024 11:37:14 +0800 Subject: [PATCH 290/327] chore: fix function names in comment Signed-off-by: rustfix <771054535@qq.com> --- robotgo_win.go | 2 +- robotgo_x11.go | 2 +- screen.go | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/robotgo_win.go b/robotgo_win.go index d2208bca..e99823c2 100644 --- a/robotgo_win.go +++ b/robotgo_win.go @@ -57,7 +57,7 @@ func SetForeg(hwnd win.HWND) bool { return win.SetForegroundWindow(hwnd) } -// GetMian get the main display hwnd +// GetMain get the main display hwnd func GetMain() win.HWND { return win.GetActiveWindow() } diff --git a/robotgo_x11.go b/robotgo_x11.go index 26355a18..97aa9151 100644 --- a/robotgo_x11.go +++ b/robotgo_x11.go @@ -190,7 +190,7 @@ func DisplaysNum() int { return int(reply.Number) } -// GetMianId get the main display id +// GetMainId get the main display id func GetMainId() int { conn, err := xgb.NewConn() if err != nil { diff --git a/screen.go b/screen.go index e0eca41e..e6b7a16f 100644 --- a/screen.go +++ b/screen.go @@ -16,13 +16,13 @@ import ( "github.com/kbinani/screenshot" ) -// GetScreenBound gets the display screen bounds +// GetDisplayBounds gets the display screen bounds func GetDisplayBounds(i int) (x, y, w, h int) { bs := screenshot.GetDisplayBounds(i) return bs.Min.X, bs.Min.Y, bs.Dx(), bs.Dy() } -// GetDisplayBounds gets the display rect +// GetDisplayRect gets the display rect func GetDisplayRect(i int) Rect { x, y, w, h := GetDisplayBounds(i) return Rect{ From 9424b71a731158080ba8682109d3d51060b203a0 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 5 Jun 2024 12:38:39 -0700 Subject: [PATCH 291/327] Update: update CI and dockerfile --- .circleci/images/primary/Dockerfile | 2 +- .github/workflows/go.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index b9618cdb..ceaf93bd 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.21.7-stretch AS build +FROM golang:1.22.3-stretch AS build # FROM govgo/go:1.11.1 RUN apt update && apt install -y --no-install-recommends \ diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 2e4ff929..59655b42 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -10,10 +10,10 @@ jobs: runs-on: ${{ matrix.os }} steps: - - name: Set up Go 1.21.0 + - name: Set up Go 1.22.0 uses: actions/setup-go@v1 with: - go-version: 1.21.0 + go-version: 1.22.0 id: go - name: Check out code into the Go module directory From 8a990ac0427672c2a73bff3ff2cc66a3b28f00f5 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Wed, 12 Jun 2024 13:02:30 -0700 Subject: [PATCH 292/327] Update: update go mod to newest --- go.mod | 21 ++++++------ go.sum | 87 ++++++++++++++++++++++++++++++++++++++------------ robotgo_win.go | 3 +- 3 files changed, 79 insertions(+), 32 deletions(-) diff --git a/go.mod b/go.mod index b987153a..ab3bfe9d 100644 --- a/go.mod +++ b/go.mod @@ -3,32 +3,33 @@ module github.com/go-vgo/robotgo go 1.17 require ( - github.com/lxn/win v0.0.0-20210218163916-a377121e959e - github.com/otiai10/gosseract v2.2.1+incompatible + github.com/otiai10/gosseract/v2 v2.4.1 // github.com/robotn/gohook v0.31.3 github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 - github.com/vcaesar/gops v0.30.2 - github.com/vcaesar/imgo v0.40.0 + github.com/tailscale/win v0.0.0-20240403170916-6580b55d49ca + github.com/vcaesar/gops v0.40.0 + github.com/vcaesar/imgo v0.40.1 github.com/vcaesar/keycode v0.10.1 - github.com/vcaesar/tt v0.20.0 + github.com/vcaesar/tt v0.20.1 ) require ( + github.com/dblohm7/wingoes v0.0.0-20231019175336-f6e33aa7cc34 // indirect github.com/gen2brain/shm v0.0.0-20230802011745-f2460f5984f7 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/jezek/xgb v1.1.0 // indirect github.com/kbinani/screenshot v0.0.0-20230812210009-b87d31814237 github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a // indirect - github.com/otiai10/mint v1.3.0 // indirect + github.com/lxn/win v0.0.0-20210218163916-a377121e959e // indirect github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect - github.com/shirou/gopsutil/v3 v3.23.8 // indirect + github.com/shirou/gopsutil/v4 v4.24.5 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect - github.com/yusufpapurcu/wmi v1.2.3 // indirect - golang.org/x/image v0.12.0 // indirect - golang.org/x/sys v0.12.0 // indirect + github.com/yusufpapurcu/wmi v1.2.4 // indirect + golang.org/x/image v0.17.0 // indirect + golang.org/x/sys v0.20.0 // indirect ) // replace golang.org/x/sys => github.com/golang/sys v0.0.0-20190109145017-48ac38b7c8cb diff --git a/go.sum b/go.sum index 3b660c78..b02d9062 100644 --- a/go.sum +++ b/go.sum @@ -3,14 +3,18 @@ github.com/BurntSushi/graphics-go v0.0.0-20160129215708-b43f31a4a966/go.mod h1:M github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dblohm7/wingoes v0.0.0-20231019175336-f6e33aa7cc34 h1:FBMro26TLQwBk+n4fbTSmSf3QUKb09pvW4fz49lxpl0= +github.com/dblohm7/wingoes v0.0.0-20231019175336-f6e33aa7cc34/go.mod h1:6NCrWM5jRefaG7iN0iMShPalLsljHWBh9v1zxM2f8Xs= github.com/gen2brain/shm v0.0.0-20230802011745-f2460f5984f7 h1:VLEKvjGJYAMCXw0/32r9io61tEXnMWDRxMk+peyRVFc= github.com/gen2brain/shm v0.0.0-20230802011745-f2460f5984f7/go.mod h1:uF6rMu/1nvu+5DpiRLwusA6xB8zlkNoGzKn8lmYONUo= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/jezek/xgb v1.1.0 h1:wnpxJzP1+rkbGclEkmwpVFQWpuE2PUGNUzP8SbfFobk= github.com/jezek/xgb v1.1.0/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk= github.com/kbinani/screenshot v0.0.0-20230812210009-b87d31814237 h1:YOp8St+CM/AQ9Vp4XYm4272E77MptJDHkwypQHIRl9Q= @@ -20,11 +24,10 @@ github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a h1:N9zuLhTvBSRt0g github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE= github.com/lxn/win v0.0.0-20210218163916-a377121e959e h1:H+t6A/QJMbhCSEH5rAuRxh+CtW96g0Or0Fxa9IKr4uc= github.com/lxn/win v0.0.0-20210218163916-a377121e959e/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk= -github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= -github.com/otiai10/gosseract v2.2.1+incompatible h1:Ry5ltVdpdp4LAa2bMjsSJH34XHVOV7XMi41HtzL8X2I= -github.com/otiai10/gosseract v2.2.1+incompatible/go.mod h1:XrzWItCzCpFRZ35n3YtVTgq5bLAhFIkascoRo8G32QE= -github.com/otiai10/mint v1.3.0 h1:Ady6MKVezQwHBkGzLFbrsywyp09Ah7rkmfjV3Bcr5uc= -github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= +github.com/otiai10/gosseract/v2 v2.4.1 h1:G8AyBpXEeSlcq8TI85LH/pM5SXk8Djy2GEXisgyblRw= +github.com/otiai10/gosseract/v2 v2.4.1/go.mod h1:1gNWP4Hgr2o7yqWfs6r5bZxAatjOIdqWxJLWsTsembk= +github.com/otiai10/mint v1.6.3 h1:87qsV/aw1F5as1eH1zS/yqHY85ANKVMgkDrf9rcxbQs= +github.com/otiai10/mint v1.6.3/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= @@ -34,8 +37,8 @@ github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 h1:2lhSR8N3T6I30q096DT7 github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934/go.mod h1:SxQhJskUJ4rleVU44YvnrdvxQr0tKy5SRSigBrCgyyQ= github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 h1:2uX8QRLkkxn2EpAQ6I3KhA79BkdRZfvugJUzJadiJwk= github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770/go.mod h1:svkDXUDQjUiWzLrA0OZgHc4lbOts3C+uRfP6/yjwYnU= -github.com/shirou/gopsutil/v3 v3.23.8 h1:xnATPiybo6GgdRoC4YoGnxXZFRc3dqQTGi73oLvvBrE= -github.com/shirou/gopsutil/v3 v3.23.8/go.mod h1:7hmCaBn+2ZwaZOr6jmPBZDfawwMGuo1id3C6aM8EDqQ= +github.com/shirou/gopsutil/v4 v4.24.5 h1:gGsArG5K6vmsh5hcFOHaPm87UD003CaDMkAOweSQjhM= +github.com/shirou/gopsutil/v4 v4.24.5/go.mod h1:aoebb2vxetJ/yIDZISmduFvVNPHqXQ9SEJwRXxkf0RA= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= @@ -43,39 +46,62 @@ github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnj github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tailscale/win v0.0.0-20240403170916-6580b55d49ca h1:oYYp7AvemDkWtxmsgVSpcFxcHMv/2jjbOk5ZC16e77Y= +github.com/tailscale/win v0.0.0-20240403170916-6580b55d49ca/go.mod h1:aMd4yDHLjbOuYP6fMxj1d9ACDQlSWwYztcpybGHCQc8= github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= -github.com/vcaesar/gops v0.30.2 h1:fANyUGCjLkfcYmJRVnXv+QZhT8cL2e0GWpRFZe58p/4= -github.com/vcaesar/gops v0.30.2/go.mod h1:2NSA2Q9M1irGnGD9tWdo0Z+MwKjUj4Q4EgUDukN/Vsk= -github.com/vcaesar/imgo v0.40.0 h1:okI1eonRAfGLzjqgTIBkUwhm4j/rH19qGno4eFOBQsc= -github.com/vcaesar/imgo v0.40.0/go.mod h1:E5uI53XkEfbI20VvcIZ/19G2hHidPfH9h4NtQooEY+8= +github.com/vcaesar/gops v0.40.0 h1:I+1RCGiV+LkZJUYNzAd373xs0uM2UyeFdZBmow8HfCM= +github.com/vcaesar/gops v0.40.0/go.mod h1:3u/USW7JovqUK6i13VOD3qWfvXXd2TIIKE4PYIv4TOM= +github.com/vcaesar/imgo v0.40.1 h1:OSX+qV8SgbVJksXXZkzfDNm6+oi2H3t8Y2Sl0QO0q70= +github.com/vcaesar/imgo v0.40.1/go.mod h1:8gotN26eyM0ITbSuse0EU6GFweKW/zgfTT2fQir1qOo= github.com/vcaesar/keycode v0.10.1 h1:0DesGmMAPWpYTCYddOFiCMKCDKgNnwiQa2QXindVUHw= github.com/vcaesar/keycode v0.10.1/go.mod h1:JNlY7xbKsh+LAGfY2j4M3znVrGEm5W1R8s/Uv6BJcfQ= -github.com/vcaesar/tt v0.20.0 h1:9t2Ycb9RNHcP0WgQgIaRKJBB+FrRdejuaL6uWIHuoBA= -github.com/vcaesar/tt v0.20.0/go.mod h1:GHPxQYhn+7OgKakRusH7KJ0M5MhywoeLb8Fcffs/Gtg= +github.com/vcaesar/tt v0.20.1 h1:D/jUeeVCNbq3ad8M7hhtB3J9x5RZ6I1n1eZ0BJp7M+4= +github.com/vcaesar/tt v0.20.1/go.mod h1:cH2+AwGAJm19Wa6xvEa+0r+sXDJBT0QgNQey6mwqLeU= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= -github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= +github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/image v0.12.0 h1:w13vZbU4o5rKOFFR8y7M+c4A5jXDC0uXTdHYRP8X2DQ= -golang.org/x/image v0.12.0/go.mod h1:Lu90jvHG7GfemOIcldsh9A2hS01ocl6oNO7ype5mEnk= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/exp v0.0.0-20230127140709-cafedaf64729 h1:H2kBA039yqxDv2DScpuC0knhZXO6Evfmt7mN8sGMh/4= +golang.org/x/exp v0.0.0-20230127140709-cafedaf64729/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/image v0.17.0 h1:nTRVVdajgB8zCMZVsViyzhnMKPwYeroEERRC64JuLco= +golang.org/x/image v0.17.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0 h1:L4ZwwTvKW9gr0ZMS1yrHD9GZhIuVjOBBnaKH+SPQK0Q= +golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -86,22 +112,41 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/robotgo_win.go b/robotgo_win.go index e99823c2..07364483 100644 --- a/robotgo_win.go +++ b/robotgo_win.go @@ -17,7 +17,8 @@ import ( "syscall" "unsafe" - "github.com/lxn/win" + // "github.com/lxn/win" + "github.com/tailscale/win" ) // FindWindow find window hwnd by name From d90493e63ed865eb87081b5f39e64c9c435fb813 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 5 Aug 2024 13:11:56 -0700 Subject: [PATCH 293/327] Update: add svae capture and update go mod --- go.mod | 4 ++-- go.sum | 8 ++++---- screen.go | 10 ++++++++++ 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index ab3bfe9d..1b14579b 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 github.com/tailscale/win v0.0.0-20240403170916-6580b55d49ca github.com/vcaesar/gops v0.40.0 - github.com/vcaesar/imgo v0.40.1 + github.com/vcaesar/imgo v0.40.2 github.com/vcaesar/keycode v0.10.1 github.com/vcaesar/tt v0.20.1 ) @@ -28,7 +28,7 @@ require ( github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect - golang.org/x/image v0.17.0 // indirect + golang.org/x/image v0.18.0 // indirect golang.org/x/sys v0.20.0 // indirect ) diff --git a/go.sum b/go.sum index b02d9062..5edcf14d 100644 --- a/go.sum +++ b/go.sum @@ -60,8 +60,8 @@ github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+F github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/vcaesar/gops v0.40.0 h1:I+1RCGiV+LkZJUYNzAd373xs0uM2UyeFdZBmow8HfCM= github.com/vcaesar/gops v0.40.0/go.mod h1:3u/USW7JovqUK6i13VOD3qWfvXXd2TIIKE4PYIv4TOM= -github.com/vcaesar/imgo v0.40.1 h1:OSX+qV8SgbVJksXXZkzfDNm6+oi2H3t8Y2Sl0QO0q70= -github.com/vcaesar/imgo v0.40.1/go.mod h1:8gotN26eyM0ITbSuse0EU6GFweKW/zgfTT2fQir1qOo= +github.com/vcaesar/imgo v0.40.2 h1:5GWScRLdBCMtO1v2I1bs+ZmDLZFINxYSMZ+mtUw5qPM= +github.com/vcaesar/imgo v0.40.2/go.mod h1:MVCl+FxHI2gTgmiHoi0n5xNCbYcfv9SVtdEOUC92+eo= github.com/vcaesar/keycode v0.10.1 h1:0DesGmMAPWpYTCYddOFiCMKCDKgNnwiQa2QXindVUHw= github.com/vcaesar/keycode v0.10.1/go.mod h1:JNlY7xbKsh+LAGfY2j4M3znVrGEm5W1R8s/Uv6BJcfQ= github.com/vcaesar/tt v0.20.1 h1:D/jUeeVCNbq3ad8M7hhtB3J9x5RZ6I1n1eZ0BJp7M+4= @@ -77,8 +77,8 @@ golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDf golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/exp v0.0.0-20230127140709-cafedaf64729 h1:H2kBA039yqxDv2DScpuC0knhZXO6Evfmt7mN8sGMh/4= golang.org/x/exp v0.0.0-20230127140709-cafedaf64729/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= -golang.org/x/image v0.17.0 h1:nTRVVdajgB8zCMZVsViyzhnMKPwYeroEERRC64JuLco= -golang.org/x/image v0.17.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E= +golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ= +golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= diff --git a/screen.go b/screen.go index e6b7a16f..9f8b28ad 100644 --- a/screen.go +++ b/screen.go @@ -50,3 +50,13 @@ func Capture(args ...int) (*image.RGBA, error) { return screenshot.Capture(x, y, w, h) } + +// SaveCapture capture screen and save the screenshot to image +func SaveCapture(path string, args ...int) error { + img, err := Capture(args...) + if err != nil { + return err + } + + return Save(img, path) +} From f98b4c52bd545b7d3b5789314f8278b29546a02f Mon Sep 17 00:00:00 2001 From: vcaesar Date: Fri, 16 Aug 2024 11:35:18 -0700 Subject: [PATCH 294/327] Update: update CI to newest --- .circleci/config.yml | 2 +- .github/workflows/go.yml | 4 ++-- appveyor.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 544556f8..930c89f6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,7 +5,7 @@ jobs: docker: # using custom image, see .circleci/images/primary/Dockerfile # - image: govgo/robotgoci:1.10.3 - - image: golang:1.22.0 + - image: golang:1.23.0 working_directory: /gopath/src/github.com/go-vgo/robotgo steps: - checkout diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 59655b42..6b1426c9 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -10,10 +10,10 @@ jobs: runs-on: ${{ matrix.os }} steps: - - name: Set up Go 1.22.0 + - name: Set up Go 1.23.0 uses: actions/setup-go@v1 with: - go-version: 1.22.0 + go-version: 1.23.0 id: go - name: Check out code into the Go module directory diff --git a/appveyor.yml b/appveyor.yml index ae1d56e9..d82094a2 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -34,7 +34,7 @@ environment: PATH: C:\msys64\mingw32\bin\;C:\Program Files (x86)\NSIS\;%PATH% # - COMPILER: MINGW_W64 # ARCHITECTURE: x64 - GOVERSION: 1.22.0 + GOVERSION: 1.23.0 # GOPATH: c:\gopath # scripts that run after cloning repository From 1f437d12e42883cdfeab23d2789bc30582d50df7 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 5 Sep 2024 13:09:51 -0700 Subject: [PATCH 295/327] Update: update go mod --- go.mod | 34 +++++++------ go.sum | 151 ++++++++++++++------------------------------------------- 2 files changed, 55 insertions(+), 130 deletions(-) diff --git a/go.mod b/go.mod index 1b14579b..e9879ee4 100644 --- a/go.mod +++ b/go.mod @@ -1,13 +1,15 @@ module github.com/go-vgo/robotgo -go 1.17 +go 1.22 + +toolchain go1.23.0 require ( github.com/otiai10/gosseract/v2 v2.4.1 // github.com/robotn/gohook v0.31.3 - github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 - github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 - github.com/tailscale/win v0.0.0-20240403170916-6580b55d49ca + github.com/robotn/xgb v0.10.0 + github.com/robotn/xgbutil v0.10.0 + github.com/tailscale/win v0.0.0-20240830200727-2d6766fe9b74 github.com/vcaesar/gops v0.40.0 github.com/vcaesar/imgo v0.40.2 github.com/vcaesar/keycode v0.10.1 @@ -15,21 +17,23 @@ require ( ) require ( - github.com/dblohm7/wingoes v0.0.0-20231019175336-f6e33aa7cc34 // indirect - github.com/gen2brain/shm v0.0.0-20230802011745-f2460f5984f7 // indirect + github.com/dblohm7/wingoes v0.0.0-20240820181039-f2b84150679e // indirect + github.com/gen2brain/shm v0.1.0 // indirect github.com/go-ole/go-ole v1.3.0 // indirect - github.com/jezek/xgb v1.1.0 // indirect - github.com/kbinani/screenshot v0.0.0-20230812210009-b87d31814237 - github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a // indirect + github.com/godbus/dbus/v5 v5.1.0 // indirect + github.com/jezek/xgb v1.1.1 // indirect + github.com/kbinani/screenshot v0.0.0-20240820160931-a8a2c5d0e191 + github.com/lufia/plan9stats v0.0.0-20240819163618-b1d8f4d146e7 // indirect github.com/lxn/win v0.0.0-20210218163916-a377121e959e // indirect - github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect - github.com/shirou/gopsutil/v4 v4.24.5 // indirect + github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect + github.com/shirou/gopsutil/v4 v4.24.8 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect - github.com/tklauser/go-sysconf v0.3.12 // indirect - github.com/tklauser/numcpus v0.6.1 // indirect + github.com/tklauser/go-sysconf v0.3.14 // indirect + github.com/tklauser/numcpus v0.8.0 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect - golang.org/x/image v0.18.0 // indirect - golang.org/x/sys v0.20.0 // indirect + golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e // indirect + golang.org/x/image v0.20.0 // indirect + golang.org/x/sys v0.25.0 // indirect ) // replace golang.org/x/sys => github.com/golang/sys v0.0.0-20190109145017-48ac38b7c8cb diff --git a/go.sum b/go.sum index 5edcf14d..1f853bef 100644 --- a/go.sum +++ b/go.sum @@ -1,63 +1,57 @@ github.com/BurntSushi/freetype-go v0.0.0-20160129220410-b763ddbfe298/go.mod h1:D+QujdIlUNfa0igpNMk6UIvlb6C252URs4yupRUV4lQ= github.com/BurntSushi/graphics-go v0.0.0-20160129215708-b43f31a4a966/go.mod h1:Mid70uvE93zn9wgF92A/r5ixgnvX8Lh68fxp9KQBaI0= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dblohm7/wingoes v0.0.0-20231019175336-f6e33aa7cc34 h1:FBMro26TLQwBk+n4fbTSmSf3QUKb09pvW4fz49lxpl0= -github.com/dblohm7/wingoes v0.0.0-20231019175336-f6e33aa7cc34/go.mod h1:6NCrWM5jRefaG7iN0iMShPalLsljHWBh9v1zxM2f8Xs= -github.com/gen2brain/shm v0.0.0-20230802011745-f2460f5984f7 h1:VLEKvjGJYAMCXw0/32r9io61tEXnMWDRxMk+peyRVFc= -github.com/gen2brain/shm v0.0.0-20230802011745-f2460f5984f7/go.mod h1:uF6rMu/1nvu+5DpiRLwusA6xB8zlkNoGzKn8lmYONUo= +github.com/dblohm7/wingoes v0.0.0-20240820181039-f2b84150679e h1:L+XrFvD0vBIBm+Wf9sFN6aU395t7JROoai0qXZraA4U= +github.com/dblohm7/wingoes v0.0.0-20240820181039-f2b84150679e/go.mod h1:SUxUaAK/0UG5lYyZR1L1nC4AaYYvSSYTWQSH3FPcxKU= +github.com/gen2brain/shm v0.1.0 h1:MwPeg+zJQXN0RM9o+HqaSFypNoNEcNpeoGp0BTSx2YY= +github.com/gen2brain/shm v0.1.0/go.mod h1:UgIcVtvmOu+aCJpqJX7GOtiN7X2ct+TKLg4RTxwPIUA= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= +github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/jezek/xgb v1.1.0 h1:wnpxJzP1+rkbGclEkmwpVFQWpuE2PUGNUzP8SbfFobk= -github.com/jezek/xgb v1.1.0/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk= -github.com/kbinani/screenshot v0.0.0-20230812210009-b87d31814237 h1:YOp8St+CM/AQ9Vp4XYm4272E77MptJDHkwypQHIRl9Q= -github.com/kbinani/screenshot v0.0.0-20230812210009-b87d31814237/go.mod h1:e7qQlOY68wOz4b82D7n+DdaptZAi+SHW0+yKiWZzEYE= -github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= -github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a h1:N9zuLhTvBSRt0gWSiJswwQ2HqDmtX/ZCDJURnKUt1Ik= -github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE= +github.com/jezek/xgb v1.1.1 h1:bE/r8ZZtSv7l9gk6nU0mYx51aXrvnyb44892TwSaqS4= +github.com/jezek/xgb v1.1.1/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk= +github.com/kbinani/screenshot v0.0.0-20240820160931-a8a2c5d0e191 h1:5UHVWNX1qrIbNw7OpKbxe5bHkhHRk3xRKztMjERuCsU= +github.com/kbinani/screenshot v0.0.0-20240820160931-a8a2c5d0e191/go.mod h1:Pmpz2BLf55auQZ67u3rvyI2vAQvNetkK/4zYUmpauZQ= +github.com/lufia/plan9stats v0.0.0-20240819163618-b1d8f4d146e7 h1:5RK988zAqB3/AN3opGfRpoQgAVqr6/A5+qRTi67VUZY= +github.com/lufia/plan9stats v0.0.0-20240819163618-b1d8f4d146e7/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k= github.com/lxn/win v0.0.0-20210218163916-a377121e959e h1:H+t6A/QJMbhCSEH5rAuRxh+CtW96g0Or0Fxa9IKr4uc= github.com/lxn/win v0.0.0-20210218163916-a377121e959e/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk= +github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= +github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= github.com/otiai10/gosseract/v2 v2.4.1 h1:G8AyBpXEeSlcq8TI85LH/pM5SXk8Djy2GEXisgyblRw= github.com/otiai10/gosseract/v2 v2.4.1/go.mod h1:1gNWP4Hgr2o7yqWfs6r5bZxAatjOIdqWxJLWsTsembk= github.com/otiai10/mint v1.6.3 h1:87qsV/aw1F5as1eH1zS/yqHY85ANKVMgkDrf9rcxbQs= github.com/otiai10/mint v1.6.3/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= -github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b h1:0LFwY6Q3gMACTjAbMZBjXAqTOzOwFaj2Ld6cjeQ7Rig= -github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= -github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934 h1:2lhSR8N3T6I30q096DT7/5AKEIcf1vvnnWAmS0wfnNY= +github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU= +github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/robotn/xgb v0.0.0-20190912153532-2cb92d044934/go.mod h1:SxQhJskUJ4rleVU44YvnrdvxQr0tKy5SRSigBrCgyyQ= -github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770 h1:2uX8QRLkkxn2EpAQ6I3KhA79BkdRZfvugJUzJadiJwk= -github.com/robotn/xgbutil v0.0.0-20190912154524-c861d6f87770/go.mod h1:svkDXUDQjUiWzLrA0OZgHc4lbOts3C+uRfP6/yjwYnU= -github.com/shirou/gopsutil/v4 v4.24.5 h1:gGsArG5K6vmsh5hcFOHaPm87UD003CaDMkAOweSQjhM= -github.com/shirou/gopsutil/v4 v4.24.5/go.mod h1:aoebb2vxetJ/yIDZISmduFvVNPHqXQ9SEJwRXxkf0RA= +github.com/robotn/xgb v0.10.0 h1:O3kFbIwtwZ3pgLbp1h5slCQ4OpY8BdwugJLrUe6GPIM= +github.com/robotn/xgb v0.10.0/go.mod h1:SxQhJskUJ4rleVU44YvnrdvxQr0tKy5SRSigBrCgyyQ= +github.com/robotn/xgbutil v0.10.0 h1:gvf7mGQqCWQ68aHRtCxgdewRk+/KAJui6l3MJQQRCKw= +github.com/robotn/xgbutil v0.10.0/go.mod h1:svkDXUDQjUiWzLrA0OZgHc4lbOts3C+uRfP6/yjwYnU= +github.com/shirou/gopsutil/v4 v4.24.8 h1:pVQjIenQkIhqO81mwTaXjTzOMT7d3TZkf43PlVFHENI= +github.com/shirou/gopsutil/v4 v4.24.8/go.mod h1:wE0OrJtj4dG+hYkxqDH3QiBICdKSf04/npcvLLc/oRg= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/tailscale/win v0.0.0-20240403170916-6580b55d49ca h1:oYYp7AvemDkWtxmsgVSpcFxcHMv/2jjbOk5ZC16e77Y= -github.com/tailscale/win v0.0.0-20240403170916-6580b55d49ca/go.mod h1:aMd4yDHLjbOuYP6fMxj1d9ACDQlSWwYztcpybGHCQc8= -github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= -github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= -github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= -github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/tailscale/win v0.0.0-20240830200727-2d6766fe9b74 h1:a6itf7Z0Ahy5z5RVTkasDAbcOIJ/GwWRjkWVgaUhWuo= +github.com/tailscale/win v0.0.0-20240830200727-2d6766fe9b74/go.mod h1:aMd4yDHLjbOuYP6fMxj1d9ACDQlSWwYztcpybGHCQc8= +github.com/tc-hib/winres v0.2.1 h1:YDE0FiP0VmtRaDn7+aaChp1KiF4owBiJa5l964l5ujA= +github.com/tc-hib/winres v0.2.1/go.mod h1:C/JaNhH3KBvhNKVbvdlDWkbMDO9H4fKKDaN7/07SSuk= +github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZb78yU= +github.com/tklauser/go-sysconf v0.3.14/go.mod h1:1ym4lWMLUOhuBOPGtRcJm7tEGX4SCYNEEEtghGG/8uY= +github.com/tklauser/numcpus v0.8.0 h1:Mx4Wwe/FjZLeQsK/6kt2EOepwwSl7SmJrK5bV/dXYgY= +github.com/tklauser/numcpus v0.8.0/go.mod h1:ZJZlAY+dmR4eut8epnzf0u/VwodKmryxR8txiloSqBE= github.com/vcaesar/gops v0.40.0 h1:I+1RCGiV+LkZJUYNzAd373xs0uM2UyeFdZBmow8HfCM= github.com/vcaesar/gops v0.40.0/go.mod h1:3u/USW7JovqUK6i13VOD3qWfvXXd2TIIKE4PYIv4TOM= github.com/vcaesar/imgo v0.40.2 h1:5GWScRLdBCMtO1v2I1bs+ZmDLZFINxYSMZ+mtUw5qPM= @@ -66,90 +60,17 @@ github.com/vcaesar/keycode v0.10.1 h1:0DesGmMAPWpYTCYddOFiCMKCDKgNnwiQa2QXindVUH github.com/vcaesar/keycode v0.10.1/go.mod h1:JNlY7xbKsh+LAGfY2j4M3znVrGEm5W1R8s/Uv6BJcfQ= github.com/vcaesar/tt v0.20.1 h1:D/jUeeVCNbq3ad8M7hhtB3J9x5RZ6I1n1eZ0BJp7M+4= github.com/vcaesar/tt v0.20.1/go.mod h1:cH2+AwGAJm19Wa6xvEa+0r+sXDJBT0QgNQey6mwqLeU= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= -golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= -golang.org/x/exp v0.0.0-20230127140709-cafedaf64729 h1:H2kBA039yqxDv2DScpuC0knhZXO6Evfmt7mN8sGMh/4= -golang.org/x/exp v0.0.0-20230127140709-cafedaf64729/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= -golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ= -golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e h1:I88y4caeGeuDQxgdoFPUq097j7kNfw6uvuiNxUBfcBk= +golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ= +golang.org/x/image v0.20.0 h1:7cVCUjQwfL18gyBJOmYvptfSHS8Fb3YUDtfLIZ7Nbpw= +golang.org/x/image v0.20.0/go.mod h1:0a88To4CYVBAHp5FXJm8o7QbUl37Vd85ply1vyD8auM= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4= -golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From b201ab9f80bb99d7223daf52b622f5f7afaef50f Mon Sep 17 00:00:00 2001 From: vcaesar Date: Thu, 5 Sep 2024 13:23:14 -0700 Subject: [PATCH 296/327] Update: update screengrad with fixed macos 15 --- robotgo.go | 4 ++++ screen/screengrab_c.h | 55 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/robotgo.go b/robotgo.go index f4660ac8..7c79bd4c 100644 --- a/robotgo.go +++ b/robotgo.go @@ -33,6 +33,10 @@ package robotgo #cgo darwin CFLAGS: -x objective-c -Wno-deprecated-declarations #cgo darwin LDFLAGS: -framework Cocoa -framework OpenGL -framework IOKit #cgo darwin LDFLAGS: -framework Carbon -framework CoreFoundation +// +#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > MAC_OS_VERSION_14_4 +#cgo darwin LDFLAGS: -framework ScreenCaptureKit +#endif #cgo linux CFLAGS: -I/usr/src #cgo linux LDFLAGS: -L/usr/src -lm -lX11 -lXtst diff --git a/screen/screengrab_c.h b/screen/screengrab_c.h index 9af73022..3007fb73 100644 --- a/screen/screengrab_c.h +++ b/screen/screengrab_c.h @@ -5,6 +5,7 @@ #include #include #include + #include #elif defined(USE_X11) #include #include @@ -13,6 +14,49 @@ #include #endif +#if defined(IS_MACOSX) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > MAC_OS_VERSION_14_4 + static CGImageRef capture15(CGDirectDisplayID id, CGRect diIntersectDisplayLocal, CGColorSpaceRef colorSpace) { + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + __block CGImageRef image1 = nil; + [SCShareableContent getShareableContentWithCompletionHandler:^(SCShareableContent* content, NSError* error) { + @autoreleasepool { + if (error) { + dispatch_semaphore_signal(semaphore); + return; + } + SCDisplay* target = nil; + for (SCDisplay *display in content.displays) { + if (display.displayID == id) { + target = display; + break; + } + } + if (!target) { + dispatch_semaphore_signal(semaphore); + return; + } + + SCContentFilter* filter = [[SCContentFilter alloc] initWithDisplay:target excludingWindows:@[]]; + SCStreamConfiguration* config = [[SCStreamConfiguration alloc] init]; + config.sourceRect = diIntersectDisplayLocal; + config.width = diIntersectDisplayLocal.size.width; + config.height = diIntersectDisplayLocal.size.height; + [SCScreenshotManager captureImageWithFilter:filter + configuration:config + completionHandler:^(CGImageRef img, NSError* error) { + if (!error) { + image1 = CGImageCreateCopyWithColorSpace(img, colorSpace); + } + dispatch_semaphore_signal(semaphore); + }]; + } + }]; + dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); + dispatch_release(semaphore); + return image1; + } +#endif + MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id, int8_t isPid) { #if defined(IS_MACOSX) MMBitmapRef bitmap = NULL; @@ -25,9 +69,16 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id, } MMPointInt32 o = rect.origin; MMSizeInt32 s = rect.size; - CGImageRef image = CGDisplayCreateImageForRect(displayID, CGRectMake(o.x, o.y, s.w, s.h)); + #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > MAC_OS_VERSION_14_4 + CGColorSpaceRef color = CGColorSpaceCreateWithName(kCGColorSpaceSRGB); + CGImageRef image = capture15(displayID, CGRectMake(o.x, o.y, s.w, s.h), color); + CGColorSpaceRelease(color); + #else + // This API is deprecated in macos 15, use ScreenCaptureKit's captureScreenshot + CGImageRef image = CGDisplayCreateImageForRect(displayID, CGRectMake(o.x, o.y, s.w, s.h)); + #endif if (!image) { return NULL; } - + CFDataRef imageData = CGDataProviderCopyData(CGImageGetDataProvider(image)); if (!imageData) { return NULL; } From cb51e2aa10f1083b4c66a40103fac09a4b12ef15 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 17 Sep 2024 12:59:15 -0700 Subject: [PATCH 297/327] Update: cleary some code style --- screen/screengrab_c.h | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/screen/screengrab_c.h b/screen/screengrab_c.h index 3007fb73..32c30f7c 100644 --- a/screen/screengrab_c.h +++ b/screen/screengrab_c.h @@ -24,6 +24,7 @@ dispatch_semaphore_signal(semaphore); return; } + SCDisplay* target = nil; for (SCDisplay *display in content.displays) { if (display.displayID == id) { @@ -41,16 +42,18 @@ config.sourceRect = diIntersectDisplayLocal; config.width = diIntersectDisplayLocal.size.width; config.height = diIntersectDisplayLocal.size.height; + [SCScreenshotManager captureImageWithFilter:filter - configuration:config - completionHandler:^(CGImageRef img, NSError* error) { - if (!error) { - image1 = CGImageCreateCopyWithColorSpace(img, colorSpace); - } - dispatch_semaphore_signal(semaphore); + configuration:config + completionHandler:^(CGImageRef img, NSError* error) { + if (!error) { + image1 = CGImageCreateCopyWithColorSpace(img, colorSpace); + } + dispatch_semaphore_signal(semaphore); }]; } }]; + dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); dispatch_release(semaphore); return image1; From 3e5b10f7208312e1ac2cdc1fcad415cac8410077 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 17 Sep 2024 13:11:02 -0700 Subject: [PATCH 298/327] Add: export XClose main display function --- robotgo.go | 5 +++++ screen/goScreen.h | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/robotgo.go b/robotgo.go index 7c79bd4c..5ac065a6 100644 --- a/robotgo.go +++ b/robotgo.go @@ -457,6 +457,11 @@ func GetXDisplayName() string { return gname } +// CloseMainDisplay close the main X11 display +func CloseMainDisplay() { + C.close_main_display() +} + // Deprecated: use the ScaledF(), // // ScaleX get the primary display horizontal DPI scale factor, drop diff --git a/screen/goScreen.h b/screen/goScreen.h index 24321bf6..d4349a5a 100644 --- a/screen/goScreen.h +++ b/screen/goScreen.h @@ -79,6 +79,14 @@ char* get_XDisplay_name() { #endif } +void close_main_display() { + #if defined(USE_X11) + XCloseMainDisplay(); + #else + // + #endif +} + uint32_t get_num_displays() { #if defined(IS_MACOSX) uint32_t count = 0; From b1ad7db6bead8499aa3c275be7557f8077e69ed1 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 17 Sep 2024 13:32:46 -0700 Subject: [PATCH 299/327] Add: export Handle data and add more window handle function #683 --- robotgo.go | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/robotgo.go b/robotgo.go index 5ac065a6..f0647fca 100644 --- a/robotgo.go +++ b/robotgo.go @@ -90,6 +90,8 @@ type ( CHex C.MMRGBHex // CBitmap define CBitmap as C.MMBitmapRef type CBitmap C.MMBitmapRef + // Handle define window Handle as C.MData type + Handle C.MData ) // Bitmap define the go Bitmap struct @@ -875,12 +877,22 @@ func IsValid() bool { } // SetActive set the window active -func SetActive(win C.MData) { +func SetActive(win Handle) { + SetActiveC(C.MData(win)) +} + +// SetActiveC set the window active +func SetActiveC(win C.MData) { C.set_active(win) } // GetActive get the active window -func GetActive() C.MData { +func GetActive() Handle { + return Handle(GetActiveC()) +} + +// GetActive get the active window +func GetActiveC() C.MData { mdata := C.get_active() // fmt.Println("active----", mdata) return mdata @@ -954,8 +966,29 @@ func SetHandlePid(pid int, args ...int) { C.set_handle_pid_mData(C.uintptr(pid), C.int8_t(isPid)) } +// GetHandById get handle mdata by id +func GetHandById(id int, args ...int) Handle { + isPid := 1 + if len(args) > 0 { + isPid = args[0] + } + return GetHandByPid(id, isPid) +} + +// GetHandByPid get handle mdata by pid +func GetHandByPid(pid int, args ...int) Handle { + return Handle(GetHandByPidC(pid, args...)) +} + +// Deprecated: use the GetHandByPid(), +// // GetHandPid get handle mdata by pid -func GetHandPid(pid int, args ...int) C.MData { +func GetHandPid(pid int, args ...int) Handle { + return GetHandByPid(pid, args...) +} + +// GetHandByPidC get handle mdata by pid +func GetHandByPidC(pid int, args ...int) C.MData { var isPid int if len(args) > 0 || NotPid { isPid = 1 From c48e3d072c0e8698ec5adf91a4559795a3c2102c Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 17 Sep 2024 13:38:38 -0700 Subject: [PATCH 300/327] Update: Fixed godoc --- robotgo.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/robotgo.go b/robotgo.go index f0647fca..4057b28e 100644 --- a/robotgo.go +++ b/robotgo.go @@ -891,7 +891,7 @@ func GetActive() Handle { return Handle(GetActiveC()) } -// GetActive get the active window +// GetActiveC get the active window func GetActiveC() C.MData { mdata := C.get_active() // fmt.Println("active----", mdata) From 32585668024ce15c2cf9d1354a1f005d1e94e916 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 6 Oct 2024 17:40:34 -0700 Subject: [PATCH 301/327] Update: move scale to screen and rename pub mdata --- screen/screen_c.h | 60 +++++++++++++++++++++++++++++++++++++ window/goWindow.h | 6 ++-- window/pub.h | 2 +- window/win_sys.h | 59 ------------------------------------ window/window.h | 76 +++++++++++++++++++++++------------------------ 5 files changed, 102 insertions(+), 101 deletions(-) diff --git a/screen/screen_c.h b/screen/screen_c.h index 88dcd834..9e5c3a04 100644 --- a/screen/screen_c.h +++ b/screen/screen_c.h @@ -7,6 +7,66 @@ // #include "../base/xdisplay_c.h" #endif +intptr scaleX(); + +double sys_scale(int32_t display_id) { + #if defined(IS_MACOSX) + CGDirectDisplayID displayID = (CGDirectDisplayID) display_id; + if (displayID == -1) { + displayID = CGMainDisplayID(); + } + + CGDisplayModeRef modeRef = CGDisplayCopyDisplayMode(displayID); + double pixelWidth = CGDisplayModeGetPixelWidth(modeRef); + double targetWidth = CGDisplayModeGetWidth(modeRef); + + return pixelWidth / targetWidth; + #elif defined(USE_X11) + Display *dpy = XOpenDisplay(NULL); + + int scr = 0; /* Screen number */ + double xres = ((((double) DisplayWidth(dpy, scr)) * 25.4) / + ((double) DisplayWidthMM(dpy, scr))); + + char *rms = XResourceManagerString(dpy); + if (rms) { + XrmDatabase db = XrmGetStringDatabase(rms); + if (db) { + XrmValue value; + char *type = NULL; + + if (XrmGetResource(db, "Xft.dpi", "String", &type, &value)) { + if (value.addr) { + xres = atof(value.addr); + } + } + + XrmDestroyDatabase(db); + } + } + XCloseDisplay (dpy); + + return xres / 96.0; + #elif defined(IS_WINDOWS) + double s = scaleX() / 96.0; + return s; + #endif +} + +intptr scaleX(){ + #if defined(IS_MACOSX) + return 0; + #elif defined(USE_X11) + return 0; + #elif defined(IS_WINDOWS) + // Get desktop dc + HDC desktopDc = GetDC(NULL); + // Get native resolution + intptr horizontalDPI = GetDeviceCaps(desktopDc, LOGPIXELSX); + return horizontalDPI; + #endif +} + MMSizeInt32 getMainDisplaySize(void) { #if defined(IS_MACOSX) CGDirectDisplayID displayID = CGMainDisplayID(); diff --git a/window/goWindow.h b/window/goWindow.h index cee4ed30..07301807 100644 --- a/window/goWindow.h +++ b/window/goWindow.h @@ -55,11 +55,11 @@ uintptr get_handle(){ uintptr b_get_handle() { #if defined(IS_MACOSX) - return (uintptr)mData.CgID; + return (uintptr)pub_mData.CgID; #elif defined(USE_X11) - return (uintptr)mData.XWin; + return (uintptr)pub_mData.XWin; #elif defined(IS_WINDOWS) - return (uintptr)mData.HWnd; + return (uintptr)pub_mData.HWnd; #endif } diff --git a/window/pub.h b/window/pub.h index af1158b8..cfd0f317 100644 --- a/window/pub.h +++ b/window/pub.h @@ -28,7 +28,7 @@ struct _MData{ }; typedef struct _MData MData; -MData mData; +MData pub_mData; struct _Bounds { int32_t X; // Top left X coordinate diff --git a/window/win_sys.h b/window/win_sys.h index 776899b3..5c15375e 100644 --- a/window/win_sys.h +++ b/window/win_sys.h @@ -13,65 +13,6 @@ #endif Bounds get_client(uintptr pid, int8_t isPid); -intptr scaleX(); - -double sys_scale(int32_t display_id) { - #if defined(IS_MACOSX) - CGDirectDisplayID displayID = (CGDirectDisplayID) display_id; - if (displayID == -1) { - displayID = CGMainDisplayID(); - } - - CGDisplayModeRef modeRef = CGDisplayCopyDisplayMode(displayID); - double pixelWidth = CGDisplayModeGetPixelWidth(modeRef); - double targetWidth = CGDisplayModeGetWidth(modeRef); - - return pixelWidth / targetWidth; - #elif defined(USE_X11) - Display *dpy = XOpenDisplay(NULL); - - int scr = 0; /* Screen number */ - double xres = ((((double) DisplayWidth(dpy, scr)) * 25.4) / - ((double) DisplayWidthMM(dpy, scr))); - - char *rms = XResourceManagerString(dpy); - if (rms) { - XrmDatabase db = XrmGetStringDatabase(rms); - if (db) { - XrmValue value; - char *type = NULL; - - if (XrmGetResource(db, "Xft.dpi", "String", &type, &value)) { - if (value.addr) { - xres = atof(value.addr); - } - } - - XrmDestroyDatabase(db); - } - } - XCloseDisplay (dpy); - - return xres / 96.0; - #elif defined(IS_WINDOWS) - double s = scaleX() / 96.0; - return s; - #endif -} - -intptr scaleX(){ - #if defined(IS_MACOSX) - return 0; - #elif defined(USE_X11) - return 0; - #elif defined(IS_WINDOWS) - // Get desktop dc - HDC desktopDc = GetDC(NULL); - // Get native resolution - intptr horizontalDPI = GetDeviceCaps(desktopDc, LOGPIXELSX); - return horizontalDPI; - #endif -} Bounds get_bounds(uintptr pid, int8_t isPid){ // Check if the window is valid diff --git a/window/window.h b/window/window.h index b206aa8c..bb1382bc 100644 --- a/window/window.h +++ b/window/window.h @@ -24,8 +24,8 @@ uintptr initHandle = 0; void initWindow(uintptr handle){ #if defined(IS_MACOSX) - mData.CgID = 0; - mData.AxID = 0; + pub_mData.CgID = 0; + pub_mData.AxID = 0; #elif defined(USE_X11) Display *rDisplay = XOpenDisplay(NULL); // If atoms loaded @@ -34,10 +34,10 @@ void initWindow(uintptr handle){ if (rDisplay != NULL) {LoadAtoms();} } - mData.XWin = 0; + pub_mData.XWin = 0; XCloseDisplay(rDisplay); #elif defined(IS_WINDOWS) - mData.HWnd = 0; + pub_mData.HWnd = 0; #endif setHandle(handle); } @@ -67,33 +67,33 @@ MData set_handle_pid(uintptr pid, int8_t isPid){ void set_handle_pid_mData(uintptr pid, int8_t isPid){ MData win = set_handle_pid(pid, isPid); - mData = win; + pub_mData = win; } bool is_valid() { initWindow(initHandle); if (!IsAxEnabled(true)) { - printf("%s\n", "Window: Accessibility API is disabled!\n" - "Failed to enable access for assistive devices."); + printf("%s\n", "Window: Accessibility API is disabled! " + "Failed to enable access for assistive devices. \n"); } MData actdata = get_active(); #if defined(IS_MACOSX) - mData.CgID = actdata.CgID; - mData.AxID = actdata.AxID; - if (mData.CgID == 0 || mData.AxID == 0) { return false; } + pub_mData.CgID = actdata.CgID; + pub_mData.AxID = actdata.AxID; + if (pub_mData.CgID == 0 || pub_mData.AxID == 0) { return false; } CFTypeRef r = NULL; // Attempt to get the window role - if (AXUIElementCopyAttributeValue(mData.AxID, kAXRoleAttribute, &r) == kAXErrorSuccess && r){ + if (AXUIElementCopyAttributeValue(pub_mData.AxID, kAXRoleAttribute, &r) == kAXErrorSuccess && r){ CFRelease(r); return true; } return false; #elif defined(USE_X11) - mData.XWin = actdata.XWin; - if (mData.XWin == 0) { return false; } + pub_mData.XWin = actdata.XWin; + if (pub_mData.XWin == 0) { return false; } Display *rDisplay = XOpenDisplay(NULL); // Check for a valid X-Window display @@ -103,7 +103,7 @@ bool is_valid() { XDismissErrors(); // Get the window PID property - void* result = GetWindowProperty(mData, WM_PID,NULL); + void* result = GetWindowProperty(pub_mData, WM_PID,NULL); if (result == NULL) { XCloseDisplay(rDisplay); return false; @@ -115,12 +115,12 @@ bool is_valid() { return true; #elif defined(IS_WINDOWS) - mData.HWnd = actdata.HWnd; - if (mData.HWnd == 0) { + pub_mData.HWnd = actdata.HWnd; + if (pub_mData.HWnd == 0) { return false; } - return IsWindow(mData.HWnd) != 0; + return IsWindow(pub_mData.HWnd) != 0; #endif } @@ -175,13 +175,13 @@ bool IsAxEnabled(bool options){ bool setHandle(uintptr handle){ #if defined(IS_MACOSX) // Release the AX element - if (mData.AxID != NULL) { - CFRelease(mData.AxID); + if (pub_mData.AxID != NULL) { + CFRelease(pub_mData.AxID); } // Reset both values - mData.CgID = 0; - mData.AxID = 0; + pub_mData.CgID = 0; + pub_mData.AxID = 0; if (handle == 0) { // return 0; @@ -192,8 +192,8 @@ bool setHandle(uintptr handle){ CGWindowID cgID = (CGWindowID)handle; AXUIElementRef axID = GetUIElement(cgID); if (axID != NULL){ - mData.CgID = cgID; - mData.AxID = axID; + pub_mData.CgID = cgID; + pub_mData.AxID = axID; // return 0; return true; } @@ -201,7 +201,7 @@ bool setHandle(uintptr handle){ // return 1; return false; #elif defined(USE_X11) - mData.XWin = (Window)handle; + pub_mData.XWin = (Window)handle; if (handle == 0) { return true; } @@ -210,10 +210,10 @@ bool setHandle(uintptr handle){ return true; } - mData.XWin = 0; + pub_mData.XWin = 0; return false; #elif defined(IS_WINDOWS) - mData.HWnd = (HWND)handle; + pub_mData.HWnd = (HWND)handle; if (handle == 0) { return true; } @@ -222,7 +222,7 @@ bool setHandle(uintptr handle){ return true; } - mData.HWnd = 0; + pub_mData.HWnd = 0; return false; #endif } @@ -237,7 +237,7 @@ bool IsTopMost(void){ // XDismissErrors (); // return GetState (mData.XWin, STATE_TOPMOST); #elif defined(IS_WINDOWS) - return (GetWindowLongPtr(mData.HWnd, GWL_EXSTYLE) & WS_EX_TOPMOST) != 0; + return (GetWindowLongPtr(pub_mData.HWnd, GWL_EXSTYLE) & WS_EX_TOPMOST) != 0; #endif } @@ -247,7 +247,7 @@ bool IsMinimized(void){ #if defined(IS_MACOSX) CFBooleanRef data = NULL; // Determine whether the window is minimized - if (AXUIElementCopyAttributeValue(mData.AxID, kAXMinimizedAttribute, + if (AXUIElementCopyAttributeValue(pub_mData.AxID, kAXMinimizedAttribute, (CFTypeRef*) &data) == kAXErrorSuccess && data != NULL) { // Convert resulting data into a bool bool result = CFBooleanGetValue(data); @@ -261,7 +261,7 @@ bool IsMinimized(void){ // XDismissErrors(); // return GetState(mData.XWin, STATE_MINIMIZE); #elif defined(IS_WINDOWS) - return (GetWindowLongPtr(mData.HWnd, GWL_STYLE) & WS_MINIMIZE) != 0; + return (GetWindowLongPtr(pub_mData.HWnd, GWL_STYLE) & WS_MINIMIZE) != 0; #endif } @@ -276,7 +276,7 @@ bool IsMaximized(void){ // XDismissErrors(); // return GetState(mData.XWin, STATE_MAXIMIZE); #elif defined(IS_WINDOWS) - return (GetWindowLongPtr(mData.HWnd, GWL_STYLE) & WS_MAXIMIZE) != 0; + return (GetWindowLongPtr(pub_mData.HWnd, GWL_STYLE) & WS_MAXIMIZE) != 0; #endif } @@ -453,9 +453,9 @@ void SetTopMost(bool state){ #elif defined(USE_X11) // Ignore X errors // XDismissErrors(); - // SetState(mData.XWin, STATE_TOPMOST, state); + // SetState(pub_mData.XWin, STATE_TOPMOST, state); #elif defined(IS_WINDOWS) - SetWindowPos(mData.HWnd, state ? HWND_TOPMOST : HWND_NOTOPMOST, + SetWindowPos(pub_mData.HWnd, state ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); #endif } @@ -464,7 +464,7 @@ void close_main_window () { // Check if the window is valid if (!is_valid()) { return; } - close_window_by_Id(mData); + close_window_by_Id(pub_mData); } void close_window_by_PId(uintptr pid, int8_t isPid){ @@ -502,7 +502,7 @@ char* get_main_title(){ // Check if the window is valid if (!is_valid()) { return "is_valid failed."; } - return get_title_by_hand(mData); + return get_title_by_hand(pub_mData); } char* get_title_by_pid(uintptr pid, int8_t isPid){ @@ -591,7 +591,7 @@ int32_t get_PID(void) { #if defined(IS_MACOSX) pid_t pid = 0; // Attempt to retrieve the window pid - if (AXUIElementGetPid(mData.AxID, &pid)== kAXErrorSuccess) { + if (AXUIElementGetPid(pub_mData.AxID, &pid)== kAXErrorSuccess) { return pid; } return 0; @@ -600,7 +600,7 @@ int32_t get_PID(void) { XDismissErrors(); // Get the window PID - long* result = (long*)GetWindowProperty(mData, WM_PID,NULL); + long* result = (long*)GetWindowProperty(pub_mData, WM_PID,NULL); // Check result and convert it if (result == NULL) { return 0; } @@ -609,7 +609,7 @@ int32_t get_PID(void) { return pid; #elif defined(IS_WINDOWS) DWORD id = 0; - GetWindowThreadProcessId(mData.HWnd, &id); + GetWindowThreadProcessId(pub_mData.HWnd, &id); return id; #endif } From ead43d062eb8f472c34a36fa8c66c4106d040a49 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 6 Oct 2024 17:51:51 -0700 Subject: [PATCH 302/327] Fixed: fix x11 build --- screen/screen_c.h | 1 + window/win_sys.h | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/screen/screen_c.h b/screen/screen_c.h index 9e5c3a04..732feaea 100644 --- a/screen/screen_c.h +++ b/screen/screen_c.h @@ -4,6 +4,7 @@ #include #elif defined(USE_X11) #include + #include // #include "../base/xdisplay_c.h" #endif diff --git a/window/win_sys.h b/window/win_sys.h index 5c15375e..6d536134 100644 --- a/window/win_sys.h +++ b/window/win_sys.h @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#if defined(USE_X11) - #include -#endif +// #if defined(USE_X11) +// #include +// #endif Bounds get_client(uintptr pid, int8_t isPid); From bed6776ca2bdb8a1f9fba988dc1bf82a0c38f56e Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 6 Oct 2024 18:04:17 -0700 Subject: [PATCH 303/327] Fixed: default use high capture resolution in macos15 --- screen.go | 7 ++++--- screen/goScreen.h | 1 - screen/screengrab_c.h | 8 ++++++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/screen.go b/screen.go index 9f8b28ad..1e23bba7 100644 --- a/screen.go +++ b/screen.go @@ -11,6 +11,7 @@ package robotgo import ( + "errors" "image" "github.com/kbinani/screenshot" @@ -53,9 +54,9 @@ func Capture(args ...int) (*image.RGBA, error) { // SaveCapture capture screen and save the screenshot to image func SaveCapture(path string, args ...int) error { - img, err := Capture(args...) - if err != nil { - return err + img := CaptureImg(args...) + if img == nil { + return errors.New("Capture image not found") } return Save(img, path) diff --git a/screen/goScreen.h b/screen/goScreen.h index d4349a5a..1d93d075 100644 --- a/screen/goScreen.h +++ b/screen/goScreen.h @@ -12,7 +12,6 @@ #include "../base/pubs.h" #include "../base/rgb.h" #include "screengrab_c.h" -#include "screen_c.h" #include void padHex(MMRGBHex color, char* hex) { diff --git a/screen/screengrab_c.h b/screen/screengrab_c.h index 32c30f7c..73dcac0e 100644 --- a/screen/screengrab_c.h +++ b/screen/screengrab_c.h @@ -1,4 +1,5 @@ #include "../base/bitmap_free_c.h" +#include "screen_c.h" #include /* malloc() */ #if defined(IS_MACOSX) @@ -39,9 +40,12 @@ SCContentFilter* filter = [[SCContentFilter alloc] initWithDisplay:target excludingWindows:@[]]; SCStreamConfiguration* config = [[SCStreamConfiguration alloc] init]; + config.queueDepth = 5; config.sourceRect = diIntersectDisplayLocal; - config.width = diIntersectDisplayLocal.size.width; - config.height = diIntersectDisplayLocal.size.height; + config.width = diIntersectDisplayLocal.size.width * sys_scale(id); + config.height = diIntersectDisplayLocal.size.height * sys_scale(id); + config.scalesToFit = false; + config.captureResolution = 1; [SCScreenshotManager captureImageWithFilter:filter configuration:config From 75fd24ea0a32f764c249bd3ebc729d25bf4ddb09 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 6 Oct 2024 18:11:23 -0700 Subject: [PATCH 304/327] Fixed: Fixed x11 build --- screen/screengrab_c.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/screen/screengrab_c.h b/screen/screengrab_c.h index 73dcac0e..579c3802 100644 --- a/screen/screengrab_c.h +++ b/screen/screengrab_c.h @@ -1,5 +1,4 @@ #include "../base/bitmap_free_c.h" -#include "screen_c.h" #include /* malloc() */ #if defined(IS_MACOSX) @@ -14,6 +13,7 @@ #elif defined(IS_WINDOWS) #include #endif +#include "screen_c.h" #if defined(IS_MACOSX) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > MAC_OS_VERSION_14_4 static CGImageRef capture15(CGDirectDisplayID id, CGRect diIntersectDisplayLocal, CGColorSpaceRef colorSpace) { From 8db59aac2d88c7e6263d67a7917d13e736955888 Mon Sep 17 00:00:00 2001 From: aohanhongzhi <37319319+aohanhongzhi@users.noreply.github.com> Date: Tue, 8 Oct 2024 04:29:39 +0800 Subject: [PATCH 305/327] capture error (#663) * capture error * aohanhongzhi * Update go.mod --------- Co-authored-by: Evans --- robotgo.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/robotgo.go b/robotgo.go index 4057b28e..b7b68882 100644 --- a/robotgo.go +++ b/robotgo.go @@ -50,6 +50,7 @@ package robotgo import "C" import ( + "errors" "image" "runtime" "time" @@ -366,11 +367,14 @@ func CaptureGo(args ...int) Bitmap { } // CaptureImg capture the screen and return image.Image -func CaptureImg(args ...int) image.Image { +func CaptureImg(args ...int) (image.Image, error) { bit := CaptureScreen(args...) + if bit == nil { + return nil, errors.New("capture error") + } defer FreeBitmap(bit) - return ToImage(bit) + return ToImage(bit), nil } // FreeBitmap free and dealloc the C bitmap From 47cde13dabd393433d846ed05459daa7a4388c58 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 7 Oct 2024 13:45:03 -0700 Subject: [PATCH 306/327] Update: update screen capture code and examples --- .circleci/images/primary/Dockerfile | 2 +- robotgo.go | 4 ++-- screen.go | 9 ++++----- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index ceaf93bd..98f4a97a 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.22.3-stretch AS build +FROM golang:1.23.2-stretch AS build # FROM govgo/go:1.11.1 RUN apt update && apt install -y --no-install-recommends \ diff --git a/robotgo.go b/robotgo.go index b7b68882..7fcca4ce 100644 --- a/robotgo.go +++ b/robotgo.go @@ -366,11 +366,11 @@ func CaptureGo(args ...int) Bitmap { return ToBitmap(bit) } -// CaptureImg capture the screen and return image.Image +// CaptureImg capture the screen and return image.Image, error func CaptureImg(args ...int) (image.Image, error) { bit := CaptureScreen(args...) if bit == nil { - return nil, errors.New("capture error") + return nil, errors.New("Capture image not found.") } defer FreeBitmap(bit) diff --git a/screen.go b/screen.go index 1e23bba7..5062b11c 100644 --- a/screen.go +++ b/screen.go @@ -11,7 +11,6 @@ package robotgo import ( - "errors" "image" "github.com/kbinani/screenshot" @@ -31,7 +30,7 @@ func GetDisplayRect(i int) Rect { Size{W: w, H: h}} } -// Capture capture the screenshot +// Capture capture the screenshot, use the CaptureImg default func Capture(args ...int) (*image.RGBA, error) { displayId := 0 if DisplayID != -1 { @@ -54,9 +53,9 @@ func Capture(args ...int) (*image.RGBA, error) { // SaveCapture capture screen and save the screenshot to image func SaveCapture(path string, args ...int) error { - img := CaptureImg(args...) - if img == nil { - return errors.New("Capture image not found") + img, err := CaptureImg(args...) + if err != nil { + return err } return Save(img, path) From 78d01703b851907cc38d7c303cd2e3d67346a491 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 7 Oct 2024 13:56:46 -0700 Subject: [PATCH 307/327] Update: update examples and test code, README.md --- README.md | 13 +++++++++---- examples/screen/main.go | 14 ++++++++++---- robotgo_test.go | 3 ++- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 763b6bb7..1c6e7918 100644 --- a/README.md +++ b/README.md @@ -268,13 +268,18 @@ func main() { num := robotgo.DisplaysNum() for i := 0; i < num; i++ { robotgo.DisplayID = i - img1 := robotgo.CaptureImg() + img1, _ := robotgo.CaptureImg() path1 := "save_" + strconv.Itoa(i) robotgo.Save(img1, path1+".png") robotgo.SaveJpeg(img1, path1+".jpeg", 50) - img2 := robotgo.CaptureImg(10, 10, 20, 20) + img2, _ := robotgo.CaptureImg(10, 10, 20, 20) robotgo.Save(img2, "test_"+strconv.Itoa(i)+".png") + + x, y, w, h := robotgo.GetDisplayBounds(i) + img3, err := robotgo.CaptureImg(x, y, w, h) + fmt.Println("Capture error: ", err) + robotgo.Save(img3, path1+"_1.png") } } ``` @@ -354,8 +359,8 @@ func opencv() { // bit1 := robotgo.CaptureScreen(10, 10, 30, 30) // img1 := robotgo.ToImage(bit1) // defer robotgo.FreeBitmapArr(bit0, bit1) - img := robotgo.CaptureImg() - img1 := robotgo.CaptureImg(10, 10, 30, 30) + img, _ := robotgo.CaptureImg() + img1, _ := robotgo.CaptureImg(10, 10, 30, 30) fmt.Print("gcv find image: ") fmt.Println(gcv.FindImg(img1, img)) diff --git a/examples/screen/main.go b/examples/screen/main.go index 6ea37f89..9e8ebe76 100644 --- a/examples/screen/main.go +++ b/examples/screen/main.go @@ -29,23 +29,29 @@ func bitmap() { gbitMap := robotgo.CaptureGo() fmt.Println("Go CaptureScreen...", gbitMap.Width) // fmt.Println("...", gbitmap.Width, gbitmap.BytesPerPixel) - // robotgo.SaveCapture("saveCapture.png", 10, 20, 100, 100) + robotgo.SaveCapture("saveCapture.png", 10, 20, 100, 100) - img := robotgo.CaptureImg() + img, err := robotgo.CaptureImg() + fmt.Println("error: ", err) robotgo.Save(img, "save.png") num := robotgo.DisplaysNum() for i := 0; i < num; i++ { robotgo.DisplayID = i - img1 := robotgo.CaptureImg() + img1, _ := robotgo.CaptureImg() path1 := "save_" + strconv.Itoa(i) robotgo.Save(img1, path1+".png") robotgo.SaveJpeg(img1, path1+".jpeg", 50) - img2 := robotgo.CaptureImg(10, 10, 20, 20) + img2, _ := robotgo.CaptureImg(10, 10, 20, 20) path2 := "test_" + strconv.Itoa(i) robotgo.Save(img2, path2+".png") robotgo.SaveJpeg(img2, path2+".jpeg", 50) + + x, y, w, h := robotgo.GetDisplayBounds(i) + img3, err := robotgo.CaptureImg(x, y, w, h) + fmt.Println("Capture error: ", err) + robotgo.Save(img3, path2+"_1.png") } } diff --git a/robotgo_test.go b/robotgo_test.go index 82d0e9e0..a9bcc4ce 100644 --- a/robotgo_test.go +++ b/robotgo_test.go @@ -179,7 +179,8 @@ func TestImage(t *testing.T) { err := SavePng(img, "robot_test.png") tt.Nil(t, err) - img1 := CaptureImg(10, 10, 20, 20) + img1, err := CaptureImg(10, 10, 20, 20) + tt.Nil(t, err) e := Save(img1, "robot_img.jpeg", 50) tt.Nil(t, e) From 70f811ce53dd8e0fb0c1a55c760558862604ac50 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 7 Oct 2024 14:09:01 -0700 Subject: [PATCH 308/327] Update: update readme.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1c6e7918..4c1a72fd 100644 --- a/README.md +++ b/README.md @@ -277,9 +277,9 @@ func main() { robotgo.Save(img2, "test_"+strconv.Itoa(i)+".png") x, y, w, h := robotgo.GetDisplayBounds(i) - img3, err := robotgo.CaptureImg(x, y, w, h) - fmt.Println("Capture error: ", err) - robotgo.Save(img3, path1+"_1.png") + img3, err := robotgo.CaptureImg(x, y, w, h) + fmt.Println("Capture error: ", err) + robotgo.Save(img3, path1+"_1.png") } } ``` From a84a195c4c71a8ee9999e4f265c4e7d09d411c24 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 7 Oct 2024 14:15:17 -0700 Subject: [PATCH 309/327] Update: update go mod --- go.mod | 22 +++++++++++----------- go.sum | 38 ++++++++++++++++++-------------------- 2 files changed, 29 insertions(+), 31 deletions(-) diff --git a/go.mod b/go.mod index e9879ee4..a30d11ba 100644 --- a/go.mod +++ b/go.mod @@ -1,15 +1,15 @@ module github.com/go-vgo/robotgo -go 1.22 +go 1.22.0 -toolchain go1.23.0 +toolchain go1.23.2 require ( github.com/otiai10/gosseract/v2 v2.4.1 // github.com/robotn/gohook v0.31.3 github.com/robotn/xgb v0.10.0 github.com/robotn/xgbutil v0.10.0 - github.com/tailscale/win v0.0.0-20240830200727-2d6766fe9b74 + github.com/tailscale/win v0.0.0-20240926211701-28f7e73c7afb github.com/vcaesar/gops v0.40.0 github.com/vcaesar/imgo v0.40.2 github.com/vcaesar/keycode v0.10.1 @@ -18,22 +18,22 @@ require ( require ( github.com/dblohm7/wingoes v0.0.0-20240820181039-f2b84150679e // indirect - github.com/gen2brain/shm v0.1.0 // indirect + github.com/ebitengine/purego v0.8.0 // indirect + github.com/gen2brain/shm v0.1.1 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/jezek/xgb v1.1.1 // indirect github.com/kbinani/screenshot v0.0.0-20240820160931-a8a2c5d0e191 - github.com/lufia/plan9stats v0.0.0-20240819163618-b1d8f4d146e7 // indirect + github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 // indirect github.com/lxn/win v0.0.0-20210218163916-a377121e959e // indirect github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect - github.com/shirou/gopsutil/v4 v4.24.8 // indirect - github.com/shoenig/go-m1cpu v0.1.6 // indirect + github.com/shirou/gopsutil/v4 v4.24.9 // indirect github.com/tklauser/go-sysconf v0.3.14 // indirect - github.com/tklauser/numcpus v0.8.0 // indirect + github.com/tklauser/numcpus v0.9.0 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect - golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e // indirect - golang.org/x/image v0.20.0 // indirect - golang.org/x/sys v0.25.0 // indirect + golang.org/x/exp v0.0.0-20241004190924-225e2abe05e6 // indirect + golang.org/x/image v0.21.0 // indirect + golang.org/x/sys v0.26.0 // indirect ) // replace golang.org/x/sys => github.com/golang/sys v0.0.0-20190109145017-48ac38b7c8cb diff --git a/go.sum b/go.sum index 1f853bef..97a9b3f0 100644 --- a/go.sum +++ b/go.sum @@ -4,8 +4,10 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dblohm7/wingoes v0.0.0-20240820181039-f2b84150679e h1:L+XrFvD0vBIBm+Wf9sFN6aU395t7JROoai0qXZraA4U= github.com/dblohm7/wingoes v0.0.0-20240820181039-f2b84150679e/go.mod h1:SUxUaAK/0UG5lYyZR1L1nC4AaYYvSSYTWQSH3FPcxKU= -github.com/gen2brain/shm v0.1.0 h1:MwPeg+zJQXN0RM9o+HqaSFypNoNEcNpeoGp0BTSx2YY= -github.com/gen2brain/shm v0.1.0/go.mod h1:UgIcVtvmOu+aCJpqJX7GOtiN7X2ct+TKLg4RTxwPIUA= +github.com/ebitengine/purego v0.8.0 h1:JbqvnEzRvPpxhCJzJJ2y0RbiZ8nyjccVUrSM3q+GvvE= +github.com/ebitengine/purego v0.8.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= +github.com/gen2brain/shm v0.1.1 h1:1cTVA5qcsUFixnDHl14TmRoxgfWEEZlTezpUj1vm5uQ= +github.com/gen2brain/shm v0.1.1/go.mod h1:UgIcVtvmOu+aCJpqJX7GOtiN7X2ct+TKLg4RTxwPIUA= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= @@ -17,8 +19,8 @@ github.com/jezek/xgb v1.1.1 h1:bE/r8ZZtSv7l9gk6nU0mYx51aXrvnyb44892TwSaqS4= github.com/jezek/xgb v1.1.1/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk= github.com/kbinani/screenshot v0.0.0-20240820160931-a8a2c5d0e191 h1:5UHVWNX1qrIbNw7OpKbxe5bHkhHRk3xRKztMjERuCsU= github.com/kbinani/screenshot v0.0.0-20240820160931-a8a2c5d0e191/go.mod h1:Pmpz2BLf55auQZ67u3rvyI2vAQvNetkK/4zYUmpauZQ= -github.com/lufia/plan9stats v0.0.0-20240819163618-b1d8f4d146e7 h1:5RK988zAqB3/AN3opGfRpoQgAVqr6/A5+qRTi67VUZY= -github.com/lufia/plan9stats v0.0.0-20240819163618-b1d8f4d146e7/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k= +github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 h1:7UMa6KCCMjZEMDtTVdcGu0B1GmmC7QJKiCCjyTAWQy0= +github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k= github.com/lxn/win v0.0.0-20210218163916-a377121e959e h1:H+t6A/QJMbhCSEH5rAuRxh+CtW96g0Or0Fxa9IKr4uc= github.com/lxn/win v0.0.0-20210218163916-a377121e959e/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= @@ -36,22 +38,18 @@ github.com/robotn/xgb v0.10.0 h1:O3kFbIwtwZ3pgLbp1h5slCQ4OpY8BdwugJLrUe6GPIM= github.com/robotn/xgb v0.10.0/go.mod h1:SxQhJskUJ4rleVU44YvnrdvxQr0tKy5SRSigBrCgyyQ= github.com/robotn/xgbutil v0.10.0 h1:gvf7mGQqCWQ68aHRtCxgdewRk+/KAJui6l3MJQQRCKw= github.com/robotn/xgbutil v0.10.0/go.mod h1:svkDXUDQjUiWzLrA0OZgHc4lbOts3C+uRfP6/yjwYnU= -github.com/shirou/gopsutil/v4 v4.24.8 h1:pVQjIenQkIhqO81mwTaXjTzOMT7d3TZkf43PlVFHENI= -github.com/shirou/gopsutil/v4 v4.24.8/go.mod h1:wE0OrJtj4dG+hYkxqDH3QiBICdKSf04/npcvLLc/oRg= -github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= -github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= -github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= -github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= +github.com/shirou/gopsutil/v4 v4.24.9 h1:KIV+/HaHD5ka5f570RZq+2SaeFsb/pq+fp2DGNWYoOI= +github.com/shirou/gopsutil/v4 v4.24.9/go.mod h1:3fkaHNeYsUFCGZ8+9vZVWtbyM1k2eRnlL+bWO8Bxa/Q= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/tailscale/win v0.0.0-20240830200727-2d6766fe9b74 h1:a6itf7Z0Ahy5z5RVTkasDAbcOIJ/GwWRjkWVgaUhWuo= -github.com/tailscale/win v0.0.0-20240830200727-2d6766fe9b74/go.mod h1:aMd4yDHLjbOuYP6fMxj1d9ACDQlSWwYztcpybGHCQc8= +github.com/tailscale/win v0.0.0-20240926211701-28f7e73c7afb h1:5C+a9Lxq5GYIxsAF8JsMOlZ90+bOFSUQJ8J6XVk4vUM= +github.com/tailscale/win v0.0.0-20240926211701-28f7e73c7afb/go.mod h1:aMd4yDHLjbOuYP6fMxj1d9ACDQlSWwYztcpybGHCQc8= github.com/tc-hib/winres v0.2.1 h1:YDE0FiP0VmtRaDn7+aaChp1KiF4owBiJa5l964l5ujA= github.com/tc-hib/winres v0.2.1/go.mod h1:C/JaNhH3KBvhNKVbvdlDWkbMDO9H4fKKDaN7/07SSuk= github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZb78yU= github.com/tklauser/go-sysconf v0.3.14/go.mod h1:1ym4lWMLUOhuBOPGtRcJm7tEGX4SCYNEEEtghGG/8uY= -github.com/tklauser/numcpus v0.8.0 h1:Mx4Wwe/FjZLeQsK/6kt2EOepwwSl7SmJrK5bV/dXYgY= -github.com/tklauser/numcpus v0.8.0/go.mod h1:ZJZlAY+dmR4eut8epnzf0u/VwodKmryxR8txiloSqBE= +github.com/tklauser/numcpus v0.9.0 h1:lmyCHtANi8aRUgkckBgoDk1nHCux3n2cgkJLXdQGPDo= +github.com/tklauser/numcpus v0.9.0/go.mod h1:SN6Nq1O3VychhC1npsWostA+oW+VOQTxZrS604NSRyI= github.com/vcaesar/gops v0.40.0 h1:I+1RCGiV+LkZJUYNzAd373xs0uM2UyeFdZBmow8HfCM= github.com/vcaesar/gops v0.40.0/go.mod h1:3u/USW7JovqUK6i13VOD3qWfvXXd2TIIKE4PYIv4TOM= github.com/vcaesar/imgo v0.40.2 h1:5GWScRLdBCMtO1v2I1bs+ZmDLZFINxYSMZ+mtUw5qPM= @@ -62,15 +60,15 @@ github.com/vcaesar/tt v0.20.1 h1:D/jUeeVCNbq3ad8M7hhtB3J9x5RZ6I1n1eZ0BJp7M+4= github.com/vcaesar/tt v0.20.1/go.mod h1:cH2+AwGAJm19Wa6xvEa+0r+sXDJBT0QgNQey6mwqLeU= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e h1:I88y4caeGeuDQxgdoFPUq097j7kNfw6uvuiNxUBfcBk= -golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ= -golang.org/x/image v0.20.0 h1:7cVCUjQwfL18gyBJOmYvptfSHS8Fb3YUDtfLIZ7Nbpw= -golang.org/x/image v0.20.0/go.mod h1:0a88To4CYVBAHp5FXJm8o7QbUl37Vd85ply1vyD8auM= +golang.org/x/exp v0.0.0-20241004190924-225e2abe05e6 h1:1wqE9dj9NpSm04INVsJhhEUzhuDVjbcyKH91sVyPATw= +golang.org/x/exp v0.0.0-20241004190924-225e2abe05e6/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8= +golang.org/x/image v0.21.0 h1:c5qV36ajHpdj4Qi0GnE0jUc/yuo33OLFaa0d+crTD5s= +golang.org/x/image v0.21.0/go.mod h1:vUbsLavqK/W303ZroQQVKQ+Af3Yl6Uz1Ppu5J/cLz78= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From 0b18fa505855510e1dcc6612ce22918eb109ee64 Mon Sep 17 00:00:00 2001 From: Ronald Petty Date: Mon, 9 Dec 2024 19:51:43 -0800 Subject: [PATCH 310/327] Update README.md Added missing import --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 4c1a72fd..8d92f5fd 100644 --- a/README.md +++ b/README.md @@ -244,6 +244,7 @@ package main import ( "fmt" + "strconv" "github.com/go-vgo/robotgo" "github.com/vcaesar/imgo" From d300eedf5432e2a1c63588ec7442011eb5bec5e1 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Mon, 17 Feb 2025 15:54:57 -0800 Subject: [PATCH 311/327] Update: updated go mod --- go.mod | 18 +++++++++--------- go.sum | 32 ++++++++++++++++---------------- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/go.mod b/go.mod index a30d11ba..3d05e374 100644 --- a/go.mod +++ b/go.mod @@ -1,15 +1,15 @@ module github.com/go-vgo/robotgo -go 1.22.0 +go 1.23.0 -toolchain go1.23.2 +toolchain go1.23.6 require ( github.com/otiai10/gosseract/v2 v2.4.1 // github.com/robotn/gohook v0.31.3 github.com/robotn/xgb v0.10.0 github.com/robotn/xgbutil v0.10.0 - github.com/tailscale/win v0.0.0-20240926211701-28f7e73c7afb + github.com/tailscale/win v0.0.0-20250213223159-5992cb43ca35 github.com/vcaesar/gops v0.40.0 github.com/vcaesar/imgo v0.40.2 github.com/vcaesar/keycode v0.10.1 @@ -18,22 +18,22 @@ require ( require ( github.com/dblohm7/wingoes v0.0.0-20240820181039-f2b84150679e // indirect - github.com/ebitengine/purego v0.8.0 // indirect + github.com/ebitengine/purego v0.8.2 // indirect github.com/gen2brain/shm v0.1.1 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/jezek/xgb v1.1.1 // indirect - github.com/kbinani/screenshot v0.0.0-20240820160931-a8a2c5d0e191 + github.com/kbinani/screenshot v0.0.0-20250118074034-a3924b7bbc8c github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 // indirect github.com/lxn/win v0.0.0-20210218163916-a377121e959e // indirect github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect - github.com/shirou/gopsutil/v4 v4.24.9 // indirect + github.com/shirou/gopsutil/v4 v4.25.1 // indirect github.com/tklauser/go-sysconf v0.3.14 // indirect github.com/tklauser/numcpus v0.9.0 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect - golang.org/x/exp v0.0.0-20241004190924-225e2abe05e6 // indirect - golang.org/x/image v0.21.0 // indirect - golang.org/x/sys v0.26.0 // indirect + golang.org/x/exp v0.0.0-20250215185904-eff6e970281f // indirect + golang.org/x/image v0.24.0 // indirect + golang.org/x/sys v0.30.0 // indirect ) // replace golang.org/x/sys => github.com/golang/sys v0.0.0-20190109145017-48ac38b7c8cb diff --git a/go.sum b/go.sum index 97a9b3f0..aaa9f16b 100644 --- a/go.sum +++ b/go.sum @@ -4,8 +4,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dblohm7/wingoes v0.0.0-20240820181039-f2b84150679e h1:L+XrFvD0vBIBm+Wf9sFN6aU395t7JROoai0qXZraA4U= github.com/dblohm7/wingoes v0.0.0-20240820181039-f2b84150679e/go.mod h1:SUxUaAK/0UG5lYyZR1L1nC4AaYYvSSYTWQSH3FPcxKU= -github.com/ebitengine/purego v0.8.0 h1:JbqvnEzRvPpxhCJzJJ2y0RbiZ8nyjccVUrSM3q+GvvE= -github.com/ebitengine/purego v0.8.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= +github.com/ebitengine/purego v0.8.2 h1:jPPGWs2sZ1UgOSgD2bClL0MJIqu58nOmIcBuXr62z1I= +github.com/ebitengine/purego v0.8.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= github.com/gen2brain/shm v0.1.1 h1:1cTVA5qcsUFixnDHl14TmRoxgfWEEZlTezpUj1vm5uQ= github.com/gen2brain/shm v0.1.1/go.mod h1:UgIcVtvmOu+aCJpqJX7GOtiN7X2ct+TKLg4RTxwPIUA= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= @@ -17,8 +17,8 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/jezek/xgb v1.1.1 h1:bE/r8ZZtSv7l9gk6nU0mYx51aXrvnyb44892TwSaqS4= github.com/jezek/xgb v1.1.1/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk= -github.com/kbinani/screenshot v0.0.0-20240820160931-a8a2c5d0e191 h1:5UHVWNX1qrIbNw7OpKbxe5bHkhHRk3xRKztMjERuCsU= -github.com/kbinani/screenshot v0.0.0-20240820160931-a8a2c5d0e191/go.mod h1:Pmpz2BLf55auQZ67u3rvyI2vAQvNetkK/4zYUmpauZQ= +github.com/kbinani/screenshot v0.0.0-20250118074034-a3924b7bbc8c h1:1IlzDla/ZATV/FsRn1ETf7ir91PHS2mrd4VMunEtd9k= +github.com/kbinani/screenshot v0.0.0-20250118074034-a3924b7bbc8c/go.mod h1:Pmpz2BLf55auQZ67u3rvyI2vAQvNetkK/4zYUmpauZQ= github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 h1:7UMa6KCCMjZEMDtTVdcGu0B1GmmC7QJKiCCjyTAWQy0= github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k= github.com/lxn/win v0.0.0-20210218163916-a377121e959e h1:H+t6A/QJMbhCSEH5rAuRxh+CtW96g0Or0Fxa9IKr4uc= @@ -38,12 +38,12 @@ github.com/robotn/xgb v0.10.0 h1:O3kFbIwtwZ3pgLbp1h5slCQ4OpY8BdwugJLrUe6GPIM= github.com/robotn/xgb v0.10.0/go.mod h1:SxQhJskUJ4rleVU44YvnrdvxQr0tKy5SRSigBrCgyyQ= github.com/robotn/xgbutil v0.10.0 h1:gvf7mGQqCWQ68aHRtCxgdewRk+/KAJui6l3MJQQRCKw= github.com/robotn/xgbutil v0.10.0/go.mod h1:svkDXUDQjUiWzLrA0OZgHc4lbOts3C+uRfP6/yjwYnU= -github.com/shirou/gopsutil/v4 v4.24.9 h1:KIV+/HaHD5ka5f570RZq+2SaeFsb/pq+fp2DGNWYoOI= -github.com/shirou/gopsutil/v4 v4.24.9/go.mod h1:3fkaHNeYsUFCGZ8+9vZVWtbyM1k2eRnlL+bWO8Bxa/Q= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/tailscale/win v0.0.0-20240926211701-28f7e73c7afb h1:5C+a9Lxq5GYIxsAF8JsMOlZ90+bOFSUQJ8J6XVk4vUM= -github.com/tailscale/win v0.0.0-20240926211701-28f7e73c7afb/go.mod h1:aMd4yDHLjbOuYP6fMxj1d9ACDQlSWwYztcpybGHCQc8= +github.com/shirou/gopsutil/v4 v4.25.1 h1:QSWkTc+fu9LTAWfkZwZ6j8MSUk4A2LV7rbH0ZqmLjXs= +github.com/shirou/gopsutil/v4 v4.25.1/go.mod h1:RoUCUpndaJFtT+2zsZzzmhvbfGoDCJ7nFXKJf8GqJbI= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tailscale/win v0.0.0-20250213223159-5992cb43ca35 h1:wAZbkTZkqDzWsqxPh2qkBd3KvFU7tcxV0BP0Rnhkxog= +github.com/tailscale/win v0.0.0-20250213223159-5992cb43ca35/go.mod h1:aMd4yDHLjbOuYP6fMxj1d9ACDQlSWwYztcpybGHCQc8= github.com/tc-hib/winres v0.2.1 h1:YDE0FiP0VmtRaDn7+aaChp1KiF4owBiJa5l964l5ujA= github.com/tc-hib/winres v0.2.1/go.mod h1:C/JaNhH3KBvhNKVbvdlDWkbMDO9H4fKKDaN7/07SSuk= github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZb78yU= @@ -60,15 +60,15 @@ github.com/vcaesar/tt v0.20.1 h1:D/jUeeVCNbq3ad8M7hhtB3J9x5RZ6I1n1eZ0BJp7M+4= github.com/vcaesar/tt v0.20.1/go.mod h1:cH2+AwGAJm19Wa6xvEa+0r+sXDJBT0QgNQey6mwqLeU= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -golang.org/x/exp v0.0.0-20241004190924-225e2abe05e6 h1:1wqE9dj9NpSm04INVsJhhEUzhuDVjbcyKH91sVyPATw= -golang.org/x/exp v0.0.0-20241004190924-225e2abe05e6/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8= -golang.org/x/image v0.21.0 h1:c5qV36ajHpdj4Qi0GnE0jUc/yuo33OLFaa0d+crTD5s= -golang.org/x/image v0.21.0/go.mod h1:vUbsLavqK/W303ZroQQVKQ+Af3Yl6Uz1Ppu5J/cLz78= +golang.org/x/exp v0.0.0-20250215185904-eff6e970281f h1:oFMYAjX0867ZD2jcNiLBrI9BdpmEkvPyi5YrBGXbamg= +golang.org/x/exp v0.0.0-20250215185904-eff6e970281f/go.mod h1:BHOTPb3L19zxehTsLoJXVaTktb06DFgmdW6Wb9s8jqk= +golang.org/x/image v0.24.0 h1:AN7zRgVsbvmTfNyqIbbOraYL8mSwcKncEj8ofjgzcMQ= +golang.org/x/image v0.24.0/go.mod h1:4b/ITuLfqYq1hqZcjofwctIhi7sZh2WaCjvsBNjjya8= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= -golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From 6a1f060a8c907cdb37a2890db2bbc7a7c66d1904 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sat, 8 Mar 2025 15:02:39 -0800 Subject: [PATCH 312/327] Refactor: simplify mouse movement implementation for Windows, use setCursorPos instead of mouse_event --- mouse/mouse_c.h | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/mouse/mouse_c.h b/mouse/mouse_c.h index 0f4ee863..adf8b7d2 100644 --- a/mouse/mouse_c.h +++ b/mouse/mouse_c.h @@ -96,25 +96,7 @@ void moveMouse(MMPointInt32 point){ XSync(display, false); #elif defined(IS_WINDOWS) - // Mouse motion is now done using SendInput with MOUSEINPUT. - // We use Absolute mouse positioning - #define MOUSE_COORD_TO_ABS(coord, width_or_height) ( \ - ((65536 * coord) / width_or_height) + (coord < 0 ? -1 : 1)) - - MMRectInt32 rect = getScreenRect(1); - int32_t x = MOUSE_COORD_TO_ABS(point.x - rect.origin.x, rect.size.w); - int32_t y = MOUSE_COORD_TO_ABS(point.y - rect.origin.y, rect.size.h); - - INPUT mouseInput; - mouseInput.type = INPUT_MOUSE; - mouseInput.mi.dx = x; - mouseInput.mi.dy = y; - mouseInput.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE | MOUSEEVENTF_VIRTUALDESK; - mouseInput.mi.time = 0; // System will provide the timestamp - - mouseInput.mi.dwExtraInfo = 0; - mouseInput.mi.mouseData = 0; - SendInput(1, &mouseInput, sizeof(mouseInput)); + SetCursorPos(point.x, point.y); #endif } From df0731c4df589c96da3f5183ebd745ccee6b1d24 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Fri, 11 Apr 2025 14:34:15 -0700 Subject: [PATCH 313/327] Fixed: fixed windows Scale #713 and Update readme.md --- README.md | 24 ++++++++++++++++++++++-- robotgo.go | 4 ++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 8d92f5fd..fe5b6bd3 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,9 @@ GCC ``` #### For MacOS: +``` +brew install go +``` Xcode Command Line Tools (And Privacy setting: [#277](https://github.com/go-vgo/robotgo/issues/277)) @@ -69,8 +72,15 @@ xcode-select --install ``` #### For Windows: +``` +winget install Golang.go +``` + +``` +winget install MartinStorsjo.LLVM-MinGW.UCRT +``` -[MinGW-w64](https://sourceforge.net/projects/mingw-w64/files) (Use recommended) or others Mingw [llvm-mingw](https://github.com/mstorsjo/llvm-mingw); +Or [MinGW-w64](https://sourceforge.net/projects/mingw-w64/files) (Use recommended) or others Mingw [llvm-mingw](https://github.com/mstorsjo/llvm-mingw); Download the Mingw, then set system environment variables `C:\mingw64\bin` to the Path. [Set environment variables to run GCC from command line](https://www.youtube.com/results?search_query=Set+environment+variables+to+run+GCC+from+command+line). @@ -96,6 +106,9 @@ X11 with the XTest extension (the Xtst library) ##### Ubuntu: ```yml +# sudo apt install golang +sudo snap install go --classic + # gcc sudo apt install gcc libc6-dev @@ -165,11 +178,18 @@ Note go1.10.x C file compilation cache problem, [golang #24355](https://github.c package main import ( + "fmt" "github.com/go-vgo/robotgo" ) func main() { - robotgo.MouseSleep = 100 + robotgo.MouseSleep = 300 + + robotgo.Move(100, 100) + fmt.Println(robotgo.Location()) + robotgo.Move(100, -200) // multi screen supported + robotgo.MoveSmooth(120, -150) + fmt.Println(robotgo.Location()) robotgo.ScrollDir(10, "up") robotgo.ScrollDir(20, "right") diff --git a/robotgo.go b/robotgo.go index 7fcca4ce..e946539a 100644 --- a/robotgo.go +++ b/robotgo.go @@ -506,7 +506,7 @@ func CheckMouse(btn string) C.MMMouseButton { // MoveScale calculate the os scale factor x, y func MoveScale(x, y int, displayId ...int) (int, int) { - if Scale && runtime.GOOS == "windows" { + if Scale || runtime.GOOS == "windows" { f := ScaleF() x, y = Scaled1(x, f), Scaled1(y, f) } @@ -630,7 +630,7 @@ func Location() (int, int) { x := int(pos.x) y := int(pos.y) - if runtime.GOOS == "windows" { + if Scale || runtime.GOOS == "windows" { f := ScaleF() x, y = Scaled0(x, f), Scaled0(y, f) } From 5fc2bd4c73257589ec8b3881e5d4adc7a16148ae Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sat, 19 Apr 2025 10:05:01 -0700 Subject: [PATCH 314/327] Fix: fixed mac os version min required #698 --- go.mod | 2 +- go.sum | 4 ++-- screen/screengrab_c.h | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 3d05e374..c3fdaf5e 100644 --- a/go.mod +++ b/go.mod @@ -23,13 +23,13 @@ require ( github.com/go-ole/go-ole v1.3.0 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/jezek/xgb v1.1.1 // indirect - github.com/kbinani/screenshot v0.0.0-20250118074034-a3924b7bbc8c github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 // indirect github.com/lxn/win v0.0.0-20210218163916-a377121e959e // indirect github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect github.com/shirou/gopsutil/v4 v4.25.1 // indirect github.com/tklauser/go-sysconf v0.3.14 // indirect github.com/tklauser/numcpus v0.9.0 // indirect + github.com/vcaesar/screenshot v0.11.0 github.com/yusufpapurcu/wmi v1.2.4 // indirect golang.org/x/exp v0.0.0-20250215185904-eff6e970281f // indirect golang.org/x/image v0.24.0 // indirect diff --git a/go.sum b/go.sum index aaa9f16b..f721e402 100644 --- a/go.sum +++ b/go.sum @@ -17,8 +17,6 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/jezek/xgb v1.1.1 h1:bE/r8ZZtSv7l9gk6nU0mYx51aXrvnyb44892TwSaqS4= github.com/jezek/xgb v1.1.1/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk= -github.com/kbinani/screenshot v0.0.0-20250118074034-a3924b7bbc8c h1:1IlzDla/ZATV/FsRn1ETf7ir91PHS2mrd4VMunEtd9k= -github.com/kbinani/screenshot v0.0.0-20250118074034-a3924b7bbc8c/go.mod h1:Pmpz2BLf55auQZ67u3rvyI2vAQvNetkK/4zYUmpauZQ= github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 h1:7UMa6KCCMjZEMDtTVdcGu0B1GmmC7QJKiCCjyTAWQy0= github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k= github.com/lxn/win v0.0.0-20210218163916-a377121e959e h1:H+t6A/QJMbhCSEH5rAuRxh+CtW96g0Or0Fxa9IKr4uc= @@ -56,6 +54,8 @@ github.com/vcaesar/imgo v0.40.2 h1:5GWScRLdBCMtO1v2I1bs+ZmDLZFINxYSMZ+mtUw5qPM= github.com/vcaesar/imgo v0.40.2/go.mod h1:MVCl+FxHI2gTgmiHoi0n5xNCbYcfv9SVtdEOUC92+eo= github.com/vcaesar/keycode v0.10.1 h1:0DesGmMAPWpYTCYddOFiCMKCDKgNnwiQa2QXindVUHw= github.com/vcaesar/keycode v0.10.1/go.mod h1:JNlY7xbKsh+LAGfY2j4M3znVrGEm5W1R8s/Uv6BJcfQ= +github.com/vcaesar/screenshot v0.11.0 h1:ULNC6tTye6oNzleuqskzTMSjH8xonmuUIYfYjlYAM3g= +github.com/vcaesar/screenshot v0.11.0/go.mod h1:wixTD3T2Sz3Oi6Hfl33CMcBffd3mLbT7WavfK2UrQcI= github.com/vcaesar/tt v0.20.1 h1:D/jUeeVCNbq3ad8M7hhtB3J9x5RZ6I1n1eZ0BJp7M+4= github.com/vcaesar/tt v0.20.1/go.mod h1:cH2+AwGAJm19Wa6xvEa+0r+sXDJBT0QgNQey6mwqLeU= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= diff --git a/screen/screengrab_c.h b/screen/screengrab_c.h index 579c3802..68f674da 100644 --- a/screen/screengrab_c.h +++ b/screen/screengrab_c.h @@ -15,7 +15,7 @@ #endif #include "screen_c.h" -#if defined(IS_MACOSX) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > MAC_OS_VERSION_14_4 +#if defined(IS_MACOSX) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 140400 static CGImageRef capture15(CGDirectDisplayID id, CGRect diIntersectDisplayLocal, CGColorSpaceRef colorSpace) { dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); __block CGImageRef image1 = nil; @@ -76,7 +76,7 @@ MMBitmapRef copyMMBitmapFromDisplayInRect(MMRectInt32 rect, int32_t display_id, } MMPointInt32 o = rect.origin; MMSizeInt32 s = rect.size; - #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > MAC_OS_VERSION_14_4 + #if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 140400 CGColorSpaceRef color = CGColorSpaceCreateWithName(kCGColorSpaceSRGB); CGImageRef image = capture15(displayID, CGRectMake(o.x, o.y, s.w, s.h), color); CGColorSpaceRelease(color); From 8031f7f52684142d7c06489863510bfe4eb3e33a Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sat, 19 Apr 2025 12:54:47 -0700 Subject: [PATCH 315/327] Update: update import --- .circleci/images/primary/Dockerfile | 2 +- robotgo.go | 6 +++--- screen.go | 3 ++- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.circleci/images/primary/Dockerfile b/.circleci/images/primary/Dockerfile index 98f4a97a..ff104e61 100644 --- a/.circleci/images/primary/Dockerfile +++ b/.circleci/images/primary/Dockerfile @@ -1,5 +1,5 @@ # FROM golang:1.10.1 -FROM golang:1.23.2-stretch AS build +FROM golang:1.24.2-stretch AS build # FROM govgo/go:1.11.1 RUN apt update && apt install -y --no-install-recommends \ diff --git a/robotgo.go b/robotgo.go index e946539a..b4027b61 100644 --- a/robotgo.go +++ b/robotgo.go @@ -31,10 +31,10 @@ package robotgo /* #cgo darwin CFLAGS: -x objective-c -Wno-deprecated-declarations -#cgo darwin LDFLAGS: -framework Cocoa -framework OpenGL -framework IOKit -#cgo darwin LDFLAGS: -framework Carbon -framework CoreFoundation +#cgo darwin LDFLAGS: -framework Cocoa -framework CoreFoundation -framework IOKit +#cgo darwin LDFLAGS: -framework Carbon -framework OpenGL // -#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > MAC_OS_VERSION_14_4 +#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 140400 #cgo darwin LDFLAGS: -framework ScreenCaptureKit #endif diff --git a/screen.go b/screen.go index 5062b11c..0045ddf0 100644 --- a/screen.go +++ b/screen.go @@ -13,7 +13,8 @@ package robotgo import ( "image" - "github.com/kbinani/screenshot" + // "github.com/kbinani/screenshot" + "github.com/vcaesar/screenshot" ) // GetDisplayBounds gets the display screen bounds From 912ddcbfe4edba223c6ac0bf858b7107629c909d Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sat, 17 May 2025 11:53:45 -0700 Subject: [PATCH 316/327] Update: update go mod and CI --- .github/workflows/go.yml | 4 ++-- go.mod | 23 +++++++++--------- go.sum | 51 +++++++++++++++++++--------------------- 3 files changed, 37 insertions(+), 41 deletions(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 6b1426c9..aab570a3 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -10,10 +10,10 @@ jobs: runs-on: ${{ matrix.os }} steps: - - name: Set up Go 1.23.0 + - name: Set up Go 1.24.0 uses: actions/setup-go@v1 with: - go-version: 1.23.0 + go-version: 1.24.0 id: go - name: Check out code into the Go module directory diff --git a/go.mod b/go.mod index c3fdaf5e..40fb4a17 100644 --- a/go.mod +++ b/go.mod @@ -10,30 +10,29 @@ require ( github.com/robotn/xgb v0.10.0 github.com/robotn/xgbutil v0.10.0 github.com/tailscale/win v0.0.0-20250213223159-5992cb43ca35 - github.com/vcaesar/gops v0.40.0 - github.com/vcaesar/imgo v0.40.2 + github.com/vcaesar/gops v0.41.0 + github.com/vcaesar/imgo v0.41.0 github.com/vcaesar/keycode v0.10.1 github.com/vcaesar/tt v0.20.1 ) require ( github.com/dblohm7/wingoes v0.0.0-20240820181039-f2b84150679e // indirect - github.com/ebitengine/purego v0.8.2 // indirect + github.com/ebitengine/purego v0.8.3 // indirect github.com/gen2brain/shm v0.1.1 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/jezek/xgb v1.1.1 // indirect - github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 // indirect - github.com/lxn/win v0.0.0-20210218163916-a377121e959e // indirect + github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35 // indirect github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect - github.com/shirou/gopsutil/v4 v4.25.1 // indirect - github.com/tklauser/go-sysconf v0.3.14 // indirect - github.com/tklauser/numcpus v0.9.0 // indirect - github.com/vcaesar/screenshot v0.11.0 + github.com/shirou/gopsutil/v4 v4.25.4 // indirect + github.com/tklauser/go-sysconf v0.3.15 // indirect + github.com/tklauser/numcpus v0.10.0 // indirect + github.com/vcaesar/screenshot v0.11.1 github.com/yusufpapurcu/wmi v1.2.4 // indirect - golang.org/x/exp v0.0.0-20250215185904-eff6e970281f // indirect - golang.org/x/image v0.24.0 // indirect - golang.org/x/sys v0.30.0 // indirect + golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 // indirect + golang.org/x/image v0.27.0 // indirect + golang.org/x/sys v0.33.0 // indirect ) // replace golang.org/x/sys => github.com/golang/sys v0.0.0-20190109145017-48ac38b7c8cb diff --git a/go.sum b/go.sum index f721e402..77e32a58 100644 --- a/go.sum +++ b/go.sum @@ -4,8 +4,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dblohm7/wingoes v0.0.0-20240820181039-f2b84150679e h1:L+XrFvD0vBIBm+Wf9sFN6aU395t7JROoai0qXZraA4U= github.com/dblohm7/wingoes v0.0.0-20240820181039-f2b84150679e/go.mod h1:SUxUaAK/0UG5lYyZR1L1nC4AaYYvSSYTWQSH3FPcxKU= -github.com/ebitengine/purego v0.8.2 h1:jPPGWs2sZ1UgOSgD2bClL0MJIqu58nOmIcBuXr62z1I= -github.com/ebitengine/purego v0.8.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= +github.com/ebitengine/purego v0.8.3 h1:K+0AjQp63JEZTEMZiwsI9g0+hAMNohwUOtY0RPGexmc= +github.com/ebitengine/purego v0.8.3/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= github.com/gen2brain/shm v0.1.1 h1:1cTVA5qcsUFixnDHl14TmRoxgfWEEZlTezpUj1vm5uQ= github.com/gen2brain/shm v0.1.1/go.mod h1:UgIcVtvmOu+aCJpqJX7GOtiN7X2ct+TKLg4RTxwPIUA= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= @@ -13,14 +13,12 @@ github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/jezek/xgb v1.1.1 h1:bE/r8ZZtSv7l9gk6nU0mYx51aXrvnyb44892TwSaqS4= github.com/jezek/xgb v1.1.1/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk= -github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 h1:7UMa6KCCMjZEMDtTVdcGu0B1GmmC7QJKiCCjyTAWQy0= -github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k= -github.com/lxn/win v0.0.0-20210218163916-a377121e959e h1:H+t6A/QJMbhCSEH5rAuRxh+CtW96g0Or0Fxa9IKr4uc= -github.com/lxn/win v0.0.0-20210218163916-a377121e959e/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk= +github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35 h1:PpXWgLPs+Fqr325bN2FD2ISlRRztXibcX6e8f5FR5Dc= +github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= github.com/otiai10/gosseract/v2 v2.4.1 h1:G8AyBpXEeSlcq8TI85LH/pM5SXk8Djy2GEXisgyblRw= @@ -36,39 +34,38 @@ github.com/robotn/xgb v0.10.0 h1:O3kFbIwtwZ3pgLbp1h5slCQ4OpY8BdwugJLrUe6GPIM= github.com/robotn/xgb v0.10.0/go.mod h1:SxQhJskUJ4rleVU44YvnrdvxQr0tKy5SRSigBrCgyyQ= github.com/robotn/xgbutil v0.10.0 h1:gvf7mGQqCWQ68aHRtCxgdewRk+/KAJui6l3MJQQRCKw= github.com/robotn/xgbutil v0.10.0/go.mod h1:svkDXUDQjUiWzLrA0OZgHc4lbOts3C+uRfP6/yjwYnU= -github.com/shirou/gopsutil/v4 v4.25.1 h1:QSWkTc+fu9LTAWfkZwZ6j8MSUk4A2LV7rbH0ZqmLjXs= -github.com/shirou/gopsutil/v4 v4.25.1/go.mod h1:RoUCUpndaJFtT+2zsZzzmhvbfGoDCJ7nFXKJf8GqJbI= +github.com/shirou/gopsutil/v4 v4.25.4 h1:cdtFO363VEOOFrUCjZRh4XVJkb548lyF0q0uTeMqYPw= +github.com/shirou/gopsutil/v4 v4.25.4/go.mod h1:xbuxyoZj+UsgnZrENu3lQivsngRR5BdjbJwf2fv4szA= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tailscale/win v0.0.0-20250213223159-5992cb43ca35 h1:wAZbkTZkqDzWsqxPh2qkBd3KvFU7tcxV0BP0Rnhkxog= github.com/tailscale/win v0.0.0-20250213223159-5992cb43ca35/go.mod h1:aMd4yDHLjbOuYP6fMxj1d9ACDQlSWwYztcpybGHCQc8= github.com/tc-hib/winres v0.2.1 h1:YDE0FiP0VmtRaDn7+aaChp1KiF4owBiJa5l964l5ujA= github.com/tc-hib/winres v0.2.1/go.mod h1:C/JaNhH3KBvhNKVbvdlDWkbMDO9H4fKKDaN7/07SSuk= -github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZb78yU= -github.com/tklauser/go-sysconf v0.3.14/go.mod h1:1ym4lWMLUOhuBOPGtRcJm7tEGX4SCYNEEEtghGG/8uY= -github.com/tklauser/numcpus v0.9.0 h1:lmyCHtANi8aRUgkckBgoDk1nHCux3n2cgkJLXdQGPDo= -github.com/tklauser/numcpus v0.9.0/go.mod h1:SN6Nq1O3VychhC1npsWostA+oW+VOQTxZrS604NSRyI= -github.com/vcaesar/gops v0.40.0 h1:I+1RCGiV+LkZJUYNzAd373xs0uM2UyeFdZBmow8HfCM= -github.com/vcaesar/gops v0.40.0/go.mod h1:3u/USW7JovqUK6i13VOD3qWfvXXd2TIIKE4PYIv4TOM= -github.com/vcaesar/imgo v0.40.2 h1:5GWScRLdBCMtO1v2I1bs+ZmDLZFINxYSMZ+mtUw5qPM= -github.com/vcaesar/imgo v0.40.2/go.mod h1:MVCl+FxHI2gTgmiHoi0n5xNCbYcfv9SVtdEOUC92+eo= +github.com/tklauser/go-sysconf v0.3.15 h1:VE89k0criAymJ/Os65CSn1IXaol+1wrsFHEB8Ol49K4= +github.com/tklauser/go-sysconf v0.3.15/go.mod h1:Dmjwr6tYFIseJw7a3dRLJfsHAMXZ3nEnL/aZY+0IuI4= +github.com/tklauser/numcpus v0.10.0 h1:18njr6LDBk1zuna922MgdjQuJFjrdppsZG60sHGfjso= +github.com/tklauser/numcpus v0.10.0/go.mod h1:BiTKazU708GQTYF4mB+cmlpT2Is1gLk7XVuEeem8LsQ= +github.com/vcaesar/gops v0.41.0 h1:FG748Jyw3FOuZnbzSgB+CQSx2e5LbLCPWV2JU1brFdc= +github.com/vcaesar/gops v0.41.0/go.mod h1:/3048L7Rj7QjQKTSB+kKc7hDm63YhTWy5QJ10TCP37A= +github.com/vcaesar/imgo v0.41.0 h1:kNLYGrThXhB9Dd6IwFmfPnxq9P6yat2g7dpPjr7OWO8= +github.com/vcaesar/imgo v0.41.0/go.mod h1:/LGOge8etlzaVu/7l+UfhJxR6QqaoX5yeuzGIMfWb4I= github.com/vcaesar/keycode v0.10.1 h1:0DesGmMAPWpYTCYddOFiCMKCDKgNnwiQa2QXindVUHw= github.com/vcaesar/keycode v0.10.1/go.mod h1:JNlY7xbKsh+LAGfY2j4M3znVrGEm5W1R8s/Uv6BJcfQ= -github.com/vcaesar/screenshot v0.11.0 h1:ULNC6tTye6oNzleuqskzTMSjH8xonmuUIYfYjlYAM3g= -github.com/vcaesar/screenshot v0.11.0/go.mod h1:wixTD3T2Sz3Oi6Hfl33CMcBffd3mLbT7WavfK2UrQcI= +github.com/vcaesar/screenshot v0.11.1 h1:GgPuN89XC4Yh38dLx4quPlSo3YiWWhwIria/j3LtrqU= +github.com/vcaesar/screenshot v0.11.1/go.mod h1:gJNwHBiP1v1v7i8TQ4yV1XJtcyn2I/OJL7OziVQkwjs= github.com/vcaesar/tt v0.20.1 h1:D/jUeeVCNbq3ad8M7hhtB3J9x5RZ6I1n1eZ0BJp7M+4= github.com/vcaesar/tt v0.20.1/go.mod h1:cH2+AwGAJm19Wa6xvEa+0r+sXDJBT0QgNQey6mwqLeU= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -golang.org/x/exp v0.0.0-20250215185904-eff6e970281f h1:oFMYAjX0867ZD2jcNiLBrI9BdpmEkvPyi5YrBGXbamg= -golang.org/x/exp v0.0.0-20250215185904-eff6e970281f/go.mod h1:BHOTPb3L19zxehTsLoJXVaTktb06DFgmdW6Wb9s8jqk= -golang.org/x/image v0.24.0 h1:AN7zRgVsbvmTfNyqIbbOraYL8mSwcKncEj8ofjgzcMQ= -golang.org/x/image v0.24.0/go.mod h1:4b/ITuLfqYq1hqZcjofwctIhi7sZh2WaCjvsBNjjya8= +golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 h1:y5zboxd6LQAqYIhHnB48p0ByQ/GnQx2BE33L8BOHQkI= +golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6/go.mod h1:U6Lno4MTRCDY+Ba7aCcauB9T60gsv5s4ralQzP72ZoQ= +golang.org/x/image v0.27.0 h1:C8gA4oWU/tKkdCfYT6T2u4faJu3MeNS5O8UPWlPF61w= +golang.org/x/image v0.27.0/go.mod h1:xbdrClrAUway1MUTEZDq9mz/UpRwYAkFFNUslZtcB+g= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= -golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From 73c07dc99103c689e618e65fe1f85d13e72f2b33 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sat, 17 May 2025 12:01:12 -0700 Subject: [PATCH 317/327] Fixed: fixed default key toggle delay --- key.go | 6 ++---- robotgo.go | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/key.go b/key.go index 98c53425..98644bbf 100644 --- a/key.go +++ b/key.go @@ -416,7 +416,7 @@ func keyTaps(k string, keyArr []string, pid int) error { return nil } -func keyToggles(k string, keyArr []string, pid int, args ...interface{}) error { +func keyToggles(k string, keyArr []string, pid int) error { if len(keyArr) <= 0 { keyArr = append(keyArr, "down") } @@ -437,9 +437,7 @@ func keyToggles(k string, keyArr []string, pid int, args ...interface{}) error { } C.toggleKeyCode(key, C.bool(down), flags, C.uintptr(pid)) - if len(args) > 0 { - MilliSleep(KeySleep) - } + MilliSleep(KeySleep) return nil } diff --git a/robotgo.go b/robotgo.go index b4027b61..f7038e90 100644 --- a/robotgo.go +++ b/robotgo.go @@ -73,7 +73,7 @@ var ( // MouseSleep set the mouse default millisecond sleep time MouseSleep = 0 // KeySleep set the key default millisecond sleep time - KeySleep = 0 + KeySleep = 10 // DisplayID set the screen display id DisplayID = -1 From 5c2864485d16b8bf3eb1a3baaf1dfcddda3d263e Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sat, 17 May 2025 12:33:16 -0700 Subject: [PATCH 318/327] Update: use hid event in macos --- key/keycode_c.h | 3 ++- key/keypress_c.h | 8 +++++--- mouse/mouse_c.h | 15 +++++++++------ 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/key/keycode_c.h b/key/keycode_c.h index 01f1bdbc..efc4f6bd 100644 --- a/key/keycode_c.h +++ b/key/keycode_c.h @@ -90,7 +90,8 @@ MMKeyCode keyCodeForChar(const char c) { #if defined(IS_MACOSX) CFStringRef createStringForKey(CGKeyCode keyCode){ - TISInputSourceRef currentKeyboard = TISCopyCurrentASCIICapableKeyboardInputSource(); + // TISInputSourceRef currentKeyboard = TISCopyCurrentASCIICapableKeyboardInputSource(); + TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardLayoutInputSource(); CFDataRef layoutData = (CFDataRef) TISGetInputSourceProperty( currentKeyboard, kTISPropertyUnicodeKeyLayoutData); diff --git a/key/keypress_c.h b/key/keypress_c.h index a606f044..48de33ab 100644 --- a/key/keypress_c.h +++ b/key/keypress_c.h @@ -58,7 +58,7 @@ if (pid != 0) { CGEventPostToPid(pid, event); } else { - CGEventPost(kCGSessionEventTap, event); + CGEventPost(kCGHIDEventTap, event); } CFRelease(event); @@ -179,7 +179,8 @@ void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags, uintptr pi NX_SYSDEFINED, loc, &event, kNXEventDataVersion, 0, FALSE); assert(KERN_SUCCESS == kr); } else { - CGEventRef keyEvent = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)code, down); + CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState); + CGEventRef keyEvent = CGEventCreateKeyboardEvent(source, (CGKeyCode)code, down); assert(keyEvent != NULL); CGEventSetType(keyEvent, down ? kCGEventKeyDown : kCGEventKeyUp); @@ -273,7 +274,8 @@ void toggleKey(char c, const bool down, MMKeyFlags flags, uintptr pid) { convert characters to a keycode, but does not support adding modifier flags. It is only used in typeString(). -- if you need modifier keys, use the above functions instead. */ - CGEventRef keyEvent = CGEventCreateKeyboardEvent(NULL, 0, down); + CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState); + CGEventRef keyEvent = CGEventCreateKeyboardEvent(source, 0, down); if (keyEvent == NULL) { fputs("Could not create keyboard event.\n", stderr); return; diff --git a/mouse/mouse_c.h b/mouse/mouse_c.h index adf8b7d2..26d5e989 100644 --- a/mouse/mouse_c.h +++ b/mouse/mouse_c.h @@ -83,12 +83,13 @@ /* Move the mouse to a specific point. */ void moveMouse(MMPointInt32 point){ #if defined(IS_MACOSX) - CGEventRef move = CGEventCreateMouseEvent(NULL, kCGEventMouseMoved, + CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState); + CGEventRef move = CGEventCreateMouseEvent(source, kCGEventMouseMoved, CGPointFromMMPointInt32(point), kCGMouseButtonLeft); calculateDeltas(&move, point); - CGEventPost(kCGSessionEventTap, move); + CGEventPost(kCGHIDEventTap, move); CFRelease(move); #elif defined(USE_X11) Display *display = XGetMainDisplay(); @@ -103,12 +104,13 @@ void moveMouse(MMPointInt32 point){ void dragMouse(MMPointInt32 point, const MMMouseButton button){ #if defined(IS_MACOSX) const CGEventType dragType = MMMouseDragToCGEventType(button); - CGEventRef drag = CGEventCreateMouseEvent(NULL, dragType, + CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState); + CGEventRef drag = CGEventCreateMouseEvent(source, dragType, CGPointFromMMPointInt32(point), (CGMouseButton)button); calculateDeltas(&drag, point); - CGEventPost(kCGSessionEventTap, drag); + CGEventPost(kCGHIDEventTap, drag); CFRelease(drag); #else moveMouse(point); @@ -145,9 +147,10 @@ void toggleMouse(bool down, MMMouseButton button) { #if defined(IS_MACOSX) const CGPoint currentPos = CGPointFromMMPointInt32(location()); const CGEventType mouseType = MMMouseToCGEventType(down, button); - CGEventRef event = CGEventCreateMouseEvent(NULL, mouseType, currentPos, (CGMouseButton)button); + CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState); + CGEventRef event = CGEventCreateMouseEvent(source, mouseType, currentPos, (CGMouseButton)button); - CGEventPost(kCGSessionEventTap, event); + CGEventPost(kCGHIDEventTap, event); CFRelease(event); #elif defined(USE_X11) Display *display = XGetMainDisplay(); From 02c668a94689cc1d17ace13e2f35bef61a4f2988 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sat, 17 May 2025 12:37:38 -0700 Subject: [PATCH 319/327] Update: add CFRelease source --- key/keypress_c.h | 2 ++ mouse/mouse_c.h | 3 +++ 2 files changed, 5 insertions(+) diff --git a/key/keypress_c.h b/key/keypress_c.h index 48de33ab..81bad315 100644 --- a/key/keypress_c.h +++ b/key/keypress_c.h @@ -189,6 +189,7 @@ void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags, uintptr pi } SendTo(pid, keyEvent); + CFRelease(source); } #elif defined(IS_WINDOWS) const DWORD dwFlags = down ? 0 : KEYEVENTF_KEYUP; @@ -284,6 +285,7 @@ void toggleKey(char c, const bool down, MMKeyFlags flags, uintptr pid) { CGEventKeyboardSetUnicodeString(keyEvent, 1, &ch); SendTo(pid, keyEvent); + CFRelease(source); } #else #define toggleUniKey(c, down) toggleKey(c, down, MOD_NONE, 0) diff --git a/mouse/mouse_c.h b/mouse/mouse_c.h index 26d5e989..cc2127d7 100644 --- a/mouse/mouse_c.h +++ b/mouse/mouse_c.h @@ -91,6 +91,7 @@ void moveMouse(MMPointInt32 point){ CGEventPost(kCGHIDEventTap, move); CFRelease(move); + CFRelease(source); #elif defined(USE_X11) Display *display = XGetMainDisplay(); XWarpPointer(display, None, DefaultRootWindow(display), 0, 0, 0, 0, point.x, point.y); @@ -112,6 +113,7 @@ void dragMouse(MMPointInt32 point, const MMMouseButton button){ CGEventPost(kCGHIDEventTap, drag); CFRelease(drag); + CFRelease(source); #else moveMouse(point); #endif @@ -152,6 +154,7 @@ void toggleMouse(bool down, MMMouseButton button) { CGEventPost(kCGHIDEventTap, event); CFRelease(event); + CFRelease(source); #elif defined(USE_X11) Display *display = XGetMainDisplay(); XTestFakeButtonEvent(display, button, down ? True : False, CurrentTime); From b731094f615b1a3fbb34318649500f1809cac348 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sat, 17 May 2025 12:54:35 -0700 Subject: [PATCH 320/327] Update: update if defined --- mouse/mouse_c.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/mouse/mouse_c.h b/mouse/mouse_c.h index cc2127d7..11655d89 100644 --- a/mouse/mouse_c.h +++ b/mouse/mouse_c.h @@ -214,11 +214,8 @@ void scrollMouseXY(int x, int y) { INPUT mouseScrollInputV; #endif - /* Direction should only be considered based on the scrollDirection. This Should not interfere. */ - /* Set up the OS specific solution */ - #if defined(__APPLE__) - CGEventRef event; - event = CGEventCreateScrollWheelEvent(NULL, kCGScrollEventUnitPixel, 2, y, x); + #if defined(IS_MACOSX) + CGEventRef event = CGEventCreateScrollWheelEvent(NULL, kCGScrollEventUnitPixel, 2, y, x); CGEventPost(kCGHIDEventTap, event); CFRelease(event); From 3eef3b5879a6839daed5638a060617bd3f440632 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sat, 17 May 2025 13:01:03 -0700 Subject: [PATCH 321/327] Add: add CGEventSourceRef source --- mouse/mouse_c.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/mouse/mouse_c.h b/mouse/mouse_c.h index 11655d89..f9697a95 100644 --- a/mouse/mouse_c.h +++ b/mouse/mouse_c.h @@ -188,7 +188,8 @@ void doubleClick(MMMouseButton button){ const CGEventType mouseTypeDown = MMMouseToCGEventType(true, button); const CGEventType mouseTypeUP = MMMouseToCGEventType(false, button); - CGEventRef event = CGEventCreateMouseEvent(NULL, mouseTypeDown, currentPos, kCGMouseButtonLeft); + CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState); + CGEventRef event = CGEventCreateMouseEvent(source, mouseTypeDown, currentPos, kCGMouseButtonLeft); /* Set event to double click. */ CGEventSetIntegerValueField(event, kCGMouseEventClickState, 2); @@ -198,6 +199,7 @@ void doubleClick(MMMouseButton button){ CGEventPost(kCGHIDEventTap, event); CFRelease(event); + CFRelease(source); #else /* Double click for everything else. */ clickMouse(button); @@ -215,10 +217,12 @@ void scrollMouseXY(int x, int y) { #endif #if defined(IS_MACOSX) - CGEventRef event = CGEventCreateScrollWheelEvent(NULL, kCGScrollEventUnitPixel, 2, y, x); + CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState); + CGEventRef event = CGEventCreateScrollWheelEvent(source, kCGScrollEventUnitPixel, 2, y, x); CGEventPost(kCGHIDEventTap, event); CFRelease(event); + CFRelease(source); #elif defined(USE_X11) int ydir = 4; /* Button 4 is up, 5 is down. */ int xdir = 6; From c1115cebc7bd02aa4779b0ee3a33fb71aa3efef5 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Fri, 23 May 2025 19:00:53 -0700 Subject: [PATCH 322/327] Update: update import --- robotgo_ocr.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/robotgo_ocr.go b/robotgo_ocr.go index b931a853..0f160b68 100644 --- a/robotgo_ocr.go +++ b/robotgo_ocr.go @@ -14,7 +14,7 @@ package robotgo import ( - "github.com/otiai10/gosseract" + "github.com/otiai10/gosseract/v2" ) // GetText get the image text by tesseract ocr From a183783e9c6f9995d3ac41eda475bcd4834d5b7d Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 3 Jun 2025 11:16:33 -0700 Subject: [PATCH 323/327] Update: simply key code --- key.go | 75 ++++++++++++++++++++++++++++++---------------------------- 1 file changed, 39 insertions(+), 36 deletions(-) diff --git a/key.go b/key.go index 98644bbf..add5f523 100644 --- a/key.go +++ b/key.go @@ -416,7 +416,7 @@ func keyTaps(k string, keyArr []string, pid int) error { return nil } -func keyToggles(k string, keyArr []string, pid int) error { +func getKeyDown(keyArr []string) (bool, []string) { if len(keyArr) <= 0 { keyArr = append(keyArr, "down") } @@ -429,8 +429,11 @@ func keyToggles(k string, keyArr []string, pid int) error { if keyArr[0] == "up" || keyArr[0] == "down" { keyArr = keyArr[1:] } - flags := getFlagsFromValue(keyArr) + return down, keyArr +} +func keyTogglesB(k string, down bool, keyArr []string, pid int) error { + flags := getFlagsFromValue(keyArr) key, err := checkKeyCodes(k) if err != nil { return err @@ -441,6 +444,11 @@ func keyToggles(k string, keyArr []string, pid int) error { return nil } +func keyToggles(k string, keyArr []string, pid int) error { + down, keyArr1 := getKeyDown(keyArr) + return keyTogglesB(k, down, keyArr1, pid) +} + /* __ ___ ___________ ____ .______ ______ ___ .______ _______ | |/ / | ____\ \ / / | _ \ / __ \ / \ | _ \ | \ @@ -478,6 +486,22 @@ func toErr(str *C.char) error { return errors.New(gstr) } +func appendShift(key string, len1 int, args ...interface{}) []interface{} { + if len(key) > 0 && unicode.IsUpper([]rune(key)[0]) { + args = append(args, "shift") + } + + key = strings.ToLower(key) + if _, ok := Special[key]; ok { + key = Special[key] + if len(args) <= len1 { + args = append(args, "shift") + } + } + + return args +} + // KeyTap taps the keyboard code; // // See keys supported: @@ -496,18 +520,7 @@ func toErr(str *C.char) error { // robotgo.KeyTap("k", pid int) func KeyTap(key string, args ...interface{}) error { var keyArr []string - - if len(key) > 0 && unicode.IsUpper([]rune(key)[0]) { - args = append(args, "shift") - } - - key = strings.ToLower(key) - if _, ok := Special[key]; ok { - key = Special[key] - if len(args) <= 0 { - args = append(args, "shift") - } - } + args = appendShift(key, 0, args...) pid := 0 if len(args) > 0 { @@ -526,6 +539,16 @@ func KeyTap(key string, args ...interface{}) error { return keyTaps(key, keyArr, pid) } +func getToggleArgs(args ...interface{}) (pid int, keyArr []string) { + if len(args) > 0 && reflect.TypeOf(args[0]) == reflect.TypeOf(pid) { + pid = args[0].(int) + keyArr = ToStrings(args[1:]) + } else { + keyArr = ToStrings(args) + } + return +} + // KeyToggle toggles the keyboard, if there not have args default is "down" // // See keys: @@ -540,28 +563,8 @@ func KeyTap(key string, args ...interface{}) error { // robotgo.KeyToggle("a", "up", "alt", "cmd") // robotgo.KeyToggle("k", pid int) func KeyToggle(key string, args ...interface{}) error { - - if len(key) > 0 && unicode.IsUpper([]rune(key)[0]) { - args = append(args, "shift") - } - - key = strings.ToLower(key) - if _, ok := Special[key]; ok { - key = Special[key] - if len(args) <= 1 { - args = append(args, "shift") - } - } - - pid := 0 - var keyArr []string - if len(args) > 0 && reflect.TypeOf(args[0]) == reflect.TypeOf(pid) { - pid = args[0].(int) - keyArr = ToStrings(args[1:]) - } else { - keyArr = ToStrings(args) - } - + args = appendShift(key, 1, args...) + pid, keyArr := getToggleArgs(args...) return keyToggles(key, keyArr, pid) } From d34a1491cbd81f04f6b0fcc28dff220fb724a8d0 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Tue, 3 Jun 2025 11:25:15 -0700 Subject: [PATCH 324/327] Fix: return key --- key.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/key.go b/key.go index add5f523..167fa78f 100644 --- a/key.go +++ b/key.go @@ -486,7 +486,7 @@ func toErr(str *C.char) error { return errors.New(gstr) } -func appendShift(key string, len1 int, args ...interface{}) []interface{} { +func appendShift(key string, len1 int, args ...interface{}) (string, []interface{}) { if len(key) > 0 && unicode.IsUpper([]rune(key)[0]) { args = append(args, "shift") } @@ -499,7 +499,7 @@ func appendShift(key string, len1 int, args ...interface{}) []interface{} { } } - return args + return key, args } // KeyTap taps the keyboard code; @@ -520,7 +520,7 @@ func appendShift(key string, len1 int, args ...interface{}) []interface{} { // robotgo.KeyTap("k", pid int) func KeyTap(key string, args ...interface{}) error { var keyArr []string - args = appendShift(key, 0, args...) + key, args = appendShift(key, 0, args...) pid := 0 if len(args) > 0 { @@ -563,7 +563,7 @@ func getToggleArgs(args ...interface{}) (pid int, keyArr []string) { // robotgo.KeyToggle("a", "up", "alt", "cmd") // robotgo.KeyToggle("k", pid int) func KeyToggle(key string, args ...interface{}) error { - args = appendShift(key, 1, args...) + key, args = appendShift(key, 1, args...) pid, keyArr := getToggleArgs(args...) return keyToggles(key, keyArr, pid) } From 48706562fc34dcd710da5ca49f3d16a4ca3d423f Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sun, 8 Jun 2025 10:51:14 -0700 Subject: [PATCH 325/327] Update: unify and clean License to Apache2.0 --- CONTRIBUTING.md | 12 +++++------- README.md | 6 ++++-- doc.go | 6 +++--- examples/key/main.go | 6 +++--- examples/main.go | 6 +++--- examples/mouse/main.go | 6 +++--- examples/screen/main.go | 6 +++--- examples/window/main.go | 6 +++--- img.go | 6 +++--- key.go | 6 +++--- key/key.go | 6 +++--- key/keypress_c.h | 6 +++--- keycode.go | 6 +++--- mouse/mouse.go | 6 +++--- ps.go | 6 +++--- robot_info_test.go | 6 +++--- robotgo.go | 6 +++--- robotgo_mac.go | 6 +++--- robotgo_mac_unix.go | 6 +++--- robotgo_mac_win.go | 6 +++--- robotgo_ocr.go | 6 +++--- robotgo_test.go | 6 +++--- robotgo_win.go | 6 +++--- robotgo_x11.go | 6 +++--- screen.go | 6 +++--- screen/goScreen.h | 6 +++--- window/goWindow.h | 6 +++--- window/pub.h | 6 +++--- window/win_sys.h | 6 +++--- window/window.h | 6 +++--- 30 files changed, 93 insertions(+), 93 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6c15d203..e136b21d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -30,20 +30,18 @@ Before sending code out for review, run all the tests for the whole tree to make In addition to the owner, Changes to Robotgo must be reviewed before they are accepted, no matter who makes the change even if it is a maintainer. We use GitHub's pull request workflow to do that and we also use [LGTM](http://lgtm.co) to ensure every PR is reviewed by vz or least 2 maintainers. - ## Sign your work -The sign-off is a simple line at the end of the explanation for the patch. Your signature certifies that you wrote the patch or otherwise have the right to pass it on as an open-source patch. +The sign-off is a simple line at the end of the explanation for the patch. Your signature certifies that you wrote the patch or otherwise have the right to pass it on as an open-source patch. ## Maintainers -To make sure every PR is checked, we got team maintainers. A maintainer should be a contributor of Robotgo and contributed at least 4 accepted PRs. +To make sure every PR is checked, we got team maintainers. A maintainer should be a contributor of Robotgo and contributed at least 4 accepted PRs. ## Owners Since Robotgo is a pure community organization without any company support, Copyright 2016 The go-vgo Project Developers. - ## Versions Robotgo has the `master` branch as a tip branch and has version branches such as `v0.30.0`. `v0.40.0` is a release branch and we will tag `v0.40.0` for binary download. If `v0.40.0` has bugs, we will accept pull requests on the `v0.40.0` branch and publish a `v0.40.1` tag, after bringing the bug fix also to the master branch. @@ -60,9 +58,9 @@ Code that you contribute should use the standard copyright header: // https://github.com/go-vgo/robotgo/blob/master/LICENSE // // Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed +// http://www.apache.org/licenses/LICENSE-2.0> +// +// This file may not be copied, modified, or distributed // except according to those terms. ``` diff --git a/README.md b/README.md index fe5b6bd3..bcf7478c 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,7 @@ GCC ``` #### For MacOS: + ``` brew install go ``` @@ -72,6 +73,7 @@ xcode-select --install ``` #### For Windows: + ``` winget install Golang.go ``` @@ -535,6 +537,6 @@ func main() { ## License -Robotgo is primarily distributed under the terms of "both the MIT license and the Apache License (Version 2.0)", with portions covered by various BSD-like licenses. +Robotgo is primarily distributed under the terms of "the Apache License (Version 2.0)", with portions covered by various BSD-like licenses. -See [LICENSE-APACHE](http://www.apache.org/licenses/LICENSE-2.0), [LICENSE-MIT](https://github.com/go-vgo/robotgo/blob/master/LICENSE). +See [LICENSE-APACHE](http://www.apache.org/licenses/LICENSE-2.0), [LICENSE](https://github.com/go-vgo/robotgo/blob/master/LICENSE). diff --git a/doc.go b/doc.go index b28cde23..e2b57bb7 100644 --- a/doc.go +++ b/doc.go @@ -3,9 +3,9 @@ // https://github.com/go-vgo/robotgo/blob/master/LICENSE // // Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed +// http://www.apache.org/licenses/LICENSE-2.0> +// +// This file may not be copied, modified, or distributed // except according to those terms. package robotgo diff --git a/examples/key/main.go b/examples/key/main.go index 84e12574..5967d58e 100644 --- a/examples/key/main.go +++ b/examples/key/main.go @@ -3,9 +3,9 @@ // https://github.com/go-vgo/robotgo/blob/master/LICENSE // // Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed +// http://www.apache.org/licenses/LICENSE-2.0> +// +// This file may not be copied, modified, or distributed // except according to those terms. package main diff --git a/examples/main.go b/examples/main.go index eade852a..343d9f5d 100644 --- a/examples/main.go +++ b/examples/main.go @@ -3,9 +3,9 @@ // https://github.com/go-vgo/robotgo/blob/master/LICENSE // // Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed +// http://www.apache.org/licenses/LICENSE-2.0> +// +// This file may not be copied, modified, or distributed // except according to those terms. package main diff --git a/examples/mouse/main.go b/examples/mouse/main.go index d9ef7e32..7eb1e606 100644 --- a/examples/mouse/main.go +++ b/examples/mouse/main.go @@ -3,9 +3,9 @@ // https://github.com/go-vgo/robotgo/blob/master/LICENSE // // Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed +// http://www.apache.org/licenses/LICENSE-2.0> +// +// This file may not be copied, modified, or distributed // except according to those terms. package main diff --git a/examples/screen/main.go b/examples/screen/main.go index 9e8ebe76..2d4be1dc 100644 --- a/examples/screen/main.go +++ b/examples/screen/main.go @@ -3,9 +3,9 @@ // https://github.com/go-vgo/robotgo/blob/master/LICENSE // // Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed +// http://www.apache.org/licenses/LICENSE-2.0> +// +// This file may not be copied, modified, or distributed // except according to those terms. package main diff --git a/examples/window/main.go b/examples/window/main.go index 5d631456..fc3594d0 100644 --- a/examples/window/main.go +++ b/examples/window/main.go @@ -3,9 +3,9 @@ // https://github.com/go-vgo/robotgo/blob/master/LICENSE // // Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed +// http://www.apache.org/licenses/LICENSE-2.0> +// +// This file may not be copied, modified, or distributed // except according to those terms. package main diff --git a/img.go b/img.go index 62ec5f60..0e8d32cd 100644 --- a/img.go +++ b/img.go @@ -3,9 +3,9 @@ // https://github.com/go-vgo/robotgo/blob/master/LICENSE // // Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed +// http://www.apache.org/licenses/LICENSE-2.0> +// +// This file may not be copied, modified, or distributed // except according to those terms. package robotgo diff --git a/key.go b/key.go index 167fa78f..14b1cd29 100644 --- a/key.go +++ b/key.go @@ -3,9 +3,9 @@ // https://github.com/go-vgo/robotgo/blob/master/LICENSE // // Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed +// http://www.apache.org/licenses/LICENSE-2.0> +// +// This file may not be copied, modified, or distributed // except according to those terms. package robotgo diff --git a/key/key.go b/key/key.go index 6daa8367..82a4d8c2 100644 --- a/key/key.go +++ b/key/key.go @@ -3,9 +3,9 @@ // https://github.com/go-vgo/robotgo/blob/master/LICENSE // // Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed +// http://www.apache.org/licenses/LICENSE-2.0> +// +// This file may not be copied, modified, or distributed // except according to those terms. package key diff --git a/key/keypress_c.h b/key/keypress_c.h index 81bad315..060f5f45 100644 --- a/key/keypress_c.h +++ b/key/keypress_c.h @@ -3,9 +3,9 @@ // https://github.com/go-vgo/robotgo/blob/master/LICENSE // // Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed +// http://www.apache.org/licenses/LICENSE-2.0> +// +// This file may not be copied, modified, or distributed // except according to those terms. #include "../base/deadbeef_rand_c.h" diff --git a/keycode.go b/keycode.go index 4b9e9348..a26aa67e 100644 --- a/keycode.go +++ b/keycode.go @@ -3,9 +3,9 @@ // https://github.com/go-vgo/robotgo/blob/master/LICENSE // // Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed +// http://www.apache.org/licenses/LICENSE-2.0> +// +// This file may not be copied, modified, or distributed // except according to those terms. package robotgo diff --git a/mouse/mouse.go b/mouse/mouse.go index e22c34b1..74e8955d 100644 --- a/mouse/mouse.go +++ b/mouse/mouse.go @@ -3,9 +3,9 @@ // https://github.com/go-vgo/robotgo/blob/master/LICENSE // // Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed +// http://www.apache.org/licenses/LICENSE-2.0> +// +// This file may not be copied, modified, or distributed // except according to those terms. package mouse diff --git a/ps.go b/ps.go index cba6f1b6..13bf8dee 100644 --- a/ps.go +++ b/ps.go @@ -3,9 +3,9 @@ // https://github.com/go-vgo/robotgo/blob/master/LICENSE // // Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed +// http://www.apache.org/licenses/LICENSE-2.0> +// +// This file may not be copied, modified, or distributed // except according to those terms. package robotgo diff --git a/robot_info_test.go b/robot_info_test.go index 93a9eb3c..8f890894 100644 --- a/robot_info_test.go +++ b/robot_info_test.go @@ -3,9 +3,9 @@ // https://github.com/go-vgo/robotgo/blob/master/LICENSE // // Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed +// http://www.apache.org/licenses/LICENSE-2.0> +// +// This file may not be copied, modified, or distributed // except according to those terms. package robotgo_test diff --git a/robotgo.go b/robotgo.go index f7038e90..e521e839 100644 --- a/robotgo.go +++ b/robotgo.go @@ -3,9 +3,9 @@ // https://github.com/go-vgo/robotgo/blob/master/LICENSE // // Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed +// http://www.apache.org/licenses/LICENSE-2.0> +// +// This file may not be copied, modified, or distributed // except according to those terms. /* diff --git a/robotgo_mac.go b/robotgo_mac.go index 0d8ac311..b8f73573 100644 --- a/robotgo_mac.go +++ b/robotgo_mac.go @@ -3,9 +3,9 @@ // https://github.com/go-vgo/robotgo/blob/master/LICENSE // // Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed +// http://www.apache.org/licenses/LICENSE-2.0> +// +// This file may not be copied, modified, or distributed // except according to those terms. //go:build darwin diff --git a/robotgo_mac_unix.go b/robotgo_mac_unix.go index 72ad4ec5..65c759a1 100644 --- a/robotgo_mac_unix.go +++ b/robotgo_mac_unix.go @@ -3,9 +3,9 @@ // https://github.com/go-vgo/robotgo/blob/master/LICENSE // // Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed +// http://www.apache.org/licenses/LICENSE-2.0> +// +// This file may not be copied, modified, or distributed // except according to those terms. //go:build !windows diff --git a/robotgo_mac_win.go b/robotgo_mac_win.go index ec31e581..8fd82686 100644 --- a/robotgo_mac_win.go +++ b/robotgo_mac_win.go @@ -3,9 +3,9 @@ // https://github.com/go-vgo/robotgo/blob/master/LICENSE // // Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed +// http://www.apache.org/licenses/LICENSE-2.0> +// +// This file may not be copied, modified, or distributed // except according to those terms. //go:build darwin || windows diff --git a/robotgo_ocr.go b/robotgo_ocr.go index 0f160b68..3249917b 100644 --- a/robotgo_ocr.go +++ b/robotgo_ocr.go @@ -3,9 +3,9 @@ // https://github.com/go-vgo/robotgo/blob/master/LICENSE // // Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed +// http://www.apache.org/licenses/LICENSE-2.0> +// +// This file may not be copied, modified, or distributed // except according to those terms. //go:build ocr diff --git a/robotgo_test.go b/robotgo_test.go index a9bcc4ce..d6bbcc58 100644 --- a/robotgo_test.go +++ b/robotgo_test.go @@ -3,9 +3,9 @@ // https://github.com/go-vgo/robotgo/blob/master/LICENSE // // Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed +// http://www.apache.org/licenses/LICENSE-2.0> +// +// This file may not be copied, modified, or distributed // except according to those terms. //go:build darwin || windows diff --git a/robotgo_win.go b/robotgo_win.go index 07364483..737ae513 100644 --- a/robotgo_win.go +++ b/robotgo_win.go @@ -3,9 +3,9 @@ // https://github.com/go-vgo/robotgo/blob/master/LICENSE // // Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed +// http://www.apache.org/licenses/LICENSE-2.0> +// +// This file may not be copied, modified, or distributed // except according to those terms. //go:build windows diff --git a/robotgo_x11.go b/robotgo_x11.go index 97aa9151..d929fba8 100644 --- a/robotgo_x11.go +++ b/robotgo_x11.go @@ -3,9 +3,9 @@ // https://github.com/go-vgo/robotgo/blob/master/LICENSE // // Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed +// http://www.apache.org/licenses/LICENSE-2.0> +// +// This file may not be copied, modified, or distributed // except according to those terms. //go:build !darwin && !windows diff --git a/screen.go b/screen.go index 0045ddf0..b0852bb1 100644 --- a/screen.go +++ b/screen.go @@ -3,9 +3,9 @@ // https://github.com/go-vgo/robotgo/blob/master/LICENSE // // Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed +// http://www.apache.org/licenses/LICENSE-2.0> +// +// This file may not be copied, modified, or distributed // except according to those terms. package robotgo diff --git a/screen/goScreen.h b/screen/goScreen.h index 1d93d075..a4bab458 100644 --- a/screen/goScreen.h +++ b/screen/goScreen.h @@ -3,9 +3,9 @@ // https://github.com/go-vgo/robotgo/blob/master/LICENSE // // Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed +// http://www.apache.org/licenses/LICENSE-2.0> +// +// This file may not be copied, modified, or distributed // except according to those terms. #include "../base/types.h" diff --git a/window/goWindow.h b/window/goWindow.h index 07301807..4e442a99 100644 --- a/window/goWindow.h +++ b/window/goWindow.h @@ -3,9 +3,9 @@ // https://github.com/go-vgo/robotgo/blob/master/LICENSE // // Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed +// http://www.apache.org/licenses/LICENSE-2.0> +// +// This file may not be copied, modified, or distributed // except according to those terms. #include "alert_c.h" diff --git a/window/pub.h b/window/pub.h index cfd0f317..57f9e594 100644 --- a/window/pub.h +++ b/window/pub.h @@ -3,9 +3,9 @@ // https://github.com/go-vgo/robotgo/blob/master/LICENSE // // Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed +// http://www.apache.org/licenses/LICENSE-2.0> +// +// This file may not be copied, modified, or distributed // except according to those terms. // #include "../base/os.h" diff --git a/window/win_sys.h b/window/win_sys.h index 6d536134..d71ba11c 100644 --- a/window/win_sys.h +++ b/window/win_sys.h @@ -3,9 +3,9 @@ // https://github.com/go-vgo/robotgo/blob/master/LICENSE // // Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed +// http://www.apache.org/licenses/LICENSE-2.0> +// +// This file may not be copied, modified, or distributed // except according to those terms. // #if defined(USE_X11) diff --git a/window/window.h b/window/window.h index bb1382bc..a7cf867a 100644 --- a/window/window.h +++ b/window/window.h @@ -3,9 +3,9 @@ // https://github.com/go-vgo/robotgo/blob/master/LICENSE // // Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed +// http://www.apache.org/licenses/LICENSE-2.0> +// +// This file may not be copied, modified, or distributed // except according to those terms. #include "pub.h" From ae4390f607a4726777d6a810fc3f24354890d4f0 Mon Sep 17 00:00:00 2001 From: Wang Jie Date: Sun, 15 Jun 2025 00:05:35 +0800 Subject: [PATCH 326/327] Fix: use window ref instead of app ref to get bounds on macos --- window/win_sys.h | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/window/win_sys.h b/window/win_sys.h index d71ba11c..2185ebb3 100644 --- a/window/win_sys.h +++ b/window/win_sys.h @@ -3,7 +3,7 @@ // https://github.com/go-vgo/robotgo/blob/master/LICENSE // // Licensed under the Apache License, Version 2.0 +// http://www.apache.org/licenses/LICENSE-2.0> // // This file may not be copied, modified, or distributed // except according to those terms. @@ -24,33 +24,45 @@ Bounds get_bounds(uintptr pid, int8_t isPid){ AXValueRef axp = NULL; AXValueRef axs = NULL; AXUIElementRef AxID = AXUIElementCreateApplication(pid); + AXUIElementRef AxWin = NULL; + + // Get the window from the application + if (AXUIElementCopyAttributeValue(AxID, kAXFocusedWindowAttribute, (CFTypeRef *)&AxWin) + != kAXErrorSuccess || AxWin == NULL) { + // If no focused window, try to get the main window + if (AXUIElementCopyAttributeValue(AxID, kAXMainWindowAttribute, (CFTypeRef *)&AxWin) + != kAXErrorSuccess || AxWin == NULL) { + goto exit; + } + } // Determine the current point of the window - if (AXUIElementCopyAttributeValue(AxID, kAXPositionAttribute, (CFTypeRef*) &axp) - != kAXErrorSuccess || axp == NULL){ + if (AXUIElementCopyAttributeValue(AxWin, kAXPositionAttribute, (CFTypeRef*) &axp) + != kAXErrorSuccess || axp == NULL) { goto exit; } // Determine the current size of the window - if (AXUIElementCopyAttributeValue(AxID, kAXSizeAttribute, (CFTypeRef*) &axs) - != kAXErrorSuccess || axs == NULL){ + if (AXUIElementCopyAttributeValue(AxWin, kAXSizeAttribute, (CFTypeRef*) &axs) + != kAXErrorSuccess || axs == NULL) { goto exit; } CGPoint p; CGSize s; // Attempt to convert both values into atomic types - if (AXValueGetValue(axp, kAXValueCGPointType, &p) && - AXValueGetValue(axs, kAXValueCGSizeType, &s)){ + if (AXValueGetValue(axp, kAXValueCGPointType, &p) && + AXValueGetValue(axs, kAXValueCGSizeType, &s)) { bounds.X = p.x; bounds.Y = p.y; bounds.W = s.width; bounds.H = s.height; } - - // return bounds; + exit: if (axp != NULL) { CFRelease(axp); } if (axs != NULL) { CFRelease(axs); } + if (AxWin != NULL) { CFRelease(AxWin); } + if (AxID != NULL) { CFRelease(AxID); } return bounds; #elif defined(USE_X11) @@ -126,7 +138,7 @@ Bounds get_client(uintptr pid, int8_t isPid) { bounds.W = attr.width; bounds.H = attr.height; XCloseDisplay(rDisplay); - + return bounds; #elif defined(IS_WINDOWS) HWND hwnd = getHwnd(pid, isPid); @@ -148,4 +160,4 @@ Bounds get_client(uintptr pid, int8_t isPid) { return bounds; #endif -} \ No newline at end of file +} From da8bc790f9bfd562d06429cf626e1825a8e7d8e7 Mon Sep 17 00:00:00 2001 From: vcaesar Date: Sat, 2 Aug 2025 17:55:25 -0700 Subject: [PATCH 327/327] Update: move old docs to archive --- README_zh.md => docs/archive/README_zh.md | 34 ++++++++++++++--------- docs/{ => archive}/doc.md | 0 docs/{ => archive}/doc_zh.md | 0 3 files changed, 21 insertions(+), 13 deletions(-) rename README_zh.md => docs/archive/README_zh.md (96%) rename docs/{ => archive}/doc.md (100%) rename docs/{ => archive}/doc_zh.md (100%) diff --git a/README_zh.md b/docs/archive/README_zh.md similarity index 96% rename from README_zh.md rename to docs/archive/README_zh.md index c6f84d92..7229ec38 100644 --- a/README_zh.md +++ b/docs/archive/README_zh.md @@ -1,6 +1,6 @@ # Robotgo -## !!! Warning: this page not updated !!! +# !!! Warning: this page not updated !!! [![Build Status](https://github.com/go-vgo/robotgo/workflows/Go/badge.svg)](https://github.com/go-vgo/robotgo/commits/master) [![CircleCI Status](https://circleci.com/gh/go-vgo/robotgo.svg?style=shield)](https://circleci.com/gh/go-vgo/robotgo) @@ -20,6 +20,7 @@ RobotGo 支持 Mac, Windows, and Linux(X11). 提 Issues 请到 [Github](https://github.com/go-vgo/robotgo), 便于统一管理和即时更新; `REDAME_zh.md 已废弃, 不再更新` ## Contents + - [Docs](#docs) - [Binding](#binding) - [Requirements](#requirements) @@ -34,6 +35,7 @@ RobotGo 支持 Mac, Windows, and Linux(X11). - [License](#license) ## Docs + - [GoDoc](https://godoc.org/github.com/go-vgo/robotgo)

V;MF)>Z}cG&_%X(#TsSp11^<*L%%W| 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 nS#Z@@5%Sf~LiAQy+R@O!z9;R73Yp57eq - * - * If you just need to read a PNG file and don't want to read the documentation - * skip to the end of this file and read the section entitled 'simplified API'. - */ - -/* Version information for png.h - this should match the version in png.c */ -#define PNG_LIBPNG_VER_STRING "1.6.34" -#define PNG_HEADER_VERSION_STRING " libpng version 1.6.34 - September 29, 2017\n" - -#define PNG_LIBPNG_VER_SONUM 16 -#define PNG_LIBPNG_VER_DLLNUM 16 - -/* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */ -#define PNG_LIBPNG_VER_MAJOR 1 -#define PNG_LIBPNG_VER_MINOR 6 -#define PNG_LIBPNG_VER_RELEASE 34 - -/* This should match the numeric part of the final component of - * PNG_LIBPNG_VER_STRING, omitting any leading zero: - */ - -#define PNG_LIBPNG_VER_BUILD 0 - -/* Release Status */ -#define PNG_LIBPNG_BUILD_ALPHA 1 -#define PNG_LIBPNG_BUILD_BETA 2 -#define PNG_LIBPNG_BUILD_RC 3 -#define PNG_LIBPNG_BUILD_STABLE 4 -#define PNG_LIBPNG_BUILD_RELEASE_STATUS_MASK 7 - -/* Release-Specific Flags */ -#define PNG_LIBPNG_BUILD_PATCH 8 /* Can be OR'ed with - PNG_LIBPNG_BUILD_STABLE only */ -#define PNG_LIBPNG_BUILD_PRIVATE 16 /* Cannot be OR'ed with - PNG_LIBPNG_BUILD_SPECIAL */ -#define PNG_LIBPNG_BUILD_SPECIAL 32 /* Cannot be OR'ed with - PNG_LIBPNG_BUILD_PRIVATE */ - -#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_STABLE - -/* Careful here. At one time, Guy wanted to use 082, but that would be octal. - * We must not include leading zeros. - * Versions 0.7 through 1.0.0 were in the range 0 to 100 here (only - * version 1.0.0 was mis-numbered 100 instead of 10000). From - * version 1.0.1 it's xxyyzz, where x=major, y=minor, z=release - */ -#define PNG_LIBPNG_VER 10634 /* 1.6.34 */ - -/* Library configuration: these options cannot be changed after - * the library has been built. - */ -#ifndef PNGLCONF_H -/* If pnglibconf.h is missing, you can - * copy scripts/pnglibconf.h.prebuilt to pnglibconf.h - */ -# include "pnglibconf.h" -#endif - -#ifndef PNG_VERSION_INFO_ONLY -/* Machine specific configuration. */ -# include "pngconf.h" -#endif - -/* - * Added at libpng-1.2.8 - * - * Ref MSDN: Private as priority over Special - * VS_FF_PRIVATEBUILD File *was not* built using standard release - * procedures. If this value is given, the StringFileInfo block must - * contain a PrivateBuild string. - * - * VS_FF_SPECIALBUILD File *was* built by the original company using - * standard release procedures but is a variation of the standard - * file of the same version number. If this value is given, the - * StringFileInfo block must contain a SpecialBuild string. - */ - -#ifdef PNG_USER_PRIVATEBUILD /* From pnglibconf.h */ -# define PNG_LIBPNG_BUILD_TYPE \ - (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_PRIVATE) -#else -# ifdef PNG_LIBPNG_SPECIALBUILD -# define PNG_LIBPNG_BUILD_TYPE \ - (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_SPECIAL) -# else -# define PNG_LIBPNG_BUILD_TYPE (PNG_LIBPNG_BUILD_BASE_TYPE) -# endif -#endif - -#ifndef PNG_VERSION_INFO_ONLY - -/* Inhibit C++ name-mangling for libpng functions but not for system calls. */ -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/* Version information for C files, stored in png.c. This had better match - * the version above. - */ -#define png_libpng_ver png_get_header_ver(NULL) - -/* This file is arranged in several sections: - * - * 1. [omitted] - * 2. Any configuration options that can be specified by for the application - * code when it is built. (Build time configuration is in pnglibconf.h) - * 3. Type definitions (base types are defined in pngconf.h), structure - * definitions. - * 4. Exported library functions. - * 5. Simplified API. - * 6. Implementation options. - * - * The library source code has additional files (principally pngpriv.h) that - * allow configuration of the library. - */ - -/* Section 1: [omitted] */ - -/* Section 2: run time configuration - * See pnglibconf.h for build time configuration - * - * Run time configuration allows the application to choose between - * implementations of certain arithmetic APIs. The default is set - * at build time and recorded in pnglibconf.h, but it is safe to - * override these (and only these) settings. Note that this won't - * change what the library does, only application code, and the - * settings can (and probably should) be made on a per-file basis - * by setting the #defines before including png.h - * - * Use macros to read integers from PNG data or use the exported - * functions? - * PNG_USE_READ_MACROS: use the macros (see below) Note that - * the macros evaluate their argument multiple times. - * PNG_NO_USE_READ_MACROS: call the relevant library function. - * - * Use the alternative algorithm for compositing alpha samples that - * does not use division? - * PNG_READ_COMPOSITE_NODIV_SUPPORTED: use the 'no division' - * algorithm. - * PNG_NO_READ_COMPOSITE_NODIV: use the 'division' algorithm. - * - * How to handle benign errors if PNG_ALLOW_BENIGN_ERRORS is - * false? - * PNG_ALLOW_BENIGN_ERRORS: map calls to the benign error - * APIs to png_warning. - * Otherwise the calls are mapped to png_error. - */ - -/* Section 3: type definitions, including structures and compile time - * constants. - * See pngconf.h for base types that vary by machine/system - */ - -/* This triggers a compiler error in png.c, if png.c and png.h - * do not agree upon the version number. - */ -typedef char* png_libpng_version_1_6_34; - -/* Basic control structions. Read libpng-manual.txt or libpng.3 for more info. - * - * png_struct is the cache of information used while reading or writing a single - * PNG file. One of these is always required, although the simplified API - * (below) hides the creation and destruction of it. - */ -typedef struct png_struct_def png_struct; -typedef const png_struct * png_const_structp; -typedef png_struct * png_structp; -typedef png_struct * * png_structpp; - -/* png_info contains information read from or to be written to a PNG file. One - * or more of these must exist while reading or creating a PNG file. The - * information is not used by libpng during read but is used to control what - * gets written when a PNG file is created. "png_get_" function calls read - * information during read and "png_set_" functions calls write information - * when creating a PNG. - * been moved into a separate header file that is not accessible to - * applications. Read libpng-manual.txt or libpng.3 for more info. - */ -typedef struct png_info_def png_info; -typedef png_info * png_infop; -typedef const png_info * png_const_infop; -typedef png_info * * png_infopp; - -/* Types with names ending 'p' are pointer types. The corresponding types with - * names ending 'rp' are identical pointer types except that the pointer is - * marked 'restrict', which means that it is the only pointer to the object - * passed to the function. Applications should not use the 'restrict' types; - * it is always valid to pass 'p' to a pointer with a function argument of the - * corresponding 'rp' type. Different compilers have different rules with - * regard to type matching in the presence of 'restrict'. For backward - * compatibility libpng callbacks never have 'restrict' in their parameters and, - * consequentially, writing portable application code is extremely difficult if - * an attempt is made to use 'restrict'. - */ -typedef png_struct * PNG_RESTRICT png_structrp; -typedef const png_struct * PNG_RESTRICT png_const_structrp; -typedef png_info * PNG_RESTRICT png_inforp; -typedef const png_info * PNG_RESTRICT png_const_inforp; - -/* Three color definitions. The order of the red, green, and blue, (and the - * exact size) is not important, although the size of the fields need to - * be png_byte or png_uint_16 (as defined below). - */ -typedef struct png_color_struct -{ - png_byte red; - png_byte green; - png_byte blue; -} png_color; -typedef png_color * png_colorp; -typedef const png_color * png_const_colorp; -typedef png_color * * png_colorpp; - -typedef struct png_color_16_struct -{ - png_byte index; /* used for palette files */ - png_uint_16 red; /* for use in red green blue files */ - png_uint_16 green; - png_uint_16 blue; - png_uint_16 gray; /* for use in grayscale files */ -} png_color_16; -typedef png_color_16 * png_color_16p; -typedef const png_color_16 * png_const_color_16p; -typedef png_color_16 * * png_color_16pp; - -typedef struct png_color_8_struct -{ - png_byte red; /* for use in red green blue files */ - png_byte green; - png_byte blue; - png_byte gray; /* for use in grayscale files */ - png_byte alpha; /* for alpha channel files */ -} png_color_8; -typedef png_color_8 * png_color_8p; -typedef const png_color_8 * png_const_color_8p; -typedef png_color_8 * * png_color_8pp; - -/* - * The following two structures are used for the in-core representation - * of sPLT chunks. - */ -typedef struct png_sPLT_entry_struct -{ - png_uint_16 red; - png_uint_16 green; - png_uint_16 blue; - png_uint_16 alpha; - png_uint_16 frequency; -} png_sPLT_entry; -typedef png_sPLT_entry * png_sPLT_entryp; -typedef const png_sPLT_entry * png_const_sPLT_entryp; -typedef png_sPLT_entry * * png_sPLT_entrypp; - -/* When the depth of the sPLT palette is 8 bits, the color and alpha samples - * occupy the LSB of their respective members, and the MSB of each member - * is zero-filled. The frequency member always occupies the full 16 bits. - */ - -typedef struct png_sPLT_struct -{ - png_charp name; /* palette name */ - png_byte depth; /* depth of palette samples */ - png_sPLT_entryp entries; /* palette entries */ - png_int_32 nentries; /* number of palette entries */ -} png_sPLT_t; -typedef png_sPLT_t * png_sPLT_tp; -typedef const png_sPLT_t * png_const_sPLT_tp; -typedef png_sPLT_t * * png_sPLT_tpp; - -#ifdef PNG_TEXT_SUPPORTED -/* png_text holds the contents of a text/ztxt/itxt chunk in a PNG file, - * and whether that contents is compressed or not. The "key" field - * points to a regular zero-terminated C string. The "text" fields can be a - * regular C string, an empty string, or a NULL pointer. - * However, the structure returned by png_get_text() will always contain - * the "text" field as a regular zero-terminated C string (possibly - * empty), never a NULL pointer, so it can be safely used in printf() and - * other string-handling functions. Note that the "itxt_length", "lang", and - * "lang_key" members of the structure only exist when the library is built - * with iTXt chunk support. Prior to libpng-1.4.0 the library was built by - * default without iTXt support. Also note that when iTXt *is* supported, - * the "lang" and "lang_key" fields contain NULL pointers when the - * "compression" field contains * PNG_TEXT_COMPRESSION_NONE or - * PNG_TEXT_COMPRESSION_zTXt. Note that the "compression value" is not the - * same as what appears in the PNG tEXt/zTXt/iTXt chunk's "compression flag" - * which is always 0 or 1, or its "compression method" which is always 0. - */ -typedef struct png_text_struct -{ - int compression; /* compression value: - -1: tEXt, none - 0: zTXt, deflate - 1: iTXt, none - 2: iTXt, deflate */ - png_charp key; /* keyword, 1-79 character description of "text" */ - png_charp text; /* comment, may be an empty string (ie "") - or a NULL pointer */ - png_size_t text_length; /* length of the text string */ - png_size_t itxt_length; /* length of the itxt string */ - png_charp lang; /* language code, 0-79 characters - or a NULL pointer */ - png_charp lang_key; /* keyword translated UTF-8 string, 0 or more - chars or a NULL pointer */ -} png_text; -typedef png_text * png_textp; -typedef const png_text * png_const_textp; -typedef png_text * * png_textpp; -#endif - -/* Supported compression types for text in PNG files (tEXt, and zTXt). - * The values of the PNG_TEXT_COMPRESSION_ defines should NOT be changed. */ -#define PNG_TEXT_COMPRESSION_NONE_WR -3 -#define PNG_TEXT_COMPRESSION_zTXt_WR -2 -#define PNG_TEXT_COMPRESSION_NONE -1 -#define PNG_TEXT_COMPRESSION_zTXt 0 -#define PNG_ITXT_COMPRESSION_NONE 1 -#define PNG_ITXT_COMPRESSION_zTXt 2 -#define PNG_TEXT_COMPRESSION_LAST 3 /* Not a valid value */ - -/* png_time is a way to hold the time in an machine independent way. - * Two conversions are provided, both from time_t and struct tm. There - * is no portable way to convert to either of these structures, as far - * as I know. If you know of a portable way, send it to me. As a side - * note - PNG has always been Year 2000 compliant! - */ -typedef struct png_time_struct -{ - png_uint_16 year; /* full year, as in, 1995 */ - png_byte month; /* month of year, 1 - 12 */ - png_byte day; /* day of month, 1 - 31 */ - png_byte hour; /* hour of day, 0 - 23 */ - png_byte minute; /* minute of hour, 0 - 59 */ - png_byte second; /* second of minute, 0 - 60 (for leap seconds) */ -} png_time; -typedef png_time * png_timep; -typedef const png_time * png_const_timep; -typedef png_time * * png_timepp; - -#if defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) ||\ - defined(PNG_USER_CHUNKS_SUPPORTED) -/* png_unknown_chunk is a structure to hold queued chunks for which there is - * no specific support. The idea is that we can use this to queue - * up private chunks for output even though the library doesn't actually - * know about their semantics. - * - * The data in the structure is set by libpng on read and used on write. - */ -typedef struct png_unknown_chunk_t -{ - png_byte name[5]; /* Textual chunk name with '\0' terminator */ - png_byte *data; /* Data, should not be modified on read! */ - png_size_t size; - - /* On write 'location' must be set using the flag values listed below. - * Notice that on read it is set by libpng however the values stored have - * more bits set than are listed below. Always treat the value as a - * bitmask. On write set only one bit - setting multiple bits may cause the - * chunk to be written in multiple places. - */ - png_byte location; /* mode of operation at read time */ -} -png_unknown_chunk; - -typedef png_unknown_chunk * png_unknown_chunkp; -typedef const png_unknown_chunk * png_const_unknown_chunkp; -typedef png_unknown_chunk * * png_unknown_chunkpp; -#endif - -/* Flag values for the unknown chunk location byte. */ -#define PNG_HAVE_IHDR 0x01 -#define PNG_HAVE_PLTE 0x02 -#define PNG_AFTER_IDAT 0x08 - -/* Maximum positive integer used in PNG is (2^31)-1 */ -#define PNG_UINT_31_MAX ((png_uint_32)0x7fffffffL) -#define PNG_UINT_32_MAX ((png_uint_32)(-1)) -#define PNG_SIZE_MAX ((png_size_t)(-1)) - -/* These are constants for fixed point values encoded in the - * PNG specification manner (x100000) - */ -#define PNG_FP_1 100000 -#define PNG_FP_HALF 50000 -#define PNG_FP_MAX ((png_fixed_point)0x7fffffffL) -#define PNG_FP_MIN (-PNG_FP_MAX) - -/* These describe the color_type field in png_info. */ -/* color type masks */ -#define PNG_COLOR_MASK_PALETTE 1 -#define PNG_COLOR_MASK_COLOR 2 -#define PNG_COLOR_MASK_ALPHA 4 - -/* color types. Note that not all combinations are legal */ -#define PNG_COLOR_TYPE_GRAY 0 -#define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE) -#define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR) -#define PNG_COLOR_TYPE_RGB_ALPHA (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA) -#define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA) -/* aliases */ -#define PNG_COLOR_TYPE_RGBA PNG_COLOR_TYPE_RGB_ALPHA -#define PNG_COLOR_TYPE_GA PNG_COLOR_TYPE_GRAY_ALPHA - -/* This is for compression type. PNG 1.0-1.2 only define the single type. */ -#define PNG_COMPRESSION_TYPE_BASE 0 /* Deflate method 8, 32K window */ -#define PNG_COMPRESSION_TYPE_DEFAULT PNG_COMPRESSION_TYPE_BASE - -/* This is for filter type. PNG 1.0-1.2 only define the single type. */ -#define PNG_FILTER_TYPE_BASE 0 /* Single row per-byte filtering */ -#define PNG_INTRAPIXEL_DIFFERENCING 64 /* Used only in MNG datastreams */ -#define PNG_FILTER_TYPE_DEFAULT PNG_FILTER_TYPE_BASE - -/* These are for the interlacing type. These values should NOT be changed. */ -#define PNG_INTERLACE_NONE 0 /* Non-interlaced image */ -#define PNG_INTERLACE_ADAM7 1 /* Adam7 interlacing */ -#define PNG_INTERLACE_LAST 2 /* Not a valid value */ - -/* These are for the oFFs chunk. These values should NOT be changed. */ -#define PNG_OFFSET_PIXEL 0 /* Offset in pixels */ -#define PNG_OFFSET_MICROMETER 1 /* Offset in micrometers (1/10^6 meter) */ -#define PNG_OFFSET_LAST 2 /* Not a valid value */ - -/* These are for the pCAL chunk. These values should NOT be changed. */ -#define PNG_EQUATION_LINEAR 0 /* Linear transformation */ -#define PNG_EQUATION_BASE_E 1 /* Exponential base e transform */ -#define PNG_EQUATION_ARBITRARY 2 /* Arbitrary base exponential transform */ -#define PNG_EQUATION_HYPERBOLIC 3 /* Hyperbolic sine transformation */ -#define PNG_EQUATION_LAST 4 /* Not a valid value */ - -/* These are for the sCAL chunk. These values should NOT be changed. */ -#define PNG_SCALE_UNKNOWN 0 /* unknown unit (image scale) */ -#define PNG_SCALE_METER 1 /* meters per pixel */ -#define PNG_SCALE_RADIAN 2 /* radians per pixel */ -#define PNG_SCALE_LAST 3 /* Not a valid value */ - -/* These are for the pHYs chunk. These values should NOT be changed. */ -#define PNG_RESOLUTION_UNKNOWN 0 /* pixels/unknown unit (aspect ratio) */ -#define PNG_RESOLUTION_METER 1 /* pixels/meter */ -#define PNG_RESOLUTION_LAST 2 /* Not a valid value */ - -/* These are for the sRGB chunk. These values should NOT be changed. */ -#define PNG_sRGB_INTENT_PERCEPTUAL 0 -#define PNG_sRGB_INTENT_RELATIVE 1 -#define PNG_sRGB_INTENT_SATURATION 2 -#define PNG_sRGB_INTENT_ABSOLUTE 3 -#define PNG_sRGB_INTENT_LAST 4 /* Not a valid value */ - -/* This is for text chunks */ -#define PNG_KEYWORD_MAX_LENGTH 79 - -/* Maximum number of entries in PLTE/sPLT/tRNS arrays */ -#define PNG_MAX_PALETTE_LENGTH 256 - -/* These determine if an ancillary chunk's data has been successfully read - * from the PNG header, or if the application has filled in the corresponding - * data in the info_struct to be written into the output file. The values - * of the PNG_INFO_ defines should NOT be changed. - */ -#define PNG_INFO_gAMA 0x0001U -#define PNG_INFO_sBIT 0x0002U -#define PNG_INFO_cHRM 0x0004U -#define PNG_INFO_PLTE 0x0008U -#define PNG_INFO_tRNS 0x0010U -#define PNG_INFO_bKGD 0x0020U -#define PNG_INFO_hIST 0x0040U -#define PNG_INFO_pHYs 0x0080U -#define PNG_INFO_oFFs 0x0100U -#define PNG_INFO_tIME 0x0200U -#define PNG_INFO_pCAL 0x0400U -#define PNG_INFO_sRGB 0x0800U /* GR-P, 0.96a */ -#define PNG_INFO_iCCP 0x1000U /* ESR, 1.0.6 */ -#define PNG_INFO_sPLT 0x2000U /* ESR, 1.0.6 */ -#define PNG_INFO_sCAL 0x4000U /* ESR, 1.0.6 */ -#define PNG_INFO_IDAT 0x8000U /* ESR, 1.0.6 */ -#define PNG_INFO_eXIf 0x10000U /* GR-P, 1.6.31 */ - -/* This is used for the transformation routines, as some of them - * change these values for the row. It also should enable using - * the routines for other purposes. - */ -typedef struct png_row_info_struct -{ - png_uint_32 width; /* width of row */ - png_size_t rowbytes; /* number of bytes in row */ - png_byte color_type; /* color type of row */ - png_byte bit_depth; /* bit depth of row */ - png_byte channels; /* number of channels (1, 2, 3, or 4) */ - png_byte pixel_depth; /* bits per pixel (depth * channels) */ -} png_row_info; - -typedef png_row_info * png_row_infop; -typedef png_row_info * * png_row_infopp; - -/* These are the function types for the I/O functions and for the functions - * that allow the user to override the default I/O functions with his or her - * own. The png_error_ptr type should match that of user-supplied warning - * and error functions, while the png_rw_ptr type should match that of the - * user read/write data functions. Note that the 'write' function must not - * modify the buffer it is passed. The 'read' function, on the other hand, is - * expected to return the read data in the buffer. - */ -typedef PNG_CALLBACK(void, *png_error_ptr, (png_structp, png_const_charp)); -typedef PNG_CALLBACK(void, *png_rw_ptr, (png_structp, png_bytep, png_size_t)); -typedef PNG_CALLBACK(void, *png_flush_ptr, (png_structp)); -typedef PNG_CALLBACK(void, *png_read_status_ptr, (png_structp, png_uint_32, - int)); -typedef PNG_CALLBACK(void, *png_write_status_ptr, (png_structp, png_uint_32, - int)); - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop)); -typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop)); - -/* The following callback receives png_uint_32 row_number, int pass for the - * png_bytep data of the row. When transforming an interlaced image the - * row number is the row number within the sub-image of the interlace pass, so - * the value will increase to the height of the sub-image (not the full image) - * then reset to 0 for the next pass. - * - * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to - * find the output pixel (x,y) given an interlaced sub-image pixel - * (row,col,pass). (See below for these macros.) - */ -typedef PNG_CALLBACK(void, *png_progressive_row_ptr, (png_structp, png_bytep, - png_uint_32, int)); -#endif - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) -typedef PNG_CALLBACK(void, *png_user_transform_ptr, (png_structp, png_row_infop, - png_bytep)); -#endif - -#ifdef PNG_USER_CHUNKS_SUPPORTED -typedef PNG_CALLBACK(int, *png_user_chunk_ptr, (png_structp, - png_unknown_chunkp)); -#endif -#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED -/* not used anywhere */ -/* typedef PNG_CALLBACK(void, *png_unknown_chunk_ptr, (png_structp)); */ -#endif - -#ifdef PNG_SETJMP_SUPPORTED -/* This must match the function definition in , and the application - * must include this before png.h to obtain the definition of jmp_buf. The - * function is required to be PNG_NORETURN, but this is not checked. If the - * function does return the application will crash via an abort() or similar - * system level call. - * - * If you get a warning here while building the library you may need to make - * changes to ensure that pnglibconf.h records the calling convention used by - * your compiler. This may be very difficult - try using a different compiler - * to build the library! - */ -PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), typedef); -#endif - -/* Transform masks for the high-level interface */ -#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */ -#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */ -#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */ -#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */ -#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */ -#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */ -#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */ -#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */ -#define PNG_TRANSFORM_BGR 0x0080 /* read and write */ -#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */ -#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */ -#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */ -#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* write only */ -/* Added to libpng-1.2.34 */ -#define PNG_TRANSFORM_STRIP_FILLER_BEFORE PNG_TRANSFORM_STRIP_FILLER -#define PNG_TRANSFORM_STRIP_FILLER_AFTER 0x1000 /* write only */ -/* Added to libpng-1.4.0 */ -#define PNG_TRANSFORM_GRAY_TO_RGB 0x2000 /* read only */ -/* Added to libpng-1.5.4 */ -#define PNG_TRANSFORM_EXPAND_16 0x4000 /* read only */ -#if INT_MAX >= 0x8000 /* else this might break */ -#define PNG_TRANSFORM_SCALE_16 0x8000 /* read only */ -#endif - -/* Flags for MNG supported features */ -#define PNG_FLAG_MNG_EMPTY_PLTE 0x01 -#define PNG_FLAG_MNG_FILTER_64 0x04 -#define PNG_ALL_MNG_FEATURES 0x05 - -/* NOTE: prior to 1.5 these functions had no 'API' style declaration, - * this allowed the zlib default functions to be used on Windows - * platforms. In 1.5 the zlib default malloc (which just calls malloc and - * ignores the first argument) should be completely compatible with the - * following. - */ -typedef PNG_CALLBACK(png_voidp, *png_malloc_ptr, (png_structp, - png_alloc_size_t)); -typedef PNG_CALLBACK(void, *png_free_ptr, (png_structp, png_voidp)); - -/* Section 4: exported functions - * Here are the function definitions most commonly used. This is not - * the place to find out how to use libpng. See libpng-manual.txt for the - * full explanation, see example.c for the summary. This just provides - * a simple one line description of the use of each function. - * - * The PNG_EXPORT() and PNG_EXPORTA() macros used below are defined in - * pngconf.h and in the *.dfn files in the scripts directory. - * - * PNG_EXPORT(ordinal, type, name, (args)); - * - * ordinal: ordinal that is used while building - * *.def files. The ordinal value is only - * relevant when preprocessing png.h with - * the *.dfn files for building symbol table - * entries, and are removed by pngconf.h. - * type: return type of the function - * name: function name - * args: function arguments, with types - * - * When we wish to append attributes to a function prototype we use - * the PNG_EXPORTA() macro instead. - * - * PNG_EXPORTA(ordinal, type, name, (args), attributes); - * - * ordinal, type, name, and args: same as in PNG_EXPORT(). - * attributes: function attributes - */ - -/* Returns the version number of the library */ -PNG_EXPORT(1, png_uint_32, png_access_version_number, (void)); - -/* Tell lib we have already handled the first magic bytes. - * Handling more than 8 bytes from the beginning of the file is an error. - */ -PNG_EXPORT(2, void, png_set_sig_bytes, (png_structrp png_ptr, int num_bytes)); - -/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a - * PNG file. Returns zero if the supplied bytes match the 8-byte PNG - * signature, and non-zero otherwise. Having num_to_check == 0 or - * start > 7 will always fail (ie return non-zero). - */ -PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, png_size_t start, - png_size_t num_to_check)); - -/* Simple signature checking function. This is the same as calling - * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). - */ -#define png_check_sig(sig, n) !png_sig_cmp((sig), 0, (n)) - -/* Allocate and initialize png_ptr struct for reading, and any other memory. */ -PNG_EXPORTA(4, png_structp, png_create_read_struct, - (png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn), - PNG_ALLOCATED); - -/* Allocate and initialize png_ptr struct for writing, and any other memory */ -PNG_EXPORTA(5, png_structp, png_create_write_struct, - (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, - png_error_ptr warn_fn), - PNG_ALLOCATED); - -PNG_EXPORT(6, png_size_t, png_get_compression_buffer_size, - (png_const_structrp png_ptr)); - -PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structrp png_ptr, - png_size_t size)); - -/* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp - * match up. - */ -#ifdef PNG_SETJMP_SUPPORTED -/* This function returns the jmp_buf built in to *png_ptr. It must be - * supplied with an appropriate 'longjmp' function to use on that jmp_buf - * unless the default error function is overridden in which case NULL is - * acceptable. The size of the jmp_buf is checked against the actual size - * allocated by the library - the call will return NULL on a mismatch - * indicating an ABI mismatch. - */ -PNG_EXPORT(8, jmp_buf*, png_set_longjmp_fn, (png_structrp png_ptr, - png_longjmp_ptr longjmp_fn, size_t jmp_buf_size)); -# define png_jmpbuf(png_ptr) \ - (*png_set_longjmp_fn((png_ptr), longjmp, (sizeof (jmp_buf)))) -#else -# define png_jmpbuf(png_ptr) \ - (LIBPNG_WAS_COMPILED_WITH__PNG_NO_SETJMP) -#endif -/* This function should be used by libpng applications in place of - * longjmp(png_ptr->jmpbuf, val). If longjmp_fn() has been set, it - * will use it; otherwise it will call PNG_ABORT(). This function was - * added in libpng-1.5.0. - */ -PNG_EXPORTA(9, void, png_longjmp, (png_const_structrp png_ptr, int val), - PNG_NORETURN); - -#ifdef PNG_READ_SUPPORTED -/* Reset the compression stream */ -PNG_EXPORTA(10, int, png_reset_zstream, (png_structrp png_ptr), PNG_DEPRECATED); -#endif - -/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ -#ifdef PNG_USER_MEM_SUPPORTED -PNG_EXPORTA(11, png_structp, png_create_read_struct_2, - (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, - png_error_ptr warn_fn, - png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), - PNG_ALLOCATED); -PNG_EXPORTA(12, png_structp, png_create_write_struct_2, - (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, - png_error_ptr warn_fn, - png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), - PNG_ALLOCATED); -#endif - -/* Write the PNG file signature. */ -PNG_EXPORT(13, void, png_write_sig, (png_structrp png_ptr)); - -/* Write a PNG chunk - size, type, (optional) data, CRC. */ -PNG_EXPORT(14, void, png_write_chunk, (png_structrp png_ptr, png_const_bytep - chunk_name, png_const_bytep data, png_size_t length)); - -/* Write the start of a PNG chunk - length and chunk name. */ -PNG_EXPORT(15, void, png_write_chunk_start, (png_structrp png_ptr, - png_const_bytep chunk_name, png_uint_32 length)); - -/* Write the data of a PNG chunk started with png_write_chunk_start(). */ -PNG_EXPORT(16, void, png_write_chunk_data, (png_structrp png_ptr, - png_const_bytep data, png_size_t length)); - -/* Finish a chunk started with png_write_chunk_start() (includes CRC). */ -PNG_EXPORT(17, void, png_write_chunk_end, (png_structrp png_ptr)); - -/* Allocate and initialize the info structure */ -PNG_EXPORTA(18, png_infop, png_create_info_struct, (png_const_structrp png_ptr), - PNG_ALLOCATED); - -/* DEPRECATED: this function allowed init structures to be created using the - * default allocation method (typically malloc). Use is deprecated in 1.6.0 and - * the API will be removed in the future. - */ -PNG_EXPORTA(19, void, png_info_init_3, (png_infopp info_ptr, - png_size_t png_info_struct_size), PNG_DEPRECATED); - -/* Writes all the PNG information before the image. */ -PNG_EXPORT(20, void, png_write_info_before_PLTE, - (png_structrp png_ptr, png_const_inforp info_ptr)); -PNG_EXPORT(21, void, png_write_info, - (png_structrp png_ptr, png_const_inforp info_ptr)); - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read the information before the actual image data. */ -PNG_EXPORT(22, void, png_read_info, - (png_structrp png_ptr, png_inforp info_ptr)); -#endif - -#ifdef PNG_TIME_RFC1123_SUPPORTED - /* Convert to a US string format: there is no localization support in this - * routine. The original implementation used a 29 character buffer in - * png_struct, this will be removed in future versions. - */ -#if PNG_LIBPNG_VER < 10700 -/* To do: remove this from libpng17 (and from libpng17/png.c and pngstruct.h) */ -PNG_EXPORTA(23, png_const_charp, png_convert_to_rfc1123, (png_structrp png_ptr, - png_const_timep ptime),PNG_DEPRECATED); -#endif -PNG_EXPORT(241, int, png_convert_to_rfc1123_buffer, (char out[29], - png_const_timep ptime)); -#endif - -#ifdef PNG_CONVERT_tIME_SUPPORTED -/* Convert from a struct tm to png_time */ -PNG_EXPORT(24, void, png_convert_from_struct_tm, (png_timep ptime, - const struct tm * ttime)); - -/* Convert from time_t to png_time. Uses gmtime() */ -PNG_EXPORT(25, void, png_convert_from_time_t, (png_timep ptime, time_t ttime)); -#endif /* CONVERT_tIME */ - -#ifdef PNG_READ_EXPAND_SUPPORTED -/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */ -PNG_EXPORT(26, void, png_set_expand, (png_structrp png_ptr)); -PNG_EXPORT(27, void, png_set_expand_gray_1_2_4_to_8, (png_structrp png_ptr)); -PNG_EXPORT(28, void, png_set_palette_to_rgb, (png_structrp png_ptr)); -PNG_EXPORT(29, void, png_set_tRNS_to_alpha, (png_structrp png_ptr)); -#endif - -#ifdef PNG_READ_EXPAND_16_SUPPORTED -/* Expand to 16-bit channels, forces conversion of palette to RGB and expansion - * of a tRNS chunk if present. - */ -PNG_EXPORT(221, void, png_set_expand_16, (png_structrp png_ptr)); -#endif - -#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) -/* Use blue, green, red order for pixels. */ -PNG_EXPORT(30, void, png_set_bgr, (png_structrp png_ptr)); -#endif - -#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED -/* Expand the grayscale to 24-bit RGB if necessary. */ -PNG_EXPORT(31, void, png_set_gray_to_rgb, (png_structrp png_ptr)); -#endif - -#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED -/* Reduce RGB to grayscale. */ -#define PNG_ERROR_ACTION_NONE 1 -#define PNG_ERROR_ACTION_WARN 2 -#define PNG_ERROR_ACTION_ERROR 3 -#define PNG_RGB_TO_GRAY_DEFAULT (-1)/*for red/green coefficients*/ - -PNG_FP_EXPORT(32, void, png_set_rgb_to_gray, (png_structrp png_ptr, - int error_action, double red, double green)) -PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed, (png_structrp png_ptr, - int error_action, png_fixed_point red, png_fixed_point green)) - -PNG_EXPORT(34, png_byte, png_get_rgb_to_gray_status, (png_const_structrp - png_ptr)); -#endif - -#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED -PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth, - png_colorp palette)); -#endif - -#ifdef PNG_READ_ALPHA_MODE_SUPPORTED -/* How the alpha channel is interpreted - this affects how the color channels - * of a PNG file are returned to the calling application when an alpha channel, - * or a tRNS chunk in a palette file, is present. - * - * This has no effect on the way pixels are written into a PNG output - * datastream. The color samples in a PNG datastream are never premultiplied - * with the alpha samples. - * - * The default is to return data according to the PNG specification: the alpha - * channel is a linear measure of the contribution of the pixel to the - * corresponding composited pixel, and the color channels are unassociated - * (not premultiplied). The gamma encoded color channels must be scaled - * according to the contribution and to do this it is necessary to undo - * the encoding, scale the color values, perform the composition and reencode - * the values. This is the 'PNG' mode. - * - * The alternative is to 'associate' the alpha with the color information by - * storing color channel values that have been scaled by the alpha. - * image. These are the 'STANDARD', 'ASSOCIATED' or 'PREMULTIPLIED' modes - * (the latter being the two common names for associated alpha color channels). - * - * For the 'OPTIMIZED' mode, a pixel is treated as opaque only if the alpha - * value is equal to the maximum value. - * - * The final choice is to gamma encode the alpha channel as well. This is - * broken because, in practice, no implementation that uses this choice - * correctly undoes the encoding before handling alpha composition. Use this - * choice only if other serious errors in the software or hardware you use - * mandate it; the typical serious error is for dark halos to appear around - * opaque areas of the composited PNG image because of arithmetic overflow. - * - * The API function png_set_alpha_mode specifies which of these choices to use - * with an enumerated 'mode' value and the gamma of the required output: - */ -#define PNG_ALPHA_PNG 0 /* according to the PNG standard */ -#define PNG_ALPHA_STANDARD 1 /* according to Porter/Duff */ -#define PNG_ALPHA_ASSOCIATED 1 /* as above; this is the normal practice */ -#define PNG_ALPHA_PREMULTIPLIED 1 /* as above */ -#define PNG_ALPHA_OPTIMIZED 2 /* 'PNG' for opaque pixels, else 'STANDARD' */ -#define PNG_ALPHA_BROKEN 3 /* the alpha channel is gamma encoded */ - -PNG_FP_EXPORT(227, void, png_set_alpha_mode, (png_structrp png_ptr, int mode, - double output_gamma)) -PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structrp png_ptr, - int mode, png_fixed_point output_gamma)) -#endif - -#if defined(PNG_GAMMA_SUPPORTED) || defined(PNG_READ_ALPHA_MODE_SUPPORTED) -/* The output_gamma value is a screen gamma in libpng terminology: it expresses - * how to decode the output values, not how they are encoded. - */ -#define PNG_DEFAULT_sRGB -1 /* sRGB gamma and color space */ -#define PNG_GAMMA_MAC_18 -2 /* Old Mac '1.8' gamma and color space */ -#define PNG_GAMMA_sRGB 220000 /* Television standards--matches sRGB gamma */ -#define PNG_GAMMA_LINEAR PNG_FP_1 /* Linear */ -#endif - -/* The following are examples of calls to png_set_alpha_mode to achieve the - * required overall gamma correction and, where necessary, alpha - * premultiplication. - * - * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); - * This is the default libpng handling of the alpha channel - it is not - * pre-multiplied into the color components. In addition the call states - * that the output is for a sRGB system and causes all PNG files without gAMA - * chunks to be assumed to be encoded using sRGB. - * - * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); - * In this case the output is assumed to be something like an sRGB conformant - * display preceeded by a power-law lookup table of power 1.45. This is how - * early Mac systems behaved. - * - * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_GAMMA_LINEAR); - * This is the classic Jim Blinn approach and will work in academic - * environments where everything is done by the book. It has the shortcoming - * of assuming that input PNG data with no gamma information is linear - this - * is unlikely to be correct unless the PNG files where generated locally. - * Most of the time the output precision will be so low as to show - * significant banding in dark areas of the image. - * - * png_set_expand_16(pp); - * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_DEFAULT_sRGB); - * This is a somewhat more realistic Jim Blinn inspired approach. PNG files - * are assumed to have the sRGB encoding if not marked with a gamma value and - * the output is always 16 bits per component. This permits accurate scaling - * and processing of the data. If you know that your input PNG files were - * generated locally you might need to replace PNG_DEFAULT_sRGB with the - * correct value for your system. - * - * png_set_alpha_mode(pp, PNG_ALPHA_OPTIMIZED, PNG_DEFAULT_sRGB); - * If you just need to composite the PNG image onto an existing background - * and if you control the code that does this you can use the optimization - * setting. In this case you just copy completely opaque pixels to the - * output. For pixels that are not completely transparent (you just skip - * those) you do the composition math using png_composite or png_composite_16 - * below then encode the resultant 8-bit or 16-bit values to match the output - * encoding. - * - * Other cases - * If neither the PNG nor the standard linear encoding work for you because - * of the software or hardware you use then you have a big problem. The PNG - * case will probably result in halos around the image. The linear encoding - * will probably result in a washed out, too bright, image (it's actually too - * contrasty.) Try the ALPHA_OPTIMIZED mode above - this will probably - * substantially reduce the halos. Alternatively try: - * - * png_set_alpha_mode(pp, PNG_ALPHA_BROKEN, PNG_DEFAULT_sRGB); - * This option will also reduce the halos, but there will be slight dark - * halos round the opaque parts of the image where the background is light. - * In the OPTIMIZED mode the halos will be light halos where the background - * is dark. Take your pick - the halos are unavoidable unless you can get - * your hardware/software fixed! (The OPTIMIZED approach is slightly - * faster.) - * - * When the default gamma of PNG files doesn't match the output gamma. - * If you have PNG files with no gamma information png_set_alpha_mode allows - * you to provide a default gamma, but it also sets the ouput gamma to the - * matching value. If you know your PNG files have a gamma that doesn't - * match the output you can take advantage of the fact that - * png_set_alpha_mode always sets the output gamma but only sets the PNG - * default if it is not already set: - * - * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); - * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); - * The first call sets both the default and the output gamma values, the - * second call overrides the output gamma without changing the default. This - * is easier than achieving the same effect with png_set_gamma. You must use - * PNG_ALPHA_PNG for the first call - internal checking in png_set_alpha will - * fire if more than one call to png_set_alpha_mode and png_set_background is - * made in the same read operation, however multiple calls with PNG_ALPHA_PNG - * are ignored. - */ - -#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED -PNG_EXPORT(36, void, png_set_strip_alpha, (png_structrp png_ptr)); -#endif - -#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ - defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) -PNG_EXPORT(37, void, png_set_swap_alpha, (png_structrp png_ptr)); -#endif - -#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ - defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) -PNG_EXPORT(38, void, png_set_invert_alpha, (png_structrp png_ptr)); -#endif - -#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) -/* Add a filler byte to 8-bit or 16-bit Gray or 24-bit or 48-bit RGB images. */ -PNG_EXPORT(39, void, png_set_filler, (png_structrp png_ptr, png_uint_32 filler, - int flags)); -/* The values of the PNG_FILLER_ defines should NOT be changed */ -# define PNG_FILLER_BEFORE 0 -# define PNG_FILLER_AFTER 1 -/* Add an alpha byte to 8-bit or 16-bit Gray or 24-bit or 48-bit RGB images. */ -PNG_EXPORT(40, void, png_set_add_alpha, (png_structrp png_ptr, - png_uint_32 filler, int flags)); -#endif /* READ_FILLER || WRITE_FILLER */ - -#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) -/* Swap bytes in 16-bit depth files. */ -PNG_EXPORT(41, void, png_set_swap, (png_structrp png_ptr)); -#endif - -#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) -/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */ -PNG_EXPORT(42, void, png_set_packing, (png_structrp png_ptr)); -#endif - -#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ - defined(PNG_WRITE_PACKSWAP_SUPPORTED) -/* Swap packing order of pixels in bytes. */ -PNG_EXPORT(43, void, png_set_packswap, (png_structrp png_ptr)); -#endif - -#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) -/* Converts files to legal bit depths. */ -PNG_EXPORT(44, void, png_set_shift, (png_structrp png_ptr, png_const_color_8p - true_bits)); -#endif - -#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ - defined(PNG_WRITE_INTERLACING_SUPPORTED) -/* Have the code handle the interlacing. Returns the number of passes. - * MUST be called before png_read_update_info or png_start_read_image, - * otherwise it will not have the desired effect. Note that it is still - * necessary to call png_read_row or png_read_rows png_get_image_height - * times for each pass. -*/ -PNG_EXPORT(45, int, png_set_interlace_handling, (png_structrp png_ptr)); -#endif - -#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) -/* Invert monochrome files */ -PNG_EXPORT(46, void, png_set_invert_mono, (png_structrp png_ptr)); -#endif - -#ifdef PNG_READ_BACKGROUND_SUPPORTED -/* Handle alpha and tRNS by replacing with a background color. Prior to - * libpng-1.5.4 this API must not be called before the PNG file header has been - * read. Doing so will result in unexpected behavior and possible warnings or - * errors if the PNG file contains a bKGD chunk. - */ -PNG_FP_EXPORT(47, void, png_set_background, (png_structrp png_ptr, - png_const_color_16p background_color, int background_gamma_code, - int need_expand, double background_gamma)) -PNG_FIXED_EXPORT(215, void, png_set_background_fixed, (png_structrp png_ptr, - png_const_color_16p background_color, int background_gamma_code, - int need_expand, png_fixed_point background_gamma)) -#endif -#ifdef PNG_READ_BACKGROUND_SUPPORTED -# define PNG_BACKGROUND_GAMMA_UNKNOWN 0 -# define PNG_BACKGROUND_GAMMA_SCREEN 1 -# define PNG_BACKGROUND_GAMMA_FILE 2 -# define PNG_BACKGROUND_GAMMA_UNIQUE 3 -#endif - -#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED -/* Scale a 16-bit depth file down to 8-bit, accurately. */ -PNG_EXPORT(229, void, png_set_scale_16, (png_structrp png_ptr)); -#endif - -#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED -#define PNG_READ_16_TO_8_SUPPORTED /* Name prior to 1.5.4 */ -/* Strip the second byte of information from a 16-bit depth file. */ -PNG_EXPORT(48, void, png_set_strip_16, (png_structrp png_ptr)); -#endif - -#ifdef PNG_READ_QUANTIZE_SUPPORTED -/* Turn on quantizing, and reduce the palette to the number of colors - * available. - */ -PNG_EXPORT(49, void, png_set_quantize, (png_structrp png_ptr, - png_colorp palette, int num_palette, int maximum_colors, - png_const_uint_16p histogram, int full_quantize)); -#endif - -#ifdef PNG_READ_GAMMA_SUPPORTED -/* The threshold on gamma processing is configurable but hard-wired into the - * library. The following is the floating point variant. - */ -#define PNG_GAMMA_THRESHOLD (PNG_GAMMA_THRESHOLD_FIXED*.00001) - -/* Handle gamma correction. Screen_gamma=(display_exponent). - * NOTE: this API simply sets the screen and file gamma values. It will - * therefore override the value for gamma in a PNG file if it is called after - * the file header has been read - use with care - call before reading the PNG - * file for best results! - * - * These routines accept the same gamma values as png_set_alpha_mode (described - * above). The PNG_GAMMA_ defines and PNG_DEFAULT_sRGB can be passed to either - * API (floating point or fixed.) Notice, however, that the 'file_gamma' value - * is the inverse of a 'screen gamma' value. - */ -PNG_FP_EXPORT(50, void, png_set_gamma, (png_structrp png_ptr, - double screen_gamma, double override_file_gamma)) -PNG_FIXED_EXPORT(208, void, png_set_gamma_fixed, (png_structrp png_ptr, - png_fixed_point screen_gamma, png_fixed_point override_file_gamma)) -#endif - -#ifdef PNG_WRITE_FLUSH_SUPPORTED -/* Set how many lines between output flushes - 0 for no flushing */ -PNG_EXPORT(51, void, png_set_flush, (png_structrp png_ptr, int nrows)); -/* Flush the current PNG output buffer */ -PNG_EXPORT(52, void, png_write_flush, (png_structrp png_ptr)); -#endif - -/* Optional update palette with requested transformations */ -PNG_EXPORT(53, void, png_start_read_image, (png_structrp png_ptr)); - -/* Optional call to update the users info structure */ -PNG_EXPORT(54, void, png_read_update_info, (png_structrp png_ptr, - png_inforp info_ptr)); - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read one or more rows of image data. */ -PNG_EXPORT(55, void, png_read_rows, (png_structrp png_ptr, png_bytepp row, - png_bytepp display_row, png_uint_32 num_rows)); -#endif - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read a row of data. */ -PNG_EXPORT(56, void, png_read_row, (png_structrp png_ptr, png_bytep row, - png_bytep display_row)); -#endif - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read the whole image into memory at once. */ -PNG_EXPORT(57, void, png_read_image, (png_structrp png_ptr, png_bytepp image)); -#endif - -/* Write a row of image data */ -PNG_EXPORT(58, void, png_write_row, (png_structrp png_ptr, - png_const_bytep row)); - -/* Write a few rows of image data: (*row) is not written; however, the type - * is declared as writeable to maintain compatibility with previous versions - * of libpng and to allow the 'display_row' array from read_rows to be passed - * unchanged to write_rows. - */ -PNG_EXPORT(59, void, png_write_rows, (png_structrp png_ptr, png_bytepp row, - png_uint_32 num_rows)); - -/* Write the image data */ -PNG_EXPORT(60, void, png_write_image, (png_structrp png_ptr, png_bytepp image)); - -/* Write the end of the PNG file. */ -PNG_EXPORT(61, void, png_write_end, (png_structrp png_ptr, - png_inforp info_ptr)); - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read the end of the PNG file. */ -PNG_EXPORT(62, void, png_read_end, (png_structrp png_ptr, png_inforp info_ptr)); -#endif - -/* Free any memory associated with the png_info_struct */ -PNG_EXPORT(63, void, png_destroy_info_struct, (png_const_structrp png_ptr, - png_infopp info_ptr_ptr)); - -/* Free any memory associated with the png_struct and the png_info_structs */ -PNG_EXPORT(64, void, png_destroy_read_struct, (png_structpp png_ptr_ptr, - png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); - -/* Free any memory associated with the png_struct and the png_info_structs */ -PNG_EXPORT(65, void, png_destroy_write_struct, (png_structpp png_ptr_ptr, - png_infopp info_ptr_ptr)); - -/* Set the libpng method of handling chunk CRC errors */ -PNG_EXPORT(66, void, png_set_crc_action, (png_structrp png_ptr, int crit_action, - int ancil_action)); - -/* Values for png_set_crc_action() say how to handle CRC errors in - * ancillary and critical chunks, and whether to use the data contained - * therein. Note that it is impossible to "discard" data in a critical - * chunk. For versions prior to 0.90, the action was always error/quit, - * whereas in version 0.90 and later, the action for CRC errors in ancillary - * chunks is warn/discard. These values should NOT be changed. - * - * value action:critical action:ancillary - */ -#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */ -#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */ -#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */ -#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */ -#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */ -#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */ - -#ifdef PNG_WRITE_SUPPORTED -/* These functions give the user control over the scan-line filtering in - * libpng and the compression methods used by zlib. These functions are - * mainly useful for testing, as the defaults should work with most users. - * Those users who are tight on memory or want faster performance at the - * expense of compression can modify them. See the compression library - * header file (zlib.h) for an explination of the compression functions. - */ - -/* Set the filtering method(s) used by libpng. Currently, the only valid - * value for "method" is 0. - */ -PNG_EXPORT(67, void, png_set_filter, (png_structrp png_ptr, int method, - int filters)); -#endif /* WRITE */ - -/* Flags for png_set_filter() to say which filters to use. The flags - * are chosen so that they don't conflict with real filter types - * below, in case they are supplied instead of the #defined constants. - * These values should NOT be changed. - */ -#define PNG_NO_FILTERS 0x00 -#define PNG_FILTER_NONE 0x08 -#define PNG_FILTER_SUB 0x10 -#define PNG_FILTER_UP 0x20 -#define PNG_FILTER_AVG 0x40 -#define PNG_FILTER_PAETH 0x80 -#define PNG_FAST_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP) -#define PNG_ALL_FILTERS (PNG_FAST_FILTERS | PNG_FILTER_AVG | PNG_FILTER_PAETH) - -/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now. - * These defines should NOT be changed. - */ -#define PNG_FILTER_VALUE_NONE 0 -#define PNG_FILTER_VALUE_SUB 1 -#define PNG_FILTER_VALUE_UP 2 -#define PNG_FILTER_VALUE_AVG 3 -#define PNG_FILTER_VALUE_PAETH 4 -#define PNG_FILTER_VALUE_LAST 5 - -#ifdef PNG_WRITE_SUPPORTED -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* DEPRECATED */ -PNG_FP_EXPORT(68, void, png_set_filter_heuristics, (png_structrp png_ptr, - int heuristic_method, int num_weights, png_const_doublep filter_weights, - png_const_doublep filter_costs)) -PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed, - (png_structrp png_ptr, int heuristic_method, int num_weights, - png_const_fixed_point_p filter_weights, - png_const_fixed_point_p filter_costs)) -#endif /* WRITE_WEIGHTED_FILTER */ - -/* The following are no longer used and will be removed from libpng-1.7: */ -#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */ -#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */ -#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ -#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ - -/* Set the library compression level. Currently, valid values range from - * 0 - 9, corresponding directly to the zlib compression levels 0 - 9 - * (0 - no compression, 9 - "maximal" compression). Note that tests have - * shown that zlib compression levels 3-6 usually perform as well as level 9 - * for PNG images, and do considerably fewer caclulations. In the future, - * these values may not correspond directly to the zlib compression levels. - */ -#ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED -PNG_EXPORT(69, void, png_set_compression_level, (png_structrp png_ptr, - int level)); - -PNG_EXPORT(70, void, png_set_compression_mem_level, (png_structrp png_ptr, - int mem_level)); - -PNG_EXPORT(71, void, png_set_compression_strategy, (png_structrp png_ptr, - int strategy)); - -/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a - * smaller value of window_bits if it can do so safely. - */ -PNG_EXPORT(72, void, png_set_compression_window_bits, (png_structrp png_ptr, - int window_bits)); - -PNG_EXPORT(73, void, png_set_compression_method, (png_structrp png_ptr, - int method)); -#endif /* WRITE_CUSTOMIZE_COMPRESSION */ - -#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED -/* Also set zlib parameters for compressing non-IDAT chunks */ -PNG_EXPORT(222, void, png_set_text_compression_level, (png_structrp png_ptr, - int level)); - -PNG_EXPORT(223, void, png_set_text_compression_mem_level, (png_structrp png_ptr, - int mem_level)); - -PNG_EXPORT(224, void, png_set_text_compression_strategy, (png_structrp png_ptr, - int strategy)); - -/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a - * smaller value of window_bits if it can do so safely. - */ -PNG_EXPORT(225, void, png_set_text_compression_window_bits, - (png_structrp png_ptr, int window_bits)); - -PNG_EXPORT(226, void, png_set_text_compression_method, (png_structrp png_ptr, - int method)); -#endif /* WRITE_CUSTOMIZE_ZTXT_COMPRESSION */ -#endif /* WRITE */ - -/* These next functions are called for input/output, memory, and error - * handling. They are in the file pngrio.c, pngwio.c, and pngerror.c, - * and call standard C I/O routines such as fread(), fwrite(), and - * fprintf(). These functions can be made to use other I/O routines - * at run time for those applications that need to handle I/O in a - * different manner by calling png_set_???_fn(). See libpng-manual.txt for - * more information. - */ - -#ifdef PNG_STDIO_SUPPORTED -/* Initialize the input/output for the PNG file to the default functions. */ -PNG_EXPORT(74, void, png_init_io, (png_structrp png_ptr, png_FILE_p fp)); -#endif - -/* Replace the (error and abort), and warning functions with user - * supplied functions. If no messages are to be printed you must still - * write and use replacement functions. The replacement error_fn should - * still do a longjmp to the last setjmp location if you are using this - * method of error handling. If error_fn or warning_fn is NULL, the - * default function will be used. - */ - -PNG_EXPORT(75, void, png_set_error_fn, (png_structrp png_ptr, - png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn)); - -/* Return the user pointer associated with the error functions */ -PNG_EXPORT(76, png_voidp, png_get_error_ptr, (png_const_structrp png_ptr)); - -/* Replace the default data output functions with a user supplied one(s). - * If buffered output is not used, then output_flush_fn can be set to NULL. - * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time - * output_flush_fn will be ignored (and thus can be NULL). - * It is probably a mistake to use NULL for output_flush_fn if - * write_data_fn is not also NULL unless you have built libpng with - * PNG_WRITE_FLUSH_SUPPORTED undefined, because in this case libpng's - * default flush function, which uses the standard *FILE structure, will - * be used. - */ -PNG_EXPORT(77, void, png_set_write_fn, (png_structrp png_ptr, png_voidp io_ptr, - png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)); - -/* Replace the default data input function with a user supplied one. */ -PNG_EXPORT(78, void, png_set_read_fn, (png_structrp png_ptr, png_voidp io_ptr, - png_rw_ptr read_data_fn)); - -/* Return the user pointer associated with the I/O functions */ -PNG_EXPORT(79, png_voidp, png_get_io_ptr, (png_const_structrp png_ptr)); - -PNG_EXPORT(80, void, png_set_read_status_fn, (png_structrp png_ptr, - png_read_status_ptr read_row_fn)); - -PNG_EXPORT(81, void, png_set_write_status_fn, (png_structrp png_ptr, - png_write_status_ptr write_row_fn)); - -#ifdef PNG_USER_MEM_SUPPORTED -/* Replace the default memory allocation functions with user supplied one(s). */ -PNG_EXPORT(82, void, png_set_mem_fn, (png_structrp png_ptr, png_voidp mem_ptr, - png_malloc_ptr malloc_fn, png_free_ptr free_fn)); -/* Return the user pointer associated with the memory functions */ -PNG_EXPORT(83, png_voidp, png_get_mem_ptr, (png_const_structrp png_ptr)); -#endif - -#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED -PNG_EXPORT(84, void, png_set_read_user_transform_fn, (png_structrp png_ptr, - png_user_transform_ptr read_user_transform_fn)); -#endif - -#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED -PNG_EXPORT(85, void, png_set_write_user_transform_fn, (png_structrp png_ptr, - png_user_transform_ptr write_user_transform_fn)); -#endif - -#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED -PNG_EXPORT(86, void, png_set_user_transform_info, (png_structrp png_ptr, - png_voidp user_transform_ptr, int user_transform_depth, - int user_transform_channels)); -/* Return the user pointer associated with the user transform functions */ -PNG_EXPORT(87, png_voidp, png_get_user_transform_ptr, - (png_const_structrp png_ptr)); -#endif - -#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED -/* Return information about the row currently being processed. Note that these - * APIs do not fail but will return unexpected results if called outside a user - * transform callback. Also note that when transforming an interlaced image the - * row number is the row number within the sub-image of the interlace pass, so - * the value will increase to the height of the sub-image (not the full image) - * then reset to 0 for the next pass. - * - * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to - * find the output pixel (x,y) given an interlaced sub-image pixel - * (row,col,pass). (See below for these macros.) - */ -PNG_EXPORT(217, png_uint_32, png_get_current_row_number, (png_const_structrp)); -PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structrp)); -#endif - -#ifdef PNG_READ_USER_CHUNKS_SUPPORTED -/* This callback is called only for *unknown* chunks. If - * PNG_HANDLE_AS_UNKNOWN_SUPPORTED is set then it is possible to set known - * chunks to be treated as unknown, however in this case the callback must do - * any processing required by the chunk (e.g. by calling the appropriate - * png_set_ APIs.) - * - * There is no write support - on write, by default, all the chunks in the - * 'unknown' list are written in the specified position. - * - * The integer return from the callback function is interpreted thus: - * - * negative: An error occurred; png_chunk_error will be called. - * zero: The chunk was not handled, the chunk will be saved. A critical - * chunk will cause an error at this point unless it is to be saved. - * positive: The chunk was handled, libpng will ignore/discard it. - * - * See "INTERACTION WTIH USER CHUNK CALLBACKS" below for important notes about - * how this behavior will change in libpng 1.7 - */ -PNG_EXPORT(88, void, png_set_read_user_chunk_fn, (png_structrp png_ptr, - png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); -#endif - -#ifdef PNG_USER_CHUNKS_SUPPORTED -PNG_EXPORT(89, png_voidp, png_get_user_chunk_ptr, (png_const_structrp png_ptr)); -#endif - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -/* Sets the function callbacks for the push reader, and a pointer to a - * user-defined structure available to the callback functions. - */ -PNG_EXPORT(90, void, png_set_progressive_read_fn, (png_structrp png_ptr, - png_voidp progressive_ptr, png_progressive_info_ptr info_fn, - png_progressive_row_ptr row_fn, png_progressive_end_ptr end_fn)); - -/* Returns the user pointer associated with the push read functions */ -PNG_EXPORT(91, png_voidp, png_get_progressive_ptr, - (png_const_structrp png_ptr)); - -/* Function to be called when data becomes available */ -PNG_EXPORT(92, void, png_process_data, (png_structrp png_ptr, - png_inforp info_ptr, png_bytep buffer, png_size_t buffer_size)); - -/* A function which may be called *only* within png_process_data to stop the - * processing of any more data. The function returns the number of bytes - * remaining, excluding any that libpng has cached internally. A subsequent - * call to png_process_data must supply these bytes again. If the argument - * 'save' is set to true the routine will first save all the pending data and - * will always return 0. - */ -PNG_EXPORT(219, png_size_t, png_process_data_pause, (png_structrp, int save)); - -/* A function which may be called *only* outside (after) a call to - * png_process_data. It returns the number of bytes of data to skip in the - * input. Normally it will return 0, but if it returns a non-zero value the - * application must skip than number of bytes of input data and pass the - * following data to the next call to png_process_data. - */ -PNG_EXPORT(220, png_uint_32, png_process_data_skip, (png_structrp)); - -/* Function that combines rows. 'new_row' is a flag that should come from - * the callback and be non-NULL if anything needs to be done; the library - * stores its own version of the new data internally and ignores the passed - * in value. - */ -PNG_EXPORT(93, void, png_progressive_combine_row, (png_const_structrp png_ptr, - png_bytep old_row, png_const_bytep new_row)); -#endif /* PROGRESSIVE_READ */ - -PNG_EXPORTA(94, png_voidp, png_malloc, (png_const_structrp png_ptr, - png_alloc_size_t size), PNG_ALLOCATED); -/* Added at libpng version 1.4.0 */ -PNG_EXPORTA(95, png_voidp, png_calloc, (png_const_structrp png_ptr, - png_alloc_size_t size), PNG_ALLOCATED); - -/* Added at libpng version 1.2.4 */ -PNG_EXPORTA(96, png_voidp, png_malloc_warn, (png_const_structrp png_ptr, - png_alloc_size_t size), PNG_ALLOCATED); - -/* Frees a pointer allocated by png_malloc() */ -PNG_EXPORT(97, void, png_free, (png_const_structrp png_ptr, png_voidp ptr)); - -/* Free data that was allocated internally */ -PNG_EXPORT(98, void, png_free_data, (png_const_structrp png_ptr, - png_inforp info_ptr, png_uint_32 free_me, int num)); - -/* Reassign responsibility for freeing existing data, whether allocated - * by libpng or by the application; this works on the png_info structure passed - * in, it does not change the state for other png_info structures. - * - * It is unlikely that this function works correctly as of 1.6.0 and using it - * may result either in memory leaks or double free of allocated data. - */ -PNG_EXPORT(99, void, png_data_freer, (png_const_structrp png_ptr, - png_inforp info_ptr, int freer, png_uint_32 mask)); - -/* Assignments for png_data_freer */ -#define PNG_DESTROY_WILL_FREE_DATA 1 -#define PNG_SET_WILL_FREE_DATA 1 -#define PNG_USER_WILL_FREE_DATA 2 -/* Flags for png_ptr->free_me and info_ptr->free_me */ -#define PNG_FREE_HIST 0x0008U -#define PNG_FREE_ICCP 0x0010U -#define PNG_FREE_SPLT 0x0020U -#define PNG_FREE_ROWS 0x0040U -#define PNG_FREE_PCAL 0x0080U -#define PNG_FREE_SCAL 0x0100U -#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED -# define PNG_FREE_UNKN 0x0200U -#endif -/* PNG_FREE_LIST 0x0400U removed in 1.6.0 because it is ignored */ -#define PNG_FREE_PLTE 0x1000U -#define PNG_FREE_TRNS 0x2000U -#define PNG_FREE_TEXT 0x4000U -#define PNG_FREE_EXIF 0x8000U /* Added at libpng-1.6.31 */ -#define PNG_FREE_ALL 0xffffU -#define PNG_FREE_MUL 0x4220U /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ - -#ifdef PNG_USER_MEM_SUPPORTED -PNG_EXPORTA(100, png_voidp, png_malloc_default, (png_const_structrp png_ptr, - png_alloc_size_t size), PNG_ALLOCATED PNG_DEPRECATED); -PNG_EXPORTA(101, void, png_free_default, (png_const_structrp png_ptr, - png_voidp ptr), PNG_DEPRECATED); -#endif - -#ifdef PNG_ERROR_TEXT_SUPPORTED -/* Fatal error in PNG image of libpng - can't continue */ -PNG_EXPORTA(102, void, png_error, (png_const_structrp png_ptr, - png_const_charp error_message), PNG_NORETURN); - -/* The same, but the chunk name is prepended to the error string. */ -PNG_EXPORTA(103, void, png_chunk_error, (png_const_structrp png_ptr, - png_const_charp error_message), PNG_NORETURN); - -#else -/* Fatal error in PNG image of libpng - can't continue */ -PNG_EXPORTA(104, void, png_err, (png_const_structrp png_ptr), PNG_NORETURN); -# define png_error(s1,s2) png_err(s1) -# define png_chunk_error(s1,s2) png_err(s1) -#endif - -#ifdef PNG_WARNINGS_SUPPORTED -/* Non-fatal error in libpng. Can continue, but may have a problem. */ -PNG_EXPORT(105, void, png_warning, (png_const_structrp png_ptr, - png_const_charp warning_message)); - -/* Non-fatal error in libpng, chunk name is prepended to message. */ -PNG_EXPORT(106, void, png_chunk_warning, (png_const_structrp png_ptr, - png_const_charp warning_message)); -#else -# define png_warning(s1,s2) ((void)(s1)) -# define png_chunk_warning(s1,s2) ((void)(s1)) -#endif - -#ifdef PNG_BENIGN_ERRORS_SUPPORTED -/* Benign error in libpng. Can continue, but may have a problem. - * User can choose whether to handle as a fatal error or as a warning. */ -PNG_EXPORT(107, void, png_benign_error, (png_const_structrp png_ptr, - png_const_charp warning_message)); - -#ifdef PNG_READ_SUPPORTED -/* Same, chunk name is prepended to message (only during read) */ -PNG_EXPORT(108, void, png_chunk_benign_error, (png_const_structrp png_ptr, - png_const_charp warning_message)); -#endif - -PNG_EXPORT(109, void, png_set_benign_errors, - (png_structrp png_ptr, int allowed)); -#else -# ifdef PNG_ALLOW_BENIGN_ERRORS -# define png_benign_error png_warning -# define png_chunk_benign_error png_chunk_warning -# else -# define png_benign_error png_error -# define png_chunk_benign_error png_chunk_error -# endif -#endif - -/* The png_set_ functions are for storing values in the png_info_struct. - * Similarly, the png_get_ calls are used to read values from the - * png_info_struct, either storing the parameters in the passed variables, or - * setting pointers into the png_info_struct where the data is stored. The - * png_get_ functions return a non-zero value if the data was available - * in info_ptr, or return zero and do not change any of the parameters if the - * data was not available. - * - * These functions should be used instead of directly accessing png_info - * to avoid problems with future changes in the size and internal layout of - * png_info_struct. - */ -/* Returns "flag" if chunk data is valid in info_ptr. */ -PNG_EXPORT(110, png_uint_32, png_get_valid, (png_const_structrp png_ptr, - png_const_inforp info_ptr, png_uint_32 flag)); - -/* Returns number of bytes needed to hold a transformed row. */ -PNG_EXPORT(111, png_size_t, png_get_rowbytes, (png_const_structrp png_ptr, - png_const_inforp info_ptr)); - -#ifdef PNG_INFO_IMAGE_SUPPORTED -/* Returns row_pointers, which is an array of pointers to scanlines that was - * returned from png_read_png(). - */ -PNG_EXPORT(112, png_bytepp, png_get_rows, (png_const_structrp png_ptr, - png_const_inforp info_ptr)); - -/* Set row_pointers, which is an array of pointers to scanlines for use - * by png_write_png(). - */ -PNG_EXPORT(113, void, png_set_rows, (png_const_structrp png_ptr, - png_inforp info_ptr, png_bytepp row_pointers)); -#endif - -/* Returns number of color channels in image. */ -PNG_EXPORT(114, png_byte, png_get_channels, (png_const_structrp png_ptr, - png_const_inforp info_ptr)); - -#ifdef PNG_EASY_ACCESS_SUPPORTED -/* Returns image width in pixels. */ -PNG_EXPORT(115, png_uint_32, png_get_image_width, (png_const_structrp png_ptr, - png_const_inforp info_ptr)); - -/* Returns image height in pixels. */ -PNG_EXPORT(116, png_uint_32, png_get_image_height, (png_const_structrp png_ptr, - png_const_inforp info_ptr)); - -/* Returns image bit_depth. */ -PNG_EXPORT(117, png_byte, png_get_bit_depth, (png_const_structrp png_ptr, - png_const_inforp info_ptr)); - -/* Returns image color_type. */ -PNG_EXPORT(118, png_byte, png_get_color_type, (png_const_structrp png_ptr, - png_const_inforp info_ptr)); - -/* Returns image filter_type. */ -PNG_EXPORT(119, png_byte, png_get_filter_type, (png_const_structrp png_ptr, - png_const_inforp info_ptr)); - -/* Returns image interlace_type. */ -PNG_EXPORT(120, png_byte, png_get_interlace_type, (png_const_structrp png_ptr, - png_const_inforp info_ptr)); - -/* Returns image compression_type. */ -PNG_EXPORT(121, png_byte, png_get_compression_type, (png_const_structrp png_ptr, - png_const_inforp info_ptr)); - -/* Returns image resolution in pixels per meter, from pHYs chunk data. */ -PNG_EXPORT(122, png_uint_32, png_get_pixels_per_meter, - (png_const_structrp png_ptr, png_const_inforp info_ptr)); -PNG_EXPORT(123, png_uint_32, png_get_x_pixels_per_meter, - (png_const_structrp png_ptr, png_const_inforp info_ptr)); -PNG_EXPORT(124, png_uint_32, png_get_y_pixels_per_meter, - (png_const_structrp png_ptr, png_const_inforp info_ptr)); - -/* Returns pixel aspect ratio, computed from pHYs chunk data. */ -PNG_FP_EXPORT(125, float, png_get_pixel_aspect_ratio, - (png_const_structrp png_ptr, png_const_inforp info_ptr)) -PNG_FIXED_EXPORT(210, png_fixed_point, png_get_pixel_aspect_ratio_fixed, - (png_const_structrp png_ptr, png_const_inforp info_ptr)) - -/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ -PNG_EXPORT(126, png_int_32, png_get_x_offset_pixels, - (png_const_structrp png_ptr, png_const_inforp info_ptr)); -PNG_EXPORT(127, png_int_32, png_get_y_offset_pixels, - (png_const_structrp png_ptr, png_const_inforp info_ptr)); -PNG_EXPORT(128, png_int_32, png_get_x_offset_microns, - (png_const_structrp png_ptr, png_const_inforp info_ptr)); -PNG_EXPORT(129, png_int_32, png_get_y_offset_microns, - (png_const_structrp png_ptr, png_const_inforp info_ptr)); - -#endif /* EASY_ACCESS */ - -#ifdef PNG_READ_SUPPORTED -/* Returns pointer to signature string read from PNG header */ -PNG_EXPORT(130, png_const_bytep, png_get_signature, (png_const_structrp png_ptr, - png_const_inforp info_ptr)); -#endif - -#ifdef PNG_bKGD_SUPPORTED -PNG_EXPORT(131, png_uint_32, png_get_bKGD, (png_const_structrp png_ptr, - png_inforp info_ptr, png_color_16p *background)); -#endif - -#ifdef PNG_bKGD_SUPPORTED -PNG_EXPORT(132, void, png_set_bKGD, (png_const_structrp png_ptr, - png_inforp info_ptr, png_const_color_16p background)); -#endif - -#ifdef PNG_cHRM_SUPPORTED -PNG_FP_EXPORT(133, png_uint_32, png_get_cHRM, (png_const_structrp png_ptr, - png_const_inforp info_ptr, double *white_x, double *white_y, double *red_x, - double *red_y, double *green_x, double *green_y, double *blue_x, - double *blue_y)) -PNG_FP_EXPORT(230, png_uint_32, png_get_cHRM_XYZ, (png_const_structrp png_ptr, - png_const_inforp info_ptr, double *red_X, double *red_Y, double *red_Z, - double *green_X, double *green_Y, double *green_Z, double *blue_X, - double *blue_Y, double *blue_Z)) -PNG_FIXED_EXPORT(134, png_uint_32, png_get_cHRM_fixed, - (png_const_structrp png_ptr, png_const_inforp info_ptr, - png_fixed_point *int_white_x, png_fixed_point *int_white_y, - png_fixed_point *int_red_x, png_fixed_point *int_red_y, - png_fixed_point *int_green_x, png_fixed_point *int_green_y, - png_fixed_point *int_blue_x, png_fixed_point *int_blue_y)) -PNG_FIXED_EXPORT(231, png_uint_32, png_get_cHRM_XYZ_fixed, - (png_const_structrp png_ptr, png_const_inforp info_ptr, - png_fixed_point *int_red_X, png_fixed_point *int_red_Y, - png_fixed_point *int_red_Z, png_fixed_point *int_green_X, - png_fixed_point *int_green_Y, png_fixed_point *int_green_Z, - png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y, - png_fixed_point *int_blue_Z)) -#endif - -#ifdef PNG_cHRM_SUPPORTED -PNG_FP_EXPORT(135, void, png_set_cHRM, (png_const_structrp png_ptr, - png_inforp info_ptr, - double white_x, double white_y, double red_x, double red_y, double green_x, - double green_y, double blue_x, double blue_y)) -PNG_FP_EXPORT(232, void, png_set_cHRM_XYZ, (png_const_structrp png_ptr, - png_inforp info_ptr, double red_X, double red_Y, double red_Z, - double green_X, double green_Y, double green_Z, double blue_X, - double blue_Y, double blue_Z)) -PNG_FIXED_EXPORT(136, void, png_set_cHRM_fixed, (png_const_structrp png_ptr, - png_inforp info_ptr, png_fixed_point int_white_x, - png_fixed_point int_white_y, png_fixed_point int_red_x, - png_fixed_point int_red_y, png_fixed_point int_green_x, - png_fixed_point int_green_y, png_fixed_point int_blue_x, - png_fixed_point int_blue_y)) -PNG_FIXED_EXPORT(233, void, png_set_cHRM_XYZ_fixed, (png_const_structrp png_ptr, - png_inforp info_ptr, png_fixed_point int_red_X, png_fixed_point int_red_Y, - png_fixed_point int_red_Z, png_fixed_point int_green_X, - png_fixed_point int_green_Y, png_fixed_point int_green_Z, - png_fixed_point int_blue_X, png_fixed_point int_blue_Y, - png_fixed_point int_blue_Z)) -#endif - -#ifdef PNG_eXIf_SUPPORTED -PNG_EXPORT(246, png_uint_32, png_get_eXIf, (png_const_structrp png_ptr, - png_inforp info_ptr, png_bytep *exif)); -PNG_EXPORT(247, void, png_set_eXIf, (png_const_structrp png_ptr, - png_inforp info_ptr, const png_bytep exif)); - -PNG_EXPORT(248, png_uint_32, png_get_eXIf_1, (png_const_structrp png_ptr, - png_const_inforp info_ptr, png_uint_32 *num_exif, png_bytep *exif)); -PNG_EXPORT(249, void, png_set_eXIf_1, (png_const_structrp png_ptr, - png_inforp info_ptr, const png_uint_32 num_exif, const png_bytep exif)); -#endif - -#ifdef PNG_gAMA_SUPPORTED -PNG_FP_EXPORT(137, png_uint_32, png_get_gAMA, (png_const_structrp png_ptr, - png_const_inforp info_ptr, double *file_gamma)) -PNG_FIXED_EXPORT(138, png_uint_32, png_get_gAMA_fixed, - (png_const_structrp png_ptr, png_const_inforp info_ptr, - png_fixed_point *int_file_gamma)) -#endif - -#ifdef PNG_gAMA_SUPPORTED -PNG_FP_EXPORT(139, void, png_set_gAMA, (png_const_structrp png_ptr, - png_inforp info_ptr, double file_gamma)) -PNG_FIXED_EXPORT(140, void, png_set_gAMA_fixed, (png_const_structrp png_ptr, - png_inforp info_ptr, png_fixed_point int_file_gamma)) -#endif - -#ifdef PNG_hIST_SUPPORTED -PNG_EXPORT(141, png_uint_32, png_get_hIST, (png_const_structrp png_ptr, - png_inforp info_ptr, png_uint_16p *hist)); -PNG_EXPORT(142, void, png_set_hIST, (png_const_structrp png_ptr, - png_inforp info_ptr, png_const_uint_16p hist)); -#endif - -PNG_EXPORT(143, png_uint_32, png_get_IHDR, (png_const_structrp png_ptr, - png_const_inforp info_ptr, png_uint_32 *width, png_uint_32 *height, - int *bit_depth, int *color_type, int *interlace_method, - int *compression_method, int *filter_method)); - -PNG_EXPORT(144, void, png_set_IHDR, (png_const_structrp png_ptr, - png_inforp info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, - int color_type, int interlace_method, int compression_method, - int filter_method)); - -#ifdef PNG_oFFs_SUPPORTED -PNG_EXPORT(145, png_uint_32, png_get_oFFs, (png_const_structrp png_ptr, - png_const_inforp info_ptr, png_int_32 *offset_x, png_int_32 *offset_y, - int *unit_type)); -#endif - -#ifdef PNG_oFFs_SUPPORTED -PNG_EXPORT(146, void, png_set_oFFs, (png_const_structrp png_ptr, - png_inforp info_ptr, png_int_32 offset_x, png_int_32 offset_y, - int unit_type)); -#endif - -#ifdef PNG_pCAL_SUPPORTED -PNG_EXPORT(147, png_uint_32, png_get_pCAL, (png_const_structrp png_ptr, - png_inforp info_ptr, png_charp *purpose, png_int_32 *X0, - png_int_32 *X1, int *type, int *nparams, png_charp *units, - png_charpp *params)); -#endif - -#ifdef PNG_pCAL_SUPPORTED -PNG_EXPORT(148, void, png_set_pCAL, (png_const_structrp png_ptr, - png_inforp info_ptr, png_const_charp purpose, png_int_32 X0, png_int_32 X1, - int type, int nparams, png_const_charp units, png_charpp params)); -#endif - -#ifdef PNG_pHYs_SUPPORTED -PNG_EXPORT(149, png_uint_32, png_get_pHYs, (png_const_structrp png_ptr, - png_const_inforp info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, - int *unit_type)); -#endif - -#ifdef PNG_pHYs_SUPPORTED -PNG_EXPORT(150, void, png_set_pHYs, (png_const_structrp png_ptr, - png_inforp info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type)); -#endif - -PNG_EXPORT(151, png_uint_32, png_get_PLTE, (png_const_structrp png_ptr, - png_inforp info_ptr, png_colorp *palette, int *num_palette)); - -PNG_EXPORT(152, void, png_set_PLTE, (png_structrp png_ptr, - png_inforp info_ptr, png_const_colorp palette, int num_palette)); - -#ifdef PNG_sBIT_SUPPORTED -PNG_EXPORT(153, png_uint_32, png_get_sBIT, (png_const_structrp png_ptr, - png_inforp info_ptr, png_color_8p *sig_bit)); -#endif - -#ifdef PNG_sBIT_SUPPORTED -PNG_EXPORT(154, void, png_set_sBIT, (png_const_structrp png_ptr, - png_inforp info_ptr, png_const_color_8p sig_bit)); -#endif - -#ifdef PNG_sRGB_SUPPORTED -PNG_EXPORT(155, png_uint_32, png_get_sRGB, (png_const_structrp png_ptr, - png_const_inforp info_ptr, int *file_srgb_intent)); -#endif - -#ifdef PNG_sRGB_SUPPORTED -PNG_EXPORT(156, void, png_set_sRGB, (png_const_structrp png_ptr, - png_inforp info_ptr, int srgb_intent)); -PNG_EXPORT(157, void, png_set_sRGB_gAMA_and_cHRM, (png_const_structrp png_ptr, - png_inforp info_ptr, int srgb_intent)); -#endif - -#ifdef PNG_iCCP_SUPPORTED -PNG_EXPORT(158, png_uint_32, png_get_iCCP, (png_const_structrp png_ptr, - png_inforp info_ptr, png_charpp name, int *compression_type, - png_bytepp profile, png_uint_32 *proflen)); -#endif - -#ifdef PNG_iCCP_SUPPORTED -PNG_EXPORT(159, void, png_set_iCCP, (png_const_structrp png_ptr, - png_inforp info_ptr, png_const_charp name, int compression_type, - png_const_bytep profile, png_uint_32 proflen)); -#endif - -#ifdef PNG_sPLT_SUPPORTED -PNG_EXPORT(160, int, png_get_sPLT, (png_const_structrp png_ptr, - png_inforp info_ptr, png_sPLT_tpp entries)); -#endif - -#ifdef PNG_sPLT_SUPPORTED -PNG_EXPORT(161, void, png_set_sPLT, (png_const_structrp png_ptr, - png_inforp info_ptr, png_const_sPLT_tp entries, int nentries)); -#endif - -#ifdef PNG_TEXT_SUPPORTED -/* png_get_text also returns the number of text chunks in *num_text */ -PNG_EXPORT(162, int, png_get_text, (png_const_structrp png_ptr, - png_inforp info_ptr, png_textp *text_ptr, int *num_text)); -#endif - -/* Note while png_set_text() will accept a structure whose text, - * language, and translated keywords are NULL pointers, the structure - * returned by png_get_text will always contain regular - * zero-terminated C strings. They might be empty strings but - * they will never be NULL pointers. - */ - -#ifdef PNG_TEXT_SUPPORTED -PNG_EXPORT(163, void, png_set_text, (png_const_structrp png_ptr, - png_inforp info_ptr, png_const_textp text_ptr, int num_text)); -#endif - -#ifdef PNG_tIME_SUPPORTED -PNG_EXPORT(164, png_uint_32, png_get_tIME, (png_const_structrp png_ptr, - png_inforp info_ptr, png_timep *mod_time)); -#endif - -#ifdef PNG_tIME_SUPPORTED -PNG_EXPORT(165, void, png_set_tIME, (png_const_structrp png_ptr, - png_inforp info_ptr, png_const_timep mod_time)); -#endif - -#ifdef PNG_tRNS_SUPPORTED -PNG_EXPORT(166, png_uint_32, png_get_tRNS, (png_const_structrp png_ptr, - png_inforp info_ptr, png_bytep *trans_alpha, int *num_trans, - png_color_16p *trans_color)); -#endif - -#ifdef PNG_tRNS_SUPPORTED -PNG_EXPORT(167, void, png_set_tRNS, (png_structrp png_ptr, - png_inforp info_ptr, png_const_bytep trans_alpha, int num_trans, - png_const_color_16p trans_color)); -#endif - -#ifdef PNG_sCAL_SUPPORTED -PNG_FP_EXPORT(168, png_uint_32, png_get_sCAL, (png_const_structrp png_ptr, - png_const_inforp info_ptr, int *unit, double *width, double *height)) -#if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) || \ - defined(PNG_FLOATING_POINT_SUPPORTED) -/* NOTE: this API is currently implemented using floating point arithmetic, - * consequently it can only be used on systems with floating point support. - * In any case the range of values supported by png_fixed_point is small and it - * is highly recommended that png_get_sCAL_s be used instead. - */ -PNG_FIXED_EXPORT(214, png_uint_32, png_get_sCAL_fixed, - (png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit, - png_fixed_point *width, png_fixed_point *height)) -#endif -PNG_EXPORT(169, png_uint_32, png_get_sCAL_s, - (png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit, - png_charpp swidth, png_charpp sheight)); - -PNG_FP_EXPORT(170, void, png_set_sCAL, (png_const_structrp png_ptr, - png_inforp info_ptr, int unit, double width, double height)) -PNG_FIXED_EXPORT(213, void, png_set_sCAL_fixed, (png_const_structrp png_ptr, - png_inforp info_ptr, int unit, png_fixed_point width, - png_fixed_point height)) -PNG_EXPORT(171, void, png_set_sCAL_s, (png_const_structrp png_ptr, - png_inforp info_ptr, int unit, - png_const_charp swidth, png_const_charp sheight)); -#endif /* sCAL */ - -#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED -/* Provide the default handling for all unknown chunks or, optionally, for - * specific unknown chunks. - * - * NOTE: prior to 1.6.0 the handling specified for particular chunks on read was - * ignored and the default was used, the per-chunk setting only had an effect on - * write. If you wish to have chunk-specific handling on read in code that must - * work on earlier versions you must use a user chunk callback to specify the - * desired handling (keep or discard.) - * - * The 'keep' parameter is a PNG_HANDLE_CHUNK_ value as listed below. The - * parameter is interpreted as follows: - * - * READ: - * PNG_HANDLE_CHUNK_AS_DEFAULT: - * Known chunks: do normal libpng processing, do not keep the chunk (but - * see the comments below about PNG_HANDLE_AS_UNKNOWN_SUPPORTED) - * Unknown chunks: for a specific chunk use the global default, when used - * as the default discard the chunk data. - * PNG_HANDLE_CHUNK_NEVER: - * Discard the chunk data. - * PNG_HANDLE_CHUNK_IF_SAFE: - * Keep the chunk data if the chunk is not critical else raise a chunk - * error. - * PNG_HANDLE_CHUNK_ALWAYS: - * Keep the chunk data. - * - * If the chunk data is saved it can be retrieved using png_get_unknown_chunks, - * below. Notice that specifying "AS_DEFAULT" as a global default is equivalent - * to specifying "NEVER", however when "AS_DEFAULT" is used for specific chunks - * it simply resets the behavior to the libpng default. - * - * INTERACTION WTIH USER CHUNK CALLBACKS: - * The per-chunk handling is always used when there is a png_user_chunk_ptr - * callback and the callback returns 0; the chunk is then always stored *unless* - * it is critical and the per-chunk setting is other than ALWAYS. Notice that - * the global default is *not* used in this case. (In effect the per-chunk - * value is incremented to at least IF_SAFE.) - * - * IMPORTANT NOTE: this behavior will change in libpng 1.7 - the global and - * per-chunk defaults will be honored. If you want to preserve the current - * behavior when your callback returns 0 you must set PNG_HANDLE_CHUNK_IF_SAFE - * as the default - if you don't do this libpng 1.6 will issue a warning. - * - * If you want unhandled unknown chunks to be discarded in libpng 1.6 and - * earlier simply return '1' (handled). - * - * PNG_HANDLE_AS_UNKNOWN_SUPPORTED: - * If this is *not* set known chunks will always be handled by libpng and - * will never be stored in the unknown chunk list. Known chunks listed to - * png_set_keep_unknown_chunks will have no effect. If it is set then known - * chunks listed with a keep other than AS_DEFAULT will *never* be processed - * by libpng, in addition critical chunks must either be processed by the - * callback or saved. - * - * The IHDR and IEND chunks must not be listed. Because this turns off the - * default handling for chunks that would otherwise be recognized the - * behavior of libpng transformations may well become incorrect! - * - * WRITE: - * When writing chunks the options only apply to the chunks specified by - * png_set_unknown_chunks (below), libpng will *always* write known chunks - * required by png_set_ calls and will always write the core critical chunks - * (as required for PLTE). - * - * Each chunk in the png_set_unknown_chunks list is looked up in the - * png_set_keep_unknown_chunks list to find the keep setting, this is then - * interpreted as follows: - * - * PNG_HANDLE_CHUNK_AS_DEFAULT: - * Write safe-to-copy chunks and write other chunks if the global - * default is set to _ALWAYS, otherwise don't write this chunk. - * PNG_HANDLE_CHUNK_NEVER: - * Do not write the chunk. - * PNG_HANDLE_CHUNK_IF_SAFE: - * Write the chunk if it is safe-to-copy, otherwise do not write it. - * PNG_HANDLE_CHUNK_ALWAYS: - * Write the chunk. - * - * Note that the default behavior is effectively the opposite of the read case - - * in read unknown chunks are not stored by default, in write they are written - * by default. Also the behavior of PNG_HANDLE_CHUNK_IF_SAFE is very different - * - on write the safe-to-copy bit is checked, on read the critical bit is - * checked and on read if the chunk is critical an error will be raised. - * - * num_chunks: - * =========== - * If num_chunks is positive, then the "keep" parameter specifies the manner - * for handling only those chunks appearing in the chunk_list array, - * otherwise the chunk list array is ignored. - * - * If num_chunks is 0 the "keep" parameter specifies the default behavior for - * unknown chunks, as described above. - * - * If num_chunks is negative, then the "keep" parameter specifies the manner - * for handling all unknown chunks plus all chunks recognized by libpng - * except for the IHDR, PLTE, tRNS, IDAT, and IEND chunks (which continue to - * be processed by libpng. - */ -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED -PNG_EXPORT(172, void, png_set_keep_unknown_chunks, (png_structrp png_ptr, - int keep, png_const_bytep chunk_list, int num_chunks)); -#endif /* HANDLE_AS_UNKNOWN */ - -/* The "keep" PNG_HANDLE_CHUNK_ parameter for the specified chunk is returned; - * the result is therefore true (non-zero) if special handling is required, - * false for the default handling. - */ -PNG_EXPORT(173, int, png_handle_as_unknown, (png_const_structrp png_ptr, - png_const_bytep chunk_name)); -#endif /* SET_UNKNOWN_CHUNKS */ - -#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED -PNG_EXPORT(174, void, png_set_unknown_chunks, (png_const_structrp png_ptr, - png_inforp info_ptr, png_const_unknown_chunkp unknowns, - int num_unknowns)); - /* NOTE: prior to 1.6.0 this routine set the 'location' field of the added - * unknowns to the location currently stored in the png_struct. This is - * invariably the wrong value on write. To fix this call the following API - * for each chunk in the list with the correct location. If you know your - * code won't be compiled on earlier versions you can rely on - * png_set_unknown_chunks(write-ptr, png_get_unknown_chunks(read-ptr)) doing - * the correct thing. - */ - -PNG_EXPORT(175, void, png_set_unknown_chunk_location, - (png_const_structrp png_ptr, png_inforp info_ptr, int chunk, int location)); - -PNG_EXPORT(176, int, png_get_unknown_chunks, (png_const_structrp png_ptr, - png_inforp info_ptr, png_unknown_chunkpp entries)); -#endif - -/* Png_free_data() will turn off the "valid" flag for anything it frees. - * If you need to turn it off for a chunk that your application has freed, - * you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); - */ -PNG_EXPORT(177, void, png_set_invalid, (png_const_structrp png_ptr, - png_inforp info_ptr, int mask)); - -#ifdef PNG_INFO_IMAGE_SUPPORTED -/* The "params" pointer is currently not used and is for future expansion. */ -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -PNG_EXPORT(178, void, png_read_png, (png_structrp png_ptr, png_inforp info_ptr, - int transforms, png_voidp params)); -#endif -#ifdef PNG_WRITE_SUPPORTED -PNG_EXPORT(179, void, png_write_png, (png_structrp png_ptr, png_inforp info_ptr, - int transforms, png_voidp params)); -#endif -#endif - -PNG_EXPORT(180, png_const_charp, png_get_copyright, - (png_const_structrp png_ptr)); -PNG_EXPORT(181, png_const_charp, png_get_header_ver, - (png_const_structrp png_ptr)); -PNG_EXPORT(182, png_const_charp, png_get_header_version, - (png_const_structrp png_ptr)); -PNG_EXPORT(183, png_const_charp, png_get_libpng_ver, - (png_const_structrp png_ptr)); - -#ifdef PNG_MNG_FEATURES_SUPPORTED -PNG_EXPORT(184, png_uint_32, png_permit_mng_features, (png_structrp png_ptr, - png_uint_32 mng_features_permitted)); -#endif - -/* For use in png_set_keep_unknown, added to version 1.2.6 */ -#define PNG_HANDLE_CHUNK_AS_DEFAULT 0 -#define PNG_HANDLE_CHUNK_NEVER 1 -#define PNG_HANDLE_CHUNK_IF_SAFE 2 -#define PNG_HANDLE_CHUNK_ALWAYS 3 -#define PNG_HANDLE_CHUNK_LAST 4 - -/* Strip the prepended error numbers ("#nnn ") from error and warning - * messages before passing them to the error or warning handler. - */ -#ifdef PNG_ERROR_NUMBERS_SUPPORTED -PNG_EXPORT(185, void, png_set_strip_error_numbers, (png_structrp png_ptr, - png_uint_32 strip_mode)); -#endif - -/* Added in libpng-1.2.6 */ -#ifdef PNG_SET_USER_LIMITS_SUPPORTED -PNG_EXPORT(186, void, png_set_user_limits, (png_structrp png_ptr, - png_uint_32 user_width_max, png_uint_32 user_height_max)); -PNG_EXPORT(187, png_uint_32, png_get_user_width_max, - (png_const_structrp png_ptr)); -PNG_EXPORT(188, png_uint_32, png_get_user_height_max, - (png_const_structrp png_ptr)); -/* Added in libpng-1.4.0 */ -PNG_EXPORT(189, void, png_set_chunk_cache_max, (png_structrp png_ptr, - png_uint_32 user_chunk_cache_max)); -PNG_EXPORT(190, png_uint_32, png_get_chunk_cache_max, - (png_const_structrp png_ptr)); -/* Added in libpng-1.4.1 */ -PNG_EXPORT(191, void, png_set_chunk_malloc_max, (png_structrp png_ptr, - png_alloc_size_t user_chunk_cache_max)); -PNG_EXPORT(192, png_alloc_size_t, png_get_chunk_malloc_max, - (png_const_structrp png_ptr)); -#endif - -#if defined(PNG_INCH_CONVERSIONS_SUPPORTED) -PNG_EXPORT(193, png_uint_32, png_get_pixels_per_inch, - (png_const_structrp png_ptr, png_const_inforp info_ptr)); - -PNG_EXPORT(194, png_uint_32, png_get_x_pixels_per_inch, - (png_const_structrp png_ptr, png_const_inforp info_ptr)); - -PNG_EXPORT(195, png_uint_32, png_get_y_pixels_per_inch, - (png_const_structrp png_ptr, png_const_inforp info_ptr)); - -PNG_FP_EXPORT(196, float, png_get_x_offset_inches, - (png_const_structrp png_ptr, png_const_inforp info_ptr)) -#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ -PNG_FIXED_EXPORT(211, png_fixed_point, png_get_x_offset_inches_fixed, - (png_const_structrp png_ptr, png_const_inforp info_ptr)) -#endif - -PNG_FP_EXPORT(197, float, png_get_y_offset_inches, (png_const_structrp png_ptr, - png_const_inforp info_ptr)) -#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ -PNG_FIXED_EXPORT(212, png_fixed_point, png_get_y_offset_inches_fixed, - (png_const_structrp png_ptr, png_const_inforp info_ptr)) -#endif - -# ifdef PNG_pHYs_SUPPORTED -PNG_EXPORT(198, png_uint_32, png_get_pHYs_dpi, (png_const_structrp png_ptr, - png_const_inforp info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, - int *unit_type)); -# endif /* pHYs */ -#endif /* INCH_CONVERSIONS */ - -/* Added in libpng-1.4.0 */ -#ifdef PNG_IO_STATE_SUPPORTED -PNG_EXPORT(199, png_uint_32, png_get_io_state, (png_const_structrp png_ptr)); - -/* Removed from libpng 1.6; use png_get_io_chunk_type. */ -PNG_REMOVED(200, png_const_bytep, png_get_io_chunk_name, (png_structrp png_ptr), - PNG_DEPRECATED) - -PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type, - (png_const_structrp png_ptr)); - -/* The flags returned by png_get_io_state() are the following: */ -# define PNG_IO_NONE 0x0000 /* no I/O at this moment */ -# define PNG_IO_READING 0x0001 /* currently reading */ -# define PNG_IO_WRITING 0x0002 /* currently writing */ -# define PNG_IO_SIGNATURE 0x0010 /* currently at the file signature */ -# define PNG_IO_CHUNK_HDR 0x0020 /* currently at the chunk header */ -# define PNG_IO_CHUNK_DATA 0x0040 /* currently at the chunk data */ -# define PNG_IO_CHUNK_CRC 0x0080 /* currently at the chunk crc */ -# define PNG_IO_MASK_OP 0x000f /* current operation: reading/writing */ -# define PNG_IO_MASK_LOC 0x00f0 /* current location: sig/hdr/data/crc */ -#endif /* IO_STATE */ - -/* Interlace support. The following macros are always defined so that if - * libpng interlace handling is turned off the macros may be used to handle - * interlaced images within the application. - */ -#define PNG_INTERLACE_ADAM7_PASSES 7 - -/* Two macros to return the first row and first column of the original, - * full, image which appears in a given pass. 'pass' is in the range 0 - * to 6 and the result is in the range 0 to 7. - */ -#define PNG_PASS_START_ROW(pass) (((1&~(pass))<<(3-((pass)>>1)))&7) -#define PNG_PASS_START_COL(pass) (((1& (pass))<<(3-(((pass)+1)>>1)))&7) - -/* A macro to return the offset between pixels in the output row for a pair of - * pixels in the input - effectively the inverse of the 'COL_SHIFT' macro that - * follows. Note that ROW_OFFSET is the offset from one row to the next whereas - * COL_OFFSET is from one column to the next, within a row. - */ -#define PNG_PASS_ROW_OFFSET(pass) ((pass)>2?(8>>(((pass)-1)>>1)):8) -#define PNG_PASS_COL_OFFSET(pass) (1<<((7-(pass))>>1)) - -/* Two macros to help evaluate the number of rows or columns in each - * pass. This is expressed as a shift - effectively log2 of the number or - * rows or columns in each 8x8 tile of the original image. - */ -#define PNG_PASS_ROW_SHIFT(pass) ((pass)>2?(8-(pass))>>1:3) -#define PNG_PASS_COL_SHIFT(pass) ((pass)>1?(7-(pass))>>1:3) - -/* Hence two macros to determine the number of rows or columns in a given - * pass of an image given its height or width. In fact these macros may - * return non-zero even though the sub-image is empty, because the other - * dimension may be empty for a small image. - */ -#define PNG_PASS_ROWS(height, pass) (((height)+(((1<>PNG_PASS_ROW_SHIFT(pass)) -#define PNG_PASS_COLS(width, pass) (((width)+(((1<>PNG_PASS_COL_SHIFT(pass)) - -/* For the reader row callbacks (both progressive and sequential) it is - * necessary to find the row in the output image given a row in an interlaced - * image, so two more macros: - */ -#define PNG_ROW_FROM_PASS_ROW(y_in, pass) \ - (((y_in)<>(((7-(off))-(pass))<<2)) & 0xF) | \ - ((0x01145AF0>>(((7-(off))-(pass))<<2)) & 0xF0)) - -#define PNG_ROW_IN_INTERLACE_PASS(y, pass) \ - ((PNG_PASS_MASK(pass,0) >> ((y)&7)) & 1) -#define PNG_COL_IN_INTERLACE_PASS(x, pass) \ - ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1) - -#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED -/* With these routines we avoid an integer divide, which will be slower on - * most machines. However, it does take more operations than the corresponding - * divide method, so it may be slower on a few RISC systems. There are two - * shifts (by 8 or 16 bits) and an addition, versus a single integer divide. - * - * Note that the rounding factors are NOT supposed to be the same! 128 and - * 32768 are correct for the NODIV code; 127 and 32767 are correct for the - * standard method. - * - * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ] - */ - - /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ - -# define png_composite(composite, fg, alpha, bg) \ - { \ - png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) \ - * (png_uint_16)(alpha) \ - + (png_uint_16)(bg)*(png_uint_16)(255 \ - - (png_uint_16)(alpha)) + 128); \ - (composite) = (png_byte)(((temp + (temp >> 8)) >> 8) & 0xff); \ - } - -# define png_composite_16(composite, fg, alpha, bg) \ - { \ - png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) \ - * (png_uint_32)(alpha) \ - + (png_uint_32)(bg)*(65535 \ - - (png_uint_32)(alpha)) + 32768); \ - (composite) = (png_uint_16)(0xffff & ((temp + (temp >> 16)) >> 16)); \ - } - -#else /* Standard method using integer division */ - -# define png_composite(composite, fg, alpha, bg) \ - (composite) = \ - (png_byte)(0xff & (((png_uint_16)(fg) * (png_uint_16)(alpha) + \ - (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ - 127) / 255)) - -# define png_composite_16(composite, fg, alpha, bg) \ - (composite) = \ - (png_uint_16)(0xffff & (((png_uint_32)(fg) * (png_uint_32)(alpha) + \ - (png_uint_32)(bg)*(png_uint_32)(65535 - (png_uint_32)(alpha)) + \ - 32767) / 65535)) -#endif /* READ_COMPOSITE_NODIV */ - -#ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED -PNG_EXPORT(201, png_uint_32, png_get_uint_32, (png_const_bytep buf)); -PNG_EXPORT(202, png_uint_16, png_get_uint_16, (png_const_bytep buf)); -PNG_EXPORT(203, png_int_32, png_get_int_32, (png_const_bytep buf)); -#endif - -PNG_EXPORT(204, png_uint_32, png_get_uint_31, (png_const_structrp png_ptr, - png_const_bytep buf)); -/* No png_get_int_16 -- may be added if there's a real need for it. */ - -/* Place a 32-bit number into a buffer in PNG byte order (big-endian). */ -#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED -PNG_EXPORT(205, void, png_save_uint_32, (png_bytep buf, png_uint_32 i)); -#endif -#ifdef PNG_SAVE_INT_32_SUPPORTED -PNG_EXPORT(206, void, png_save_int_32, (png_bytep buf, png_int_32 i)); -#endif - -/* Place a 16-bit number into a buffer in PNG byte order. - * The parameter is declared unsigned int, not png_uint_16, - * just to avoid potential problems on pre-ANSI C compilers. - */ -#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED -PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i)); -/* No png_save_int_16 -- may be added if there's a real need for it. */ -#endif - -#ifdef PNG_USE_READ_MACROS -/* Inline macros to do direct reads of bytes from the input buffer. - * The png_get_int_32() routine assumes we are using two's complement - * format for negative values, which is almost certainly true. - */ -# define PNG_get_uint_32(buf) \ - (((png_uint_32)(*(buf)) << 24) + \ - ((png_uint_32)(*((buf) + 1)) << 16) + \ - ((png_uint_32)(*((buf) + 2)) << 8) + \ - ((png_uint_32)(*((buf) + 3)))) - - /* From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the - * function) incorrectly returned a value of type png_uint_32. - */ -# define PNG_get_uint_16(buf) \ - ((png_uint_16) \ - (((unsigned int)(*(buf)) << 8) + \ - ((unsigned int)(*((buf) + 1))))) - -# define PNG_get_int_32(buf) \ - ((png_int_32)((*(buf) & 0x80) \ - ? -((png_int_32)(((png_get_uint_32(buf)^0xffffffffU)+1U)&0x7fffffffU)) \ - : (png_int_32)png_get_uint_32(buf))) - -/* If PNG_PREFIX is defined the same thing as below happens in pnglibconf.h, - * but defining a macro name prefixed with PNG_PREFIX. - */ -# ifndef PNG_PREFIX -# define png_get_uint_32(buf) PNG_get_uint_32(buf) -# define png_get_uint_16(buf) PNG_get_uint_16(buf) -# define png_get_int_32(buf) PNG_get_int_32(buf) -# endif -#else -# ifdef PNG_PREFIX - /* No macros; revert to the (redefined) function */ -# define PNG_get_uint_32 (png_get_uint_32) -# define PNG_get_uint_16 (png_get_uint_16) -# define PNG_get_int_32 (png_get_int_32) -# endif -#endif - -#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED -PNG_EXPORT(242, void, png_set_check_for_invalid_index, - (png_structrp png_ptr, int allowed)); -# ifdef PNG_GET_PALETTE_MAX_SUPPORTED -PNG_EXPORT(243, int, png_get_palette_max, (png_const_structp png_ptr, - png_const_infop info_ptr)); -# endif -#endif /* CHECK_FOR_INVALID_INDEX */ - -/******************************************************************************* - * Section 5: SIMPLIFIED API - ******************************************************************************* - * - * Please read the documentation in libpng-manual.txt (TODO: write said - * documentation) if you don't understand what follows. - * - * The simplified API hides the details of both libpng and the PNG file format - * itself. It allows PNG files to be read into a very limited number of - * in-memory bitmap formats or to be written from the same formats. If these - * formats do not accomodate your needs then you can, and should, use the more - * sophisticated APIs above - these support a wide variety of in-memory formats - * and a wide variety of sophisticated transformations to those formats as well - * as a wide variety of APIs to manipulate ancillary information. - * - * To read a PNG file using the simplified API: - * - * 1) Declare a 'png_image' structure (see below) on the stack, set the - * version field to PNG_IMAGE_VERSION and the 'opaque' pointer to NULL - * (this is REQUIRED, your program may crash if you don't do it.) - * 2) Call the appropriate png_image_begin_read... function. - * 3) Set the png_image 'format' member to the required sample format. - * 4) Allocate a buffer for the image and, if required, the color-map. - * 5) Call png_image_finish_read to read the image and, if required, the - * color-map into your buffers. - * - * There are no restrictions on the format of the PNG input itself; all valid - * color types, bit depths, and interlace methods are acceptable, and the - * input image is transformed as necessary to the requested in-memory format - * during the png_image_finish_read() step. The only caveat is that if you - * request a color-mapped image from a PNG that is full-color or makes - * complex use of an alpha channel the transformation is extremely lossy and the - * result may look terrible. - * - * To write a PNG file using the simplified API: - * - * 1) Declare a 'png_image' structure on the stack and memset() it to all zero. - * 2) Initialize the members of the structure that describe the image, setting - * the 'format' member to the format of the image samples. - * 3) Call the appropriate png_image_write... function with a pointer to the - * image and, if necessary, the color-map to write the PNG data. - * - * png_image is a structure that describes the in-memory format of an image - * when it is being read or defines the in-memory format of an image that you - * need to write: - */ -#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) || \ - defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) - -#define PNG_IMAGE_VERSION 1 - -typedef struct png_control *png_controlp; -typedef struct -{ - png_controlp opaque; /* Initialize to NULL, free with png_image_free */ - png_uint_32 version; /* Set to PNG_IMAGE_VERSION */ - png_uint_32 width; /* Image width in pixels (columns) */ - png_uint_32 height; /* Image height in pixels (rows) */ - png_uint_32 format; /* Image format as defined below */ - png_uint_32 flags; /* A bit mask containing informational flags */ - png_uint_32 colormap_entries; - /* Number of entries in the color-map */ - - /* In the event of an error or warning the following field will be set to a - * non-zero value and the 'message' field will contain a '\0' terminated - * string with the libpng error or warning message. If both warnings and - * an error were encountered, only the error is recorded. If there - * are multiple warnings, only the first one is recorded. - * - * The upper 30 bits of this value are reserved, the low two bits contain - * a value as follows: - */ -# define PNG_IMAGE_WARNING 1 -# define PNG_IMAGE_ERROR 2 - /* - * The result is a two-bit code such that a value more than 1 indicates - * a failure in the API just called: - * - * 0 - no warning or error - * 1 - warning - * 2 - error - * 3 - error preceded by warning - */ -# define PNG_IMAGE_FAILED(png_cntrl) ((((png_cntrl).warning_or_error)&0x03)>1) - - png_uint_32 warning_or_error; - - char message[64]; -} png_image, *png_imagep; - -/* The samples of the image have one to four channels whose components have - * original values in the range 0 to 1.0: - * - * 1: A single gray or luminance channel (G). - * 2: A gray/luminance channel and an alpha channel (GA). - * 3: Three red, green, blue color channels (RGB). - * 4: Three color channels and an alpha channel (RGBA). - * - * The components are encoded in one of two ways: - * - * a) As a small integer, value 0..255, contained in a single byte. For the - * alpha channel the original value is simply value/255. For the color or - * luminance channels the value is encoded according to the sRGB specification - * and matches the 8-bit format expected by typical display devices. - * - * The color/gray channels are not scaled (pre-multiplied) by the alpha - * channel and are suitable for passing to color management software. - * - * b) As a value in the range 0..65535, contained in a 2-byte integer. All - * channels can be converted to the original value by dividing by 65535; all - * channels are linear. Color channels use the RGB encoding (RGB end-points) of - * the sRGB specification. This encoding is identified by the - * PNG_FORMAT_FLAG_LINEAR flag below. - * - * When the simplified API needs to convert between sRGB and linear colorspaces, - * the actual sRGB transfer curve defined in the sRGB specification (see the - * article at https://en.wikipedia.org/wiki/SRGB) is used, not the gamma=1/2.2 - * approximation used elsewhere in libpng. - * - * When an alpha channel is present it is expected to denote pixel coverage - * of the color or luminance channels and is returned as an associated alpha - * channel: the color/gray channels are scaled (pre-multiplied) by the alpha - * value. - * - * The samples are either contained directly in the image data, between 1 and 8 - * bytes per pixel according to the encoding, or are held in a color-map indexed - * by bytes in the image data. In the case of a color-map the color-map entries - * are individual samples, encoded as above, and the image data has one byte per - * pixel to select the relevant sample from the color-map. - */ - -/* PNG_FORMAT_* - * - * #defines to be used in png_image::format. Each #define identifies a - * particular layout of sample data and, if present, alpha values. There are - * separate defines for each of the two component encodings. - * - * A format is built up using single bit flag values. All combinations are - * valid. Formats can be built up from the flag values or you can use one of - * the predefined values below. When testing formats always use the FORMAT_FLAG - * macros to test for individual features - future versions of the library may - * add new flags. - * - * When reading or writing color-mapped images the format should be set to the - * format of the entries in the color-map then png_image_{read,write}_colormap - * called to read or write the color-map and set the format correctly for the - * image data. Do not set the PNG_FORMAT_FLAG_COLORMAP bit directly! - * - * NOTE: libpng can be built with particular features disabled. If you see - * compiler errors because the definition of one of the following flags has been - * compiled out it is because libpng does not have the required support. It is - * possible, however, for the libpng configuration to enable the format on just - * read or just write; in that case you may see an error at run time. You can - * guard against this by checking for the definition of the appropriate - * "_SUPPORTED" macro, one of: - * - * PNG_SIMPLIFIED_{READ,WRITE}_{BGR,AFIRST}_SUPPORTED - */ -#define PNG_FORMAT_FLAG_ALPHA 0x01U /* format with an alpha channel */ -#define PNG_FORMAT_FLAG_COLOR 0x02U /* color format: otherwise grayscale */ -#define PNG_FORMAT_FLAG_LINEAR 0x04U /* 2-byte channels else 1-byte */ -#define PNG_FORMAT_FLAG_COLORMAP 0x08U /* image data is color-mapped */ - -#ifdef PNG_FORMAT_BGR_SUPPORTED -# define PNG_FORMAT_FLAG_BGR 0x10U /* BGR colors, else order is RGB */ -#endif - -#ifdef PNG_FORMAT_AFIRST_SUPPORTED -# define PNG_FORMAT_FLAG_AFIRST 0x20U /* alpha channel comes first */ -#endif - -#define PNG_FORMAT_FLAG_ASSOCIATED_ALPHA 0x40U /* alpha channel is associated */ - -/* Commonly used formats have predefined macros. - * - * First the single byte (sRGB) formats: - */ -#define PNG_FORMAT_GRAY 0 -#define PNG_FORMAT_GA PNG_FORMAT_FLAG_ALPHA -#define PNG_FORMAT_AG (PNG_FORMAT_GA|PNG_FORMAT_FLAG_AFIRST) -#define PNG_FORMAT_RGB PNG_FORMAT_FLAG_COLOR -#define PNG_FORMAT_BGR (PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_BGR) -#define PNG_FORMAT_RGBA (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_ALPHA) -#define PNG_FORMAT_ARGB (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_AFIRST) -#define PNG_FORMAT_BGRA (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_ALPHA) -#define PNG_FORMAT_ABGR (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_AFIRST) - -/* Then the linear 2-byte formats. When naming these "Y" is used to - * indicate a luminance (gray) channel. - */ -#define PNG_FORMAT_LINEAR_Y PNG_FORMAT_FLAG_LINEAR -#define PNG_FORMAT_LINEAR_Y_ALPHA (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_ALPHA) -#define PNG_FORMAT_LINEAR_RGB (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR) -#define PNG_FORMAT_LINEAR_RGB_ALPHA \ - (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA) - -/* With color-mapped formats the image data is one byte for each pixel, the byte - * is an index into the color-map which is formatted as above. To obtain a - * color-mapped format it is sufficient just to add the PNG_FOMAT_FLAG_COLORMAP - * to one of the above definitions, or you can use one of the definitions below. - */ -#define PNG_FORMAT_RGB_COLORMAP (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_COLORMAP) -#define PNG_FORMAT_BGR_COLORMAP (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_COLORMAP) -#define PNG_FORMAT_RGBA_COLORMAP (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_COLORMAP) -#define PNG_FORMAT_ARGB_COLORMAP (PNG_FORMAT_ARGB|PNG_FORMAT_FLAG_COLORMAP) -#define PNG_FORMAT_BGRA_COLORMAP (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_COLORMAP) -#define PNG_FORMAT_ABGR_COLORMAP (PNG_FORMAT_ABGR|PNG_FORMAT_FLAG_COLORMAP) - -/* PNG_IMAGE macros - * - * These are convenience macros to derive information from a png_image - * structure. The PNG_IMAGE_SAMPLE_ macros return values appropriate to the - * actual image sample values - either the entries in the color-map or the - * pixels in the image. The PNG_IMAGE_PIXEL_ macros return corresponding values - * for the pixels and will always return 1 for color-mapped formats. The - * remaining macros return information about the rows in the image and the - * complete image. - * - * NOTE: All the macros that take a png_image::format parameter are compile time - * constants if the format parameter is, itself, a constant. Therefore these - * macros can be used in array declarations and case labels where required. - * Similarly the macros are also pre-processor constants (sizeof is not used) so - * they can be used in #if tests. - * - * First the information about the samples. - */ -#define PNG_IMAGE_SAMPLE_CHANNELS(fmt)\ - (((fmt)&(PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA))+1) - /* Return the total number of channels in a given format: 1..4 */ - -#define PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt)\ - ((((fmt) & PNG_FORMAT_FLAG_LINEAR) >> 2)+1) - /* Return the size in bytes of a single component of a pixel or color-map - * entry (as appropriate) in the image: 1 or 2. - */ - -#define PNG_IMAGE_SAMPLE_SIZE(fmt)\ - (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt)) - /* This is the size of the sample data for one sample. If the image is - * color-mapped it is the size of one color-map entry (and image pixels are - * one byte in size), otherwise it is the size of one image pixel. - */ - -#define PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(fmt)\ - (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * 256) - /* The maximum size of the color-map required by the format expressed in a - * count of components. This can be used to compile-time allocate a - * color-map: - * - * png_uint_16 colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(linear_fmt)]; - * - * png_byte colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(sRGB_fmt)]; - * - * Alternatively use the PNG_IMAGE_COLORMAP_SIZE macro below to use the - * information from one of the png_image_begin_read_ APIs and dynamically - * allocate the required memory. - */ - -/* Corresponding information about the pixels */ -#define PNG_IMAGE_PIXEL_(test,fmt)\ - (((fmt)&PNG_FORMAT_FLAG_COLORMAP)?1:test(fmt)) - -#define PNG_IMAGE_PIXEL_CHANNELS(fmt)\ - PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_CHANNELS,fmt) - /* The number of separate channels (components) in a pixel; 1 for a - * color-mapped image. - */ - -#define PNG_IMAGE_PIXEL_COMPONENT_SIZE(fmt)\ - PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_COMPONENT_SIZE,fmt) - /* The size, in bytes, of each component in a pixel; 1 for a color-mapped - * image. - */ - -#define PNG_IMAGE_PIXEL_SIZE(fmt) PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_SIZE,fmt) - /* The size, in bytes, of a complete pixel; 1 for a color-mapped image. */ - -/* Information about the whole row, or whole image */ -#define PNG_IMAGE_ROW_STRIDE(image)\ - (PNG_IMAGE_PIXEL_CHANNELS((image).format) * (image).width) - /* Return the total number of components in a single row of the image; this - * is the minimum 'row stride', the minimum count of components between each - * row. For a color-mapped image this is the minimum number of bytes in a - * row. - * - * WARNING: this macro overflows for some images with more than one component - * and very large image widths. libpng will refuse to process an image where - * this macro would overflow. - */ - -#define PNG_IMAGE_BUFFER_SIZE(image, row_stride)\ - (PNG_IMAGE_PIXEL_COMPONENT_SIZE((image).format)*(image).height*(row_stride)) - /* Return the size, in bytes, of an image buffer given a png_image and a row - * stride - the number of components to leave space for in each row. - * - * WARNING: this macro overflows a 32-bit integer for some large PNG images, - * libpng will refuse to process an image where such an overflow would occur. - */ - -#define PNG_IMAGE_SIZE(image)\ - PNG_IMAGE_BUFFER_SIZE(image, PNG_IMAGE_ROW_STRIDE(image)) - /* Return the size, in bytes, of the image in memory given just a png_image; - * the row stride is the minimum stride required for the image. - */ - -#define PNG_IMAGE_COLORMAP_SIZE(image)\ - (PNG_IMAGE_SAMPLE_SIZE((image).format) * (image).colormap_entries) - /* Return the size, in bytes, of the color-map of this image. If the image - * format is not a color-map format this will return a size sufficient for - * 256 entries in the given format; check PNG_FORMAT_FLAG_COLORMAP if - * you don't want to allocate a color-map in this case. - */ - -/* PNG_IMAGE_FLAG_* - * - * Flags containing additional information about the image are held in the - * 'flags' field of png_image. - */ -#define PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB 0x01 - /* This indicates the the RGB values of the in-memory bitmap do not - * correspond to the red, green and blue end-points defined by sRGB. - */ - -#define PNG_IMAGE_FLAG_FAST 0x02 - /* On write emphasise speed over compression; the resultant PNG file will be - * larger but will be produced significantly faster, particular for large - * images. Do not use this option for images which will be distributed, only - * used it when producing intermediate files that will be read back in - * repeatedly. For a typical 24-bit image the option will double the read - * speed at the cost of increasing the image size by 25%, however for many - * more compressible images the PNG file can be 10 times larger with only a - * slight speed gain. - */ - -#define PNG_IMAGE_FLAG_16BIT_sRGB 0x04 - /* On read if the image is a 16-bit per component image and there is no gAMA - * or sRGB chunk assume that the components are sRGB encoded. Notice that - * images output by the simplified API always have gamma information; setting - * this flag only affects the interpretation of 16-bit images from an - * external source. It is recommended that the application expose this flag - * to the user; the user can normally easily recognize the difference between - * linear and sRGB encoding. This flag has no effect on write - the data - * passed to the write APIs must have the correct encoding (as defined - * above.) - * - * If the flag is not set (the default) input 16-bit per component data is - * assumed to be linear. - * - * NOTE: the flag can only be set after the png_image_begin_read_ call, - * because that call initializes the 'flags' field. - */ - -#ifdef PNG_SIMPLIFIED_READ_SUPPORTED -/* READ APIs - * --------- - * - * The png_image passed to the read APIs must have been initialized by setting - * the png_controlp field 'opaque' to NULL (or, safer, memset the whole thing.) - */ -#ifdef PNG_STDIO_SUPPORTED -PNG_EXPORT(234, int, png_image_begin_read_from_file, (png_imagep image, - const char *file_name)); - /* The named file is opened for read and the image header is filled in - * from the PNG header in the file. - */ - -PNG_EXPORT(235, int, png_image_begin_read_from_stdio, (png_imagep image, - FILE* file)); - /* The PNG header is read from the stdio FILE object. */ -#endif /* STDIO */ - -PNG_EXPORT(236, int, png_image_begin_read_from_memory, (png_imagep image, - png_const_voidp memory, png_size_t size)); - /* The PNG header is read from the given memory buffer. */ - -PNG_EXPORT(237, int, png_image_finish_read, (png_imagep image, - png_const_colorp background, void *buffer, png_int_32 row_stride, - void *colormap)); - /* Finish reading the image into the supplied buffer and clean up the - * png_image structure. - * - * row_stride is the step, in byte or 2-byte units as appropriate, - * between adjacent rows. A positive stride indicates that the top-most row - * is first in the buffer - the normal top-down arrangement. A negative - * stride indicates that the bottom-most row is first in the buffer. - * - * background need only be supplied if an alpha channel must be removed from - * a png_byte format and the removal is to be done by compositing on a solid - * color; otherwise it may be NULL and any composition will be done directly - * onto the buffer. The value is an sRGB color to use for the background, - * for grayscale output the green channel is used. - * - * background must be supplied when an alpha channel must be removed from a - * single byte color-mapped output format, in other words if: - * - * 1) The original format from png_image_begin_read_from_* had - * PNG_FORMAT_FLAG_ALPHA set. - * 2) The format set by the application does not. - * 3) The format set by the application has PNG_FORMAT_FLAG_COLORMAP set and - * PNG_FORMAT_FLAG_LINEAR *not* set. - * - * For linear output removing the alpha channel is always done by compositing - * on black and background is ignored. - * - * colormap must be supplied when PNG_FORMAT_FLAG_COLORMAP is set. It must - * be at least the size (in bytes) returned by PNG_IMAGE_COLORMAP_SIZE. - * image->colormap_entries will be updated to the actual number of entries - * written to the colormap; this may be less than the original value. - */ - -PNG_EXPORT(238, void, png_image_free, (png_imagep image)); - /* Free any data allocated by libpng in image->opaque, setting the pointer to - * NULL. May be called at any time after the structure is initialized. - */ -#endif /* SIMPLIFIED_READ */ - -#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED -/* WRITE APIS - * ---------- - * For write you must initialize a png_image structure to describe the image to - * be written. To do this use memset to set the whole structure to 0 then - * initialize fields describing your image. - * - * version: must be set to PNG_IMAGE_VERSION - * opaque: must be initialized to NULL - * width: image width in pixels - * height: image height in rows - * format: the format of the data (image and color-map) you wish to write - * flags: set to 0 unless one of the defined flags applies; set - * PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB for color format images where the RGB - * values do not correspond to the colors in sRGB. - * colormap_entries: set to the number of entries in the color-map (0 to 256) - */ -#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED -PNG_EXPORT(239, int, png_image_write_to_file, (png_imagep image, - const char *file, int convert_to_8bit, const void *buffer, - png_int_32 row_stride, const void *colormap)); - /* Write the image to the named file. */ - -PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file, - int convert_to_8_bit, const void *buffer, png_int_32 row_stride, - const void *colormap)); - /* Write the image to the given (FILE*). */ -#endif /* SIMPLIFIED_WRITE_STDIO */ - -/* With all write APIs if image is in one of the linear formats with 16-bit - * data then setting convert_to_8_bit will cause the output to be an 8-bit PNG - * gamma encoded according to the sRGB specification, otherwise a 16-bit linear - * encoded PNG file is written. - * - * With color-mapped data formats the colormap parameter point to a color-map - * with at least image->colormap_entries encoded in the specified format. If - * the format is linear the written PNG color-map will be converted to sRGB - * regardless of the convert_to_8_bit flag. - * - * With all APIs row_stride is handled as in the read APIs - it is the spacing - * from one row to the next in component sized units (1 or 2 bytes) and if - * negative indicates a bottom-up row layout in the buffer. If row_stride is - * zero, libpng will calculate it for you from the image width and number of - * channels. - * - * Note that the write API does not support interlacing, sub-8-bit pixels or - * most ancillary chunks. If you need to write text chunks (e.g. for copyright - * notices) you need to use one of the other APIs. - */ - -PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory, - png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8_bit, - const void *buffer, png_int_32 row_stride, const void *colormap)); - /* Write the image to the given memory buffer. The function both writes the - * whole PNG data stream to *memory and updates *memory_bytes with the count - * of bytes written. - * - * 'memory' may be NULL. In this case *memory_bytes is not read however on - * success the number of bytes which would have been written will still be - * stored in *memory_bytes. On failure *memory_bytes will contain 0. - * - * If 'memory' is not NULL it must point to memory[*memory_bytes] of - * writeable memory. - * - * If the function returns success memory[*memory_bytes] (if 'memory' is not - * NULL) contains the written PNG data. *memory_bytes will always be less - * than or equal to the original value. - * - * If the function returns false and *memory_bytes was not changed an error - * occured during write. If *memory_bytes was changed, or is not 0 if - * 'memory' was NULL, the write would have succeeded but for the memory - * buffer being too small. *memory_bytes contains the required number of - * bytes and will be bigger that the original value. - */ - -#define png_image_write_get_memory_size(image, size, convert_to_8_bit, buffer,\ - row_stride, colormap)\ - png_image_write_to_memory(&(image), 0, &(size), convert_to_8_bit, buffer,\ - row_stride, colormap) - /* Return the amount of memory in 'size' required to compress this image. - * The png_image structure 'image' must be filled in as in the above - * function and must not be changed before the actual write call, the buffer - * and all other parameters must also be identical to that in the final - * write call. The 'size' variable need not be initialized. - * - * NOTE: the macro returns true/false, if false is returned 'size' will be - * set to zero and the write failed and probably will fail if tried again. - */ - -/* You can pre-allocate the buffer by making sure it is of sufficient size - * regardless of the amount of compression achieved. The buffer size will - * always be bigger than the original image and it will never be filled. The - * following macros are provided to assist in allocating the buffer. - */ -#define PNG_IMAGE_DATA_SIZE(image) (PNG_IMAGE_SIZE(image)+(image).height) - /* The number of uncompressed bytes in the PNG byte encoding of the image; - * uncompressing the PNG IDAT data will give this number of bytes. - * - * NOTE: while PNG_IMAGE_SIZE cannot overflow for an image in memory this - * macro can because of the extra bytes used in the PNG byte encoding. You - * need to avoid this macro if your image size approaches 2^30 in width or - * height. The same goes for the remainder of these macros; they all produce - * bigger numbers than the actual in-memory image size. - */ -#ifndef PNG_ZLIB_MAX_SIZE -# define PNG_ZLIB_MAX_SIZE(b) ((b)+(((b)+7U)>>3)+(((b)+63U)>>6)+11U) - /* An upper bound on the number of compressed bytes given 'b' uncompressed - * bytes. This is based on deflateBounds() in zlib; different - * implementations of zlib compression may conceivably produce more data so - * if your zlib implementation is not zlib itself redefine this macro - * appropriately. - */ -#endif - -#define PNG_IMAGE_COMPRESSED_SIZE_MAX(image)\ - PNG_ZLIB_MAX_SIZE((png_alloc_size_t)PNG_IMAGE_DATA_SIZE(image)) - /* An upper bound on the size of the data in the PNG IDAT chunks. */ - -#define PNG_IMAGE_PNG_SIZE_MAX_(image, image_size)\ - ((8U/*sig*/+25U/*IHDR*/+16U/*gAMA*/+44U/*cHRM*/+12U/*IEND*/+\ - (((image).format&PNG_FORMAT_FLAG_COLORMAP)?/*colormap: PLTE, tRNS*/\ - 12U+3U*(image).colormap_entries/*PLTE data*/+\ - (((image).format&PNG_FORMAT_FLAG_ALPHA)?\ - 12U/*tRNS*/+(image).colormap_entries:0U):0U)+\ - 12U)+(12U*((image_size)/PNG_ZBUF_SIZE))/*IDAT*/+(image_size)) - /* A helper for the following macro; if your compiler cannot handle the - * following macro use this one with the result of - * PNG_IMAGE_COMPRESSED_SIZE_MAX(image) as the second argument (most - * compilers should handle this just fine.) - */ - -#define PNG_IMAGE_PNG_SIZE_MAX(image)\ - PNG_IMAGE_PNG_SIZE_MAX_(image, PNG_IMAGE_COMPRESSED_SIZE_MAX(image)) - /* An upper bound on the total length of the PNG data stream for 'image'. - * The result is of type png_alloc_size_t, on 32-bit systems this may - * overflow even though PNG_IMAGE_DATA_SIZE does not overflow; the write will - * run out of buffer space but return a corrected size which should work. - */ -#endif /* SIMPLIFIED_WRITE */ -/******************************************************************************* - * END OF SIMPLIFIED API - ******************************************************************************/ -#endif /* SIMPLIFIED_{READ|WRITE} */ - -/******************************************************************************* - * Section 6: IMPLEMENTATION OPTIONS - ******************************************************************************* - * - * Support for arbitrary implementation-specific optimizations. The API allows - * particular options to be turned on or off. 'Option' is the number of the - * option and 'onoff' is 0 (off) or non-0 (on). The value returned is given - * by the PNG_OPTION_ defines below. - * - * HARDWARE: normally hardware capabilites, such as the Intel SSE instructions, - * are detected at run time, however sometimes it may be impossible - * to do this in user mode, in which case it is necessary to discover - * the capabilities in an OS specific way. Such capabilities are - * listed here when libpng has support for them and must be turned - * ON by the application if present. - * - * SOFTWARE: sometimes software optimizations actually result in performance - * decrease on some architectures or systems, or with some sets of - * PNG images. 'Software' options allow such optimizations to be - * selected at run time. - */ -#ifdef PNG_SET_OPTION_SUPPORTED -#ifdef PNG_ARM_NEON_API_SUPPORTED -# define PNG_ARM_NEON 0 /* HARDWARE: ARM Neon SIMD instructions supported */ -#endif -#define PNG_MAXIMUM_INFLATE_WINDOW 2 /* SOFTWARE: force maximum window */ -#define PNG_SKIP_sRGB_CHECK_PROFILE 4 /* SOFTWARE: Check ICC profile for sRGB */ -#ifdef PNG_MIPS_MSA_API_SUPPORTED -# define PNG_MIPS_MSA 6 /* HARDWARE: MIPS Msa SIMD instructions supported */ -#endif -#define PNG_IGNORE_ADLER32 8 -#ifdef PNG_POWERPC_VSX_API_SUPPORTED -# define PNG_POWERPC_VSX 10 /* HARDWARE: PowerPC VSX SIMD instructions supported */ -#endif -#define PNG_OPTION_NEXT 12 /* Next option - numbers must be even */ - -/* Return values: NOTE: there are four values and 'off' is *not* zero */ -#define PNG_OPTION_UNSET 0 /* Unset - defaults to off */ -#define PNG_OPTION_INVALID 1 /* Option number out of range */ -#define PNG_OPTION_OFF 2 -#define PNG_OPTION_ON 3 - -PNG_EXPORT(244, int, png_set_option, (png_structrp png_ptr, int option, - int onoff)); -#endif /* SET_OPTION */ - -/******************************************************************************* - * END OF HARDWARE AND SOFTWARE OPTIONS - ******************************************************************************/ - -/* Maintainer: Put new public prototypes here ^, in libpng.3, in project - * defs, and in scripts/symbols.def. - */ - -/* The last ordinal number (this is the *last* one already used; the next - * one to use is one more than this.) - */ -#ifdef PNG_EXPORT_LAST_ORDINAL - PNG_EXPORT_LAST_ORDINAL(249); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* PNG_VERSION_INFO_ONLY */ -/* Do not put anything past this line */ -#endif /* PNG_H */ diff --git a/cdeps/mac/pngconf.h b/cdeps/mac/pngconf.h deleted file mode 100644 index d13b13e5..00000000 --- a/cdeps/mac/pngconf.h +++ /dev/null @@ -1,622 +0,0 @@ - -/* pngconf.h - machine configurable file for libpng - * - * libpng version 1.6.34, September 29, 2017 - * - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) - * - * This code is released under the libpng license. - * For conditions of distribution and use, see the disclaimer - * and license in png.h - * - * Any machine specific code is near the front of this file, so if you - * are configuring libpng for a machine, you may want to read the section - * starting here down to where it starts to typedef png_color, png_text, - * and png_info. - */ - -#ifndef PNGCONF_H -#define PNGCONF_H - -#ifndef PNG_BUILDING_SYMBOL_TABLE /* else includes may cause problems */ - -/* From libpng 1.6.0 libpng requires an ANSI X3.159-1989 ("ISOC90") compliant C - * compiler for correct compilation. The following header files are required by - * the standard. If your compiler doesn't provide these header files, or they - * do not match the standard, you will need to provide/improve them. - */ -#include -#include - -/* Library header files. These header files are all defined by ISOC90; libpng - * expects conformant implementations, however, an ISOC90 conformant system need - * not provide these header files if the functionality cannot be implemented. - * In this case it will be necessary to disable the relevant parts of libpng in - * the build of pnglibconf.h. - * - * Prior to 1.6.0 string.h was included here; the API changes in 1.6.0 to not - * include this unnecessary header file. - */ - -#ifdef PNG_STDIO_SUPPORTED - /* Required for the definition of FILE: */ -# include -#endif - -#ifdef PNG_SETJMP_SUPPORTED - /* Required for the definition of jmp_buf and the declaration of longjmp: */ -# include -#endif - -#ifdef PNG_CONVERT_tIME_SUPPORTED - /* Required for struct tm: */ -# include -#endif - -#endif /* PNG_BUILDING_SYMBOL_TABLE */ - -/* Prior to 1.6.0 it was possible to turn off 'const' in declarations using - * PNG_NO_CONST; this is no longer supported except for data declarations which - * apparently still cause problems in 2011 on some compilers. - */ -#define PNG_CONST const /* backward compatibility only */ - -/* This controls optimization of the reading of 16-bit and 32-bit values - * from PNG files. It can be set on a per-app-file basis - it - * just changes whether a macro is used when the function is called. - * The library builder sets the default; if read functions are not - * built into the library the macro implementation is forced on. - */ -#ifndef PNG_READ_INT_FUNCTIONS_SUPPORTED -# define PNG_USE_READ_MACROS -#endif -#if !defined(PNG_NO_USE_READ_MACROS) && !defined(PNG_USE_READ_MACROS) -# if PNG_DEFAULT_READ_MACROS -# define PNG_USE_READ_MACROS -# endif -#endif - -/* COMPILER SPECIFIC OPTIONS. - * - * These options are provided so that a variety of difficult compilers - * can be used. Some are fixed at build time (e.g. PNG_API_RULE - * below) but still have compiler specific implementations, others - * may be changed on a per-file basis when compiling against libpng. - */ - -/* The PNGARG macro was used in versions of libpng prior to 1.6.0 to protect - * against legacy (pre ISOC90) compilers that did not understand function - * prototypes. It is not required for modern C compilers. - */ -#ifndef PNGARG -# define PNGARG(arglist) arglist -#endif - -/* Function calling conventions. - * ============================= - * Normally it is not necessary to specify to the compiler how to call - * a function - it just does it - however on x86 systems derived from - * Microsoft and Borland C compilers ('IBM PC', 'DOS', 'Windows' systems - * and some others) there are multiple ways to call a function and the - * default can be changed on the compiler command line. For this reason - * libpng specifies the calling convention of every exported function and - * every function called via a user supplied function pointer. This is - * done in this file by defining the following macros: - * - * PNGAPI Calling convention for exported functions. - * PNGCBAPI Calling convention for user provided (callback) functions. - * PNGCAPI Calling convention used by the ANSI-C library (required - * for longjmp callbacks and sometimes used internally to - * specify the calling convention for zlib). - * - * These macros should never be overridden. If it is necessary to - * change calling convention in a private build this can be done - * by setting PNG_API_RULE (which defaults to 0) to one of the values - * below to select the correct 'API' variants. - * - * PNG_API_RULE=0 Use PNGCAPI - the 'C' calling convention - throughout. - * This is correct in every known environment. - * PNG_API_RULE=1 Use the operating system convention for PNGAPI and - * the 'C' calling convention (from PNGCAPI) for - * callbacks (PNGCBAPI). This is no longer required - * in any known environment - if it has to be used - * please post an explanation of the problem to the - * libpng mailing list. - * - * These cases only differ if the operating system does not use the C - * calling convention, at present this just means the above cases - * (x86 DOS/Windows sytems) and, even then, this does not apply to - * Cygwin running on those systems. - * - * Note that the value must be defined in pnglibconf.h so that what - * the application uses to call the library matches the conventions - * set when building the library. - */ - -/* Symbol export - * ============= - * When building a shared library it is almost always necessary to tell - * the compiler which symbols to export. The png.h macro 'PNG_EXPORT' - * is used to mark the symbols. On some systems these symbols can be - * extracted at link time and need no special processing by the compiler, - * on other systems the symbols are flagged by the compiler and just - * the declaration requires a special tag applied (unfortunately) in a - * compiler dependent way. Some systems can do either. - * - * A small number of older systems also require a symbol from a DLL to - * be flagged to the program that calls it. This is a problem because - * we do not know in the header file included by application code that - * the symbol will come from a shared library, as opposed to a statically - * linked one. For this reason the application must tell us by setting - * the magic flag PNG_USE_DLL to turn on the special processing before - * it includes png.h. - * - * Four additional macros are used to make this happen: - * - * PNG_IMPEXP The magic (if any) to cause a symbol to be exported from - * the build or imported if PNG_USE_DLL is set - compiler - * and system specific. - * - * PNG_EXPORT_TYPE(type) A macro that pre or appends PNG_IMPEXP to - * 'type', compiler specific. - * - * PNG_DLL_EXPORT Set to the magic to use during a libpng build to - * make a symbol exported from the DLL. Not used in the - * public header files; see pngpriv.h for how it is used - * in the libpng build. - * - * PNG_DLL_IMPORT Set to the magic to force the libpng symbols to come - * from a DLL - used to define PNG_IMPEXP when - * PNG_USE_DLL is set. - */ - -/* System specific discovery. - * ========================== - * This code is used at build time to find PNG_IMPEXP, the API settings - * and PNG_EXPORT_TYPE(), it may also set a macro to indicate the DLL - * import processing is possible. On Windows systems it also sets - * compiler-specific macros to the values required to change the calling - * conventions of the various functions. - */ -#if defined(_Windows) || defined(_WINDOWS) || defined(WIN32) ||\ - defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) - /* Windows system (DOS doesn't support DLLs). Includes builds under Cygwin or - * MinGW on any architecture currently supported by Windows. Also includes - * Watcom builds but these need special treatment because they are not - * compatible with GCC or Visual C because of different calling conventions. - */ -# if PNG_API_RULE == 2 - /* If this line results in an error, either because __watcall is not - * understood or because of a redefine just below you cannot use *this* - * build of the library with the compiler you are using. *This* build was - * build using Watcom and applications must also be built using Watcom! - */ -# define PNGCAPI __watcall -# endif - -# if defined(__GNUC__) || (defined(_MSC_VER) && (_MSC_VER >= 800)) -# define PNGCAPI __cdecl -# if PNG_API_RULE == 1 - /* If this line results in an error __stdcall is not understood and - * PNG_API_RULE should not have been set to '1'. - */ -# define PNGAPI __stdcall -# endif -# else - /* An older compiler, or one not detected (erroneously) above, - * if necessary override on the command line to get the correct - * variants for the compiler. - */ -# ifndef PNGCAPI -# define PNGCAPI _cdecl -# endif -# if PNG_API_RULE == 1 && !defined(PNGAPI) -# define PNGAPI _stdcall -# endif -# endif /* compiler/api */ - - /* NOTE: PNGCBAPI always defaults to PNGCAPI. */ - -# if defined(PNGAPI) && !defined(PNG_USER_PRIVATEBUILD) -# error "PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed" -# endif - -# if (defined(_MSC_VER) && _MSC_VER < 800) ||\ - (defined(__BORLANDC__) && __BORLANDC__ < 0x500) - /* older Borland and MSC - * compilers used '__export' and required this to be after - * the type. - */ -# ifndef PNG_EXPORT_TYPE -# define PNG_EXPORT_TYPE(type) type PNG_IMPEXP -# endif -# define PNG_DLL_EXPORT __export -# else /* newer compiler */ -# define PNG_DLL_EXPORT __declspec(dllexport) -# ifndef PNG_DLL_IMPORT -# define PNG_DLL_IMPORT __declspec(dllimport) -# endif -# endif /* compiler */ - -#else /* !Windows */ -# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) -# define PNGAPI _System -# else /* !Windows/x86 && !OS/2 */ - /* Use the defaults, or define PNG*API on the command line (but - * this will have to be done for every compile!) - */ -# endif /* other system, !OS/2 */ -#endif /* !Windows/x86 */ - -/* Now do all the defaulting . */ -#ifndef PNGCAPI -# define PNGCAPI -#endif -#ifndef PNGCBAPI -# define PNGCBAPI PNGCAPI -#endif -#ifndef PNGAPI -# define PNGAPI PNGCAPI -#endif - -/* PNG_IMPEXP may be set on the compilation system command line or (if not set) - * then in an internal header file when building the library, otherwise (when - * using the library) it is set here. - */ -#ifndef PNG_IMPEXP -# if defined(PNG_USE_DLL) && defined(PNG_DLL_IMPORT) - /* This forces use of a DLL, disallowing static linking */ -# define PNG_IMPEXP PNG_DLL_IMPORT -# endif - -# ifndef PNG_IMPEXP -# define PNG_IMPEXP -# endif -#endif - -/* In 1.5.2 the definition of PNG_FUNCTION has been changed to always treat - * 'attributes' as a storage class - the attributes go at the start of the - * function definition, and attributes are always appended regardless of the - * compiler. This considerably simplifies these macros but may cause problems - * if any compilers both need function attributes and fail to handle them as - * a storage class (this is unlikely.) - */ -#ifndef PNG_FUNCTION -# define PNG_FUNCTION(type, name, args, attributes) attributes type name args -#endif - -#ifndef PNG_EXPORT_TYPE -# define PNG_EXPORT_TYPE(type) PNG_IMPEXP type -#endif - - /* The ordinal value is only relevant when preprocessing png.h for symbol - * table entries, so we discard it here. See the .dfn files in the - * scripts directory. - */ - -#ifndef PNG_EXPORTA -# define PNG_EXPORTA(ordinal, type, name, args, attributes) \ - PNG_FUNCTION(PNG_EXPORT_TYPE(type), (PNGAPI name), PNGARG(args), \ - PNG_LINKAGE_API attributes) -#endif - -/* ANSI-C (C90) does not permit a macro to be invoked with an empty argument, - * so make something non-empty to satisfy the requirement: - */ -#define PNG_EMPTY /*empty list*/ - -#define PNG_EXPORT(ordinal, type, name, args) \ - PNG_EXPORTA(ordinal, type, name, args, PNG_EMPTY) - -/* Use PNG_REMOVED to comment out a removed interface. */ -#ifndef PNG_REMOVED -# define PNG_REMOVED(ordinal, type, name, args, attributes) -#endif - -#ifndef PNG_CALLBACK -# define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) PNGARG(args) -#endif - -/* Support for compiler specific function attributes. These are used - * so that where compiler support is available incorrect use of API - * functions in png.h will generate compiler warnings. - * - * Added at libpng-1.2.41. - */ - -#ifndef PNG_NO_PEDANTIC_WARNINGS -# ifndef PNG_PEDANTIC_WARNINGS_SUPPORTED -# define PNG_PEDANTIC_WARNINGS_SUPPORTED -# endif -#endif - -#ifdef PNG_PEDANTIC_WARNINGS_SUPPORTED - /* Support for compiler specific function attributes. These are used - * so that where compiler support is available, incorrect use of API - * functions in png.h will generate compiler warnings. Added at libpng - * version 1.2.41. Disabling these removes the warnings but may also produce - * less efficient code. - */ -# if defined(__clang__) && defined(__has_attribute) - /* Clang defines both __clang__ and __GNUC__. Check __clang__ first. */ -# if !defined(PNG_USE_RESULT) && __has_attribute(__warn_unused_result__) -# define PNG_USE_RESULT __attribute__((__warn_unused_result__)) -# endif -# if !defined(PNG_NORETURN) && __has_attribute(__noreturn__) -# define PNG_NORETURN __attribute__((__noreturn__)) -# endif -# if !defined(PNG_ALLOCATED) && __has_attribute(__malloc__) -# define PNG_ALLOCATED __attribute__((__malloc__)) -# endif -# if !defined(PNG_DEPRECATED) && __has_attribute(__deprecated__) -# define PNG_DEPRECATED __attribute__((__deprecated__)) -# endif -# if !defined(PNG_PRIVATE) -# ifdef __has_extension -# if __has_extension(attribute_unavailable_with_message) -# define PNG_PRIVATE __attribute__((__unavailable__(\ - "This function is not exported by libpng."))) -# endif -# endif -# endif -# ifndef PNG_RESTRICT -# define PNG_RESTRICT __restrict -# endif - -# elif defined(__GNUC__) -# ifndef PNG_USE_RESULT -# define PNG_USE_RESULT __attribute__((__warn_unused_result__)) -# endif -# ifndef PNG_NORETURN -# define PNG_NORETURN __attribute__((__noreturn__)) -# endif -# if __GNUC__ >= 3 -# ifndef PNG_ALLOCATED -# define PNG_ALLOCATED __attribute__((__malloc__)) -# endif -# ifndef PNG_DEPRECATED -# define PNG_DEPRECATED __attribute__((__deprecated__)) -# endif -# ifndef PNG_PRIVATE -# if 0 /* Doesn't work so we use deprecated instead*/ -# define PNG_PRIVATE \ - __attribute__((warning("This function is not exported by libpng."))) -# else -# define PNG_PRIVATE \ - __attribute__((__deprecated__)) -# endif -# endif -# if ((__GNUC__ > 3) || !defined(__GNUC_MINOR__) || (__GNUC_MINOR__ >= 1)) -# ifndef PNG_RESTRICT -# define PNG_RESTRICT __restrict -# endif -# endif /* __GNUC__.__GNUC_MINOR__ > 3.0 */ -# endif /* __GNUC__ >= 3 */ - -# elif defined(_MSC_VER) && (_MSC_VER >= 1300) -# ifndef PNG_USE_RESULT -# define PNG_USE_RESULT /* not supported */ -# endif -# ifndef PNG_NORETURN -# define PNG_NORETURN __declspec(noreturn) -# endif -# ifndef PNG_ALLOCATED -# if (_MSC_VER >= 1400) -# define PNG_ALLOCATED __declspec(restrict) -# endif -# endif -# ifndef PNG_DEPRECATED -# define PNG_DEPRECATED __declspec(deprecated) -# endif -# ifndef PNG_PRIVATE -# define PNG_PRIVATE __declspec(deprecated) -# endif -# ifndef PNG_RESTRICT -# if (_MSC_VER >= 1400) -# define PNG_RESTRICT __restrict -# endif -# endif - -# elif defined(__WATCOMC__) -# ifndef PNG_RESTRICT -# define PNG_RESTRICT __restrict -# endif -# endif -#endif /* PNG_PEDANTIC_WARNINGS */ - -#ifndef PNG_DEPRECATED -# define PNG_DEPRECATED /* Use of this function is deprecated */ -#endif -#ifndef PNG_USE_RESULT -# define PNG_USE_RESULT /* The result of this function must be checked */ -#endif -#ifndef PNG_NORETURN -# define PNG_NORETURN /* This function does not return */ -#endif -#ifndef PNG_ALLOCATED -# define PNG_ALLOCATED /* The result of the function is new memory */ -#endif -#ifndef PNG_PRIVATE -# define PNG_PRIVATE /* This is a private libpng function */ -#endif -#ifndef PNG_RESTRICT -# define PNG_RESTRICT /* The C99 "restrict" feature */ -#endif - -#ifndef PNG_FP_EXPORT /* A floating point API. */ -# ifdef PNG_FLOATING_POINT_SUPPORTED -# define PNG_FP_EXPORT(ordinal, type, name, args)\ - PNG_EXPORT(ordinal, type, name, args); -# else /* No floating point APIs */ -# define PNG_FP_EXPORT(ordinal, type, name, args) -# endif -#endif -#ifndef PNG_FIXED_EXPORT /* A fixed point API. */ -# ifdef PNG_FIXED_POINT_SUPPORTED -# define PNG_FIXED_EXPORT(ordinal, type, name, args)\ - PNG_EXPORT(ordinal, type, name, args); -# else /* No fixed point APIs */ -# define PNG_FIXED_EXPORT(ordinal, type, name, args) -# endif -#endif - -#ifndef PNG_BUILDING_SYMBOL_TABLE -/* Some typedefs to get us started. These should be safe on most of the common - * platforms. - * - * png_uint_32 and png_int_32 may, currently, be larger than required to hold a - * 32-bit value however this is not normally advisable. - * - * png_uint_16 and png_int_16 should always be two bytes in size - this is - * verified at library build time. - * - * png_byte must always be one byte in size. - * - * The checks below use constants from limits.h, as defined by the ISOC90 - * standard. - */ -#if CHAR_BIT == 8 && UCHAR_MAX == 255 - typedef unsigned char png_byte; -#else -# error "libpng requires 8-bit bytes" -#endif - -#if INT_MIN == -32768 && INT_MAX == 32767 - typedef int png_int_16; -#elif SHRT_MIN == -32768 && SHRT_MAX == 32767 - typedef short png_int_16; -#else -# error "libpng requires a signed 16-bit type" -#endif - -#if UINT_MAX == 65535 - typedef unsigned int png_uint_16; -#elif USHRT_MAX == 65535 - typedef unsigned short png_uint_16; -#else -# error "libpng requires an unsigned 16-bit type" -#endif - -#if INT_MIN < -2147483646 && INT_MAX > 2147483646 - typedef int png_int_32; -#elif LONG_MIN < -2147483646 && LONG_MAX > 2147483646 - typedef long int png_int_32; -#else -# error "libpng requires a signed 32-bit (or more) type" -#endif - -#if UINT_MAX > 4294967294U - typedef unsigned int png_uint_32; -#elif ULONG_MAX > 4294967294U - typedef unsigned long int png_uint_32; -#else -# error "libpng requires an unsigned 32-bit (or more) type" -#endif - -/* Prior to 1.6.0 it was possible to disable the use of size_t, 1.6.0, however, - * requires an ISOC90 compiler and relies on consistent behavior of sizeof. - */ -typedef size_t png_size_t; -typedef ptrdiff_t png_ptrdiff_t; - -/* libpng needs to know the maximum value of 'size_t' and this controls the - * definition of png_alloc_size_t, below. This maximum value of size_t limits - * but does not control the maximum allocations the library makes - there is - * direct application control of this through png_set_user_limits(). - */ -#ifndef PNG_SMALL_SIZE_T - /* Compiler specific tests for systems where size_t is known to be less than - * 32 bits (some of these systems may no longer work because of the lack of - * 'far' support; see above.) - */ -# if (defined(__TURBOC__) && !defined(__FLAT__)) ||\ - (defined(_MSC_VER) && defined(MAXSEG_64K)) -# define PNG_SMALL_SIZE_T -# endif -#endif - -/* png_alloc_size_t is guaranteed to be no smaller than png_size_t, and no - * smaller than png_uint_32. Casts from png_size_t or png_uint_32 to - * png_alloc_size_t are not necessary; in fact, it is recommended not to use - * them at all so that the compiler can complain when something turns out to be - * problematic. - * - * Casts in the other direction (from png_alloc_size_t to png_size_t or - * png_uint_32) should be explicitly applied; however, we do not expect to - * encounter practical situations that require such conversions. - * - * PNG_SMALL_SIZE_T must be defined if the maximum value of size_t is less than - * 4294967295 - i.e. less than the maximum value of png_uint_32. - */ -#ifdef PNG_SMALL_SIZE_T - typedef png_uint_32 png_alloc_size_t; -#else - typedef png_size_t png_alloc_size_t; -#endif - -/* Prior to 1.6.0 libpng offered limited support for Microsoft C compiler - * implementations of Intel CPU specific support of user-mode segmented address - * spaces, where 16-bit pointers address more than 65536 bytes of memory using - * separate 'segment' registers. The implementation requires two different - * types of pointer (only one of which includes the segment value.) - * - * If required this support is available in version 1.2 of libpng and may be - * available in versions through 1.5, although the correctness of the code has - * not been verified recently. - */ - -/* Typedef for floating-point numbers that are converted to fixed-point with a - * multiple of 100,000, e.g., gamma - */ -typedef png_int_32 png_fixed_point; - -/* Add typedefs for pointers */ -typedef void * png_voidp; -typedef const void * png_const_voidp; -typedef png_byte * png_bytep; -typedef const png_byte * png_const_bytep; -typedef png_uint_32 * png_uint_32p; -typedef const png_uint_32 * png_const_uint_32p; -typedef png_int_32 * png_int_32p; -typedef const png_int_32 * png_const_int_32p; -typedef png_uint_16 * png_uint_16p; -typedef const png_uint_16 * png_const_uint_16p; -typedef png_int_16 * png_int_16p; -typedef const png_int_16 * png_const_int_16p; -typedef char * png_charp; -typedef const char * png_const_charp; -typedef png_fixed_point * png_fixed_point_p; -typedef const png_fixed_point * png_const_fixed_point_p; -typedef png_size_t * png_size_tp; -typedef const png_size_t * png_const_size_tp; - -#ifdef PNG_STDIO_SUPPORTED -typedef FILE * png_FILE_p; -#endif - -#ifdef PNG_FLOATING_POINT_SUPPORTED -typedef double * png_doublep; -typedef const double * png_const_doublep; -#endif - -/* Pointers to pointers; i.e. arrays */ -typedef png_byte * * png_bytepp; -typedef png_uint_32 * * png_uint_32pp; -typedef png_int_32 * * png_int_32pp; -typedef png_uint_16 * * png_uint_16pp; -typedef png_int_16 * * png_int_16pp; -typedef const char * * png_const_charpp; -typedef char * * png_charpp; -typedef png_fixed_point * * png_fixed_point_pp; -#ifdef PNG_FLOATING_POINT_SUPPORTED -typedef double * * png_doublepp; -#endif - -/* Pointers to pointers to pointers; i.e., pointer to array */ -typedef char * * * png_charppp; - -#endif /* PNG_BUILDING_SYMBOL_TABLE */ - -#endif /* PNGCONF_H */ diff --git a/cdeps/mac/pnglibconf.h b/cdeps/mac/pnglibconf.h deleted file mode 100644 index cb4ea9e2..00000000 --- a/cdeps/mac/pnglibconf.h +++ /dev/null @@ -1,218 +0,0 @@ -/* pnglibconf.h - library build configuration */ - -/* libpng version 1.6.34, September 29, 2017 */ - -/* Copyright (c) 1998-2017 Glenn Randers-Pehrson */ - -/* This code is released under the libpng license. */ -/* For conditions of distribution and use, see the disclaimer */ -/* and license in png.h */ - -/* pnglibconf.h */ -/* Machine generated file: DO NOT EDIT */ -/* Derived from: scripts/pnglibconf.dfa */ -#ifndef PNGLCONF_H -#define PNGLCONF_H -/* options */ -#define PNG_16BIT_SUPPORTED -#define PNG_ALIGNED_MEMORY_SUPPORTED -/*#undef PNG_ARM_NEON_API_SUPPORTED*/ -/*#undef PNG_ARM_NEON_CHECK_SUPPORTED*/ -#define PNG_BENIGN_ERRORS_SUPPORTED -#define PNG_BENIGN_READ_ERRORS_SUPPORTED -/*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/ -#define PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED -#define PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED -#define PNG_COLORSPACE_SUPPORTED -#define PNG_CONSOLE_IO_SUPPORTED -#define PNG_CONVERT_tIME_SUPPORTED -#define PNG_EASY_ACCESS_SUPPORTED -/*#undef PNG_ERROR_NUMBERS_SUPPORTED*/ -#define PNG_ERROR_TEXT_SUPPORTED -#define PNG_FIXED_POINT_SUPPORTED -#define PNG_FLOATING_ARITHMETIC_SUPPORTED -#define PNG_FLOATING_POINT_SUPPORTED -#define PNG_FORMAT_AFIRST_SUPPORTED -#define PNG_FORMAT_BGR_SUPPORTED -#define PNG_GAMMA_SUPPORTED -#define PNG_GET_PALETTE_MAX_SUPPORTED -#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED -#define PNG_INCH_CONVERSIONS_SUPPORTED -#define PNG_INFO_IMAGE_SUPPORTED -#define PNG_IO_STATE_SUPPORTED -#define PNG_MNG_FEATURES_SUPPORTED -#define PNG_POINTER_INDEXING_SUPPORTED -/*#undef PNG_POWERPC_VSX_API_SUPPORTED*/ -/*#undef PNG_POWERPC_VSX_CHECK_SUPPORTED*/ -#define PNG_PROGRESSIVE_READ_SUPPORTED -#define PNG_READ_16BIT_SUPPORTED -#define PNG_READ_ALPHA_MODE_SUPPORTED -#define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED -#define PNG_READ_BACKGROUND_SUPPORTED -#define PNG_READ_BGR_SUPPORTED -#define PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED -#define PNG_READ_COMPOSITE_NODIV_SUPPORTED -#define PNG_READ_COMPRESSED_TEXT_SUPPORTED -#define PNG_READ_EXPAND_16_SUPPORTED -#define PNG_READ_EXPAND_SUPPORTED -#define PNG_READ_FILLER_SUPPORTED -#define PNG_READ_GAMMA_SUPPORTED -#define PNG_READ_GET_PALETTE_MAX_SUPPORTED -#define PNG_READ_GRAY_TO_RGB_SUPPORTED -#define PNG_READ_INTERLACING_SUPPORTED -#define PNG_READ_INT_FUNCTIONS_SUPPORTED -#define PNG_READ_INVERT_ALPHA_SUPPORTED -#define PNG_READ_INVERT_SUPPORTED -#define PNG_READ_OPT_PLTE_SUPPORTED -#define PNG_READ_PACKSWAP_SUPPORTED -#define PNG_READ_PACK_SUPPORTED -#define PNG_READ_QUANTIZE_SUPPORTED -#define PNG_READ_RGB_TO_GRAY_SUPPORTED -#define PNG_READ_SCALE_16_TO_8_SUPPORTED -#define PNG_READ_SHIFT_SUPPORTED -#define PNG_READ_STRIP_16_TO_8_SUPPORTED -#define PNG_READ_STRIP_ALPHA_SUPPORTED -#define PNG_READ_SUPPORTED -#define PNG_READ_SWAP_ALPHA_SUPPORTED -#define PNG_READ_SWAP_SUPPORTED -#define PNG_READ_TEXT_SUPPORTED -#define PNG_READ_TRANSFORMS_SUPPORTED -#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED -#define PNG_READ_USER_CHUNKS_SUPPORTED -#define PNG_READ_USER_TRANSFORM_SUPPORTED -#define PNG_READ_bKGD_SUPPORTED -#define PNG_READ_cHRM_SUPPORTED -#define PNG_READ_eXIf_SUPPORTED -#define PNG_READ_gAMA_SUPPORTED -#define PNG_READ_hIST_SUPPORTED -#define PNG_READ_iCCP_SUPPORTED -#define PNG_READ_iTXt_SUPPORTED -#define PNG_READ_oFFs_SUPPORTED -#define PNG_READ_pCAL_SUPPORTED -#define PNG_READ_pHYs_SUPPORTED -#define PNG_READ_sBIT_SUPPORTED -#define PNG_READ_sCAL_SUPPORTED -#define PNG_READ_sPLT_SUPPORTED -#define PNG_READ_sRGB_SUPPORTED -#define PNG_READ_tEXt_SUPPORTED -#define PNG_READ_tIME_SUPPORTED -#define PNG_READ_tRNS_SUPPORTED -#define PNG_READ_zTXt_SUPPORTED -#define PNG_SAVE_INT_32_SUPPORTED -#define PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED -#define PNG_SEQUENTIAL_READ_SUPPORTED -#define PNG_SETJMP_SUPPORTED -#define PNG_SET_OPTION_SUPPORTED -#define PNG_SET_UNKNOWN_CHUNKS_SUPPORTED -#define PNG_SET_USER_LIMITS_SUPPORTED -#define PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED -#define PNG_SIMPLIFIED_READ_BGR_SUPPORTED -#define PNG_SIMPLIFIED_READ_SUPPORTED -#define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED -#define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED -#define PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED -#define PNG_SIMPLIFIED_WRITE_SUPPORTED -#define PNG_STDIO_SUPPORTED -#define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED -#define PNG_TEXT_SUPPORTED -#define PNG_TIME_RFC1123_SUPPORTED -#define PNG_UNKNOWN_CHUNKS_SUPPORTED -#define PNG_USER_CHUNKS_SUPPORTED -#define PNG_USER_LIMITS_SUPPORTED -#define PNG_USER_MEM_SUPPORTED -#define PNG_USER_TRANSFORM_INFO_SUPPORTED -#define PNG_USER_TRANSFORM_PTR_SUPPORTED -#define PNG_WARNINGS_SUPPORTED -#define PNG_WRITE_16BIT_SUPPORTED -#define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED -#define PNG_WRITE_BGR_SUPPORTED -#define PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED -#define PNG_WRITE_COMPRESSED_TEXT_SUPPORTED -#define PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED -#define PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED -#define PNG_WRITE_FILLER_SUPPORTED -#define PNG_WRITE_FILTER_SUPPORTED -#define PNG_WRITE_FLUSH_SUPPORTED -#define PNG_WRITE_GET_PALETTE_MAX_SUPPORTED -#define PNG_WRITE_INTERLACING_SUPPORTED -#define PNG_WRITE_INT_FUNCTIONS_SUPPORTED -#define PNG_WRITE_INVERT_ALPHA_SUPPORTED -#define PNG_WRITE_INVERT_SUPPORTED -#define PNG_WRITE_OPTIMIZE_CMF_SUPPORTED -#define PNG_WRITE_PACKSWAP_SUPPORTED -#define PNG_WRITE_PACK_SUPPORTED -#define PNG_WRITE_SHIFT_SUPPORTED -#define PNG_WRITE_SUPPORTED -#define PNG_WRITE_SWAP_ALPHA_SUPPORTED -#define PNG_WRITE_SWAP_SUPPORTED -#define PNG_WRITE_TEXT_SUPPORTED -#define PNG_WRITE_TRANSFORMS_SUPPORTED -#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED -#define PNG_WRITE_USER_TRANSFORM_SUPPORTED -#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED -#define PNG_WRITE_bKGD_SUPPORTED -#define PNG_WRITE_cHRM_SUPPORTED -#define PNG_WRITE_eXIf_SUPPORTED -#define PNG_WRITE_gAMA_SUPPORTED -#define PNG_WRITE_hIST_SUPPORTED -#define PNG_WRITE_iCCP_SUPPORTED -#define PNG_WRITE_iTXt_SUPPORTED -#define PNG_WRITE_oFFs_SUPPORTED -#define PNG_WRITE_pCAL_SUPPORTED -#define PNG_WRITE_pHYs_SUPPORTED -#define PNG_WRITE_sBIT_SUPPORTED -#define PNG_WRITE_sCAL_SUPPORTED -#define PNG_WRITE_sPLT_SUPPORTED -#define PNG_WRITE_sRGB_SUPPORTED -#define PNG_WRITE_tEXt_SUPPORTED -#define PNG_WRITE_tIME_SUPPORTED -#define PNG_WRITE_tRNS_SUPPORTED -#define PNG_WRITE_zTXt_SUPPORTED -#define PNG_bKGD_SUPPORTED -#define PNG_cHRM_SUPPORTED -#define PNG_eXIf_SUPPORTED -#define PNG_gAMA_SUPPORTED -#define PNG_hIST_SUPPORTED -#define PNG_iCCP_SUPPORTED -#define PNG_iTXt_SUPPORTED -#define PNG_oFFs_SUPPORTED -#define PNG_pCAL_SUPPORTED -#define PNG_pHYs_SUPPORTED -#define PNG_sBIT_SUPPORTED -#define PNG_sCAL_SUPPORTED -#define PNG_sPLT_SUPPORTED -#define PNG_sRGB_SUPPORTED -#define PNG_tEXt_SUPPORTED -#define PNG_tIME_SUPPORTED -#define PNG_tRNS_SUPPORTED -#define PNG_zTXt_SUPPORTED -/* end of options */ -/* settings */ -#define PNG_API_RULE 0 -#define PNG_DEFAULT_READ_MACROS 1 -#define PNG_GAMMA_THRESHOLD_FIXED 5000 -#define PNG_IDAT_READ_SIZE PNG_ZBUF_SIZE -#define PNG_INFLATE_BUF_SIZE 1024 -#define PNG_LINKAGE_API extern -#define PNG_LINKAGE_CALLBACK extern -#define PNG_LINKAGE_DATA extern -#define PNG_LINKAGE_FUNCTION extern -#define PNG_MAX_GAMMA_8 11 -#define PNG_QUANTIZE_BLUE_BITS 5 -#define PNG_QUANTIZE_GREEN_BITS 5 -#define PNG_QUANTIZE_RED_BITS 5 -#define PNG_TEXT_Z_DEFAULT_COMPRESSION (-1) -#define PNG_TEXT_Z_DEFAULT_STRATEGY 0 -#define PNG_USER_CHUNK_CACHE_MAX 1000 -#define PNG_USER_CHUNK_MALLOC_MAX 8000000 -#define PNG_USER_HEIGHT_MAX 1000000 -#define PNG_USER_WIDTH_MAX 1000000 -#define PNG_ZBUF_SIZE 8192 -#define PNG_ZLIB_VERNUM 0x12b0 -#define PNG_Z_DEFAULT_COMPRESSION (-1) -#define PNG_Z_DEFAULT_NOFILTER_STRATEGY 0 -#define PNG_Z_DEFAULT_STRATEGY 1 -#define PNG_sCAL_PRECISION 5 -#define PNG_sRGB_PROFILE_CHECKS 2 -/* end of settings */ -#endif /* PNGLCONF_H */ diff --git a/cdeps/win/amd/win32/libpng.a b/cdeps/win/amd/win32/libpng.a deleted file mode 100644 index d85652f2ed222aa8a5019f6be2c82ccca3148a7f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 188520 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�tI;-p%#nZ4~k^kXooyEmGif29}g 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 diff --git a/cdeps/win/amd/win64/libpng.a b/cdeps/win/amd/win64/libpng.a deleted file mode 100644 index 6eaea0d29dc99580ce2cd7a02b225eed5096ffd3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 205978 zcmeFa4}4VBnKynX2@o)NqXtEbI_jv20wx$R!MM(Z3Ea_%rjS;wv`NSx5*v~&Je8;ECh?>{XXa1``kN| zXt%$<@4ox{yzhK+a-Q>jp7ZZH|IfYW+$)NzTC3~-YRV1H#9vOgIqA`rN$SGEZHzN*H?=4wgSwbs@Os z%@wV6)p>byWOB$yb#u$=)`k`JG9`pGHY_Kdz=QBhPWEz@Q2oF-L_aSSwRVxKjRb5@%*2bD_YG1kBNQO{qg-`P? z7J|}Q*HSS?1Q-G|qo``DZfJmRn^#uU$?~-$4V|?$BDgxHR<<|RG^`R}=W6M3>D^xw zZrBp&lm%gP%Q80tlR;E;RJBSCwANNPw6r#()`(y%=N#dlm%khp1Ohc?eUO=}))tpm zSP5HEwQ^-uMFGiHH@6}Xqr?Q9H*b7=tRyOaQ$t-tbybs5_l(*kgAY_KZc1gQ8+kiVV$-W!soCzCdk_ z(5xActX}q*siihHH?6pLWlKe!ECItQ)Lq-!+AM4K^4cauU10$-tYr5XF;ONqZxo^M zWJX6#MgnGIBxF@pV}q=1q6+ob~qPeb)l)kc|y0y8<(%S0JW3UgI z9#$!PNW!I4WVNBG+A4wsB_wbXbdbQ|xCyOoOUetUU|epJ-?8bIz8G)O?ry87X=z}f z8vSh(N{s<(PgQ~TR;zL>zkQLH*`m)8{Tg?OR3rqCkx2w>9ThyR@RWLza!L?;XmrZ7L>80t;}D}j(Xn`%fWp=rKow~LMu}(3p{@I(*{RU)C48+ZGNFL<{|D9cC;1y ztjGhkowC=X$OFDoODwSXjwS5J82B(8fU?4EU9p_T-W9D?t1&o1{}xNk9Aw91?=0-? zaCv)O9U5I*!+ln%32&l*s90ImX~j?T5ZOf};4*^hD%8Mn@Ref9lfb}4f)Z*)2tWps z&?_+7gifAQ(Nfh|8^AorOqnt5ku#nOIqD@~!lyCEq0t)yp&^zC3OSitL1IWX=W0eC zYHI7M+8bq2@$5}bsB9cVm_`i|j_6EkF-4G0D&v)Kng!C*-d2w))!0}ei$eIJ5uN5L zV)EAZ%?3HU5TcmQ)X)r5%8}=`s#Ue0>$#;0rD@3u-$K`RtS!*onh=B#Gg8*nfH*Ls zSRTyOF=(XL=k=6Zb4x3=giGIsU|aJ_+a%Nsj%TI9XFcVLCbL$&0;+A2`0|FPT240=0^(u5$e^u6>^!q%j9MfWZm&0E86u5BkW(yN?JdZZEgPuzm?=v^ z8ig%?W+ns=4%vvulQb0|c;n681w&SJ5kBSJz^HdHE24lf85c4})s}Kx5HbpLvB2RN zdLuVhEfrPO7-6ltzPzgXn=4wI+nZ`^JtfIn3{F-X8d+^c-aHGy?7C$vP}SH{FIOxS zkZ@J3Y_6$Iios%VfZuAzWYp~3$g`YvS|bW$?4`D|1&a-KnjH?UZ&oa4SW3xmH?Lw& zMLu=H1!7|DT*kBtF6AFPWF3nnuTU%7+`gMv+Sfmi-6lYs#i z0f8hIAAp3~MQNnYc|2X4Jj{$+tHcaYq=g29c3>4Z<|Vo1Kt_DQwwyxTs6bND##lg2 zkpK}8Ic#eUxav?D+T?7rrq-MR$YEFbFc#Q65i;C7YccsHcgPu?;pUl_;pT~r;pW+$ z$u}owhMVVSCf}T*8E&2d8E&3Y8g8D&8E%@T+VjJ6Ig@Wr*92i(E+wDdE>xa3u^FvT%8{ll4N5 zHO9a#I$(1)PL8A<0EQAL=q4 zO((~fGzAxa%`ztkS6JcGoMsD$S@leZTuGp>x7HxU;wniFnwuNbMbpVi;kqI?=2V>= zywD)WIP>-~Fg6vi^wvzi?GF(T+*zc81}6Wdoa{SFld>P!mg>6 ziw@yyh1^denuZisJ`GUjJ`FL+ogiS1S;V%sBt%2D`?QTbBw1BcV;dRFc$1(p!@0#+usnu-wQ!_;TOQoQw!1*=j}7_|LOYF~Csi z@u0*D4`NlfW3vy#4{C>fug%VCslqzMwh?O16gyfQFtg>Uq6ybEVo4&BpCn*0NL7+) z)KBRU8`sNgQ59;fMr^TcVVW~wbLUy?z#1#NfZXd%UpJvF?E;0CM*WW;n<=y zdt2#|88wXeBB!=sEvmTblN692H%|8NGH!Y4Dp01p2U)-g7%7Gn@O@PEz)TN zU!n4u-E4aW#(euF|Hj0(U-EKu=gphvbk3PG_a<2QRZgi{H%X!2oKi)(TTp4rY-(MC zmj7~RE6PlVqKw=u-Me5pm9om&q6XOn$06NHS#61fFbZ*GNlm7$;1sdq(p*3DKg?-tQ|?(%%q z^A%6|SMK`i60Pfl#{sH20he3NS>r16sySX)CI0(eE%^VKD+u-r>G&rC)Ay9*edx{E z?bBb@biXTC|5(!xmFT}Z^t)}Dkn!p-d2{+b`dNLA%cbw}>c_p1DgsvpSL=T-HS)kH zBn}Pw^#dM#R}844>0Vd1rl)%Kky+E*97;*gNgxGk_cLG~_d+X9(h7*F*#ASTs0>4AgkE!dvN5QGr1zbh?NJ-x4aZSB$g9^4*U$lK=5wSYR7&Ah)Ayj3MS5Zz&W_$f)nnD%7f@WIc}Kd=eujLm^5}}Hrgxm*`$#)#zbHE7Kkwks@3qJ@DmszxzB=*a_D|{Y zg+|gfePFlO<<#--iZcAW@(%pFY7zdqrsCh#Q}FMaOYra7DIM3BqSINZg+?ZIxP6f< z#D#dT(IVw(PR-FT)f?JH>US%it?7t*=%A@D>GtJBhkhmcr>&&)A@p8`KG6$_(t1Td zp!FOHEXg}4B*M=uMd5i)4Hxcho$1wg=);=&^nt00l8GMUO+7?h5wR`=Wf@TUBk$Qr z0E7fPFFN!-%sU)koHSEsl@CSlL<`J2sOhid?UP}K%B4n~_v|$5)5)$2fH^h&mzw^D zU*8$HC)`DexLQe7lw0Uuz)cyrIov~@Ili7Fs95@M+RqWS%_B0W>7VNTn&Xs+Ov^dZ z{+2F0aZNhebvJ@e5B!V~4o`O58!3xDNb;+w=ic!5DJ5$6QJ{HI&sGduO5VPqE2un5 zx(^2Y8v2Zq?r30vKQdu0d95BOQMaUJdJEE0OY|Lq3p`z~;C(4HmLF0`UUf@WswepA z?DqbieeLHOzPEv+wEx1>^*)JiC0F2HEwaW%>U%B-r#~{a43?&!7CH0jZwlC_M@eK^pAxEx{a<~8{rj=aVMu%RLX5HTPDL&Ip1R(nL)my*xv zp3sORkcIy#flE+}`yebT>xrG-$q!P|%Jy~YfcFa1=|vMU$8y;(7&StFsYKtecK;2M zfw0x?4Mc<&YvB+DMA7;5{;qcwHwwF_KTzZeogP)Y-N=})`ZRQ|MbfBK#Gw7ViCWGc zEnGf7UDnp{0!`cFEl4M>3{5}Q^`7EXl%5@GPYCe{H*9kMcf%coG`Wuncj&!LayZav zwD6;uz$isi^?2xAXHUP{GX!ZcC_-Ym^*EA>@4os>t3E?1?f=~bd-6iU zS8@tN@1;|Wmm?67JWN-}y+F7_@40(+1ePGiTq7y&@Pahd9cSKXpFV;}Fy3q7tQ|rF zh2KsyBs<sJs}E!eqGh+qYsRZQe5x+Vsum_y5!iYUtjT({!>u`#;`(jfSoc+ zHzs8%YrcpMMJ5!4oQBH_G9{L}oiH<244P2Xo<%eVQ{p=@4+vGKe?+ zC3*X_Jqs#Hy3VWLekC-~eHVNoTTW7d(d6LFwmCTrWbMV#(XRJ`@UQI&kr(=bBysvt zfEUUDqj1^+97u464wG|Fh=k||k_707Mi^KU-2N`nYWLrvobpD8rcnPLmcGJSR4^iU z>Xt`IF0#m>p`Z$PJa7a_7eSjj*(3Z=SoU1}5sDHuv3u2L7?aw?_yn&sK{LZP<)P6R zQO%)ZB$5Q^NBR5(yh6{@6FuY|gojgg`Vyyp4Al$jo^E=G!9%Blp zQ#NKpV>gG$%bM2_x0IA>HM5Q=g_p{Tk4^@f)eVU-{fP||bo zfr&#`Xy`L;3zuhO&Ot2+bJhY8VBxom9(W(R(-L!Q_9sx9M)B-fP-I5;4=A$u<)k~# zuQwc;4uu%;MUi8#(PVu3X9(EW|Jw<-g|o6nj8H&?J3aJ@R`t1pk5dCO0DUhSdRi{TsF&gc{oWwqU(0l+h7z|M&qSpg+sLPzC zh39KMqk*eY?6C%iS>6iRr~{ zsh)^uwCFN*{Zjyf_oZE=uK#a>nsBqa{&7J~EK=7$1WJowitiEg4K4E331(%{B2RB3 zRpw!|?tku5%7z}7xeASZ2_tw%#_sM(B;uqcle%R|iWZqLhzvt6bj+buAM{5u`h-uL zw_SE`yBuEi=jTwYM*K#HQmPLMe~39T(lNfb+@2=AqX$F8vSs}TywCTADDo}0Px#Bc zPc&5K*-8lz`9$nUw5c=!VgB{HR3Od2NS9J0dJI(~S1wkK{RPZSo)e;SjwhCLrUca= z%x^wSs4vht|8&fc9A3f3gi?#4JYBZ4&nRzim&jX8v1LIq)QJ|6p^{R zP*sc7Ek);fBNe~)1phd{qY~@VBX?BK_<_%H#54Ln#+U7oQGP**6Z0i~Pw024C6Q$} zpYeqLcxgv2WPj*$oFG}j_vn~Uzn>ns?CL0z722EP!(NTQ@L3o3 z`gvl9$KcEODAJ)vsl9A>QvCF9C?wqJ05={p47@70$lUUM)@ove_So_PW8k3y6$=Q)VFDNcwr9UlNb1uT_6G6{$T1Ktg-d z;#a^XcQ$MYo)4?f@aup(h1_C#P~fLksazZSBk0ujP{)QJmU6CaB4XtzXR%xkmqW7f ztw4HSG+1<@(w>GrR2TJe_k07LvhwHeABUfJDbSYKIeEQQ-;KT26PTLZ6B^A_*ZmlZ z-b%YwFOtT5g}c?YZGh@Z)Vuc8dDYpkcHEDR!CP9e#=(~2sn$HPCEQ6)a9>wLYv677 z#D?7q9ZkCzrqu0Tn5qm-+nPlo(ysH+Q*H0=o|p@^^8aCH7Wt*U)JjCRd*Uo#==WG* z>~>&BeK=kR<;wO~?wW}#?e_cvPdjAq=ndDnW|pW=|JKugCf%#Q8@nimBJ`@+(V=vY z{|$JBKZ5?3BlO|ZEs-T`5VKCed=_??$r^Z2PKEdv#|x5 zIafX-nBCtx4Lh;Bv73%L4m8x?Hq5dqc}LLwtLqM-?FzNgzPU$#2h($MP6)#3kJMlv z|FBiRu;;qln=^vY3P;opb5L-!0WO!ml-THT^*paDS6xRd611Q0+eyTDco71qLM%z*dBD-II%bWA5$MI{-g6E*R%?yo=FFO#fXSXA_{dG*FNjh*5iJD^6!bucS`68_jPcH_NmmJvS&pQH@ zU8?9i5MAM?e?0~I*`uz%1SN-u1~Vfb2L>K>{l!RT&p!2`^P#3t+@VFh=Q=EXP=W7W zIGU>!?ruM^8;$yZQ1_;0?-e;AjqJP6)qW+mjWK$`yrB#|=-1y9oh{UYhZ92P+izo& zdLL;6nh5ph#z#b->lO+E6#tFkhW<$Efy;)zCi*iJMCjNJp3sL5?B?$Xh|r>|a%f&d z8X6f@U-tLqok$Nc$sS#R~5C4(dj7v6JB0{>%OQ_gnhX_j*u* zG~@Q1dcXfzY9#GDj%ZFlvh3;AMtctG2io5*Dg0QCY(QWoJ^Svz!LJ|m>U+6AjG>KT zcfESAy2YQ7+j|>&rS@aATF@RZjg+TQ&!Bk?bxSc3PD&PMu1 z)t))XBx!*JP`q-tGCl(+_!ts?pK|I=^a-=no_t_<=JdcO42tdv)J@4ngqa>qAC6Ce zA|i_>#J`S}p6pMtgP!5TN@v~W2pzdldr!*jsNF}1z%J}_)S(IGhy~2hWOMvE;E8As z& z&fc<7FrlANY~t+^Zz?L_rxQA={SmhV_-;IPUE|qCW0@ys-))id^b|k#V&Q$an`-nx z`w4hT$K$I5tv49^lN>%kGm5rjsQAVZ;EOCk5v1l?h!!bES--hEWtOMwG@=T2O!etI z;~zn3h;8U+hGIpF=#%3So>1LAwHGxF^IgAAk94L|--Ko*H)HAP5j~^oxR^RXdOihY zZ^t?2vm^{fntmMf5gBO0dIR%!8rk;+YOz$PE5Vpng&yp>y{OljR5}t!~ zvZntkd~aH~c!oE;Ji{BlH`5y_n(Ym@PWPtXmo8eQs{~u=*P(`@4O}Q!z+xb_Jv`JR zccwu~2CE;7oq^hs=YxwPGiFNAtH0+>y$2KZJJU<_H@*5YS9a`mNO{AcAo>%arsOe5 zWyEO7Vsdp-1kg-V1P^tWxn_DD!%%2;c!ARa%S%d$b&06e?j=aDK;SJ)dP6Void7lG z&g_Y*-LoM?30M@#x?IW>N3!rt>CWk1$8oRYkOzgEYXnFWnc_(KEDT;oN>dRYWM{;t zN|DE+>XvBy9XOKo-5I{bht*VTTKK;7@Vyybelp-m%3pc+@7v8B-HWO z=)yZYy*Y#4!WeXvyQa}2y?0b&%9?in*F^*vW4(ok*OckQD7b)5CvJsM-s%}B-67+Olnx*wbsgUy9uM}&0+8y;8JssL=r(CrgkC^cY zDsILy=*@{!EM+1V&4{IuV(}xEe9=H+&r%PISo|`UvcTV>BGemUKy(>+UJ7O@J%KNP zM?VA_VV8OJ!^jK5g`+(7O(URXRO*YV)XQC3NzU(NP~TI}O$4C<+%QP#LC&Gc>^!6iAyC&g z!>jKTDWDfD@?+^j3<)CHe3OZfAc5(1RgABwt%1o>BpcI3L z^qk|duS1FizG4Ja13beB=+oG(2KOc#*XVfAwOwIwF9sKBcfqUCy--v&Imcq7*dwLT zPoW-xJKeL5TBN96@5SCTm~Tnu3>))U>?MQw3osFOE_^#J0R;V|6p$Uw6Ob~-OWJ)! z!^9r%0be+ic6yz@a2d9`p%V}S$pwK21XN>a^C-4dlzbo`v-9@LF+A3bd58JH8jaU| z5AT10y~)PzGe-d-g7!}F=TiKrYBOVJM@RvIDQGe?5l-$sJK_Ijn}1`!&f1Tn?W*{m zf8+cl@AncP18I8vgpe7tAH2k)zoPzppGQAP_CZhoP^S9yTb}-7nI84&LohGvhp`ko zr2hN}w$L009DDIn%U~w>lMj0w2TSx!kM6*hwmIKQ>c8pPtET_TqrWcp#a;)MFE z5<5(rsLO=C6}H;_CI(;Hq`SO3+I|5B{rk_w3`;oG?ro5O8e&2Xr?D;&vj(FV9`s<% z`S4fa{W+>DImZhRsSjUkIm~mfQBnFipMj1$%$v7u;@n{-HW%SgAy(N`tW8j4h^Da=U}aycT$TKy+m9s zoQ1jMn^>kA59kZe8iBPRH7CdjmO`f=c*bU~8Si0=7Xjeet07}@28n}5r>57xC`A-l zLW&45QWT?z{-V$+goMxu5TP57wzxhg^)H$h+9p&kW=$|t-ajqe`z+j8|DoSZkG*&pV<~2FGPv(iL=?=@H%CWL ztzU*tCa6@R^J)YhewaO~JyMkX2)ARC$iY@x2ImZfUlhTAidRF; z;CsH02#eAw0;=paFBHHB6Zei3_dLB){*95 z@5QQaf_z_)UYGrxcOKQXs~~PJ>eRLM!t=}#jQRzh7byjz!RfoPdzAAA=1zzHUA*0z zb3hMZW`10wPW#ZHc%8K#4}Rq%J-lq{*SG9NSYlErUPz50EWCx9_8WSs5Pe*J$NSjR za20u;M`wdN@*!e4^noW53Bsv=>eYWAd-V-;b3c!&Proz)bpzSO^Ti!n|GO%pyIga; ztU2I1b^|s@3g23_n%1BCVUK=m>&i=jpbn5xS7_qQ+t_)hG0g7r3rHgrS3K@hMS@WvjXn;oH2oqn^`TS9<+k zjEV|v@q>f*X0;A6#J0Ugt+qcQCQ&DWCAY1AhWA*n^f2^8^#8GM3r93wB<6@pY`bK} z7a%!!pD6wql$%G(RkXAsn1XmF5F@f6Rpt2g@M-{}JBibqWPS37vQ!*%vXnWS(v_UY zCn;C;PE;=KoS;mvPg5>%T%cs+o>MucWpY`1bmBnTV9Kx~&7q_f!;fiCPE{t?rzmO5 zfu&DS(u>n_Q!7(i9A$9Zd8RzsBs(!xnOK~X>!<`xX_%0rOqk=y9TUcs3Ca{lmXeyA zQt4>1`6Jp4i~MIyQZkCub0<|!Y?)A&7EKwjg*hornKVa+AmSqVDHD|`izntzs7z}~ zElZ(?J2D-nZTDl3=kwx9Ll>7Tb1w3>+{oLXqg&F6>CdhoGycrUO6Kz95<$8Ne{UR| zblM7?lD!zVnK!gxN3P*-yzoppikHfo+;)9Xd~3(X2Qj6N{^5t>QSMB^V_4W_u)hz3 zD3y({Pr(#`Rxlov!ni?}!G0YESA8mjuxG*JGSIoOt6=Iux4=FHLt!fzJXXMT5)Qi^ zrW3v7TE~84EEo{Y$h4lpTN+(TS0GqGt4fKZrHC*#XXv! z2Vm!)t0-?14toR4QP6#`e*`lOdNb@7U_JpIh5cG4&Z2-GgdKyS2YkbX!DNs^&jSXN z2|5$@beJsAPS_8U8+0G+JuoiN1F(MwL)*{8uusB>0zDsk!{e!Z;DfL$aQCMMx)Sz3 z!<2*G414pJfDsM*qZ!Bp=waC2OBLmD&}FcH4f7=ELD*%NE6P)Z!`^lkbOJgG`(_vP z0NM?^1Li2`AnZqBJ^;ND_A@ZUBoBMi)zAs(OxV|7t0-qc=fW<5$wECSgIxybpJ!Z+0hWFcgkA@ zXDPq}&erxOx+qR^l)TwW(MZ{Cyz<~4}U?CKn6 zUSVOutU0;4b7taSKK+{qXWl&LqQ=^$Cg)8EjG}Yj^ zcbn7O(72+ub*$K25<{TvtDPmS4b{#iI9l9@>$zq+7vXZ27H9sPnND9*^=#Z+j5_@v z%EuJNM<-pOSzI0GY-n@dSKHc5x)TTbe1@XL^>U_+$+P*Z?X0e?t!Z=8@kzvsL*-Tw zLQGyU^(VqNg^UO&6ZpyW8N4rw$Ve+rtUARFcUBS%j=1U0N%v7Pi^3nny}=3sCt7jm zkgS}hQbek(ddH{Go${oqJ!}#+>!d4-)>>y%bHGXWRdv+XP?%Ms znNfAd!C1Qg(hOK0_Dc@a%+?oksg#}aEZk#wfZqu-6J`*m8|E;~ewYE6*9`aDu!(;Z zCI<5X%x0KpVdy1*=V78SyI}UhB>T@mznJWQ7;>M$jKG|MQ6Q5BlMX}jnJ`%}(_v=7 zIAL5c*)TIkK-26_BPp@i8Ga=UN)io6?eu^4Who+b_b~< z?jdrvG(*zXM^h(>>opbbEvs-f+sc*z#e{>>&ZgQGXb-E9hI-tR3bMK(u-fQF%}OWI z+)lQWn-OS4yi|F*dcrUaj2L-UQRAc-mJeOKMw` zJ8_xn9nGs0Z*8^V&*hfH@U0)$zu)^mMvnd!xd%r-GVsA$;dEAPOesd|z(U|15Ah+< zkD7bUAHJEfKsuYM!CH+og>=IDY z?_G>719h87{Z3G~3yL;fWXMZE6$|VhP&DsOQ~E&NA*j!o`W9x+Qtnqwy#eY@A$N?a zkD2S3WOCC%Nx$?Si1cw4C>dKfs4@}CL!iDas9%6uEU1gqO}{?{RVuLCCY#hhGu6-3 z49qs9TrN{pOnsNBA2ankrcN?->p5m9l}!DBsr^iygX$?`yM(DuroPM6DW=k=nm!ts z`fH|sz|;h+A4)}jSA$w2sJVFitXxocf|8nS1|_w-jc)+o~N1x(d}x?TAAF;*^;`>&v6C_5P& zVC>=xOt~vSNx8X<-2&=15uTT^FSFeD8T&`ZPB8WvV^h(=$h2GnO2%;wV>dFkfUz>h zsu}wxV;zh=z}TaV{eZEbF!n5CI~n^WV<#E=jHzobGSfVlsVA8l0QFU&mn)~6as^B^ zGWBhyHi42o$UepnU#uv1iBS43F+}QPaWb9SO-e>IhjGcF_8Q#U9WOymrX6yDdRms$SOg+ZbZbi%8FB$*MNGMw>t&4g=%imibITYjXKE>PmoZk!R1I_M8Ea&!g}DL7 zI+j^aqav`;Uoa^}+dNMg&F zs$^~rWA#kY(`T7xI+a6y)0DTF8f5AyQ*`7`%6-7pFjJo}HNw;xrfA5Ke(?atpy*x& ziDfXA$y63o)0vvVl#?kJQ`t<-WQv|k$T;$uDqxDv(@CzIDKAqRQ+}q(m?~##DO0qP zli^h|Rl^h>)fwDIrs!FT^bugHlc_aK1)1t*s+Xw^O!YDK7*mfk^#oHJnR=3`O-wz- z)MlohWoj!^&odQeY8O*`ncC0P08_6qb(pEQnHps3C{r<}K45B?sZW?1Vd@N13T8%9 z&uL8IF{puMFqO$v7E{xin!%KlDHl`OOwD8}m#KWF=*0?|mf6^AtwqbD-`P<-J#oz2$LB$I%=3nZ9;d<0};0^&e^>8YR<&U7I3Y|uio zfox1bZUsWm2`w4gU!tdl7P1ToJu|eBl_Z0;yoK}tq34GdLSrgDMYNEOKd9$G+Mqs0z%IlEhGiXrKgS-axoBk_Glq=c$A(%TF7lc=sBc? z(3n6^BQ1nphEcF~w~!tn^kmXP=vgp5pR|yF20~9ME#yT)u)egA*MQIyOAGl85PEKD zA#ot|^wL63lMJ3=S_ocB5Kl5KP+g8DAj^T!b51Md4j{Q$ z`B}(AK*|!3e+1H!fNTXakbt}jWH^C7oDdVRVzoT7{#(MgJiE!o% zI{6=7PB4CEzj1y7(t>-+tslwYDKNgJW&TWGmnQha&9L-oJ>zG}T$><6Pcp>UT7(qI z;Bx#M=a`-p)7Om&zKDJ67-aDnq-G4#IR=T0LH<4gLFzg=6CyqMwnZH$kW)xwv;0w- zX#|!fu}OfzVJg==i<@-|J~n4Y^!g^Ctz?#c%Z&*_Pm>Na|?xT z#Fg9TdjgF7zt1K9zt1J2y^Q%>Vp6-WPX1Jts6f{DKN7xRX#2|II3K_=u0fYqql;h? zka549Wq|bM8S9&kxXzuvV!D_PUCK@ z5M5(KKR&zq)g^gR{grLg;oXCGeGeTA#nW*=$IB&=yMK(Mj1yL!3+hEsh3dK|A>@x- z8YHWFZ}IN5DfdKL95~kR>yM{-Lhq?s^+`|YU3C%emb?J}GS2b#X3X(MwA4sTN@?}J zP&5q^-rlS^17I)g%{YJP2ioJiu>mCRwV-s1 zyRS4~;XvDhQoO!j2=C|7^_jUEu8Si0+R~i!%rTB6DWOwl>uEKbE)dP7SzJO|r zSH+KL5zLa2!WZeZJ^kq2Z`>6*L0vx)BDghJt4<4Pj>DsaR(vneJP*ehDq;Ecy*^|k zG^kR6;PTHDPj8AxTw8!Z#HBm_!UJs?p28DreuC_`|2MiDb3ojTV(M3fX9T33`W@ax zPsK%%-_aaVUrs+RcA|K2ol9D}5BEFwrVMR_tWD03Yoi@e+-tl-%h_RwQ<~^bFuXOM zmI*)bL5X^SCZX_(fRNl&s%&b{GQ7lqG^(K*5C|sM14ZGYh+~ep2S{BXt|N%&fHKpI zXaYYQ`Wvnv$d=l(hu&X@$6VntojjWI#$B{@;_Oi1%HaH~aNkt8D-+4XfzZHtxJZi5 z{oL~nZFEqaMbg4^kxXUub?BHHiBCVQMYPJ;V|agCfYc!oBE7}e0QcjxJnfl^yO@Fn z&cG$8KU9Z8BWgQt?){oN6gJa?Yi8r$w&e%sDsTtys&wl!00H|h$G8{$4#->J9gpko1f!z=bzLqIDWS@jZb9hjxz^wQ9FsN9R^ zopb{^JxD-{z$I^&4^8v-`qRX9ZPbRfTV4RK;~Qv)>1f4)uh1ExfAa)SyW8LJs9Tmg zx{m~24gN7t?WT?Xtst}0LXLH2IzoV2e^H*K2Um2c6|+;U|=$}nfSeEF|l@%p#DzO7fXMED{RVx zGD&|v1a0W=uiyPg`Ffj%(b0)ohi*vQYQF16V79i^d@Y%r zxq)I)jW8xfzBYYmnxXHK-n3LvkwYW52BxF(q&YDB;3DSs-xlxoW)�zopLTIeNis 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