diff --git a/.jcheck/conf b/.jcheck/conf index 868e54bc32e..98cc39b606f 100644 --- a/.jcheck/conf +++ b/.jcheck/conf @@ -1,7 +1,7 @@ [general] project=jdk-updates jbs=JDK -version=11.0.27 +version=11.0.28 [checks] error=author,committer,reviewers,merge,issues,executable,symlink,message,hg-tag,whitespace,problemlists diff --git a/make/autoconf/version-numbers b/make/autoconf/version-numbers index 4ff84f492e3..2dcdb22ea01 100644 --- a/make/autoconf/version-numbers +++ b/make/autoconf/version-numbers @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -28,12 +28,12 @@ DEFAULT_VERSION_FEATURE=11 DEFAULT_VERSION_INTERIM=0 -DEFAULT_VERSION_UPDATE=27 +DEFAULT_VERSION_UPDATE=28 DEFAULT_VERSION_PATCH=0 DEFAULT_VERSION_EXTRA1=0 DEFAULT_VERSION_EXTRA2=0 DEFAULT_VERSION_EXTRA3=0 -DEFAULT_VERSION_DATE=2025-04-15 +DEFAULT_VERSION_DATE=2025-07-15 DEFAULT_VERSION_CLASSFILE_MAJOR=55 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`" DEFAULT_VERSION_CLASSFILE_MINOR=0 DEFAULT_ACCEPTABLE_BOOT_VERSIONS="10 11" diff --git a/make/common/MakeIO.gmk b/make/common/MakeIO.gmk index 342e4f5c4b5..7cd6fa1877d 100644 --- a/make/common/MakeIO.gmk +++ b/make/common/MakeIO.gmk @@ -257,7 +257,7 @@ ifeq ($(HAS_FILE_FUNCTION), true) else # Use printf to get consistent behavior on all platforms. WriteFile = \ - $(shell $(PRINTF) "%s" $(call ShellQuote, $1) > $2) + $(shell $(PRINTF) "%s\n" $(strip $(call ShellQuote, $1)) > $2) endif # Param 1 - Text to write @@ -268,5 +268,5 @@ ifeq ($(HAS_FILE_FUNCTION), true) else # Use printf to get consistent behavior on all platforms. AppendFile = \ - $(shell $(PRINTF) "%s" $(call ShellQuote, $1) >> $2) + $(shell $(PRINTF) "%s\n" $(strip $(call ShellQuote, $1)) >> $2) endif diff --git a/make/data/cacerts/baltimorecybertrustca b/make/data/cacerts/baltimorecybertrustca deleted file mode 100644 index b3cf6547c16..00000000000 --- a/make/data/cacerts/baltimorecybertrustca +++ /dev/null @@ -1,28 +0,0 @@ -Owner: CN=Baltimore CyberTrust Root, OU=CyberTrust, O=Baltimore, C=IE -Issuer: CN=Baltimore CyberTrust Root, OU=CyberTrust, O=Baltimore, C=IE -Serial number: 20000b9 -Valid from: Fri May 12 18:46:00 GMT 2000 until: Mon May 12 23:59:00 GMT 2025 -Signature algorithm name: SHA1withRSA -Subject Public Key Algorithm: 2048-bit RSA key -Version: 3 ------BEGIN CERTIFICATE----- -MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ -RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD -VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX -DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y -ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy -VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr -mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr -IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK -mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu -XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy -dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye -jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 -BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 -DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 -9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx -jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 -Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz -ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS -R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp ------END CERTIFICATE----- diff --git a/make/data/cacerts/camerfirmachamberscommerceca b/make/data/cacerts/camerfirmachamberscommerceca deleted file mode 100644 index b92255f770c..00000000000 --- a/make/data/cacerts/camerfirmachamberscommerceca +++ /dev/null @@ -1,35 +0,0 @@ -Owner: CN=Chambers of Commerce Root, OU=http://www.chambersign.org, O=AC Camerfirma SA CIF A82743287, C=EU -Issuer: CN=Chambers of Commerce Root, OU=http://www.chambersign.org, O=AC Camerfirma SA CIF A82743287, C=EU -Serial number: 0 -Valid from: Tue Sep 30 16:13:43 GMT 2003 until: Wed Sep 30 16:13:44 GMT 2037 -Signature algorithm name: SHA1withRSA -Subject Public Key Algorithm: 2048-bit RSA key -Version: 3 ------BEGIN CERTIFICATE----- -MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEn -MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL -ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMg -b2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAxNjEzNDNaFw0zNzA5MzAxNjEzNDRa -MH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZpcm1hIFNBIENJRiBB -ODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3JnMSIw -IAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0B -AQEFAAOCAQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtb -unXF/KGIJPov7coISjlUxFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0d -BmpAPrMMhe5cG3nCYsS4No41XQEMIwRHNaqbYE6gZj3LJgqcQKH0XZi/caulAGgq -7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jWDA+wWFjbw2Y3npuRVDM3 -0pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFVd9oKDMyX -roDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIG -A1UdEwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5j -aGFtYmVyc2lnbi5vcmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p -26EpW1eLTXYGduHRooowDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIA -BzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hhbWJlcnNpZ24ub3JnMCcGA1Ud -EgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYDVR0gBFEwTzBN -BgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz -aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEB -AAxBl8IahsAifJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZd -p0AJPaxJRUXcLo0waLIJuvvDL8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi -1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wNUPf6s+xCX6ndbcj0dc97wXImsQEc -XCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/nADydb47kMgkdTXg0 -eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1erfu -tGWaIZDgqtCYvDi1czyL+Nw= ------END CERTIFICATE----- diff --git a/make/data/cacerts/camerfirmachambersignca b/make/data/cacerts/camerfirmachambersignca deleted file mode 100644 index 935eea9c212..00000000000 --- a/make/data/cacerts/camerfirmachambersignca +++ /dev/null @@ -1,48 +0,0 @@ -Owner: CN=Global Chambersign Root - 2008, O=AC Camerfirma S.A., SERIALNUMBER=A82743287, L=Madrid (see current address at www.camerfirma.com/address), C=EU -Issuer: CN=Global Chambersign Root - 2008, O=AC Camerfirma S.A., SERIALNUMBER=A82743287, L=Madrid (see current address at www.camerfirma.com/address), C=EU -Serial number: c9cdd3e9d57d23ce -Valid from: Fri Aug 01 12:31:40 GMT 2008 until: Sat Jul 31 12:31:40 GMT 2038 -Signature algorithm name: SHA1withRSA -Subject Public Key Algorithm: 4096-bit RSA key -Version: 3 ------BEGIN CERTIFICATE----- -MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYD -VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0 -IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3 -MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD -aGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMxNDBaFw0zODA3MzEx -MjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3Vy -cmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAG -A1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAl -BgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZI -hvcNAQEBBQADggIPADCCAgoCggIBAMDfVtPkOpt2RbQT2//BthmLN0EYlVJH6xed -KYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXfXjaOcNFccUMd2drvXNL7 -G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0ZJJ0YPP2 -zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4 -ddPB/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyG -HoiMvvKRhI9lNNgATH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2 -Id3UwD2ln58fQ1DJu7xsepeY7s2MH/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3V -yJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfeOx2YItaswTXbo6Al/3K1dh3e -beksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSFHTynyQbehP9r -6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh -wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsog -zCtLkykPAgMBAAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQW -BBS5CcqcHtvTbDprru1U8VuTBjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDpr -ru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UEBhMCRVUxQzBBBgNVBAcTOk1hZHJp -ZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJmaXJtYS5jb20vYWRk -cmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJmaXJt -YSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiC -CQDJzdPp1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCow -KAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZI -hvcNAQEFBQADggIBAICIf3DekijZBZRG/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZ -UohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6ReAJ3spED8IXDneRRXoz -X1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/sdZ7LoR/x -fxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVz -a2Mg9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yyd -Yhz2rXzdpjEetrHHfoUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMd -SqlapskD7+3056huirRXhOukP9DuqqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9O -AP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETrP3iZ8ntxPjzxmKfFGBI/5rso -M0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVqc5iJWzouE4ge -v8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z -09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B ------END CERTIFICATE----- diff --git a/make/data/cacerts/sectigocodesignroote46 b/make/data/cacerts/sectigocodesignroote46 new file mode 100644 index 00000000000..7f13b28a401 --- /dev/null +++ b/make/data/cacerts/sectigocodesignroote46 @@ -0,0 +1,21 @@ +Owner: CN=Sectigo Public Code Signing Root E46, O=Sectigo Limited, C=GB +Issuer: CN=Sectigo Public Code Signing Root E46, O=Sectigo Limited, C=GB +Serial number: 50249ba2ef8ea6bf6c2c1f1a6385d4c3 +Valid from: Mon Mar 22 00:00:00 GMT 2021 until: Wed Mar 21 23:59:59 GMT 2046 +Signature algorithm name: SHA384withECDSA +Subject Public Key Algorithm: 384-bit EC (secp384r1) key +Version: 3 +-----BEGIN CERTIFICATE----- +MIICKDCCAa+gAwIBAgIQUCSbou+Opr9sLB8aY4XUwzAKBggqhkjOPQQDAzBWMQsw +CQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQDEyRT +ZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBFNDYwHhcNMjEwMzIyMDAw +MDAwWhcNNDYwMzIxMjM1OTU5WjBWMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2Vj +dGlnbyBMaW1pdGVkMS0wKwYDVQQDEyRTZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25p +bmcgUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQIMoEDH487om+BR4zl +e7m6wWmyW0nAKLkUWG8kM85Qm3PZO8FoOZx6Yc5c0iJHRKuAhanllayqrmZYhlan +uIODzLTRDqlR+EtnOX+MubY5aDSPGUq6jiHrQrisVp0J3AejQjBAMB0GA1UdDgQW +BBTPfSygkHqYHd22XoXC4NoVcdLlXjAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/ +BAUwAwEB/zAKBggqhkjOPQQDAwNnADBkAjACd++zAerlV83j8HflRwwwlLmgchbs +aGX/4g44dv/oG8KfzCVTRg6sZHMobtK0IqYCMGk5W6+oBFyZMtOebrSwXs8lGjll +/zHz43Zy8DMXO+iiqzSEwWGneZ6KupkGGqfVKw== +-----END CERTIFICATE----- diff --git a/make/data/cacerts/sectigocodesignrootr46 b/make/data/cacerts/sectigocodesignrootr46 new file mode 100644 index 00000000000..38270cb0c52 --- /dev/null +++ b/make/data/cacerts/sectigocodesignrootr46 @@ -0,0 +1,39 @@ +Owner: CN=Sectigo Public Code Signing Root R46, O=Sectigo Limited, C=GB +Issuer: CN=Sectigo Public Code Signing Root R46, O=Sectigo Limited, C=GB +Serial number: 4b2c3b01018bad2abc8c7b5b3eed9057 +Valid from: Mon Mar 22 00:00:00 GMT 2021 until: Wed Mar 21 23:59:59 GMT 2046 +Signature algorithm name: SHA384withRSA +Subject Public Key Algorithm: 4096-bit RSA key +Version: 3 +-----BEGIN CERTIFICATE----- +MIIFeDCCA2CgAwIBAgIQSyw7AQGLrSq8jHtbPu2QVzANBgkqhkiG9w0BAQwFADBW +MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQD +EyRTZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBSNDYwHhcNMjEwMzIy +MDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBWMQswCQYDVQQGEwJHQjEYMBYGA1UEChMP +U2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQDEyRTZWN0aWdvIFB1YmxpYyBDb2RlIFNp +Z25pbmcgUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCN +55QSIgQkdC7/FiMCkoq2rjaFrEfUI5ErPtx94jGgUW+shJHjUoq14pbe0IdjJImK +/+8Skzt9u7aKvb0Ffyeba2XTpQxpsbxJOZrxbW6q5KCDJ9qaDStQ6Utbs7hkNqR+ +Sj2pcaths3OzPAsM79szV+W+NDfjlxtd/R8SPYIDdub7P2bSlDFp+m2zNKzBenjc +klDyZMeqLQSrw2rq4C+np9xu1+j/2iGrQL+57g2extmeme/G3h+pDHazJyCh1rr9 +gOcB0u/rgimVcI3/uxXP/tEPNqIuTzKQdEZrRzUTdwUzT2MuuC3hv2WnBGsY2HH6 +zAjybYmZELGt2z4s5KoYsMYHAXVn3m3pY2MeNn9pib6qRT5uWl+PoVvLnTCGMOgD +s0DGDQ84zWeoU4j6uDBl+m/H5x2xg3RpPqzEaDux5mczmrYI4IAFSEDu9oJkRqj1 +c7AGlfJsZZ+/VVscnFcax3hGfHCqlBuCF6yH6bbJDoEcQNYWFyn8XJwYK+pF9e+9 +1WdPKF4F7pBMeufG9ND8+s0+MkYTIDaKBOq3qgdGnA2TOglmmVhcKaO5DKYwODzQ +RjY1fJy67sPV+Qp2+n4FG0DKkjXp1XrRtX8ArqmQqsV/AZwQsRb8zG4Y3G9i/qZQ +p7h7uJ0VP/4gDHXIIloTlRmQAOka1cKG8eOO7F/05QIDAQABo0IwQDAdBgNVHQ4E +FgQUMuuSmv81lkgvKEBCcCA2kVwXheYwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB +/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAHZlwuPXIkrXHYle/2lexhQCTXOm +zc0oyrA36r+nySGqql/av/aDbNCA0QpcAKTL88w5D55BcYjVPOiKe4wXI/fKNHSR +bAauUD8AWbImPDwXg1cDPi3RGj3UzwdUskMLUnKoiPXEF/Jv0Vil0WjkPZgIGO42 +9EhImvpUcPCI1HAWMEJJ0Nk/dUtFcdiuorthDoiFUFe5uhErNikfjyBynlyeidGC +2kWNapnahHFrM6UQu3nwl/Z0gaA/V8eGjDCMDjiVrgHGHqvcqB9vL9f/dh6uF3Nt +5bl1s2EGqJUzwk5vsjfylb6FVBK5yL1iQnb3Kvz1NzEDJlf+0ebb8BYCcoOMCLOE +rKnkB/ihiMQTWlBHVEKm7dBBNCyYsT6iNKEMXb2s9395p79tDFYyhRtLl7jhrOSk +PHHxo+FOY9b0Rrr1CwjhYzztolkvCtQsayOinqFN7tESzRgzUO1Bbst/PUFgC2ML +ePV170MVtzYLEK/cXBipmNk22R3YhLMGioLjexskp0LO7g8+VlwyfexL3lYrOzu6 ++XpY0FG2bNb2WKJSJHpEhqEcYD9J0/z6+YQcBcI0v+Lm8RkqmS9WVzWctfUHw0Yv +3jg9GQ37o/HfE57nqXJYMa+96trX1m13MzOO9Kz9wb9Jh9JwBWd0Bqb2eEAtFgSR +Dx/TFsS4ehcNJMmy +-----END CERTIFICATE----- diff --git a/make/data/cacerts/sectigotlsroote46 b/make/data/cacerts/sectigotlsroote46 new file mode 100644 index 00000000000..60e0b83c97e --- /dev/null +++ b/make/data/cacerts/sectigotlsroote46 @@ -0,0 +1,21 @@ +Owner: CN=Sectigo Public Server Authentication Root E46, O=Sectigo Limited, C=GB +Issuer: CN=Sectigo Public Server Authentication Root E46, O=Sectigo Limited, C=GB +Serial number: 42f2ccda1b6937445f15fe752810b8f4 +Valid from: Mon Mar 22 00:00:00 GMT 2021 until: Wed Mar 21 23:59:59 GMT 2046 +Signature algorithm name: SHA384withECDSA +Subject Public Key Algorithm: 384-bit EC (secp384r1) key +Version: 3 +-----BEGIN CERTIFICATE----- +MIICOjCCAcGgAwIBAgIQQvLM2htpN0RfFf51KBC49DAKBggqhkjOPQQDAzBfMQsw +CQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1T +ZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwHhcN +MjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEYMBYG +A1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1YmxpYyBT +ZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAAR2+pmpbiDt+dd34wc7qNs9Xzjoq1WmVk/WSOrsfy2qw7LFeeyZYX8QeccC +WvkEN/U0NSt3zn8gj1KjAIns1aeibVvjS5KToID1AZTc8GgHHs3u/iVStSBDHBv+ +6xnOQ6OjQjBAMB0GA1UdDgQWBBTRItpMWfFLXyY4qp3W7usNw/upYTAOBgNVHQ8B +Af8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNnADBkAjAn7qRa +qCG76UeXlImldCBteU/IvZNeWBj7LRoAasm4PdCkT0RHlAFWovgzJQxC36oCMB3q +4S6ILuH5px0CMk7yn2xVdOOurvulGu7t0vzCAxHrRVxgED1cf5kDW21USAGKcw== +-----END CERTIFICATE----- diff --git a/make/data/cacerts/sectigotlsrootr46 b/make/data/cacerts/sectigotlsrootr46 new file mode 100644 index 00000000000..7ec1b263de7 --- /dev/null +++ b/make/data/cacerts/sectigotlsrootr46 @@ -0,0 +1,39 @@ +Owner: CN=Sectigo Public Server Authentication Root R46, O=Sectigo Limited, C=GB +Issuer: CN=Sectigo Public Server Authentication Root R46, O=Sectigo Limited, C=GB +Serial number: 758dfd8bae7c0700faa925a7e1c7ad14 +Valid from: Mon Mar 22 00:00:00 GMT 2021 until: Wed Mar 21 23:59:59 GMT 2046 +Signature algorithm name: SHA384withRSA +Subject Public Key Algorithm: 4096-bit RSA key +Version: 3 +-----BEGIN CERTIFICATE----- +MIIFijCCA3KgAwIBAgIQdY39i658BwD6qSWn4cetFDANBgkqhkiG9w0BAQwFADBf +MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQD +Ey1TZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYw +HhcNMjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEY +MBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1Ymxp +YyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQCTvtU2UnXYASOgHEdCSe5jtrch/cSV1UgrJnwUUxDa +ef0rty2k1Cz66jLdScK5vQ9IPXtamFSvnl0xdE8H/FAh3aTPaE8bEmNtJZlMKpnz +SDBh+oF8HqcIStw+KxwfGExxqjWMrfhu6DtK2eWUAtaJhBOqbchPM8xQljeSM9xf +iOefVNlI8JhD1mb9nxc4Q8UBUQvX4yMPFF1bFOdLvt30yNoDN9HWOaEhUTCDsG3X +ME6WW5HwcCSrv0WBZEMNvSE6Lzzpng3LILVCJ8zab5vuZDCQOc2TZYEhMbUjUDM3 +IuM47fgxMMxF/mL50V0yeUKH32rMVhlATc6qu/m1dkmU8Sf4kaWD5QazYw6A3OAS +VYCmO2a0OYctyPDQ0RTp5A1NDvZdV3LFOxxHVp3i1fuBYYzMTYCQNFu31xR13NgE +SJ/AwSiItOkcyqex8Va3e0lMWeUgFaiEAin6OJRpmkkGj80feRQXEgyDet4fsZfu ++Zd4KKTIRJLpfSYFplhym3kT2BFfrsU4YjRosoYwjviQYZ4ybPUHNs2iTG7sijbt +8uaZFURww3y8nDnAtOFr94MlI1fZEoDlSfB1D++N6xybVCi0ITz8fAr/73trdf+L +HaAZBav6+CuBQug4urv7qv094PPK306Xlynt8xhW6aWWrL3DkJiy4Pmi1KZHQ3xt +zwIDAQABo0IwQDAdBgNVHQ4EFgQUVnNYZJX5khqwEioEYnmhQBWIIUkwDgYDVR0P +AQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAC9c +mTz8Bl6MlC5w6tIyMY208FHVvArzZJ8HXtXBc2hkeqK5Duj5XYUtqDdFqij0lgVQ +YKlJfp/imTYpE0RHap1VIDzYm/EDMrraQKFz6oOht0SmDpkBm+S8f74TlH7Kph52 +gDY9hAaLMyZlbcp+nv4fjFg4exqDsQ+8FxG75gbMY/qB8oFM2gsQa6H61SilzwZA +Fv97fRheORKkU55+MkIQpiGRqRxOF3yEvJ+M0ejf5lG5Nkc/kLnHvALcWxxPDkjB +JYOcCj+esQMzEhonrPcibCTRAUH4WAP+JWgiH5paPHxsnnVI84HxZmduTILA7rpX +DhjvLpr3Etiga+kFpaHpaPi8TD8SHkXoUsCjvxInebnMMTzD9joiFgOgyY9mpFui +TdaBJQbpdqQACj7LzTWb4OE4y2BThihCQRxEV+ioratF4yUQvNs+ZUH7G6aXD+u5 +dHn5HrwdVw1Hr8Mvn4dGp+smWg9WY7ViYG4A++MnESLn/pmPNPW56MORcr3Ywx65 +LvKRRFHQV80MNNVIIb/bE/FmJUNS0nAiNs2fxBx1IK1jcmMGDw4nztJqDby1ORrp +0XZ60Vzk50lJLVU3aPAaOpg+VBeHVOmmJ1CJeyAvP/+/oYtKR5j/K3tJPsMpRmAY +QqszKbrAKbkTidOIijlBO8n9pu0f9GBj39ItVQGL +-----END CERTIFICATE----- diff --git a/make/data/currency/CurrencyData.properties b/make/data/currency/CurrencyData.properties index 550662ec38a..cc845e398f1 100644 --- a/make/data/currency/CurrencyData.properties +++ b/make/data/currency/CurrencyData.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,7 @@ formatVersion=3 # Version of the currency code information in this class. # It is a serial number that accompanies with each amendment. -dataVersion=177 +dataVersion=179 # List of all valid ISO 4217 currency codes. # To ensure compatibility, do not remove codes. @@ -54,7 +54,7 @@ all=ADP020-AED784-AFA004-AFN971-ALL008-AMD051-ANG532-AOA973-ARS032-ATS040-AUD036 SBD090-SCR690-SDD736-SDG938-SEK752-SGD702-SHP654-SIT705-SKK703-SLE925-SLL694-SOS706-\ SRD968-SRG740-SSP728-STD678-STN930-SVC222-SYP760-SZL748-THB764-TJS972-TMM795-TMT934-TND788-TOP776-\ TPE626-TRL792-TRY949-TTD780-TWD901-TZS834-UAH980-UGX800-USD840-USN997-USS998-UYI940-\ - UYU858-UZS860-VEB862-VED926-VEF937-VES928-VND704-VUV548-WST882-XAF950-XAG961-XAU959-XBA955-\ + UYU858-UZS860-VEB862-VED926-VEF937-VES928-VND704-VUV548-WST882-XAD396-XAF950-XAG961-XAU959-XBA955-\ XBB956-XBC957-XBD958-XCD951-XCG532-XDR960-XFO000-XFU000-XOF952-XPD964-XPF953-\ XPT962-XSU994-XTS963-XUA965-XXX999-YER886-YUM891-ZAR710-ZMK894-ZMW967-ZWD716-ZWG924-\ ZWL932-ZWN942-ZWR935 diff --git a/make/data/tzdata/VERSION b/make/data/tzdata/VERSION index 9c056fac345..4bd54efbcdc 100644 --- a/make/data/tzdata/VERSION +++ b/make/data/tzdata/VERSION @@ -21,4 +21,4 @@ # or visit www.oracle.com if you need additional information or have any # questions. # -tzdata2025a +tzdata2025b diff --git a/make/data/tzdata/asia b/make/data/tzdata/asia index b0a6fa01d20..55b13134f9c 100644 --- a/make/data/tzdata/asia +++ b/make/data/tzdata/asia @@ -1523,6 +1523,16 @@ Zone Asia/Jayapura 9:22:48 - LMT 1932 Nov # (UIT No. 143 17.XI.1977) and not 23 September (UIT No. 141 13.IX.1977). # UIT is the Operational Bulletin of International Telecommunication Union. +# From Roozbeh Pournader (2025-03-18): +# ... the exact time of Iran's transition from +0400 to +0330 ... was Friday +# 1357/8/19 AP=1978-11-10. Here's a newspaper clip from the Ettela'at +# newspaper, dated 1357/8/14 AP=1978-11-05, translated from Persian +# (at https://w.wiki/DUEY): +# Following the government's decision about returning the official time +# to the previous status, the spokesperson for the Ministry of Energy +# announced today: At the hour 24 of Friday 19th of Aban (=1978-11-10), +# the country's time will be pulled back half an hour. +# # From Roozbeh Pournader (2003-03-15): # This is an English translation of what I just found (originally in Persian). # The Gregorian dates in brackets are mine: @@ -1650,7 +1660,7 @@ Rule Iran 2021 2022 - Sep 21 24:00 0 - Zone Asia/Tehran 3:25:44 - LMT 1916 3:25:44 - TMT 1935 Jun 13 # Tehran Mean Time 3:30 Iran %z 1977 Oct 20 24:00 - 4:00 Iran %z 1979 + 4:00 Iran %z 1978 Nov 10 24:00 3:30 Iran %z diff --git a/make/data/tzdata/northamerica b/make/data/tzdata/northamerica index 0a54e63becc..21f178ee8cb 100644 --- a/make/data/tzdata/northamerica +++ b/make/data/tzdata/northamerica @@ -1634,6 +1634,15 @@ Zone America/Moncton -4:19:08 - LMT 1883 Dec 9 # For more on Orillia, see: Daubs K. Bold attempt at daylight saving # time became a comic failure in Orillia. Toronto Star 2017-07-08. # https://www.thestar.com/news/insight/2017/07/08/bold-attempt-at-daylight-saving-time-became-a-comic-failure-in-orillia.html +# From Paul Eggert (2025-03-20): +# Also see the 1912-06-17 front page of The Evening Sunbeam, +# reproduced in: Richardson M. "Daylight saving was a confusing +# time in Orillia" in the 2025-03-15 Orillia Matters. Richardson writes, +# "The first Sunday after the switch was made, [DST proponent and +# Orillia mayor William Sword] Frost walked into church an hour late. +# This became a symbol of the downfall of daylight saving in Orillia." +# The mayor became known as "Daylight Bill". +# https://www.orilliamatters.com/local-news/column-daylight-saving-was-a-confusing-time-in-orillia-10377529 # From Mark Brader (2010-03-06): # diff --git a/make/data/tzdata/southamerica b/make/data/tzdata/southamerica index 0a5859600e8..06fee598baf 100644 --- a/make/data/tzdata/southamerica +++ b/make/data/tzdata/southamerica @@ -1,26 +1,3 @@ -# -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# # tzdb data for South America and environs # This file is in the public domain, so clarified as of @@ -1269,35 +1246,45 @@ Zone America/Rio_Branco -4:31:12 - LMT 1914 # dates to 2014. # DST End: last Saturday of April 2014 (Sun 27 Apr 2014 03:00 UTC) # DST Start: first Saturday of September 2014 (Sun 07 Sep 2014 04:00 UTC) -# http://www.diariooficial.interior.gob.cl//media/2014/02/19/do-20140219.pdf +# From Tim Parenti (2025-03-22): +# Decreto 307 of 2014 of the Ministry of the Interior and Public Security, +# promulgated 2014-01-30 and published 2014-02-19: +# https://www.diariooficial.interior.gob.cl/media/2014/02/19/do-20140219.pdf#page=1 +# https://www.bcn.cl/leychile/navegar?idNorma=1059557 # From Eduardo Romero Urra (2015-03-03): # Today has been published officially that Chile will use the DST time # permanently until March 25 of 2017 -# http://www.diariooficial.interior.gob.cl/media/2015/03/03/1-large.jpg -# -# From Paul Eggert (2015-03-03): -# For now, assume that the extension will persist indefinitely. +# From Tim Parenti (2025-03-22): +# Decreto 106 of 2015 of the Ministry of the Interior and Public Security, +# promulgated 2015-01-27 and published 2015-03-03: +# https://www.diariooficial.interior.gob.cl/media/2015/03/03/do-20150303.pdf#page=1 +# https://www.bcn.cl/leychile/navegar?idNorma=1075157 # From Juan Correa (2016-03-18): -# The decree regarding DST has been published in today's Official Gazette: -# http://www.diariooficial.interior.gob.cl/versiones-anteriores/do/20160318/ -# http://www.leychile.cl/Navegar?idNorma=1088502 +# The decree regarding DST has been published in today's Official Gazette... # It does consider the second Saturday of May and August as the dates # for the transition; and it lists DST dates until 2019, but I think # this scheme will stick. -# # From Paul Eggert (2016-03-18): -# For now, assume the pattern holds for the indefinite future. # The decree says transitions occur at 24:00; in practice this appears # to mean 24:00 mainland time, not 24:00 local time, so that Easter # Island is always two hours behind the mainland. +# From Tim Parenti (2025-03-22): +# Decreto 253 of 2016 of the Ministry of the Interior and Public Security, +# promulgated 2016-03-16 and published 2016-03-18. +# https://www.diariooficial.interior.gob.cl/media/2016/03/18/do-20160318.pdf#page=1 +# https://www.bcn.cl/leychile/navegar?idNorma=1088502 # From Juan Correa (2016-12-04): # Magallanes region ... will keep DST (UTC -3) all year round.... # http://www.soychile.cl/Santiago/Sociedad/2016/12/04/433428/Bachelet-firmo-el-decreto-para-establecer-un-horario-unico-para-la-Region-de-Magallanes.aspx -# From Deborah Goldsmith (2017-01-19): -# http://www.diariooficial.interior.gob.cl/publicaciones/2017/01/17/41660/01/1169626.pdf +# From Tim Parenti (2025-03-22), via Deborah Goldsmith (2017-01-19): +# Decreto 1820 of 2016 of the Ministry of the Interior and Public Security, +# promulgated 2016-12-02 and published 2017-01-17: +# https://www.diariooficial.interior.gob.cl/publicaciones/2017/01/17/41660/01/1169626.pdf +# https://www.bcn.cl/leychile/Navegar?idNorma=1099217 +# Model this as a change to standard offset effective 2016-12-04. # From Juan Correa (2018-08-13): # As of moments ago, the Ministry of Energy in Chile has announced the new @@ -1316,13 +1303,20 @@ Zone America/Rio_Branco -4:31:12 - LMT 1914 # https://twitter.com/MinEnergia/status/1029009354001973248 # "We will keep the new time policy unchanged for at least the next 4 years." # So we extend the new rules on Saturdays at 24:00 mainland time indefinitely. -# From Juan Correa (2019-02-04): -# http://www.diariooficial.interior.gob.cl/publicaciones/2018/11/23/42212/01/1498738.pdf +# From Tim Parenti (2025-03-22), via Juan Correa (2019-02-04): +# Decreto 1286 of 2018 of the Ministry of the Interior and Public Security, +# promulgated 2018-09-21 and published 2018-11-23: +# https://www.diariooficial.interior.gob.cl/publicaciones/2018/11/23/42212/01/1498738.pdf +# https://www.bcn.cl/leychile/Navegar?idNorma=1125760 # From Juan Correa (2022-04-02): # I found there was a decree published last Thursday that will keep -# Magallanes region to UTC -3 "indefinitely". The decree is available at +# Magallanes region to UTC -3 "indefinitely". +# From Tim Parenti (2025-03-22): +# Decreto 143 of 2022 of the Ministry of the Interior and Public Security, +# promulgated 2022-03-29 and published 2022-03-31: # https://www.diariooficial.interior.gob.cl/publicaciones/2022/03/31/43217-B/01/2108910.pdf +# https://www.bcn.cl/leychile/Navegar?idNorma=1174342 # From Juan Correa (2022-08-09): # the Internal Affairs Ministry (Ministerio del Interior) informed DST @@ -1331,13 +1325,36 @@ Zone America/Rio_Branco -4:31:12 - LMT 1914 # will keep UTC -3 "indefinitely"... This is because on September 4th # we will have a voting whether to approve a new Constitution. # -# From Eduardo Romero Urra (2022-08-17): +# From Tim Parenti (2025-03-22), via Eduardo Romero Urra (2022-08-17): +# Decreto 224 of 2022 of the Ministry of the Interior and Public Security, +# promulgated 2022-07-14 and published 2022-08-13: # https://www.diariooficial.interior.gob.cl/publicaciones/2022/08/13/43327/01/2172567.pdf +# https://www.bcn.cl/leychile/navegar?idNorma=1179983 # # From Paul Eggert (2022-08-17): # Although the presidential decree stops at fall 2026, assume that # similar DST rules will continue thereafter. +# From Paul Eggert (2025-01-15): +# Diario Regional Aysén's Sebastián Martel reports that 94% of Aysén +# citizens polled in November favored changing the rules from +# -04/-03-with-DST to -03 all year... +# https://www.diarioregionalaysen.cl/noticia/actualidad/2024/12/presentan-decision-que-gano-la-votacion-sobre-el-cambio-del-huso-horario-en-aysen +# +# From Yonathan Dossow (2025-03-20): +# [T]oday we have more confirmation of the change. [Aysén] region will keep +# UTC-3 all year... +# https://www.cnnchile.com/pais/region-de-aysen-mantendra-horario-de-verano-todo-el-ano_20250320/ +# https://www.latercera.com/nacional/noticia/tras-consulta-ciudadana-region-de-aysen-mantendra-el-horario-de-verano-durante-todo-el-ano/ +# https://x.com/min_interior/status/1902692504270672098 +# +# From Tim Parenti (2025-03-22), via Eduardo Romero Urra (2025-03-20): +# Decreto 93 of 2025 of the Ministry of the Interior and Public Security, +# promulgated 2025-03-11 and published 2025-03-20: +# https://www.diariooficial.interior.gob.cl/publicaciones/2025/03/20/44104/01/2624263.pdf +# https://www.bcn.cl/leychile/Navegar?idNorma=1211955 +# Model this as a change to standard offset effective 2025-03-20. + # Rule NAME FROM TO - IN ON AT SAVE LETTER/S Rule Chile 1927 1931 - Sep 1 0:00 1:00 - Rule Chile 1928 1932 - Apr 1 0:00 0 - @@ -1394,6 +1411,20 @@ Zone America/Santiago -4:42:45 - LMT 1890 -5:00 1:00 %z 1947 Mar 31 24:00 -5:00 - %z 1947 May 21 23:00 -4:00 Chile %z +Zone America/Coyhaique -4:48:16 - LMT 1890 + -4:42:45 - SMT 1910 Jan 10 + -5:00 - %z 1916 Jul 1 + -4:42:45 - SMT 1918 Sep 10 + -4:00 - %z 1919 Jul 1 + -4:42:45 - SMT 1927 Sep 1 + -5:00 Chile %z 1932 Sep 1 + -4:00 - %z 1942 Jun 1 + -5:00 - %z 1942 Aug 1 + -4:00 - %z 1946 Aug 28 24:00 + -5:00 1:00 %z 1947 Mar 31 24:00 + -5:00 - %z 1947 May 21 23:00 + -4:00 Chile %z 2025 Mar 20 + -3:00 - %z Zone America/Punta_Arenas -4:43:40 - LMT 1890 -4:42:45 - SMT 1910 Jan 10 -5:00 - %z 1916 Jul 1 diff --git a/make/data/tzdata/zone.tab b/make/data/tzdata/zone.tab index e7a4868c39d..c8fc601041b 100644 --- a/make/data/tzdata/zone.tab +++ b/make/data/tzdata/zone.tab @@ -162,7 +162,8 @@ CH +4723+00832 Europe/Zurich CI +0519-00402 Africa/Abidjan CK -2114-15946 Pacific/Rarotonga CL -3327-07040 America/Santiago most of Chile -CL -5309-07055 America/Punta_Arenas Region of Magallanes +CL -4534-07204 America/Coyhaique Aysen Region +CL -5309-07055 America/Punta_Arenas Magallanes Region CL -2709-10926 Pacific/Easter Easter Island CM +0403+00942 Africa/Douala CN +3114+12128 Asia/Shanghai Beijing Time diff --git a/make/lib/Awt2dLibraries.gmk b/make/lib/Awt2dLibraries.gmk index 55239f9296c..c0958bb9dbd 100644 --- a/make/lib/Awt2dLibraries.gmk +++ b/make/lib/Awt2dLibraries.gmk @@ -388,7 +388,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBLCMS, \ common/awt/debug \ libawt/java2d, \ HEADERS_FROM_SRC := $(LIBLCMS_HEADERS_FROM_SRC), \ - DISABLED_WARNINGS_gcc := format-nonliteral type-limits misleading-indentation stringop-truncation, \ + DISABLED_WARNINGS_gcc := format-nonliteral misleading-indentation stringop-truncation, \ DISABLED_WARNINGS_clang := tautological-compare, \ DISABLED_WARNINGS_solstudio := E_STATEMENT_NOT_REACHED, \ DISABLED_WARNINGS_microsoft := 4819, \ @@ -887,9 +887,10 @@ ifeq ($(ENABLE_HEADLESS_ONLY), false) $(GIFLIB_CFLAGS) $(LIBJPEG_CFLAGS) $(PNG_CFLAGS) $(LIBZ_CFLAGS), \ EXTRA_HEADER_DIRS := $(LIBSPLASHSCREEN_HEADER_DIRS), \ DISABLED_WARNINGS_gcc := sign-compare type-limits unused-result \ - maybe-uninitialized shift-negative-value implicit-fallthrough, \ + maybe-uninitialized shift-negative-value implicit-fallthrough \ + unused-function, \ DISABLED_WARNINGS_clang := incompatible-pointer-types deprecated-declarations \ - $(LIBZ_DISABLED_WARNINGS_CLANG), \ + unused-function $(LIBZ_DISABLED_WARNINGS_CLANG), \ DISABLED_WARNINGS_solstudio := E_NEWLINE_NOT_LAST E_DECLARATION_IN_CODE \ E_STATEMENT_NOT_REACHED, \ DISABLED_WARNINGS_microsoft := 4018 4244 4267, \ diff --git a/src/hotspot/cpu/aarch64/frame_aarch64.cpp b/src/hotspot/cpu/aarch64/frame_aarch64.cpp index de369a1b6cd..e41a37b4798 100644 --- a/src/hotspot/cpu/aarch64/frame_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/frame_aarch64.cpp @@ -84,7 +84,7 @@ bool frame::safe_for_sender(JavaThread *thread) { // So unextended sp must be within the stack but we need not to check // that unextended sp >= sp - bool unextended_sp_safe = (unextended_sp < thread->stack_base()); + bool unextended_sp_safe = (unextended_sp < thread->stack_base() && unextended_sp >= thread->stack_end()); if (!unextended_sp_safe) { return false; diff --git a/src/hotspot/share/asm/codeBuffer.cpp b/src/hotspot/share/asm/codeBuffer.cpp index 65b414a38ce..1f6718d3e30 100644 --- a/src/hotspot/share/asm/codeBuffer.cpp +++ b/src/hotspot/share/asm/codeBuffer.cpp @@ -1100,7 +1100,7 @@ CodeString* CodeStrings::find(intptr_t offset) const { // Convenience for add_comment. CodeString* CodeStrings::find_last(intptr_t offset) const { CodeString* a = _strings_last; - while (a != NULL && !a->is_comment() && a->offset() > offset) { + while (a != NULL && !(a->is_comment() && a->offset() == offset)) { a = a->_prev; } return a; diff --git a/src/java.base/share/classes/sun/net/ftp/impl/FtpClient.java b/src/java.base/share/classes/sun/net/ftp/impl/FtpClient.java index 5262541c1af..021cbd56729 100644 --- a/src/java.base/share/classes/sun/net/ftp/impl/FtpClient.java +++ b/src/java.base/share/classes/sun/net/ftp/impl/FtpClient.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,6 @@ */ package sun.net.ftp.impl; - import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; @@ -62,6 +61,7 @@ import java.util.regex.Pattern; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; + import sun.net.ftp.FtpDirEntry; import sun.net.ftp.FtpDirParser; import sun.net.ftp.FtpProtocolException; @@ -69,6 +69,7 @@ import sun.net.util.IPAddressUtil; import sun.util.logging.PlatformLogger; +import static sun.net.util.ProxyUtil.copyProxy; public class FtpClient extends sun.net.ftp.FtpClient { @@ -996,7 +997,7 @@ public int getReadTimeout() { } public sun.net.ftp.FtpClient setProxy(Proxy p) { - proxy = p; + proxy = copyProxy(p); return this; } diff --git a/src/java.base/share/classes/sun/net/util/ProxyUtil.java b/src/java.base/share/classes/sun/net/util/ProxyUtil.java new file mode 100644 index 00000000000..dfb60671e37 --- /dev/null +++ b/src/java.base/share/classes/sun/net/util/ProxyUtil.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.net.util; + +import sun.net.ApplicationProxy; + +import java.net.Proxy; + +public final class ProxyUtil { + + private ProxyUtil() {} + + /** + * Creates a new {@link Proxy} instance for the given proxy iff it is + * neither null, {@link Proxy#NO_PROXY Proxy.NO_PROXY}, an + * {@link ApplicationProxy} instance, nor already a {@code Proxy} instance. + */ + public static Proxy copyProxy(Proxy proxy) { + return proxy == null + || proxy.getClass() == Proxy.class + || proxy instanceof ApplicationProxy + ? proxy + : new Proxy(proxy.type(), proxy.address()); + } + +} diff --git a/src/java.base/share/classes/sun/net/www/http/HttpClient.java b/src/java.base/share/classes/sun/net/www/http/HttpClient.java index 3d0deb319cd..e10955276cb 100644 --- a/src/java.base/share/classes/sun/net/www/http/HttpClient.java +++ b/src/java.base/share/classes/sun/net/www/http/HttpClient.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,6 +40,8 @@ import sun.net.www.protocol.http.AuthenticatorKeys; import sun.net.www.protocol.http.HttpURLConnection; import sun.util.logging.PlatformLogger; + +import static sun.net.util.ProxyUtil.copyProxy; import static sun.net.www.protocol.http.HttpURLConnection.TunnelState.*; import sun.security.action.GetPropertyAction; @@ -264,7 +266,7 @@ public HttpClient(URL url, String proxyHost, int proxyPort) } protected HttpClient(URL url, Proxy p, int to) throws IOException { - proxy = (p == null) ? Proxy.NO_PROXY : p; + proxy = p == null ? Proxy.NO_PROXY : copyProxy(p); this.host = url.getHost(); this.url = url; port = url.getPort(); @@ -329,9 +331,7 @@ public static HttpClient New(URL url, boolean useCache) public static HttpClient New(URL url, Proxy p, int to, boolean useCache, HttpURLConnection httpuc) throws IOException { - if (p == null) { - p = Proxy.NO_PROXY; - } + p = p == null ? Proxy.NO_PROXY : copyProxy(p); HttpClient ret = null; /* see if one's already around */ if (useCache) { diff --git a/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java b/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java index fccf99b337b..6f77b4e95f5 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java +++ b/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,6 +48,7 @@ import java.util.Iterator; import java.security.Permission; import java.util.Properties; + import sun.net.NetworkClient; import sun.net.util.IPAddressUtil; import sun.net.www.MessageHeader; @@ -61,6 +62,7 @@ import sun.net.www.ParseUtil; import sun.security.action.GetPropertyAction; +import static sun.net.util.ProxyUtil.copyProxy; /** * This class Opens an FTP input (or output) stream given a URL. @@ -244,7 +246,7 @@ public ProxySelector run() { URI uri = sun.net.www.ParseUtil.toURI(url); Iterator it = sel.select(uri).iterator(); while (it.hasNext()) { - p = it.next(); + p = copyProxy(it.next()); if (p == null || p == Proxy.NO_PROXY || p.type() == Proxy.Type.SOCKS) { break; diff --git a/src/java.base/share/classes/sun/net/www/protocol/ftp/Handler.java b/src/java.base/share/classes/sun/net/www/protocol/ftp/Handler.java index f5caad651e5..41f4344aa7b 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/ftp/Handler.java +++ b/src/java.base/share/classes/sun/net/www/protocol/ftp/Handler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,10 +32,7 @@ import java.io.IOException; import java.net.URL; import java.net.Proxy; -import java.util.Map; -import java.util.HashMap; -import sun.net.ftp.FtpClient; -import sun.net.www.protocol.http.HttpURLConnection; +import static sun.net.util.ProxyUtil.copyProxy; /** open an ftp connection given a URL */ public class Handler extends java.net.URLStreamHandler { @@ -56,8 +53,8 @@ protected java.net.URLConnection openConnection(URL u) return openConnection(u, null); } - protected java.net.URLConnection openConnection(URL u, Proxy p) + protected java.net.URLConnection openConnection(URL u, Proxy proxy) throws IOException { - return new FtpURLConnection(u, p); + return new FtpURLConnection(u, copyProxy(proxy)); } } diff --git a/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java b/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java index 8fe24820d7f..f4eb1092fc9 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java +++ b/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -81,6 +81,8 @@ import java.nio.ByteBuffer; import java.util.Objects; import java.util.Properties; + +import static sun.net.util.ProxyUtil.copyProxy; import static sun.net.www.protocol.http.AuthScheme.BASIC; import static sun.net.www.protocol.http.AuthScheme.DIGEST; import static sun.net.www.protocol.http.AuthScheme.NTLM; @@ -898,7 +900,7 @@ protected HttpURLConnection(URL u, Proxy p, Handler handler) responses = new MessageHeader(maxHeaderSize); userHeaders = new MessageHeader(); this.handler = handler; - instProxy = p; + instProxy = copyProxy(p); if (instProxy instanceof sun.net.ApplicationProxy) { /* Application set Proxies should not have access to cookies * in a secure environment unless explicitly allowed. */ @@ -1196,7 +1198,7 @@ public ProxySelector run() { Iterator it = sel.select(uri).iterator(); Proxy p; while (it.hasNext()) { - p = it.next(); + p = copyProxy(it.next()); try { if (!failedOnce) { http = getNewHttpClient(url, p, connectTimeout); diff --git a/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java b/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java index 4d19043ac69..49f6a095c97 100644 --- a/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java +++ b/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1166,6 +1166,15 @@ public void consume(ConnectionContext context, // clean up this consumer hc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE.id); + + // Ensure that the Certificate message has not been sent w/o + // an EncryptedExtensions preceding + if (hc.handshakeConsumers.containsKey( + SSLHandshake.ENCRYPTED_EXTENSIONS.id)) { + throw hc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, + "Unexpected Certificate handshake message"); + } + T13CertificateMessage cm = new T13CertificateMessage(hc, message); if (hc.sslConfig.isClientMode) { if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { diff --git a/src/java.base/share/classes/sun/security/ssl/CertificateVerify.java b/src/java.base/share/classes/sun/security/ssl/CertificateVerify.java index 4e6e613d337..e708c0e51e0 100644 --- a/src/java.base/share/classes/sun/security/ssl/CertificateVerify.java +++ b/src/java.base/share/classes/sun/security/ssl/CertificateVerify.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1157,6 +1157,14 @@ public void consume(ConnectionContext context, // Clean up this consumer hc.handshakeConsumers.remove(SSLHandshake.CERTIFICATE_VERIFY.id); + // Ensure that the Certificate Verify message has not been sent w/o + // a Certificate message preceding + if (hc.handshakeConsumers.containsKey( + SSLHandshake.CERTIFICATE.id)) { + throw hc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, + "Unexpected Certificate Verify handshake message"); + } + T13CertificateVerifyMessage cvm = new T13CertificateVerifyMessage(hc, message); if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { diff --git a/src/java.base/share/classes/sun/security/ssl/Finished.java b/src/java.base/share/classes/sun/security/ssl/Finished.java index 626fbd5c13b..58dc461cc4b 100644 --- a/src/java.base/share/classes/sun/security/ssl/Finished.java +++ b/src/java.base/share/classes/sun/security/ssl/Finished.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -881,6 +881,14 @@ public void consume(ConnectionContext context, private void onConsumeFinished(ClientHandshakeContext chc, ByteBuffer message) throws IOException { + // Ensure that the Finished message has not been sent w/o + // an EncryptedExtensions preceding + if (chc.handshakeConsumers.containsKey( + SSLHandshake.ENCRYPTED_EXTENSIONS.id)) { + throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, + "Unexpected Finished handshake message"); + } + // Make sure that any expected CertificateVerify message // has been received and processed. if (!chc.isResumption) { diff --git a/src/java.base/share/classes/sun/security/validator/CamerfirmaTLSPolicy.java b/src/java.base/share/classes/sun/security/validator/CamerfirmaTLSPolicy.java index 266293d77b9..1d2f88f50ca 100644 --- a/src/java.base/share/classes/sun/security/validator/CamerfirmaTLSPolicy.java +++ b/src/java.base/share/classes/sun/security/validator/CamerfirmaTLSPolicy.java @@ -43,26 +43,14 @@ final class CamerfirmaTLSPolicy { private static final Debug debug = Debug.getInstance("certpath"); - // SHA-256 certificate fingerprints of distrusted roots - private static final Set FINGERPRINTS = Set.of( - // cacerts alias: camerfirmachamberscommerceca - // DN: CN=Chambers of Commerce Root, - // OU=http://www.chambersign.org, - // O=AC Camerfirma SA CIF A82743287, C=EU - "0C258A12A5674AEF25F28BA7DCFAECEEA348E541E6F5CC4EE63B71B361606AC3", - // cacerts alias: camerfirmachambersca - // DN: CN=Chambers of Commerce Root - 2008, - // O=AC Camerfirma S.A., SERIALNUMBER=A82743287, - // L=Madrid (see current address at www.camerfirma.com/address), - // C=EU - "063E4AFAC491DFD332F3089B8542E94617D893D7FE944E10A7937EE29D9693C0", - // cacerts alias: camerfirmachambersignca - // DN: CN=Global Chambersign Root - 2008, - // O=AC Camerfirma S.A., SERIALNUMBER=A82743287, - // L=Madrid (see current address at www.camerfirma.com/address), - // C=EU - "136335439334A7698016A0D324DE72284E079D7B5220BB8FBD747816EEBEBACA" - ); + // SHA-256 certificate fingerprint of distrusted root for TLS + // cacerts alias: camerfirmachambersca + // DN: CN=Chambers of Commerce Root - 2008, + // O=AC Camerfirma S.A., SERIALNUMBER=A82743287, + // L=Madrid (see current address at www.camerfirma.com/address), + // C=EU + private static final String FINGERPRINT = + "063E4AFAC491DFD332F3089B8542E94617D893D7FE944E10A7937EE29D9693C0"; // Any TLS Server certificate that is anchored by one of the Camerfirma // roots above and is issued after this date will be distrusted. @@ -85,7 +73,7 @@ static void checkDistrust(X509Certificate[] chain) throw new ValidatorException("Cannot generate fingerprint for " + "trust anchor of TLS server certificate"); } - if (FINGERPRINTS.contains(fp)) { + if (FINGERPRINT.equalsIgnoreCase(fp)) { Date notBefore = chain[0].getNotBefore(); LocalDate ldNotBefore = LocalDate.ofInstant(notBefore.toInstant(), ZoneOffset.UTC); diff --git a/src/java.base/share/classes/sun/util/resources/CurrencyNames.properties b/src/java.base/share/classes/sun/util/resources/CurrencyNames.properties index 3ed4f873a3c..e543398fac1 100644 --- a/src/java.base/share/classes/sun/util/resources/CurrencyNames.properties +++ b/src/java.base/share/classes/sun/util/resources/CurrencyNames.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -258,6 +258,7 @@ VES=VES VND=VND VUV=VUV WST=WST +XAD=XAD XAF=XAF XAG=XAG XAU=XAU @@ -485,6 +486,7 @@ ves=Venezuelan Bol\u00edvar Soberano vnd=Vietnamese Dong vuv=Vanuatu Vatu wst=Samoan Tala +xad=Arab Accounting Dinar xaf=CFA Franc BEAC xag=Silver xau=Gold diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java index 066fc16d6ab..40ed436304f 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -404,7 +404,11 @@ protected void installListeners() { } tabPane.addContainerListener(getHandler()); if (tabPane.getTabCount() > 0) { - htmlViews = createHTMLVector(); + Boolean htmlDisabled = (Boolean) + tabPane.getClientProperty("html.disable"); + if (!(Boolean.TRUE.equals(htmlDisabled))) { + htmlViews = createHTMLVector(); + } } } @@ -3443,8 +3447,10 @@ public void componentAdded(final ContainerEvent e) { private void updateHtmlViews(int index, boolean inserted) { final String title = tabPane.getTitleAt(index); + Boolean htmlDisabled = (Boolean) + tabPane.getClientProperty("html.disable"); final boolean isHTML = BasicHTML.isHTMLString(title); - if (isHTML) { + if (isHTML && !(Boolean.TRUE.equals(htmlDisabled))) { if (htmlViews == null) { // Initialize vector htmlViews = createHTMLVector(); } else { // Vector already exists diff --git a/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m b/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m index 2c991a2fc2f..a35d5401474 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m @@ -151,7 +151,7 @@ + (AWTStrike *) awtStrikeForFont:(AWTFont *)awtFont // to indicate we should use CoreText to substitute the character CGGlyph glyph; const CTFontRef fallback = CTS_CopyCTFallbackFontAndGlyphForJavaGlyphCode(awtFont, glyphCode, &glyph); - CTFontGetAdvancesForGlyphs(fallback, kCTFontDefaultOrientation, &glyph, &advance, 1); + CGGlyphImages_GetGlyphMetrics(fallback, &awtStrike->fAltTx, awtStrike->fStyle, &glyph, 1, NULL, &advance); CFRelease(fallback); advance = CGSizeApplyAffineTransform(advance, awtStrike->fFontTx); if (!JRSFontStyleUsesFractionalMetrics(awtStrike->fStyle)) { @@ -188,7 +188,7 @@ + (AWTStrike *) awtStrikeForFont:(AWTFont *)awtFont const CTFontRef fallback = CTS_CopyCTFallbackFontAndGlyphForJavaGlyphCode(awtFont, glyphCode, &glyph); CGRect bbox; - JRSFontGetBoundingBoxesForGlyphsAndStyle(fallback, &tx, awtStrike->fStyle, &glyph, 1, &bbox); + CGGlyphImages_GetGlyphMetrics(fallback, &tx, awtStrike->fStyle, &glyph, 1, &bbox, NULL); CFRelease(fallback); // the origin of this bounding box is relative to the bottom-left corner baseline diff --git a/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.h b/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.h index 73cb604bcfc..736167d2af4 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.h @@ -33,5 +33,12 @@ void CGGlyphImages_GetGlyphImagePtrs(jlong glyphInfos[], const AWTStrike *strike, jint rawGlyphCodes[], const CFIndex len); - +void +CGGlyphImages_GetGlyphMetrics(const CTFontRef font, + const CGAffineTransform *tx, + const JRSFontRenderingStyle style, + const CGGlyph glyphs[], + size_t count, + CGRect bboxes[], + CGSize advances[]); #endif /* __CGGLYPHIMAGES_H */ diff --git a/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.m b/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.m index d8deec3b283..d15fcb67c42 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.m @@ -237,6 +237,7 @@ @implementation CGGI_GlyphCanvas { UInt32 *src = (UInt32 *)canvas->image->data; size_t srcRowWidth = canvas->image->width; + size_t srcHeight = canvas->image->height; UInt8 *dest = (UInt8 *)info->image; size_t destRowWidth = info->width; @@ -246,12 +247,12 @@ @implementation CGGI_GlyphCanvas size_t y; // fill empty glyph image with black-on-white glyph - for (y = 0; y < height; y++) { + for (y = 0; y < height && y < srcHeight; y++) { size_t destRow = y * destRowWidth * 3; size_t srcRow = y * srcRowWidth; size_t x; - for (x = 0; x < destRowWidth; x++) { + for (x = 0; x < destRowWidth && x < srcRowWidth; x++) { CGGI_CopyARGBPixelToRGBPixel(src[srcRow + x], dest + destRow + x * 3); } @@ -289,6 +290,7 @@ @implementation CGGI_GlyphCanvas { UInt32 *src = (UInt32 *)canvas->image->data; size_t srcRowWidth = canvas->image->width; + size_t srcHeight = canvas->image->height; UInt8 *dest = (UInt8 *)info->image; size_t destRowWidth = info->width; @@ -298,11 +300,11 @@ @implementation CGGI_GlyphCanvas size_t y; // fill empty glyph image with black-on-white glyph - for (y = 0; y < height; y++) { + for (y = 0; y < height && y < srcHeight; y++) { size_t destRow = y * destRowWidth; size_t srcRow = y * srcRowWidth; size_t x; - for (x = 0; x < destRowWidth; x++) { + for (x = 0; x < destRowWidth && x < srcRowWidth; x++) { UInt32 p = src[srcRow + x]; dest[destRow + x] = CGGI_ConvertBWPixelToByteGray(p); } @@ -384,8 +386,10 @@ @implementation CGGI_GlyphCanvas canvas->image->data = (void *)calloc(byteCount, sizeof(UInt8)); if (canvas->image->data == NULL) { - [[NSException exceptionWithName:NSMallocException - reason:@"Failed to allocate memory for the buffer which backs the CGContext for glyph strikes." userInfo:nil] raise]; + canvas->image->width = 0; + canvas->image->height = 0; + canvas->image->rowBytes = 0; + canvas->image->data = malloc(0); } uint32_t bmpInfo = kCGImageAlphaPremultipliedFirst; @@ -435,6 +439,10 @@ @implementation CGGI_GlyphCanvas /* * Quick and easy inline to check if this canvas is big enough. + * This function only increases the size. To get a smaller canvas, free it first. + * This function adds padding / slack multiplier to the requested size. + * So resizes must be based on the size you need, not the size of the canvas. + * The function will internally account for the multiplier it uses. */ static inline void CGGI_SizeCanvas(CGGI_GlyphCanvas *canvas, const vImagePixelCount width, @@ -442,18 +450,31 @@ @implementation CGGI_GlyphCanvas const CGGI_RenderingMode* mode) { if (canvas->image != NULL && - width < canvas->image->width && - height < canvas->image->height) + width * CGGI_GLYPH_CANVAS_SLACK <= canvas->image->width && + height * CGGI_GLYPH_CANVAS_SLACK <= canvas->image->height) { return; } + vImagePixelCount w = width * CGGI_GLYPH_CANVAS_SLACK; + vImagePixelCount h = height * CGGI_GLYPH_CANVAS_SLACK; + + // Do not allow the canvas to be resized smaller. + if (canvas->image != NULL) { + if (w < canvas->image->width) { + w = canvas->image->width; + } + if (h < canvas->image->height) { + h = canvas->image->height; + } + } + // if we don't have enough space to strike the largest glyph in the // run, resize the canvas CGGI_FreeCanvas(canvas); CGGI_InitCanvas(canvas, - width * CGGI_GLYPH_CANVAS_SLACK, - height * CGGI_GLYPH_CANVAS_SLACK, + w, + h, mode); JRSFontSetRenderingStyleOnContext(canvas->context, mode->cgFontMode); } @@ -469,6 +490,12 @@ @implementation CGGI_GlyphCanvas canvasRectToClear.data = canvas->image->data; canvasRectToClear.height = info->height; canvasRectToClear.width = info->width; + if (canvas->image->width < canvasRectToClear.width) { + canvasRectToClear.width = canvas->image->width; + } + if (canvas->image->height < canvasRectToClear.height) { + canvasRectToClear.height = canvas->image->height; + } // use the row stride of the canvas, not the info canvasRectToClear.rowBytes = canvas->image->rowBytes; @@ -615,10 +642,8 @@ @implementation CGGI_GlyphCanvas JRSFontRenderingStyle style = JRSFontAlignStyleForFractionalMeasurement(strike->fStyle); CGRect bbox; - JRSFontGetBoundingBoxesForGlyphsAndStyle(fallback, &tx, style, &glyph, 1, &bbox); - CGSize advance; - CTFontGetAdvancesForGlyphs(fallback, kCTFontDefaultOrientation, &glyph, &advance, 1); + CGGlyphImages_GetGlyphMetrics(fallback, &tx, style, &glyph, 1, &bbox, &advance); // create the Sun2D GlyphInfo we are going to strike into GlyphInfo *info = CGGI_CreateNewGlyphInfoFrom(advance, bbox, strike, mode); @@ -774,8 +799,8 @@ @implementation CGGI_GlyphCanvas CGAffineTransform tx = strike->fTx; JRSFontRenderingStyle bboxCGMode = JRSFontAlignStyleForFractionalMeasurement(strike->fStyle); - JRSFontGetBoundingBoxesForGlyphsAndStyle((CTFontRef)font->fFont, &tx, bboxCGMode, glyphs, len, bboxes); - CTFontGetAdvancesForGlyphs((CTFontRef)font->fFont, kCTFontDefaultOrientation, glyphs, advances, len); + CTFontRef fontRef = (CTFontRef)font->fFont; + CGGlyphImages_GetGlyphMetrics(fontRef, &tx, bboxCGMode, glyphs, len, bboxes, advances); size_t maxWidth = 1; size_t maxHeight = 1; @@ -793,7 +818,6 @@ @implementation CGGI_GlyphCanvas CGRect bbox = bboxes[i]; GlyphInfo *glyphInfo = CGGI_CreateNewGlyphInfoFrom(advance, bbox, strike, mode); - if (maxWidth < glyphInfo->width) maxWidth = glyphInfo->width; if (maxHeight < glyphInfo->height) maxHeight = glyphInfo->height; @@ -869,22 +893,68 @@ @implementation CGGI_GlyphCanvas return; } - // just do one malloc, and carve it up for all the buffers - void *buffer = malloc(sizeof(CGRect) * sizeof(CGSize) * - sizeof(CGGlyph) * sizeof(UnicodeScalarValue) * len); - if (buffer == NULL) { + CGRect *bboxes = (CGRect*)calloc(len, sizeof(CGRect)); + CGSize *advances = (CGSize*)calloc(len, sizeof(CGSize)); + CGGlyph *glyphs = (CGGlyph*)calloc(len, sizeof(CGGlyph)); + UnicodeScalarValue *uniChars = (UnicodeScalarValue*)calloc(len, sizeof(UnicodeScalarValue)); + + if (bboxes == NULL || advances == NULL || glyphs == NULL || uniChars == NULL) { + free(bboxes); + free(advances); + free(glyphs); + free(uniChars); [[NSException exceptionWithName:NSMallocException reason:@"Failed to allocate memory for the temporary glyph strike and measurement buffers." userInfo:nil] raise]; } - CGRect *bboxes = (CGRect *)(buffer); - CGSize *advances = (CGSize *)(bboxes + sizeof(CGRect) * len); - CGGlyph *glyphs = (CGGlyph *)(advances + sizeof(CGGlyph) * len); - UnicodeScalarValue *uniChars = (UnicodeScalarValue *)(glyphs + sizeof(UnicodeScalarValue) * len); - CGGI_CreateGlyphsAndScanForComplexities(glyphInfos, strike, &mode, rawGlyphCodes, uniChars, glyphs, advances, bboxes, len); - free(buffer); + free(bboxes); + free(advances); + free(glyphs); + free(uniChars); +} + +#define TX_FIXED_UNSAFE(v) (isinf(v) || isnan(v) || fabs(v) >= (1<<30)) + +/* + * Calculates bounding boxes (for given transform) and advance (for untransformed 1pt-size font) for specified glyphs. + */ +void +CGGlyphImages_GetGlyphMetrics(const CTFontRef font, + const CGAffineTransform *tx, + const JRSFontRenderingStyle style, + const CGGlyph glyphs[], + size_t count, + CGRect bboxes[], + CGSize advances[]) { + + if (TX_FIXED_UNSAFE(tx->a) || TX_FIXED_UNSAFE(tx->b) || TX_FIXED_UNSAFE(tx->c) || + TX_FIXED_UNSAFE(tx->d) || TX_FIXED_UNSAFE(tx->tx) || TX_FIXED_UNSAFE(tx->tx)) { + + if (bboxes) { + for (int i = 0; i < count; i++) { + bboxes[i].origin.x = 0; + bboxes[i].origin.y = 0; + bboxes[i].size.width = 0; + bboxes[i].size.height = 0; + } + } + if (advances) { + for (int i = 0; i < count; i++) { + advances[i].width = 0; + advances[i].height = 0; + } + } + return; + } + + if (bboxes) { + JRSFontGetBoundingBoxesForGlyphsAndStyle(font, tx, style, glyphs, count, bboxes); + } + if (advances) { + CTFontGetAdvancesForGlyphs(font, kCTFontDefaultOrientation, glyphs, advances, count); + } } diff --git a/src/java.desktop/share/classes/javax/swing/border/TitledBorder.java b/src/java.desktop/share/classes/javax/swing/border/TitledBorder.java index 79a766fa6e4..635a1cb0fe7 100644 --- a/src/java.desktop/share/classes/javax/swing/border/TitledBorder.java +++ b/src/java.desktop/share/classes/javax/swing/border/TitledBorder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -736,6 +736,11 @@ private Color getColor(Component c) { } private JLabel getLabel(Component c) { + if (c instanceof JComponent) { + JComponent comp = (JComponent)c; + this.label.putClientProperty("html.disable", + comp.getClientProperty("html.disable")); + } this.label.setText(getTitle()); this.label.setFont(getFont(c)); this.label.setForeground(getColor(c)); diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicOptionPaneUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicOptionPaneUI.java index b3a12edb5fb..593d6565812 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicOptionPaneUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicOptionPaneUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -482,6 +482,10 @@ public Dimension getPreferredSize() { } else { JLabel label; label = new JLabel( s, JLabel.LEADING ); + if (Boolean.TRUE.equals( + this.optionPane.getClientProperty("html.disable"))) { + label.putClientProperty("html.disable", true); + } label.setName("OptionPane.label"); configureMessageLabel(label); addMessageComponents(container, cons, label, maxll, true); diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java index fee26de92ed..4b7b98eb92a 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -451,7 +451,11 @@ protected void installListeners() { } tabPane.addContainerListener(getHandler()); if (tabPane.getTabCount()>0) { - htmlViews = createHTMLVector(); + Boolean htmlDisabled = (Boolean) + tabPane.getClientProperty("html.disable"); + if (!(Boolean.TRUE.equals(htmlDisabled))) { + htmlViews = createHTMLVector(); + } } } @@ -4017,8 +4021,10 @@ else if (name =="indexForTitle") { private void updateHtmlViews(int index, boolean inserted) { String title = tabPane.getTitleAt(index); + Boolean htmlDisabled = (Boolean) + tabPane.getClientProperty("html.disable"); boolean isHTML = BasicHTML.isHTMLString(title); - if (isHTML) { + if (isHTML && !(Boolean.TRUE.equals(htmlDisabled))) { if (htmlViews==null) { // Initialize vector htmlViews = createHTMLVector(); } else { // Vector already exists diff --git a/src/java.desktop/share/legal/freetype.md b/src/java.desktop/share/legal/freetype.md index 6bcb4976fd2..2c654e154ba 100644 --- a/src/java.desktop/share/legal/freetype.md +++ b/src/java.desktop/share/legal/freetype.md @@ -1,4 +1,4 @@ -## The FreeType Project: Freetype v2.13.2 +## The FreeType Project: Freetype v2.13.3 ### FreeType Notice @@ -21,23 +21,23 @@ which fits your needs best. ### FreeType License ``` -Copyright (C) 1996-2023 by David Turner, Robert Wilhelm, and Werner Lemberg. -Copyright (C) 2007-2023 by Dereg Clegg and Michael Toftdal. -Copyright (C) 1996-2023 by Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. -Copyright (C) 2022-2023 by David Turner, Robert Wilhelm, Werner Lemberg, George Williams, and -Copyright (C) 2004-2023 by Masatake YAMATO and Redhat K.K. -Copyright (C) 2007-2023 by Derek Clegg and Michael Toftdal. -Copyright (C) 2003-2023 by Masatake YAMATO, Red Hat K.K., -Copyright (C) 1996-2023 by David Turner, Robert Wilhelm, Werner Lemberg, and Dominik Röttsches. -Copyright (C) 2007-2023 by David Turner. -Copyright (C) 2022-2023 by David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti. -Copyright (C) 2007-2023 by Rahul Bhalerao , . -Copyright (C) 2008-2023 by David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya. -Copyright (C) 2013-2023 by Google, Inc. -Copyright (C) 2019-2023 by Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg. -Copyright (C) 2009-2023 by Oran Agra and Mickey Gabel. -Copyright (C) 2018-2023 by David Turner, Robert Wilhelm, Dominik Röttsches, and Werner Lemberg. -Copyright (C) 2004-2023 by David Turner, Robert Wilhelm, Werner Lemberg, and George Williams. +Copyright (C) 1996-2024 by David Turner, Robert Wilhelm, and Werner Lemberg. +Copyright (C) 2007-2024 by Dereg Clegg and Michael Toftdal. +Copyright (C) 1996-2024 by Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg. +Copyright (C) 2022-2024 by David Turner, Robert Wilhelm, Werner Lemberg, George Williams, and +Copyright (C) 2004-2024 by Masatake YAMATO and Redhat K.K. +Copyright (C) 2007-2024 by Derek Clegg and Michael Toftdal. +Copyright (C) 2003-2024 by Masatake YAMATO, Red Hat K.K., +Copyright (C) 1996-2024 by David Turner, Robert Wilhelm, Werner Lemberg, and Dominik Röttsches. +Copyright (C) 2007-2024 by David Turner. +Copyright (C) 2022-2024 by David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti. +Copyright (C) 2007-2024 by Rahul Bhalerao , . +Copyright (C) 2008-2024 by David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya. +Copyright (C) 2013-2024 by Google, Inc. +Copyright (C) 2019-2024 by Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg. +Copyright (C) 2009-2024 by Oran Agra and Mickey Gabel. +Copyright (C) 2018-2024 by David Turner, Robert Wilhelm, Dominik Röttsches, and Werner Lemberg. +Copyright (C) 2004-2024 by David Turner, Robert Wilhelm, Werner Lemberg, and George Williams. The FreeType Project LICENSE @@ -559,7 +559,7 @@ Public License instead of this License. ``` --------------------------------- -The below license applies to the following files: +The below applies to the following file(s): libfreetype/src/psaux/psarrst.c libfreetype/src/psaux/psarrst.h libfreetype/src/psaux/psblues.c @@ -582,7 +582,7 @@ libfreetype/src/psaux/psstack.c libfreetype/src/psaux/psstack.h libfreetype/src/psaux/pstypes.h -Copyright 2006-2014 Adobe Systems Incorporated. +Copyright (C) 2006-2014 Adobe Systems Incorporated. This software, and all works of authorship, whether in source or object code form as indicated by the copyright notice(s) included @@ -618,12 +618,12 @@ and you accept them fully. ``` --------------------------------- -The below license applies to the following files: +The below applies to the following file(s): libfreetype/include/freetype/internal/fthash.h libfreetype/src/base/fthash.c -Copyright 2000 Computing Research Labs, New Mexico State University -Copyright 2001-2015 +Copyright (C) 2000 Computing Research Labs, New Mexico State University +Copyright (C) 2001-2015 Francesco Zappa Nardelli diff --git a/src/java.desktop/share/legal/lcms.md b/src/java.desktop/share/legal/lcms.md index 02af4fff000..83c47d3acdb 100644 --- a/src/java.desktop/share/legal/lcms.md +++ b/src/java.desktop/share/legal/lcms.md @@ -1,11 +1,11 @@ -## Little Color Management System (LCMS) v2.16 +## Little Color Management System (LCMS) v2.17 ### LCMS License
 
 MIT License
 
-Copyright (C) 1998-2023 Marti Maria Saguer
+Copyright (C) 1998-2025 Marti Maria Saguer
 
 Permission is hereby granted, free of charge, to any person obtaining
 a copy of this software and associated documentation files (the "Software"),
@@ -26,10 +26,10 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 ---------------------------------
-The below license applies to the following files:
+The below applies to the following file(s):
 liblcms/cmssm.c
 
-Copyright 2001, softSurfer (www.softsurfer.com)
+Copyright (C) 2001, softSurfer (www.softsurfer.com)
 
 This code may be freely used and modified for any purpose
 providing that this copyright notice is included with it.
@@ -99,5 +99,5 @@ Christian Albrecht
 Dimitrios Anastassakis
 Lemke Software
 Tim Zaman
-
-```
+Amir Montazery and Open Source Technology Improvement Fund (ostif.org), Google, for fuzzer fundings.
+```
\ No newline at end of file
diff --git a/src/java.desktop/share/legal/libpng.md b/src/java.desktop/share/legal/libpng.md
index cbffed81332..d43ccf2e8e4 100644
--- a/src/java.desktop/share/legal/libpng.md
+++ b/src/java.desktop/share/legal/libpng.md
@@ -1,4 +1,4 @@
-## libpng v1.6.43
+## libpng v1.6.47
 
 ### libpng License
 
@@ -9,8 +9,8 @@ COPYRIGHT NOTICE, DISCLAIMER, and LICENSE
 PNG Reference Library License version 2
 ---------------------------------------
 
-Copyright (C) 1995-2024 The PNG Reference Library Authors.
-Copyright (C) 2018-2024 Cosmin Truta
+Copyright (c) 1995-2025 The PNG Reference Library Authors.
+Copyright (C) 2018-2025 Cosmin Truta
 Copyright (C) 1998-2018 Glenn Randers-Pehrson
 Copyright (C) 1996-1997 Andreas Dilger
 Copyright (C) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -170,6 +170,7 @@ Authors, for copyright and licensing purposes.
  * James Yu
  * John Bowler
  * Kevin Bracey
+ * Lucas Chollet
  * Magnus Holmgren
  * Mandar Sahastrabuddhe
  * Mans Rullgard
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftconfig.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftconfig.h
index a85151699d0..0667493fec6 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftconfig.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftconfig.h
@@ -4,7 +4,7 @@
  *
  *   ANSI-specific configuration file (specification only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftheader.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftheader.h
index e607bce15c5..f6ef2618ded 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftheader.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftheader.h
@@ -4,7 +4,7 @@
  *
  *   Build macros of the FreeType 2 library.
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftoption.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftoption.h
index 4375c7a6ff3..d29a0a7cefb 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftoption.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftoption.h
@@ -4,7 +4,7 @@
  *
  *   User-selectable configuration macros (specification only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -757,6 +757,22 @@ FT_BEGIN_HEADER
 #endif
 
 
+  /**************************************************************************
+   *
+   * Option `TT_CONFIG_OPTION_GPOS_KERNING` enables a basic GPOS kerning
+   * implementation (for TrueType fonts only).  With this defined, FreeType
+   * is able to get kerning pair data from the GPOS 'kern' feature as well as
+   * legacy 'kern' tables; without this defined, FreeType will only be able
+   * to use legacy 'kern' tables.
+   *
+   * Note that FreeType does not support more advanced GPOS layout features;
+   * even the 'kern' feature implemented here doesn't handle more
+   * sophisticated kerning variants.  Use a higher-level library like
+   * HarfBuzz instead for that.
+   */
+/* #define TT_CONFIG_OPTION_GPOS_KERNING */
+
+
   /*************************************************************************/
   /*************************************************************************/
   /****                                                                 ****/
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftstdlib.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftstdlib.h
index f65148a902e..e17aa7b89d5 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/config/ftstdlib.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/ftstdlib.h
@@ -5,7 +5,7 @@
  *   ANSI-specific library and header configuration file (specification
  *   only).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/integer-types.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/integer-types.h
index 7258b508541..c27505ffc4b 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/config/integer-types.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/integer-types.h
@@ -4,7 +4,7 @@
  *
  *   FreeType integer types definitions.
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/mac-support.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/mac-support.h
index b77b96d5db8..07b6f915bd8 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/config/mac-support.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/mac-support.h
@@ -4,7 +4,7 @@
  *
  *   Mac/OS X support configuration header.
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/config/public-macros.h b/src/java.desktop/share/native/libfreetype/include/freetype/config/public-macros.h
index 23d0fa6a329..f56581a6ee7 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/config/public-macros.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/config/public-macros.h
@@ -4,7 +4,7 @@
  *
  *   Define a set of compiler macros used in public FreeType headers.
  *
- * Copyright (C) 2020-2023 by
+ * Copyright (C) 2020-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/freetype.h b/src/java.desktop/share/native/libfreetype/include/freetype/freetype.h
index 92acf3794a7..58fc33dfe60 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/freetype.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/freetype.h
@@ -4,7 +4,7 @@
  *
  *   FreeType high-level API and common types (specification only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -1322,9 +1322,13 @@ FT_BEGIN_HEADER
    *   FT_FACE_FLAG_KERNING ::
    *     The face contains kerning information.  If set, the kerning distance
    *     can be retrieved using the function @FT_Get_Kerning.  Otherwise the
-   *     function always returns the vector (0,0).  Note that FreeType
-   *     doesn't handle kerning data from the SFNT 'GPOS' table (as present
-   *     in many OpenType fonts).
+   *     function always returns the vector (0,0).
+   *
+   *     Note that for TrueType fonts only, FreeType supports both the 'kern'
+   *     table and the basic, pair-wise kerning feature from the 'GPOS' table
+   *     (with `TT_CONFIG_OPTION_GPOS_KERNING` enabled), though FreeType does
+   *     not support the more advanced GPOS layout features; use a library
+   *     like HarfBuzz for those instead.
    *
    *   FT_FACE_FLAG_FAST_GLYPHS ::
    *     THIS FLAG IS DEPRECATED.  DO NOT USE OR TEST IT.
@@ -3767,87 +3771,18 @@ FT_BEGIN_HEADER
    *     pixels and use the @FT_PIXEL_MODE_LCD_V mode.
    *
    *   FT_RENDER_MODE_SDF ::
-   *     This mode corresponds to 8-bit, single-channel signed distance field
-   *     (SDF) bitmaps.  Each pixel in the SDF grid is the value from the
-   *     pixel's position to the nearest glyph's outline.  The distances are
-   *     calculated from the center of the pixel and are positive if they are
-   *     filled by the outline (i.e., inside the outline) and negative
-   *     otherwise.  Check the note below on how to convert the output values
-   *     to usable data.
+   *     The positive (unsigned) 8-bit bitmap values can be converted to the
+   *     single-channel signed distance field (SDF) by subtracting 128, with
+   *     the positive and negative results corresponding to the inside and
+   *     the outside of a glyph contour, respectively.  The distance units are
+   *     arbitrarily determined by an adjustable @spread property.
    *
    * @note:
-   *   The selected render mode only affects vector glyphs of a font.
+   *   The selected render mode only affects scalable vector glyphs of a font.
    *   Embedded bitmaps often have a different pixel mode like
    *   @FT_PIXEL_MODE_MONO.  You can use @FT_Bitmap_Convert to transform them
    *   into 8-bit pixmaps.
    *
-   *   For @FT_RENDER_MODE_SDF the output bitmap buffer contains normalized
-   *   distances that are packed into unsigned 8-bit values.  To get pixel
-   *   values in floating point representation use the following pseudo-C
-   *   code for the conversion.
-   *
-   *   ```
-   *   // Load glyph and render using FT_RENDER_MODE_SDF,
-   *   // then use the output buffer as follows.
-   *
-   *   ...
-   *   FT_Byte  buffer = glyph->bitmap->buffer;
-   *
-   *
-   *   for pixel in buffer
-   *   {
-   *     // `sd` is the signed distance and `spread` is the current spread;
-   *     // the default spread is 2 and can be changed.
-   *
-   *     float  sd = (float)pixel - 128.0f;
-   *
-   *
-   *     // Convert to pixel values.
-   *     sd = ( sd / 128.0f ) * spread;
-   *
-   *     // Store `sd` in a buffer or use as required.
-   *   }
-   *
-   *   ```
-   *
-   *   FreeType has two rasterizers for generating SDF, namely:
-   *
-   *   1. `sdf` for generating SDF directly from glyph's outline, and
-   *
-   *   2. `bsdf` for generating SDF from rasterized bitmaps.
-   *
-   *   Depending on the glyph type (i.e., outline or bitmap), one of the two
-   *   rasterizers is chosen at runtime and used for generating SDFs.  To
-   *   force the use of `bsdf` you should render the glyph with any of the
-   *   FreeType's other rendering modes (e.g., `FT_RENDER_MODE_NORMAL`) and
-   *   then re-render with `FT_RENDER_MODE_SDF`.
-   *
-   *   There are some issues with stability and possible failures of the SDF
-   *   renderers (specifically `sdf`).
-   *
-   *   1. The `sdf` rasterizer is sensitive to really small features (e.g.,
-   *      sharp turns that are less than 1~pixel) and imperfections in the
-   *      glyph's outline, causing artifacts in the final output.
-   *
-   *   2. The `sdf` rasterizer has limited support for handling intersecting
-   *      contours and *cannot* handle self-intersecting contours whatsoever.
-   *      Self-intersection happens when a single connected contour
-   *      intersects itself at some point; having these in your font
-   *      definitely poses a problem to the rasterizer and cause artifacts,
-   *      too.
-   *
-   *   3. Generating SDF for really small glyphs may result in undesirable
-   *      output; the pixel grid (which stores distance information) becomes
-   *      too coarse.
-   *
-   *   4. Since the output buffer is normalized, precision at smaller spreads
-   *      is greater than precision at larger spread values because the
-   *      output range of [0..255] gets mapped to a smaller SDF range.  A
-   *      spread of~2 should be sufficient in most cases.
-   *
-   *   Points (1) and (2) can be avoided by using the `bsdf` rasterizer,
-   *   which is more stable than the `sdf` rasterizer in general.
-   *
    */
   typedef enum  FT_Render_Mode_
   {
@@ -4058,9 +3993,26 @@ FT_BEGIN_HEADER
    *   out of the scope of this API function -- they can be implemented
    *   through format-specific interfaces.
    *
-   *   Kerning for OpenType fonts implemented in a 'GPOS' table is not
-   *   supported; use @FT_HAS_KERNING to find out whether a font has data
-   *   that can be extracted with `FT_Get_Kerning`.
+   *   Note that, for TrueType fonts only, this can extract data from both
+   *   the 'kern' table and the basic, pair-wise kerning feature from the
+   *   GPOS table (with `TT_CONFIG_OPTION_GPOS_KERNING` enabled), though
+   *   FreeType does not support the more advanced GPOS layout features; use
+   *   a library like HarfBuzz for those instead.  If a font has both a
+   *   'kern' table and kern features of a GPOS table, the 'kern' table will
+   *   be used.
+   *
+   *   Also note for right-to-left scripts, the functionality may differ for
+   *   fonts with GPOS tables vs. 'kern' tables.  For GPOS, right-to-left
+   *   fonts typically use both a placement offset and an advance for pair
+   *   positioning, which this API does not support, so it would output
+   *   kerning values of zero; though if the right-to-left font used only
+   *   advances in GPOS pair positioning, then this API could output kerning
+   *   values for it, but it would use `left_glyph` to mean the first glyph
+   *   for that case.  Whereas 'kern' tables are always advance-only and
+   *   always store the left glyph first.
+   *
+   *   Use @FT_HAS_KERNING to find out whether a font has data that can be
+   *   extracted with `FT_Get_Kerning`.
    */
   FT_EXPORT( FT_Error )
   FT_Get_Kerning( FT_Face     face,
@@ -5222,7 +5174,7 @@ FT_BEGIN_HEADER
    */
 #define FREETYPE_MAJOR  2
 #define FREETYPE_MINOR  13
-#define FREETYPE_PATCH  2
+#define FREETYPE_PATCH  3
 
 
   /**************************************************************************
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftadvanc.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftadvanc.h
index 4560ded6dcb..85b8ba2554b 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftadvanc.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftadvanc.h
@@ -4,7 +4,7 @@
  *
  *   Quick computation of advance widths (specification only).
  *
- * Copyright (C) 2008-2023 by
+ * Copyright (C) 2008-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftbbox.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftbbox.h
index fc21740fc2b..12bbfa63a62 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftbbox.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftbbox.h
@@ -4,7 +4,7 @@
  *
  *   FreeType exact bbox computation (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftbdf.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftbdf.h
index e8ce6431285..6f63b0b1e78 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftbdf.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftbdf.h
@@ -4,7 +4,7 @@
  *
  *   FreeType API for accessing BDF-specific strings (specification).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftbitmap.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftbitmap.h
index eb6b4b1eebe..df9d462652e 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftbitmap.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftbitmap.h
@@ -4,7 +4,7 @@
  *
  *   FreeType utility functions for bitmaps (specification).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftcid.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftcid.h
index ef229390224..96b2a90fc59 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftcid.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftcid.h
@@ -4,7 +4,7 @@
  *
  *   FreeType API for accessing CID font information (specification).
  *
- * Copyright (C) 2007-2023 by
+ * Copyright (C) 2007-2024 by
  * Dereg Clegg and Michael Toftdal.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftcolor.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftcolor.h
index eae200fdf14..420720ddf22 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftcolor.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftcolor.h
@@ -4,7 +4,7 @@
  *
  *   FreeType's glyph color management (specification).
  *
- * Copyright (C) 2018-2023 by
+ * Copyright (C) 2018-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftdriver.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftdriver.h
index 7af7465bc76..1b7f539f5e2 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftdriver.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftdriver.h
@@ -4,7 +4,7 @@
  *
  *   FreeType API for controlling driver modules (specification only).
  *
- * Copyright (C) 2017-2023 by
+ * Copyright (C) 2017-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -817,6 +817,80 @@ FT_BEGIN_HEADER
    *   2.5
    */
 
+
+  /**************************************************************************
+   *
+   * @property:
+   *   spread
+   *
+   * @description:
+   *   This property of the 'sdf' and 'bsdf' renderers defines how the signed
+   *   distance field (SDF) is represented in the output bitmap.  The output
+   *   values are calculated as follows, '128 * ( SDF / spread + 1 )', with
+   *   the result clamped to the 8-bit range [0..255].  Therefore, 'spread'
+   *   is also the maximum euclidean distance from the edge after which the
+   *   values are clamped.  The spread is specified in pixels with the
+   *   default value of 8.  For accurate SDF texture mapping (interpolation),
+   *   the spread should be large enough to accommodate the target grid unit.
+   *
+   * @example:
+   *   The following example code demonstrates how to set the SDF spread
+   *   (omitting the error handling).
+   *
+   *   ```
+   *     FT_Library  library;
+   *     FT_Int      spread = 2;
+   *
+   *
+   *     FT_Init_FreeType( &library );
+   *
+   *     FT_Property_Set( library, "sdf", "spread", &spread );
+   *   ```
+   *
+   * @note:
+   *   FreeType has two rasterizers for generating SDF, namely:
+   *
+   *   1. `sdf` for generating SDF directly from glyph's outline, and
+   *
+   *   2. `bsdf` for generating SDF from rasterized bitmaps.
+   *
+   *   Depending on the glyph type (i.e., outline or bitmap), one of the two
+   *   rasterizers is chosen at runtime and used for generating SDFs.  To
+   *   force the use of `bsdf` you should render the glyph with any of the
+   *   FreeType's other rendering modes (e.g., `FT_RENDER_MODE_NORMAL`) and
+   *   then re-render with `FT_RENDER_MODE_SDF`.
+   *
+   *   There are some issues with stability and possible failures of the SDF
+   *   renderers (specifically `sdf`).
+   *
+   *   1. The `sdf` rasterizer is sensitive to really small features (e.g.,
+   *      sharp turns that are less than 1~pixel) and imperfections in the
+   *      glyph's outline, causing artifacts in the final output.
+   *
+   *   2. The `sdf` rasterizer has limited support for handling intersecting
+   *      contours and *cannot* handle self-intersecting contours whatsoever.
+   *      Self-intersection happens when a single connected contour
+   *      intersects itself at some point; having these in your font
+   *      definitely poses a problem to the rasterizer and cause artifacts,
+   *      too.
+   *
+   *   3. Generating SDF for really small glyphs may result in undesirable
+   *      output; the pixel grid (which stores distance information) becomes
+   *      too coarse.
+   *
+   *   4. Since the output buffer is normalized, precision at smaller spreads
+   *      is greater than precision at larger spread values because the
+   *      output range of [0..255] gets mapped to a smaller SDF range.  A
+   *      spread of~2 should be sufficient in most cases.
+   *
+   *   Points (1) and (2) can be avoided by using the `bsdf` rasterizer,
+   *   which is more stable than the `sdf` rasterizer in general.
+   *
+   * @since:
+   *   2.11
+   */
+
+
   /**************************************************************************
    *
    * @property:
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/fterrdef.h b/src/java.desktop/share/native/libfreetype/include/freetype/fterrdef.h
index d59b3cc2da2..710ca91bbdd 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/fterrdef.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/fterrdef.h
@@ -4,7 +4,7 @@
  *
  *   FreeType error codes (specification).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/fterrors.h b/src/java.desktop/share/native/libfreetype/include/freetype/fterrors.h
index 15ef3f76b59..27c0ece5c1c 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/fterrors.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/fterrors.h
@@ -4,7 +4,7 @@
  *
  *   FreeType error code handling (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftfntfmt.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftfntfmt.h
index c0018fc830c..7c8b0874a81 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftfntfmt.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftfntfmt.h
@@ -4,7 +4,7 @@
  *
  *   Support functions for font formats.
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftgasp.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftgasp.h
index d5f19add8f2..30e5a9bf82b 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftgasp.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftgasp.h
@@ -4,7 +4,7 @@
  *
  *   Access of TrueType's 'gasp' table (specification).
  *
- * Copyright (C) 2007-2023 by
+ * Copyright (C) 2007-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftglyph.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftglyph.h
index 4658895f7a9..dc1eb8873ae 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftglyph.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftglyph.h
@@ -4,7 +4,7 @@
  *
  *   FreeType convenience functions to handle glyphs (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftgzip.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftgzip.h
index 443ec29db1b..9516dc030ac 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftgzip.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftgzip.h
@@ -4,7 +4,7 @@
  *
  *   Gzip-compressed stream support.
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftimage.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftimage.h
index 6baa812560e..2b4b4ac60ae 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftimage.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftimage.h
@@ -5,7 +5,7 @@
  *   FreeType glyph image formats and default raster interface
  *   (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -21,6 +21,11 @@
    * Note: A 'raster' is simply a scan-line converter, used to render
    *       `FT_Outline`s into `FT_Bitmap`s.
    *
+   * Note: This file can be used for `STANDALONE_` compilation of raster
+   *       (B/W) and smooth (anti-aliased) renderers.  Therefore, it must
+   *       rely on standard variable types only instead of aliases in
+   *       `fttypes.h`.
+   *
    */
 
 
@@ -318,7 +323,7 @@ FT_BEGIN_HEADER
    *
    *     If bit~2 is set, bits 5-7 contain the drop-out mode (as defined in
    *     the OpenType specification; the value is the same as the argument to
-   *     the 'SCANMODE' instruction).
+   *     the 'SCANTYPE' instruction).
    *
    *     Bits 3 and~4 are reserved for internal purposes.
    *
@@ -341,14 +346,14 @@ FT_BEGIN_HEADER
    */
   typedef struct  FT_Outline_
   {
-    short       n_contours;      /* number of contours in glyph        */
-    short       n_points;        /* number of points in the glyph      */
+    unsigned short   n_contours;  /* number of contours in glyph        */
+    unsigned short   n_points;    /* number of points in the glyph      */
 
-    FT_Vector*  points;          /* the outline's points               */
-    char*       tags;            /* the points flags                   */
-    short*      contours;        /* the contour end points             */
+    FT_Vector*       points;      /* the outline's points               */
+    unsigned char*   tags;        /* the points flags                   */
+    unsigned short*  contours;    /* the contour end points             */
 
-    int         flags;           /* outline masks                      */
+    int              flags;       /* outline masks                      */
 
   } FT_Outline;
 
@@ -356,8 +361,8 @@ FT_BEGIN_HEADER
 
   /* Following limits must be consistent with */
   /* FT_Outline.{n_contours,n_points}         */
-#define FT_OUTLINE_CONTOURS_MAX  SHRT_MAX
-#define FT_OUTLINE_POINTS_MAX    SHRT_MAX
+#define FT_OUTLINE_CONTOURS_MAX  USHRT_MAX
+#define FT_OUTLINE_POINTS_MAX    USHRT_MAX
 
 
   /**************************************************************************
@@ -434,8 +439,8 @@ FT_BEGIN_HEADER
    *   rasterizer; see the `tags` field in @FT_Outline.
    *
    *   Please refer to the description of the 'SCANTYPE' instruction in the
-   *   OpenType specification (in file `ttinst1.doc`) how simple drop-outs,
-   *   smart drop-outs, and stubs are defined.
+   *   [OpenType specification](https://learn.microsoft.com/en-us/typography/opentype/spec/tt_instructions#scantype)
+   *   how simple drop-outs, smart drop-outs, and stubs are defined.
    */
 #define FT_OUTLINE_NONE             0x0
 #define FT_OUTLINE_OWNER            0x1
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftincrem.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftincrem.h
index 2d4f5def241..816581b78eb 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftincrem.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftincrem.h
@@ -4,7 +4,7 @@
  *
  *   FreeType incremental loading (specification).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftlcdfil.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftlcdfil.h
index d3723e16f67..25274dc4ac2 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftlcdfil.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftlcdfil.h
@@ -5,7 +5,7 @@
  *   FreeType API for color filtering of subpixel bitmap glyphs
  *   (specification).
  *
- * Copyright (C) 2006-2023 by
+ * Copyright (C) 2006-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftlist.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftlist.h
index b5531313359..972fbfa2fe4 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftlist.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftlist.h
@@ -4,7 +4,7 @@
  *
  *   Generic list support for FreeType (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftlogging.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftlogging.h
index 53b8b896427..1813cfc2c27 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftlogging.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftlogging.h
@@ -4,7 +4,7 @@
  *
  *   Additional debugging APIs.
  *
- * Copyright (C) 2020-2023 by
+ * Copyright (C) 2020-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftmac.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftmac.h
index a91e38f9ea7..e4efde33dd8 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftmac.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftmac.h
@@ -4,7 +4,7 @@
  *
  *   Additional Mac-specific API.
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftmm.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftmm.h
index d145128a9bc..35ed039c89b 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftmm.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftmm.h
@@ -4,7 +4,7 @@
  *
  *   FreeType Multiple Master font interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -19,8 +19,13 @@
 #ifndef FTMM_H_
 #define FTMM_H_
 
+#include 
 
-#include 
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
 
 
 FT_BEGIN_HEADER
@@ -53,6 +58,30 @@ FT_BEGIN_HEADER
    */
 
 
+  /**************************************************************************
+   *
+   * @enum:
+   *   T1_MAX_MM_XXX
+   *
+   * @description:
+   *   Multiple Masters limits as defined in their specifications.
+   *
+   * @values:
+   *   T1_MAX_MM_AXIS ::
+   *     The maximum number of Multiple Masters axes.
+   *
+   *   T1_MAX_MM_DESIGNS ::
+   *     The maximum number of Multiple Masters designs.
+   *
+   *   T1_MAX_MM_MAP_POINTS ::
+   *     The maximum number of elements in a design map.
+   *
+   */
+#define T1_MAX_MM_AXIS         4
+#define T1_MAX_MM_DESIGNS     16
+#define T1_MAX_MM_MAP_POINTS  20
+
+
   /**************************************************************************
    *
    * @struct:
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftmodapi.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftmodapi.h
index c8f0c2c2a45..0ee715898f7 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftmodapi.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftmodapi.h
@@ -4,7 +4,7 @@
  *
  *   FreeType modules public interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftmoderr.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftmoderr.h
index c8c892dcce8..6722fbf8b70 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftmoderr.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftmoderr.h
@@ -4,7 +4,7 @@
  *
  *   FreeType module error offsets (specification).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftoutln.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftoutln.h
index f9329ca40c9..44e94b4f5bb 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftoutln.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftoutln.h
@@ -5,7 +5,7 @@
  *   Support for the FT_Outline type used to store glyph shapes of
  *   most scalable font formats (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -112,7 +112,7 @@ FT_BEGIN_HEADER
    *   Degenerate contours, segments, and Bezier arcs may be reported.  In
    *   most cases, it is best to filter these out before using the outline
    *   for stroking or other path modification purposes (which may cause
-   *   degenerate segments to become non-degenrate and visible, like when
+   *   degenerate segments to become non-degenerate and visible, like when
    *   stroke caps are used or the path is otherwise outset).  Some glyph
    *   outlines may contain deliberate degenerate single points for mark
    *   attachement.
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftparams.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftparams.h
index 6a9f243bc90..43bf69c202f 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftparams.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftparams.h
@@ -4,7 +4,7 @@
  *
  *   FreeType API for possible FT_Parameter tags (specification only).
  *
- * Copyright (C) 2017-2023 by
+ * Copyright (C) 2017-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftrender.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftrender.h
index 0b6fad32e84..dc5018a1b54 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftrender.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftrender.h
@@ -4,7 +4,7 @@
  *
  *   FreeType renderer modules public interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftsizes.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftsizes.h
index 7bfb1aed4c2..4ef5c7955df 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftsizes.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftsizes.h
@@ -4,7 +4,7 @@
  *
  *   FreeType size objects management (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftsnames.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftsnames.h
index 9d5d22bb255..d5d5cd93103 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftsnames.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftsnames.h
@@ -7,7 +7,7 @@
  *
  *   This is _not_ used to retrieve glyph names!
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftstroke.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftstroke.h
index b3d90802a56..41626dc9d7b 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftstroke.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftstroke.h
@@ -4,7 +4,7 @@
  *
  *   FreeType path stroker (specification).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftsynth.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftsynth.h
index af90967dda0..43081b6c330 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftsynth.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftsynth.h
@@ -5,7 +5,7 @@
  *   FreeType synthesizing code for emboldening and slanting
  *   (specification).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ftsystem.h b/src/java.desktop/share/native/libfreetype/include/freetype/ftsystem.h
index 3a08f4912c9..1eacb3af398 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ftsystem.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ftsystem.h
@@ -4,7 +4,7 @@
  *
  *   FreeType low-level system interface definition (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/fttrigon.h b/src/java.desktop/share/native/libfreetype/include/freetype/fttrigon.h
index 294981a6f31..a5299e938d4 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/fttrigon.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/fttrigon.h
@@ -4,7 +4,7 @@
  *
  *   FreeType trigonometric functions (specification).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/fttypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/fttypes.h
index 5b109f0c73c..27815143a64 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/fttypes.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/fttypes.h
@@ -4,7 +4,7 @@
  *
  *   FreeType simple types definitions (specification only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/autohint.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/autohint.h
index bf9c8b7cf2a..8865d53b389 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/autohint.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/autohint.h
@@ -4,7 +4,7 @@
  *
  *   High-level 'autohint' module-specific interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/cffotypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/cffotypes.h
index 50d53538498..36b0390a5a5 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/cffotypes.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/cffotypes.h
@@ -4,7 +4,7 @@
  *
  *   Basic OpenType/CFF object type definitions (specification).
  *
- * Copyright (C) 2017-2023 by
+ * Copyright (C) 2017-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/cfftypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/cfftypes.h
index c2521764caa..ef2e8e7569c 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/cfftypes.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/cfftypes.h
@@ -5,7 +5,7 @@
  *   Basic OpenType/CFF type definitions and interface (specification
  *   only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -248,10 +248,10 @@ FT_BEGIN_HEADER
     FT_Byte   num_family_blues;
     FT_Byte   num_family_other_blues;
 
-    FT_Pos    blue_values[14];
-    FT_Pos    other_blues[10];
-    FT_Pos    family_blues[14];
-    FT_Pos    family_other_blues[10];
+    FT_Fixed  blue_values[14];
+    FT_Fixed  other_blues[10];
+    FT_Fixed  family_blues[14];
+    FT_Fixed  family_other_blues[10];
 
     FT_Fixed  blue_scale;
     FT_Pos    blue_shift;
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/compiler-macros.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/compiler-macros.h
index 6f67650979e..876f66e2561 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/compiler-macros.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/compiler-macros.h
@@ -4,7 +4,7 @@
  *
  *   Compiler-specific macro definitions used internally by FreeType.
  *
- * Copyright (C) 2020-2023 by
+ * Copyright (C) 2020-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftcalc.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftcalc.h
index d9aea236024..71128a2df90 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftcalc.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftcalc.h
@@ -4,7 +4,7 @@
  *
  *   Arithmetic computations (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -415,7 +415,7 @@ FT_BEGIN_HEADER
 
 #define FT_MSB( x )  ( 31 - _CountLeadingZeros( x ) )
 
-#elif defined( _M_ARM64 ) || defined( _M_ARM )
+#elif defined( _M_ARM64 ) || defined( _M_ARM ) || defined( _M_ARM64EC )
 
 #include 
 #pragma intrinsic( _CountLeadingZeros )
@@ -455,6 +455,12 @@ FT_BEGIN_HEADER
 
 #define FT_MSB( x )  FT_MSB_i386( x )
 
+#elif defined( __SunOS_5_11 )
+
+#include 
+
+#define FT_MSB( x )  ( fls( x ) - 1 )
+
 #elif defined( __DECC ) || defined( __DECCXX )
 
 #include 
@@ -489,8 +495,6 @@ FT_BEGIN_HEADER
             FT_Fixed  y );
 
 
-#if 0
-
   /**************************************************************************
    *
    * @function:
@@ -507,12 +511,11 @@ FT_BEGIN_HEADER
    *   The result of 'sqrt(x)'.
    *
    * @note:
-   *   This function is not very fast.
+   *   This function is slow and should be avoided.  Consider @FT_Hypot or
+   *   @FT_Vector_NormLen instead.
    */
-  FT_BASE( FT_Int32 )
-  FT_SqrtFixed( FT_Int32  x );
-
-#endif /* 0 */
+  FT_BASE( FT_UInt32 )
+  FT_SqrtFixed( FT_UInt32  x );
 
 
 #define INT_TO_F26DOT6( x )    ( (FT_Long)(x) * 64  )    /* << 6  */
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdebug.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdebug.h
index 4e013ba1e26..d7fa8dc93cf 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdebug.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdebug.h
@@ -4,7 +4,7 @@
  *
  *   Debugging and logging component (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdrv.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdrv.h
index 9001c07ad0b..5609b3ef12b 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdrv.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftdrv.h
@@ -4,7 +4,7 @@
  *
  *   FreeType internal font driver interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftgloadr.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftgloadr.h
index 36e5509f9ea..f1c155b162c 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftgloadr.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftgloadr.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType glyph loader (specification).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmemory.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmemory.h
index 5eb1d21ff67..4e05a29f13a 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmemory.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmemory.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType memory management macros (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg
  *
  * This file is part of the FreeType project, and may only be used,
@@ -371,8 +371,11 @@ extern "C++"
 #define FT_STRDUP( dst, str )                           \
           FT_MEM_SET_ERROR( FT_MEM_STRDUP( dst, str ) )
 
-#define FT_MEM_DUP( dst, address, size )                                    \
-          (dst) = ft_mem_dup( memory, (address), (FT_ULong)(size), &error )
+#define FT_MEM_DUP( dst, address, size )                       \
+          FT_ASSIGNP_INNER( dst, ft_mem_dup( memory,           \
+                                             (address),        \
+                                             (FT_ULong)(size), \
+                                             &error ) )
 
 #define FT_DUP( dst, address, size )                           \
           FT_MEM_SET_ERROR( FT_MEM_DUP( dst, address, size ) )
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmmtypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmmtypes.h
index c4b21d6144e..8449e7a010d 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmmtypes.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftmmtypes.h
@@ -5,7 +5,7 @@
  *   OpenType Variations type definitions for internal use
  *   with the multi-masters service (specification).
  *
- * Copyright (C) 2022-2023 by
+ * Copyright (C) 2022-2024 by
  * David Turner, Robert Wilhelm, Werner Lemberg, George Williams, and
  * Dominik Röttsches.
  *
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftobjs.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftobjs.h
index 28bc9b65f05..a1e93298fdb 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftobjs.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftobjs.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType private base classes (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -604,12 +604,6 @@ FT_BEGIN_HEADER
 #define FT_FACE_MEMORY( x )   FT_FACE( x )->memory
 #define FT_FACE_STREAM( x )   FT_FACE( x )->stream
 
-#define FT_SIZE_FACE( x )     FT_SIZE( x )->face
-#define FT_SLOT_FACE( x )     FT_SLOT( x )->face
-
-#define FT_FACE_SLOT( x )     FT_FACE( x )->glyph
-#define FT_FACE_SIZE( x )     FT_FACE( x )->size
-
 
   /**************************************************************************
    *
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftpsprop.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftpsprop.h
index 1d5b287ad20..4f11aa16ba1 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftpsprop.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftpsprop.h
@@ -4,7 +4,7 @@
  *
  *   Get and set properties of PostScript drivers (specification).
  *
- * Copyright (C) 2017-2023 by
+ * Copyright (C) 2017-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftrfork.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftrfork.h
index e96459921ef..05c1d6c48b5 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftrfork.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftrfork.h
@@ -4,7 +4,7 @@
  *
  *   Embedded resource forks accessor (specification).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * Masatake YAMATO and Redhat K.K.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftserv.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftserv.h
index 1e85d6d3856..8c35dbd7139 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftserv.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftserv.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType services (specification only).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftstream.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftstream.h
index 88e19287c80..fd52f767ef7 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftstream.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftstream.h
@@ -4,7 +4,7 @@
  *
  *   Stream handling (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/fttrace.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/fttrace.h
index 319fe56fd2d..42595a29ff3 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/fttrace.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/fttrace.h
@@ -4,7 +4,7 @@
  *
  *   Tracing handling (specification only).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -64,6 +64,7 @@ FT_TRACE_DEF( ttbdf )     /* TrueType embedded BDF   (ttbdf.c)    */
 FT_TRACE_DEF( ttcmap )    /* charmap handler         (ttcmap.c)   */
 FT_TRACE_DEF( ttcolr )    /* glyph layer table       (ttcolr.c)   */
 FT_TRACE_DEF( ttcpal )    /* color palette table     (ttcpal.c)   */
+FT_TRACE_DEF( ttgpos )    /* GPOS handler            (ttgpos.c)   */
 FT_TRACE_DEF( ttsvg )     /* OpenType SVG table      (ttsvg.c)    */
 FT_TRACE_DEF( ttkern )    /* kerning handler         (ttkern.c)   */
 FT_TRACE_DEF( ttload )    /* basic TrueType tables   (ttload.c)   */
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftvalid.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftvalid.h
index e98ee4e4737..a1312f2aba6 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftvalid.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/ftvalid.h
@@ -4,7 +4,7 @@
  *
  *   FreeType validation support (specification).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/psaux.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/psaux.h
index dfb1987f868..745d2cb56b7 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/psaux.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/psaux.h
@@ -5,7 +5,7 @@
  *   Auxiliary functions and data structures related to PostScript fonts
  *   (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -225,6 +225,7 @@ FT_BEGIN_HEADER
 
   typedef enum  T1_FieldLocation_
   {
+    T1_FIELD_LOCATION_NONE = 0,
     T1_FIELD_LOCATION_CID_INFO,
     T1_FIELD_LOCATION_FONT_DICT,
     T1_FIELD_LOCATION_FONT_EXTRA,
@@ -249,6 +250,7 @@ FT_BEGIN_HEADER
   /* structure type used to model object fields */
   typedef struct  T1_FieldRec_
   {
+    FT_UInt             len;          /* field identifier length        */
     const char*         ident;        /* field identifier               */
     T1_FieldLocation    location;
     T1_FieldType        type;         /* type of field                  */
@@ -273,8 +275,9 @@ FT_BEGIN_HEADER
 
 #define T1_NEW_SIMPLE_FIELD( _ident, _type, _fname, _dict ) \
           {                                                 \
+            sizeof ( _ident ) - 1,                          \
             _ident, T1CODE, _type,                          \
-            0,                                              \
+            NULL,                                           \
             FT_FIELD_OFFSET( _fname ),                      \
             FT_FIELD_SIZE( _fname ),                        \
             0, 0,                                           \
@@ -283,6 +286,7 @@ FT_BEGIN_HEADER
 
 #define T1_NEW_CALLBACK_FIELD( _ident, _reader, _dict ) \
           {                                             \
+            sizeof ( _ident ) - 1,                      \
             _ident, T1CODE, T1_FIELD_TYPE_CALLBACK,     \
             (T1_Field_ParseFunc)_reader,                \
             0, 0,                                       \
@@ -292,8 +296,9 @@ FT_BEGIN_HEADER
 
 #define T1_NEW_TABLE_FIELD( _ident, _type, _fname, _max, _dict ) \
           {                                                      \
+            sizeof ( _ident ) - 1,                               \
             _ident, T1CODE, _type,                               \
-            0,                                                   \
+            NULL,                                                \
             FT_FIELD_OFFSET( _fname ),                           \
             FT_FIELD_SIZE_DELTA( _fname ),                       \
             _max,                                                \
@@ -303,8 +308,9 @@ FT_BEGIN_HEADER
 
 #define T1_NEW_TABLE_FIELD2( _ident, _type, _fname, _max, _dict ) \
           {                                                       \
+            sizeof ( _ident ) - 1,                                \
             _ident, T1CODE, _type,                                \
-            0,                                                    \
+            NULL,                                                 \
             FT_FIELD_OFFSET( _fname ),                            \
             FT_FIELD_SIZE_DELTA( _fname ),                        \
             _max, 0,                                              \
@@ -354,6 +360,13 @@ FT_BEGIN_HEADER
 #define T1_FIELD_CALLBACK( _ident, _name, _dict )       \
           T1_NEW_CALLBACK_FIELD( _ident, _name, _dict )
 
+#define T1_FIELD_ZERO                                         \
+          {                                                   \
+            0,                                                \
+            NULL, T1_FIELD_LOCATION_NONE, T1_FIELD_TYPE_NONE, \
+            NULL, 0, 0, 0, 0, 0                               \
+          }
+
 
   /*************************************************************************/
   /*************************************************************************/
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/pshints.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/pshints.h
index ededc4c72e7..dba6c7303fd 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/pshints.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/pshints.h
@@ -6,7 +6,7 @@
  *   recorders (specification only).  These are used to support native
  *   T1/T2 hints in the 'type1', 'cid', and 'cff' font drivers.
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svbdf.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svbdf.h
index bf0c1dcc714..89e9c2e5de8 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svbdf.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svbdf.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType BDF services (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcfftl.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcfftl.h
index 4a20498ee0c..3cb483c344f 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcfftl.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcfftl.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType CFF tables loader service (specification).
  *
- * Copyright (C) 2017-2023 by
+ * Copyright (C) 2017-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcid.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcid.h
index 06d0cb8fd62..8362cb8724d 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcid.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svcid.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType CID font services (specification).
  *
- * Copyright (C) 2007-2023 by
+ * Copyright (C) 2007-2024 by
  * Derek Clegg and Michael Toftdal.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svfntfmt.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svfntfmt.h
index bc45e80568f..6b837e79fcd 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svfntfmt.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svfntfmt.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType font format service (specification only).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgldict.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgldict.h
index 6437abfbf2e..6126ec9ada4 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgldict.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgldict.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType glyph dictionary services (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgxval.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgxval.h
index 31016afe0d0..29cf5528189 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgxval.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svgxval.h
@@ -4,7 +4,7 @@
  *
  *   FreeType API for validating TrueTypeGX/AAT tables (specification).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * Masatake YAMATO, Red Hat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svkern.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svkern.h
index bcabbc3e68f..ac1bc30c412 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svkern.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svkern.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType Kerning service (specification).
  *
- * Copyright (C) 2006-2023 by
+ * Copyright (C) 2006-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmetric.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmetric.h
index 167617ebb3d..8b3563b25ca 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmetric.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmetric.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType services for metrics variations (specification).
  *
- * Copyright (C) 2016-2023 by
+ * Copyright (C) 2016-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmm.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmm.h
index 7e76ab8324e..5288fadf375 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmm.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svmm.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType Multiple Masters and GX var services (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, Werner Lemberg, and Dominik Röttsches.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svotval.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svotval.h
index a4683cd5fb6..7aea7ec11f0 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svotval.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svotval.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType OpenType validation service (specification).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpfr.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpfr.h
index fd189c7de77..b2fac6d086b 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpfr.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpfr.h
@@ -4,7 +4,7 @@
  *
  *   Internal PFR service functions (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpostnm.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpostnm.h
index 2b8f6dfecfb..d19f3adc6d5 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpostnm.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpostnm.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType PostScript name services (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svprop.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svprop.h
index 932ce32e03d..ba39c0dd4da 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svprop.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svprop.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType property service (specification).
  *
- * Copyright (C) 2012-2023 by
+ * Copyright (C) 2012-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpscmap.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpscmap.h
index 6e599f3aabe..d4908ee41aa 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpscmap.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpscmap.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType PostScript charmap service (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpsinfo.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpsinfo.h
index 09c4cdccc53..2aadcdd02a1 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpsinfo.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svpsinfo.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType PostScript info service (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svsfnt.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svsfnt.h
index f98df2ef5fe..9e0f4ff202e 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svsfnt.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svsfnt.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType SFNT table loading service (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttcmap.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttcmap.h
index 5f9eb02d665..250886bcc5d 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttcmap.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttcmap.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType TrueType/sfnt cmap extra information service.
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * Masatake YAMATO, Redhat K.K.,
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svtteng.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svtteng.h
index ad577cb2904..14967529a9a 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svtteng.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svtteng.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType TrueType engine query service (specification).
  *
- * Copyright (C) 2006-2023 by
+ * Copyright (C) 2006-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttglyf.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttglyf.h
index ca6fff74444..f190b3985d0 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttglyf.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svttglyf.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType TrueType glyph service.
  *
- * Copyright (C) 2007-2023 by
+ * Copyright (C) 2007-2024 by
  * David Turner.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svwinfnt.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svwinfnt.h
index 002923f8c91..49f3fb7f775 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svwinfnt.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/services/svwinfnt.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType Windows FNT/FONT service (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/sfnt.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/sfnt.h
index a2d4e15baaf..35e4e73af02 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/sfnt.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/sfnt.h
@@ -4,7 +4,7 @@
  *
  *   High-level 'sfnt' driver interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -924,6 +924,7 @@ FT_BEGIN_HEADER
     /* this field was called `load_kerning' up to version 2.1.10 */
     TT_Load_Table_Func  load_kern;
 
+    TT_Load_Table_Func  load_gpos;
     TT_Load_Table_Func  load_gasp;
     TT_Load_Table_Func  load_pclt;
 
@@ -944,6 +945,8 @@ FT_BEGIN_HEADER
 
     /* new elements introduced after version 2.1.10 */
 
+    TT_Face_GetKerningFunc  get_gpos_kerning;
+
     /* load the font directory, i.e., the offset table and */
     /* the table directory                                 */
     TT_Load_Table_Func    load_font_dir;
@@ -1002,6 +1005,7 @@ FT_BEGIN_HEADER
           load_name_,                    \
           free_name_,                    \
           load_kern_,                    \
+          load_gpos_,                    \
           load_gasp_,                    \
           load_pclt_,                    \
           load_bhed_,                    \
@@ -1009,6 +1013,7 @@ FT_BEGIN_HEADER
           get_psname_,                   \
           free_psnames_,                 \
           get_kerning_,                  \
+          get_gpos_kerning_,             \
           load_font_dir_,                \
           load_hmtx_,                    \
           load_eblc_,                    \
@@ -1050,6 +1055,7 @@ FT_BEGIN_HEADER
     load_name_,                          \
     free_name_,                          \
     load_kern_,                          \
+    load_gpos_,                          \
     load_gasp_,                          \
     load_pclt_,                          \
     load_bhed_,                          \
@@ -1057,6 +1063,7 @@ FT_BEGIN_HEADER
     get_psname_,                         \
     free_psnames_,                       \
     get_kerning_,                        \
+    get_gpos_kerning_,                   \
     load_font_dir_,                      \
     load_hmtx_,                          \
     load_eblc_,                          \
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/svginterface.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/svginterface.h
index f464b2c0583..68c99efb10a 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/svginterface.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/svginterface.h
@@ -4,7 +4,7 @@
  *
  *   Interface of ot-svg module (specification only).
  *
- * Copyright (C) 2022-2023 by
+ * Copyright (C) 2022-2024 by
  * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/t1types.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/t1types.h
index b9c94398fd1..1821ae5cc83 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/t1types.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/t1types.h
@@ -5,7 +5,7 @@
  *   Basic Type1/Type2 type definitions and interface (specification
  *   only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -21,7 +21,7 @@
 #define T1TYPES_H_
 
 
-#include 
+#include 
 #include 
 #include 
 #include 
@@ -137,6 +137,54 @@ FT_BEGIN_HEADER
   } CID_SubrsRec, *CID_Subrs;
 
 
+  /* this structure is used to store the BlendDesignMap entry for an axis */
+  typedef struct  PS_DesignMap_
+  {
+    FT_Byte    num_points;
+    FT_Long*   design_points;
+    FT_Fixed*  blend_points;
+
+  } PS_DesignMapRec, *PS_DesignMap;
+
+  /* backward compatible definition */
+  typedef PS_DesignMapRec  T1_DesignMap;
+
+
+  typedef struct  PS_BlendRec_
+  {
+    FT_UInt          num_designs;
+    FT_UInt          num_axis;
+
+    FT_String*       axis_names[T1_MAX_MM_AXIS];
+    FT_Fixed*        design_pos[T1_MAX_MM_DESIGNS];
+    PS_DesignMapRec  design_map[T1_MAX_MM_AXIS];
+
+    FT_Fixed*        weight_vector;
+    FT_Fixed*        default_weight_vector;
+
+    PS_FontInfo      font_infos[T1_MAX_MM_DESIGNS + 1];
+    PS_Private       privates  [T1_MAX_MM_DESIGNS + 1];
+
+    FT_ULong         blend_bitflags;
+
+    FT_BBox*         bboxes    [T1_MAX_MM_DESIGNS + 1];
+
+    /* since 2.3.0 */
+
+    /* undocumented, optional: the default design instance;   */
+    /* corresponds to default_weight_vector --                */
+    /* num_default_design_vector == 0 means it is not present */
+    /* in the font and associated metrics files               */
+    FT_UInt          default_design_vector[T1_MAX_MM_DESIGNS];
+    FT_UInt          num_default_design_vector;
+
+  } PS_BlendRec, *PS_Blend;
+
+
+  /* backward compatible definition */
+  typedef PS_BlendRec  T1_Blend;
+
+
   /*************************************************************************/
   /*************************************************************************/
   /*************************************************************************/
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/tttypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/tttypes.h
index b9788c7831e..7053e656a7e 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/tttypes.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/tttypes.h
@@ -5,7 +5,7 @@
  *   Basic SFNT/TrueType type definitions and interface (specification
  *   only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -24,6 +24,7 @@
 #include 
 #include 
 #include 
+#include "freetype/fttypes.h"
 
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
 #include 
@@ -1581,6 +1582,11 @@ FT_BEGIN_HEADER
     FT_UInt32             kern_avail_bits;
     FT_UInt32             kern_order_bits;
 
+#ifdef TT_CONFIG_OPTION_GPOS_KERNING
+    FT_Byte*              gpos_table;
+    FT_Bool               gpos_kerning_available;
+#endif
+
 #ifdef TT_CONFIG_OPTION_BDF
     TT_BDFRec             bdf;
 #endif /* TT_CONFIG_OPTION_BDF */
@@ -1649,9 +1655,9 @@ FT_BEGIN_HEADER
   {
     FT_Memory   memory;
     FT_UShort   max_points;
-    FT_Short    max_contours;
+    FT_UShort   max_contours;
     FT_UShort   n_points;    /* number of points in zone    */
-    FT_Short    n_contours;  /* number of contours          */
+    FT_UShort   n_contours;  /* number of contours          */
 
     FT_Vector*  org;         /* original point coordinates  */
     FT_Vector*  cur;         /* current point coordinates   */
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/internal/wofftypes.h b/src/java.desktop/share/native/libfreetype/include/freetype/internal/wofftypes.h
index 0c1d8eeaf8c..4a169d12f57 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/internal/wofftypes.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/internal/wofftypes.h
@@ -5,7 +5,7 @@
  *   Basic WOFF/WOFF2 type definitions and interface (specification
  *   only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/otsvg.h b/src/java.desktop/share/native/libfreetype/include/freetype/otsvg.h
index bfe9a6ab74e..9d356938cc7 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/otsvg.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/otsvg.h
@@ -4,7 +4,7 @@
  *
  *   Interface for OT-SVG support related things (specification).
  *
- * Copyright (C) 2022-2023 by
+ * Copyright (C) 2022-2024 by
  * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/t1tables.h b/src/java.desktop/share/native/libfreetype/include/freetype/t1tables.h
index 1aecfbbd902..fbd558aa34d 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/t1tables.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/t1tables.h
@@ -5,7 +5,7 @@
  *   Basic Type 1/Type 2 tables definitions and interface (specification
  *   only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -269,64 +269,6 @@ FT_BEGIN_HEADER
   /* */
 
 
-  /* maximum number of Multiple Masters designs, as defined in the spec */
-#define T1_MAX_MM_DESIGNS     16
-
-  /* maximum number of Multiple Masters axes, as defined in the spec */
-#define T1_MAX_MM_AXIS        4
-
-  /* maximum number of elements in a design map */
-#define T1_MAX_MM_MAP_POINTS  20
-
-
-  /* this structure is used to store the BlendDesignMap entry for an axis */
-  typedef struct  PS_DesignMap_
-  {
-    FT_Byte    num_points;
-    FT_Long*   design_points;
-    FT_Fixed*  blend_points;
-
-  } PS_DesignMapRec, *PS_DesignMap;
-
-  /* backward compatible definition */
-  typedef PS_DesignMapRec  T1_DesignMap;
-
-
-  typedef struct  PS_BlendRec_
-  {
-    FT_UInt          num_designs;
-    FT_UInt          num_axis;
-
-    FT_String*       axis_names[T1_MAX_MM_AXIS];
-    FT_Fixed*        design_pos[T1_MAX_MM_DESIGNS];
-    PS_DesignMapRec  design_map[T1_MAX_MM_AXIS];
-
-    FT_Fixed*        weight_vector;
-    FT_Fixed*        default_weight_vector;
-
-    PS_FontInfo      font_infos[T1_MAX_MM_DESIGNS + 1];
-    PS_Private       privates  [T1_MAX_MM_DESIGNS + 1];
-
-    FT_ULong         blend_bitflags;
-
-    FT_BBox*         bboxes    [T1_MAX_MM_DESIGNS + 1];
-
-    /* since 2.3.0 */
-
-    /* undocumented, optional: the default design instance;   */
-    /* corresponds to default_weight_vector --                */
-    /* num_default_design_vector == 0 means it is not present */
-    /* in the font and associated metrics files               */
-    FT_UInt          default_design_vector[T1_MAX_MM_DESIGNS];
-    FT_UInt          num_default_design_vector;
-
-  } PS_BlendRec, *PS_Blend;
-
-
-  /* backward compatible definition */
-  typedef PS_BlendRec  T1_Blend;
-
-
   /**************************************************************************
    *
    * @struct:
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/ttnameid.h b/src/java.desktop/share/native/libfreetype/include/freetype/ttnameid.h
index e31c68b9baf..d5d470e380f 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/ttnameid.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/ttnameid.h
@@ -4,7 +4,7 @@
  *
  *   TrueType name ID definitions (specification only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/tttables.h b/src/java.desktop/share/native/libfreetype/include/freetype/tttables.h
index a9f60e76201..2cf0ff1bc61 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/tttables.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/tttables.h
@@ -5,7 +5,7 @@
  *   Basic SFNT/TrueType tables definitions and interface
  *   (specification only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -838,8 +838,9 @@ FT_BEGIN_HEADER
    *     The target charmap.
    *
    * @return:
-   *   The format of `charmap`.  If `charmap` doesn't belong to an SFNT face,
-   *   return -1.
+   *   The format of `charmap`.  If `charmap` doesn't belong to an SFNT face
+   *   (including the synthetic Unicode charmap sometimes created by
+   *   FreeType), return -1.
    */
   FT_EXPORT( FT_Long )
   FT_Get_CMap_Format( FT_CharMap  charmap );
diff --git a/src/java.desktop/share/native/libfreetype/include/freetype/tttags.h b/src/java.desktop/share/native/libfreetype/include/freetype/tttags.h
index 9bf4fca23fb..da0af5d3f23 100644
--- a/src/java.desktop/share/native/libfreetype/include/freetype/tttags.h
+++ b/src/java.desktop/share/native/libfreetype/include/freetype/tttags.h
@@ -4,7 +4,7 @@
  *
  *   Tags for TrueType and OpenType tables (specification only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/include/ft2build.h b/src/java.desktop/share/native/libfreetype/include/ft2build.h
index 58491ceea1f..d3d7685039c 100644
--- a/src/java.desktop/share/native/libfreetype/include/ft2build.h
+++ b/src/java.desktop/share/native/libfreetype/include/ft2build.h
@@ -4,7 +4,7 @@
  *
  *   FreeType 2 build and setup macros.
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.c b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.c
index d7655b9b99e..ea83969cdc9 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.c
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.c
@@ -7,7 +7,7 @@
  *
  *   Auto-fitter data for blue strings (body).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.cin b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.cin
index d561c5093b7..d2270fac744 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.cin
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.cin
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter data for blue strings (body).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.dat b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.dat
index 8299baa2591..88bab2632ab 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.dat
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.dat
@@ -2,7 +2,7 @@
 //
 //   Auto-fitter data for blue strings.
 //
-// Copyright (C) 2013-2023 by
+// Copyright (C) 2013-2024 by
 // David Turner, Robert Wilhelm, and Werner Lemberg.
 //
 // This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.h b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.h
index 76f2f47cb00..2aa9d0984ef 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.h
@@ -7,7 +7,7 @@
  *
  *   Auto-fitter data for blue strings (specification).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.hin b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.hin
index 6a31298e65f..38031505a85 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afblue.hin
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afblue.hin
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter data for blue strings (specification).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.c b/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.c
index f414289adcd..869b60487c2 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.c
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.c
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter hinting routines for CJK writing system (body).
  *
- * Copyright (C) 2006-2023 by
+ * Copyright (C) 2006-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.h b/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.h
index f380ef6e032..bc5aaf12e6e 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afcjk.h
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter hinting routines for CJK writing system (specification).
  *
- * Copyright (C) 2006-2023 by
+ * Copyright (C) 2006-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -84,7 +84,7 @@ FT_BEGIN_HEADER
     /* used for horizontal metrics too for CJK */
     FT_Bool        control_overshoot;
     FT_UInt        blue_count;
-    AF_CJKBlueRec  blues[AF_BLUE_STRINGSET_MAX];
+    AF_CJKBlueRec  blues[AF_BLUE_STRINGSET_MAX_LEN];
 
     FT_Fixed       org_scale;
     FT_Pos         org_delta;
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afcover.h b/src/java.desktop/share/native/libfreetype/src/autofit/afcover.h
index 102ed427828..7980cf2e979 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afcover.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afcover.h
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter coverages (specification only).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.c b/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.c
index a4629b528dc..ad667d2edc7 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.c
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.c
@@ -5,7 +5,7 @@
  *   Auto-fitter dummy routines to be used if no hinting should be
  *   performed (body).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.h b/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.h
index a7af3f62c9e..613c2f88a38 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afdummy.h
@@ -5,7 +5,7 @@
  *   Auto-fitter dummy routines to be used if no hinting should be
  *   performed (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/aferrors.h b/src/java.desktop/share/native/libfreetype/src/autofit/aferrors.h
index 88faf05c950..ae584ff06db 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/aferrors.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/aferrors.h
@@ -4,7 +4,7 @@
  *
  *   Autofitter error codes (specification only).
  *
- * Copyright (C) 2005-2023 by
+ * Copyright (C) 2005-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.c b/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.c
index b1957570f03..b7403fa65e1 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.c
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.c
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter routines to compute global hinting values (body).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.h b/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.h
index 66170e419dd..ddb54c89b27 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afglobal.h
@@ -5,7 +5,7 @@
  *   Auto-fitter routines to compute global hinting values
  *   (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afhints.c b/src/java.desktop/share/native/libfreetype/src/autofit/afhints.c
index e4a378fbf74..96ffe343aa4 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afhints.c
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afhints.c
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter hinting routines (body).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -979,8 +979,8 @@
       /* compute coordinates & Bezier flags, next and prev */
       {
         FT_Vector*  vec           = outline->points;
-        char*       tag           = outline->tags;
-        FT_Short    endpoint      = outline->contours[0];
+        FT_Byte*    tag           = outline->tags;
+        FT_UShort   endpoint      = outline->contours[0];
         AF_Point    end           = points + endpoint;
         AF_Point    prev          = end;
         FT_Int      contour_index = 0;
@@ -1046,16 +1046,16 @@
 
       /* set up the contours array */
       {
-        AF_Point*  contour       = hints->contours;
-        AF_Point*  contour_limit = contour + hints->num_contours;
-        short*     end           = outline->contours;
-        short      idx           = 0;
+        AF_Point*   contour       = hints->contours;
+        AF_Point*   contour_limit = contour + hints->num_contours;
+        FT_UShort*  end           = outline->contours;
+        FT_Int      idx           = 0;
 
 
         for ( ; contour < contour_limit; contour++, end++ )
         {
           contour[0] = points + idx;
-          idx        = (short)( end[0] + 1 );
+          idx        = *end + 1;
         }
       }
 
@@ -1292,7 +1292,7 @@
     AF_Point    point = hints->points;
     AF_Point    limit = point + hints->num_points;
     FT_Vector*  vec   = outline->points;
-    char*       tag   = outline->tags;
+    FT_Byte*    tag   = outline->tags;
 
 
     for ( ; point < limit; point++, vec++, tag++ )
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afhints.h b/src/java.desktop/share/native/libfreetype/src/autofit/afhints.h
index d1cf9529bf1..76fe83006a5 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afhints.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afhints.h
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter hinting routines (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afindic.c b/src/java.desktop/share/native/libfreetype/src/autofit/afindic.c
index 7fb12c63d5a..c6d23efd86f 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afindic.c
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afindic.c
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter hinting routines for Indic writing system (body).
  *
- * Copyright (C) 2007-2023 by
+ * Copyright (C) 2007-2024 by
  * Rahul Bhalerao , .
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afindic.h b/src/java.desktop/share/native/libfreetype/src/autofit/afindic.h
index 3eb67f63b00..a7f73f25153 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afindic.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afindic.h
@@ -5,7 +5,7 @@
  *   Auto-fitter hinting routines for Indic writing system
  *   (specification).
  *
- * Copyright (C) 2007-2023 by
+ * Copyright (C) 2007-2024 by
  * Rahul Bhalerao , .
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.c b/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.c
index b86367aa94d..89287f7ea5a 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.c
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.c
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter hinting routines for latin writing system (body).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -981,7 +981,7 @@
       /* `ref' and `shoot' values of two blue zones must not overlap */
 
       FT_UInt       i;
-      AF_LatinBlue  blue_sorted[AF_BLUE_STRINGSET_MAX_LEN + 2];
+      AF_LatinBlue  blue_sorted[AF_BLUE_STRINGSET_MAX_LEN];
 
 
       for ( i = 0; i < axis->blue_count; i++ )
@@ -1263,10 +1263,9 @@
               max_height = FT_MAX( max_height, -Axis->blues[nn].descender );
             }
 
-            dist  = FT_ABS( FT_MulFix( max_height, new_scale - scale ) );
-            dist &= ~127;
+            dist  = FT_MulFix( max_height, new_scale - scale );
 
-            if ( dist == 0 )
+            if ( -128 < dist && dist < 128 )
             {
               FT_TRACE5(( "af_latin_metrics_scale_dim:"
                           " x height alignment (style `%s'):\n",
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.h b/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.h
index 31aa91d3bdb..54e50615021 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/aflatin.h
@@ -5,7 +5,7 @@
  *   Auto-fitter hinting routines for latin writing system
  *   (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -98,7 +98,7 @@ FT_BEGIN_HEADER
 
     /* ignored for horizontal metrics */
     FT_UInt          blue_count;
-    AF_LatinBlueRec  blues[AF_BLUE_STRINGSET_MAX];
+    AF_LatinBlueRec  blues[AF_BLUE_STRINGSET_MAX_LEN];
 
     FT_Fixed         org_scale;
     FT_Pos           org_delta;
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afloader.c b/src/java.desktop/share/native/libfreetype/src/autofit/afloader.c
index 7c47d562af6..af1d59a6896 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afloader.c
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afloader.c
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter glyph loading routines (body).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afloader.h b/src/java.desktop/share/native/libfreetype/src/autofit/afloader.h
index e4e197e374f..99f0e15f92b 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afloader.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afloader.h
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter glyph loading routines (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.c b/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.c
index 20a6b96bc4f..726f6ca2b78 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.c
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.c
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter module implementation (body).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -438,7 +438,7 @@
     AF_Module  module = (AF_Module)module_;
 
     FT_Error   error  = FT_Err_Ok;
-    FT_Memory  memory = module->root.library->memory;
+    FT_Memory  memory = module->root.memory;
 
 #ifdef FT_DEBUG_AUTOFIT
 
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.h b/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.h
index 4b8b4562c67..91a1abfef1f 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afmodule.h
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter module implementation (specification).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afranges.c b/src/java.desktop/share/native/libfreetype/src/autofit/afranges.c
index cfcaf340a79..007b4328189 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afranges.c
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afranges.c
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter Unicode script ranges (body).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afranges.h b/src/java.desktop/share/native/libfreetype/src/autofit/afranges.h
index 5775738bc0b..813b3ee78ef 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afranges.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afranges.h
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter Unicode script ranges (specification).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afscript.h b/src/java.desktop/share/native/libfreetype/src/autofit/afscript.h
index 3a101937d70..0a83d771501 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afscript.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afscript.h
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter scripts (specification only).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.c b/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.c
index abc6f1d292d..df0f46ada89 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.c
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.c
@@ -4,7 +4,7 @@
  *
  *   HarfBuzz interface for accessing OpenType features (body).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.h b/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.h
index 054a18ffbc2..2eb03bb5d98 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afshaper.h
@@ -4,7 +4,7 @@
  *
  *   HarfBuzz interface for accessing OpenType features (specification).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afstyles.h b/src/java.desktop/share/native/libfreetype/src/autofit/afstyles.h
index 73ebef01716..7a33f37a856 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afstyles.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afstyles.h
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter styles (specification only).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/aftypes.h b/src/java.desktop/share/native/libfreetype/src/autofit/aftypes.h
index 66151944965..27e4185e9f8 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/aftypes.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/aftypes.h
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter types (specification only).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afws-decl.h b/src/java.desktop/share/native/libfreetype/src/autofit/afws-decl.h
index 48c888afed8..b78745af74e 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afws-decl.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afws-decl.h
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter writing system declarations (specification only).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/autofit/afws-iter.h b/src/java.desktop/share/native/libfreetype/src/autofit/afws-iter.h
index a0a686f8cee..c86d609a352 100644
--- a/src/java.desktop/share/native/libfreetype/src/autofit/afws-iter.h
+++ b/src/java.desktop/share/native/libfreetype/src/autofit/afws-iter.h
@@ -4,7 +4,7 @@
  *
  *   Auto-fitter writing systems iterator (specification only).
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftadvanc.c b/src/java.desktop/share/native/libfreetype/src/base/ftadvanc.c
index de25476fe92..717f7d08b35 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftadvanc.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftadvanc.c
@@ -4,7 +4,7 @@
  *
  *   Quick computation of advance widths (body).
  *
- * Copyright (C) 2008-2023 by
+ * Copyright (C) 2008-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftbase.h b/src/java.desktop/share/native/libfreetype/src/base/ftbase.h
index 00790d3b226..1d98b26dd51 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftbase.h
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftbase.h
@@ -4,7 +4,7 @@
  *
  *   Private functions used in the `base' module (specification).
  *
- * Copyright (C) 2008-2023 by
+ * Copyright (C) 2008-2024 by
  * David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftbbox.c b/src/java.desktop/share/native/libfreetype/src/base/ftbbox.c
index 385fea40401..d6aa5d56df8 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftbbox.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftbbox.c
@@ -4,7 +4,7 @@
  *
  *   FreeType bbox computation (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used
@@ -489,7 +489,7 @@
       return FT_THROW( Invalid_Outline );
 
     /* if outline is empty, return (0,0,0,0) */
-    if ( outline->n_points == 0 || outline->n_contours <= 0 )
+    if ( outline->n_points == 0 || outline->n_contours == 0 )
     {
       abbox->xMin = abbox->xMax = 0;
       abbox->yMin = abbox->yMax = 0;
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftbitmap.c b/src/java.desktop/share/native/libfreetype/src/base/ftbitmap.c
index 1c93648dcbc..4be145679fd 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftbitmap.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftbitmap.c
@@ -4,7 +4,7 @@
  *
  *   FreeType utility functions for bitmaps (body).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftcalc.c b/src/java.desktop/share/native/libfreetype/src/base/ftcalc.c
index c5bc7e3b14e..92de09ed877 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftcalc.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftcalc.c
@@ -4,7 +4,7 @@
  *
  *   Arithmetic computations (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -69,13 +69,15 @@
 
   /* transfer sign, leaving a positive number;                        */
   /* we need an unsigned value to safely negate INT_MIN (or LONG_MIN) */
-#define FT_MOVE_SIGN( x, x_unsigned, s ) \
-  FT_BEGIN_STMNT                         \
-    if ( x < 0 )                         \
-    {                                    \
-      x_unsigned = 0U - (x_unsigned);    \
-      s          = -s;                   \
-    }                                    \
+#define FT_MOVE_SIGN( utype, x, x_unsigned, s ) \
+  FT_BEGIN_STMNT                                \
+    if ( x < 0 )                                \
+    {                                           \
+      x_unsigned = 0U - (utype)x;               \
+      s          = -s;                          \
+    }                                           \
+    else                                        \
+      x_unsigned = (utype)x;                    \
   FT_END_STMNT
 
   /* The following three functions are available regardless of whether */
@@ -179,13 +181,9 @@
     FT_Long    d_;
 
 
-    a = (FT_UInt64)a_;
-    b = (FT_UInt64)b_;
-    c = (FT_UInt64)c_;
-
-    FT_MOVE_SIGN( a_, a, s );
-    FT_MOVE_SIGN( b_, b, s );
-    FT_MOVE_SIGN( c_, c, s );
+    FT_MOVE_SIGN( FT_UInt64, a_, a, s );
+    FT_MOVE_SIGN( FT_UInt64, b_, b, s );
+    FT_MOVE_SIGN( FT_UInt64, c_, c, s );
 
     d = c > 0 ? ( a * b + ( c >> 1 ) ) / c
               : 0x7FFFFFFFUL;
@@ -208,13 +206,9 @@
     FT_Long    d_;
 
 
-    a = (FT_UInt64)a_;
-    b = (FT_UInt64)b_;
-    c = (FT_UInt64)c_;
-
-    FT_MOVE_SIGN( a_, a, s );
-    FT_MOVE_SIGN( b_, b, s );
-    FT_MOVE_SIGN( c_, c, s );
+    FT_MOVE_SIGN( FT_UInt64, a_, a, s );
+    FT_MOVE_SIGN( FT_UInt64, b_, b, s );
+    FT_MOVE_SIGN( FT_UInt64, c_, c, s );
 
     d = c > 0 ? a * b / c
               : 0x7FFFFFFFUL;
@@ -257,11 +251,8 @@
     FT_Long    q_;
 
 
-    a = (FT_UInt64)a_;
-    b = (FT_UInt64)b_;
-
-    FT_MOVE_SIGN( a_, a, s );
-    FT_MOVE_SIGN( b_, b, s );
+    FT_MOVE_SIGN( FT_UInt64, a_, a, s );
+    FT_MOVE_SIGN( FT_UInt64, b_, b, s );
 
     q = b > 0 ? ( ( a << 16 ) + ( b >> 1 ) ) / b
               : 0x7FFFFFFFUL;
@@ -422,13 +413,9 @@
 
     /* XXX: this function does not allow 64-bit arguments */
 
-    a = (FT_UInt32)a_;
-    b = (FT_UInt32)b_;
-    c = (FT_UInt32)c_;
-
-    FT_MOVE_SIGN( a_, a, s );
-    FT_MOVE_SIGN( b_, b, s );
-    FT_MOVE_SIGN( c_, c, s );
+    FT_MOVE_SIGN( FT_UInt32, a_, a, s );
+    FT_MOVE_SIGN( FT_UInt32, b_, b, s );
+    FT_MOVE_SIGN( FT_UInt32, c_, c, s );
 
     if ( c == 0 )
       a = 0x7FFFFFFFUL;
@@ -470,13 +457,9 @@
 
     /* XXX: this function does not allow 64-bit arguments */
 
-    a = (FT_UInt32)a_;
-    b = (FT_UInt32)b_;
-    c = (FT_UInt32)c_;
-
-    FT_MOVE_SIGN( a_, a, s );
-    FT_MOVE_SIGN( b_, b, s );
-    FT_MOVE_SIGN( c_, c, s );
+    FT_MOVE_SIGN( FT_UInt32, a_, a, s );
+    FT_MOVE_SIGN( FT_UInt32, b_, b, s );
+    FT_MOVE_SIGN( FT_UInt32, c_, c, s );
 
     if ( c == 0 )
       a = 0x7FFFFFFFUL;
@@ -575,11 +558,8 @@
 
     /* XXX: this function does not allow 64-bit arguments */
 
-    a = (FT_UInt32)a_;
-    b = (FT_UInt32)b_;
-
-    FT_MOVE_SIGN( a_, a, s );
-    FT_MOVE_SIGN( b_, b, s );
+    FT_MOVE_SIGN( FT_UInt32, a_, a, s );
+    FT_MOVE_SIGN( FT_UInt32, b_, b, s );
 
     if ( a + ( b >> 8 ) <= 8190UL )
       a = ( a * b + 0x8000UL ) >> 16;
@@ -614,11 +594,8 @@
 
     /* XXX: this function does not allow 64-bit arguments */
 
-    a = (FT_UInt32)a_;
-    b = (FT_UInt32)b_;
-
-    FT_MOVE_SIGN( a_, a, s );
-    FT_MOVE_SIGN( b_, b, s );
+    FT_MOVE_SIGN( FT_UInt32, a_, a, s );
+    FT_MOVE_SIGN( FT_UInt32, b_, b, s );
 
     if ( b == 0 )
     {
@@ -829,11 +806,8 @@
     FT_Int     sx = 1, sy = 1, shift;
 
 
-    x = (FT_UInt32)x_;
-    y = (FT_UInt32)y_;
-
-    FT_MOVE_SIGN( x_, x, sx );
-    FT_MOVE_SIGN( y_, y, sy );
+    FT_MOVE_SIGN( FT_UInt32, x_, x, sx );
+    FT_MOVE_SIGN( FT_UInt32, y_, y, sy );
 
     /* trivial cases */
     if ( x == 0 )
@@ -913,43 +887,71 @@
   }
 
 
-#if 0
-
   /* documentation is in ftcalc.h */
 
-  FT_BASE_DEF( FT_Int32 )
-  FT_SqrtFixed( FT_Int32  x )
+  FT_BASE_DEF( FT_UInt32 )
+  FT_SqrtFixed( FT_UInt32  v )
   {
-    FT_UInt32  root, rem_hi, rem_lo, test_div;
-    FT_Int     count;
-
+    if ( v == 0 )
+      return 0;
 
-    root = 0;
+#ifndef FT_INT64
 
-    if ( x > 0 )
+    /* Algorithm by Christophe Meessen (1993) with overflow fixed and     */
+    /* rounding added.  Any unsigned fixed 16.16 argument is acceptable.  */
+    /* However, this algorithm is slower than the Babylonian method with  */
+    /* a good initial guess.  We only use it for large 32-bit values when */
+    /* 64-bit computations are not desirable.                             */
+    else if ( v > 0x10000U )
     {
-      rem_hi = 0;
-      rem_lo = (FT_UInt32)x;
-      count  = 24;
+      FT_UInt32  r = v >> 1;
+      FT_UInt32  q = ( v & 1 ) << 15;
+      FT_UInt32  b = 0x20000000;
+      FT_UInt32  t;
+
+
       do
       {
-        rem_hi   = ( rem_hi << 2 ) | ( rem_lo >> 30 );
-        rem_lo <<= 2;
-        root   <<= 1;
-        test_div = ( root << 1 ) + 1;
-
-        if ( rem_hi >= test_div )
+        t = q + b;
+        if ( r >= t )
         {
-          rem_hi -= test_div;
-          root   += 1;
+          r -= t;
+          q  = t + b;  /* equivalent to q += 2*b */
         }
-      } while ( --count );
+        r <<= 1;
+        b >>= 1;
+
+      } while ( b > 0x10 );  /* exactly 25 cycles */
+
+      return ( q + 0x40 ) >> 7;
     }
+    else
+    {
+      FT_UInt32  r = ( v << 16 ) - 1;
 
-    return (FT_Int32)root;
-  }
+#else /* FT_INT64 */
 
-#endif /* 0 */
+    else
+    {
+      FT_UInt64  r = ( (FT_UInt64)v << 16 ) - 1;
+
+#endif /* FT_INT64 */
+
+      FT_UInt32  q = 1 << ( ( 17 + FT_MSB( v ) ) >> 1 );
+      FT_UInt32  t;
+
+
+      /* Babylonian method with rounded-up division */
+      do
+      {
+        t = q;
+        q = ( t + (FT_UInt32)( r / t ) + 1 ) >> 1;
+
+      } while ( q != t );  /* less than 6 cycles */
+
+      return q;
+    }
+  }
 
 
   /* documentation is in ftcalc.h */
@@ -1094,11 +1096,8 @@
       FT_UInt32  factor;
 
 
-      scalar = (FT_UInt32)s[i];
-      factor = (FT_UInt32)f[i];
-
-      FT_MOVE_SIGN( s[i], scalar, sign );
-      FT_MOVE_SIGN( f[i], factor, sign );
+      FT_MOVE_SIGN( FT_UInt32, s[i], scalar, sign );
+      FT_MOVE_SIGN( FT_UInt32, f[i], factor, sign );
 
       ft_multo64( scalar, factor, &multResult );
 
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftcid.c b/src/java.desktop/share/native/libfreetype/src/base/ftcid.c
index 866cd23e91b..4f2deb19a05 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftcid.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftcid.c
@@ -4,7 +4,7 @@
  *
  *   FreeType API for accessing CID font information.
  *
- * Copyright (C) 2007-2023 by
+ * Copyright (C) 2007-2024 by
  * Derek Clegg and Michael Toftdal.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftcolor.c b/src/java.desktop/share/native/libfreetype/src/base/ftcolor.c
index bcd6e893d4a..c6bf2a3cd1a 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftcolor.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftcolor.c
@@ -4,7 +4,7 @@
  *
  *   FreeType's glyph color management (body).
  *
- * Copyright (C) 2018-2023 by
+ * Copyright (C) 2018-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftdbgmem.c b/src/java.desktop/share/native/libfreetype/src/base/ftdbgmem.c
index 8fab50dd017..902a5dc8bbc 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftdbgmem.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftdbgmem.c
@@ -4,7 +4,7 @@
  *
  *   Memory debugger (body).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftdebug.c b/src/java.desktop/share/native/libfreetype/src/base/ftdebug.c
index 61c4563b0c4..11307eaace4 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftdebug.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftdebug.c
@@ -4,7 +4,7 @@
  *
  *   Debugging and logging component (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftfntfmt.c b/src/java.desktop/share/native/libfreetype/src/base/ftfntfmt.c
index 0b41f7cc83d..77b4089e7e2 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftfntfmt.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftfntfmt.c
@@ -4,7 +4,7 @@
  *
  *   FreeType utility file for font formats (body).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftfstype.c b/src/java.desktop/share/native/libfreetype/src/base/ftfstype.c
index ea24e64c6ea..1565c3b7e25 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftfstype.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftfstype.c
@@ -4,7 +4,7 @@
  *
  *   FreeType utility file to access FSType data (body).
  *
- * Copyright (C) 2008-2023 by
+ * Copyright (C) 2008-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftgasp.c b/src/java.desktop/share/native/libfreetype/src/base/ftgasp.c
index 29b7b08b787..c63d30e978c 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftgasp.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftgasp.c
@@ -4,7 +4,7 @@
  *
  *   Access of TrueType's `gasp' table (body).
  *
- * Copyright (C) 2007-2023 by
+ * Copyright (C) 2007-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftgloadr.c b/src/java.desktop/share/native/libfreetype/src/base/ftgloadr.c
index 9823d09e41a..484d98f1722 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftgloadr.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftgloadr.c
@@ -4,7 +4,7 @@
  *
  *   The FreeType glyph loader (body).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg
  *
  * This file is part of the FreeType project, and may only be used,
@@ -355,34 +355,25 @@
   FT_BASE_DEF( void )
   FT_GlyphLoader_Add( FT_GlyphLoader  loader )
   {
-    FT_GlyphLoad  base;
-    FT_GlyphLoad  current;
-
-    FT_Int        n_curr_contours;
-    FT_Int        n_base_points;
-    FT_Int        n;
+    FT_Outline*  base;
+    FT_Outline*  current;
+    FT_Int       n;
 
 
     if ( !loader )
       return;
 
-    base    = &loader->base;
-    current = &loader->current;
-
-    n_curr_contours = current->outline.n_contours;
-    n_base_points   = base->outline.n_points;
+    base    = &loader->base.outline;
+    current = &loader->current.outline;
 
-    base->outline.n_points =
-      (short)( base->outline.n_points + current->outline.n_points );
-    base->outline.n_contours =
-      (short)( base->outline.n_contours + current->outline.n_contours );
+    /* adjust contours count in newest outline */
+    for ( n = 0; n < current->n_contours; n++ )
+      current->contours[n] += base->n_points;
 
-    base->num_subglyphs += current->num_subglyphs;
+    base->n_points   += current->n_points;
+    base->n_contours += current->n_contours;
 
-    /* adjust contours count in newest outline */
-    for ( n = 0; n < n_curr_contours; n++ )
-      current->outline.contours[n] =
-        (short)( current->outline.contours[n] + n_base_points );
+    loader->base.num_subglyphs += loader->current.num_subglyphs;
 
     /* prepare for another new glyph image */
     FT_GlyphLoader_Prepare( loader );
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftglyph.c b/src/java.desktop/share/native/libfreetype/src/base/ftglyph.c
index 393d4949f84..1b5849f99af 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftglyph.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftglyph.c
@@ -4,7 +4,7 @@
  *
  *   FreeType convenience functions to handle glyphs (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftinit.c b/src/java.desktop/share/native/libfreetype/src/base/ftinit.c
index c9c71d24bf9..9a6c00e13ef 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftinit.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftinit.c
@@ -4,7 +4,7 @@
  *
  *   FreeType initialization layer (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftlcdfil.c b/src/java.desktop/share/native/libfreetype/src/base/ftlcdfil.c
index 6c3fd66e0bb..1e69d4da70f 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftlcdfil.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftlcdfil.c
@@ -4,7 +4,7 @@
  *
  *   FreeType API for color filtering of subpixel bitmap glyphs (body).
  *
- * Copyright (C) 2006-2023 by
+ * Copyright (C) 2006-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftmac.c b/src/java.desktop/share/native/libfreetype/src/base/ftmac.c
index 492d0553845..e8e35627b50 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftmac.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftmac.c
@@ -8,7 +8,7 @@
  * This file is for Mac OS X only; see builds/mac/ftoldmac.c for
  * classic platforms built by MPW.
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -812,6 +812,7 @@
     ResourceIndex  res_index;
     Handle         fond;
     short          num_faces_in_res;
+    FT_Long        count;
 
 
     if ( noErr != FT_FSPathMakeRes( pathname, &res_ref ) )
@@ -821,8 +822,10 @@
     if ( ResError() )
       return FT_THROW( Cannot_Open_Resource );
 
+    res_index        = 1;
     num_faces_in_res = 0;
-    for ( res_index = 1; ; res_index++ )
+    count            = face_index;
+    while ( count >= 0 )
     {
       short  num_faces_in_fond;
 
@@ -834,15 +837,21 @@
       num_faces_in_fond  = count_faces( fond, pathname );
       num_faces_in_res  += num_faces_in_fond;
 
-      if ( 0 <= face_index && face_index < num_faces_in_fond && error )
-        error = FT_New_Face_From_FOND( library, fond, face_index, aface );
+      if ( count < num_faces_in_fond )
+        error = FT_New_Face_From_FOND( library, fond, count, aface );
 
-      face_index -= num_faces_in_fond;
+      res_index++;
+      count -= num_faces_in_fond;
     }
 
     CloseResFile( res_ref );
+
     if ( !error && aface && *aface )
-      (*aface)->num_faces = num_faces_in_res;
+    {
+      (*aface)->num_faces  = num_faces_in_res;
+      (*aface)->face_index = face_index;
+    }
+
     return error;
   }
 
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftmm.c b/src/java.desktop/share/native/libfreetype/src/base/ftmm.c
index 9e2dd7ee79d..cc4ca22fba3 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftmm.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftmm.c
@@ -4,7 +4,7 @@
  *
  *   Multiple Master font support (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftobjs.c b/src/java.desktop/share/native/libfreetype/src/base/ftobjs.c
index 89a25bc732d..9b97820c379 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftobjs.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftobjs.c
@@ -4,7 +4,7 @@
  *
  *   The FreeType private base classes (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -2302,7 +2302,10 @@
                                       face_index_internal, aface );
       FT_FREE( data_offsets );
       if ( !error )
-        (*aface)->num_faces = count;
+      {
+        (*aface)->num_faces  = count;
+        (*aface)->face_index = face_index_internal;
+      }
     }
 
     return error;
@@ -5791,7 +5794,7 @@
     ttface = (TT_Face)face;
     sfnt   = (SFNT_Service)ttface->sfnt;
 
-    if ( sfnt->get_colr_layer )
+    if ( sfnt->get_colr_glyph_paint )
       return sfnt->get_colr_glyph_paint( ttface,
                                          base_glyph,
                                          root_transform,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftoutln.c b/src/java.desktop/share/native/libfreetype/src/base/ftoutln.c
index 134f39d2b1f..ef699b3c7cd 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftoutln.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftoutln.c
@@ -4,7 +4,7 @@
  *
  *   FreeType outline management (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -53,7 +53,7 @@
 
     FT_Vector*  point;
     FT_Vector*  limit;
-    char*       tags;
+    FT_Byte*    tags;
 
     FT_Error    error;
 
@@ -332,8 +332,8 @@
          FT_NEW_ARRAY( anoutline->contours, numContours ) )
       goto Fail;
 
-    anoutline->n_points    = (FT_Short)numPoints;
-    anoutline->n_contours  = (FT_Short)numContours;
+    anoutline->n_points    = (FT_UShort)numPoints;
+    anoutline->n_contours  = (FT_UShort)numContours;
     anoutline->flags      |= FT_OUTLINE_OWNER;
 
     return FT_Err_Ok;
@@ -359,12 +359,14 @@
       FT_Int  n;
 
 
+      FT_TRACE5(( "FT_Outline_Check: contours = %d, points = %d\n",
+                  n_contours, n_points ));
       /* empty glyph? */
       if ( n_points == 0 && n_contours == 0 )
         return FT_Err_Ok;
 
       /* check point and contour counts */
-      if ( n_points <= 0 || n_contours <= 0 )
+      if ( n_points == 0 || n_contours == 0 )
         goto Bad;
 
       end0 = -1;
@@ -576,13 +578,13 @@
 
       /* reverse tags table */
       {
-        char*  p = outline->tags + first;
-        char*  q = outline->tags + last;
+        FT_Byte*  p = outline->tags + first;
+        FT_Byte*  q = outline->tags + last;
 
 
         while ( p < q )
         {
-          char  swap;
+          FT_Byte  swap;
 
 
           swap = *p;
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftpatent.c b/src/java.desktop/share/native/libfreetype/src/base/ftpatent.c
index cb5efadffb1..2055757e023 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftpatent.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftpatent.c
@@ -5,7 +5,7 @@
  *   FreeType API for checking patented TrueType bytecode instructions
  *   (body).  Obsolete, retained for backward compatibility.
  *
- * Copyright (C) 2007-2023 by
+ * Copyright (C) 2007-2024 by
  * David Turner.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftpsprop.c b/src/java.desktop/share/native/libfreetype/src/base/ftpsprop.c
index cefdf489d7f..37a6cee6cc9 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftpsprop.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftpsprop.c
@@ -5,7 +5,7 @@
  *   Get and set properties of PostScript drivers (body).
  *   See `ftdriver.h' for available properties.
  *
- * Copyright (C) 2017-2023 by
+ * Copyright (C) 2017-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftrfork.c b/src/java.desktop/share/native/libfreetype/src/base/ftrfork.c
index 2ab430195f2..dc9b043d8bb 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftrfork.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftrfork.c
@@ -4,7 +4,7 @@
  *
  *   Embedded resource forks accessor (body).
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * Masatake YAMATO and Redhat K.K.
  *
  * FT_Raccess_Get_HeaderInfo() and raccess_guess_darwin_hfsplus() are
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftsnames.c b/src/java.desktop/share/native/libfreetype/src/base/ftsnames.c
index 1917a3f1dff..f7231fd61cc 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftsnames.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftsnames.c
@@ -7,7 +7,7 @@
  *
  *   This is _not_ used to retrieve glyph names!
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftstream.c b/src/java.desktop/share/native/libfreetype/src/base/ftstream.c
index 64826acebe5..66722246128 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftstream.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftstream.c
@@ -4,7 +4,7 @@
  *
  *   I/O stream support (body).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -763,10 +763,10 @@
       case ft_frame_bytes:  /* read a byte sequence */
       case ft_frame_skip:   /* skip some bytes      */
         {
-          FT_UInt  len = fields->size;
+          FT_Offset  len = fields->size;
 
 
-          if ( cursor + len > stream->limit )
+          if ( len > (FT_Offset)( stream->limit - cursor ) )
           {
             error = FT_THROW( Invalid_Stream_Operation );
             goto Exit;
@@ -830,7 +830,7 @@
         goto Exit;
       }
 
-      /* now, compute the signed value is necessary */
+      /* now, compute the signed value if necessary */
       if ( fields->value & FT_FRAME_OP_SIGNED )
         value = (FT_ULong)( (FT_Int32)( value << sign_shift ) >> sign_shift );
 
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftstroke.c b/src/java.desktop/share/native/libfreetype/src/base/ftstroke.c
index 92f1e43080f..64f46ce43e7 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftstroke.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftstroke.c
@@ -4,7 +4,7 @@
  *
  *   FreeType path stroker (body).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -711,7 +711,7 @@
     {
       FT_UInt   count = border->num_points;
       FT_Byte*  read  = border->tags;
-      FT_Byte*  write = (FT_Byte*)outline->tags + outline->n_points;
+      FT_Byte*  write = outline->tags + outline->n_points;
 
 
       for ( ; count > 0; count--, read++, write++ )
@@ -727,10 +727,10 @@
 
     /* copy contours */
     {
-      FT_UInt    count = border->num_points;
-      FT_Byte*   tags  = border->tags;
-      FT_Short*  write = outline->contours + outline->n_contours;
-      FT_Short   idx   = (FT_Short)outline->n_points;
+      FT_UInt     count = border->num_points;
+      FT_Byte*    tags  = border->tags;
+      FT_UShort*  write = outline->contours + outline->n_contours;
+      FT_UShort   idx   = outline->n_points;
 
 
       for ( ; count > 0; count--, tags++, idx++ )
@@ -743,7 +743,7 @@
       }
     }
 
-    outline->n_points += (short)border->num_points;
+    outline->n_points += (FT_UShort)border->num_points;
 
     FT_ASSERT( FT_Outline_Check( outline ) == 0 );
   }
@@ -2050,7 +2050,7 @@
 
     FT_Vector*  point;
     FT_Vector*  limit;
-    char*       tags;
+    FT_Byte*    tags;
 
     FT_Error    error;
 
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftsynth.c b/src/java.desktop/share/native/libfreetype/src/base/ftsynth.c
index f32edd3388b..ec05bce33a9 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftsynth.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftsynth.c
@@ -4,7 +4,7 @@
  *
  *   FreeType synthesizing code for emboldening and slanting (body).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftsystem.c b/src/java.desktop/share/native/libfreetype/src/base/ftsystem.c
index 61c99e36357..eee3642334f 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftsystem.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftsystem.c
@@ -4,7 +4,7 @@
  *
  *   ANSI-specific FreeType low-level system interface (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/fttrigon.c b/src/java.desktop/share/native/libfreetype/src/base/fttrigon.c
index 2dd2c3459e5..4b1aced1cba 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/fttrigon.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/fttrigon.c
@@ -4,7 +4,7 @@
  *
  *   FreeType trigonometric functions (body).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/fttype1.c b/src/java.desktop/share/native/libfreetype/src/base/fttype1.c
index 637c5cf775e..cedf7c40505 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/fttype1.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/fttype1.c
@@ -4,7 +4,7 @@
  *
  *   FreeType utility file for PS names support (body).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/base/ftutil.c b/src/java.desktop/share/native/libfreetype/src/base/ftutil.c
index 6120846d2ca..b13512f8704 100644
--- a/src/java.desktop/share/native/libfreetype/src/base/ftutil.c
+++ b/src/java.desktop/share/native/libfreetype/src/base/ftutil.c
@@ -4,7 +4,7 @@
  *
  *   FreeType utility file for memory and list management (body).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.c b/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.c
index 10d287bc81f..ea5f8ed2885 100644
--- a/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.c
+++ b/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.c
@@ -4,7 +4,7 @@
  *
  *   CFF character mapping table (cmap) support (body).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.h b/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.h
index b2afc2fab62..1dd8700cd8b 100644
--- a/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.h
+++ b/src/java.desktop/share/native/libfreetype/src/cff/cffcmap.h
@@ -4,7 +4,7 @@
  *
  *   CFF character mapping table (cmap) support (specification).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.c b/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.c
index 9898d625ca4..f6ebdb3810a 100644
--- a/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.c
+++ b/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.c
@@ -4,7 +4,7 @@
  *
  *   OpenType font driver implementation (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, Werner Lemberg, and Dominik Röttsches.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.h b/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.h
index ab1f147bb2a..fd5bc37ecd4 100644
--- a/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.h
+++ b/src/java.desktop/share/native/libfreetype/src/cff/cffdrivr.h
@@ -4,7 +4,7 @@
  *
  *   High-level OpenType driver interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cfferrs.h b/src/java.desktop/share/native/libfreetype/src/cff/cfferrs.h
index bc9a3043fcf..128adc3b716 100644
--- a/src/java.desktop/share/native/libfreetype/src/cff/cfferrs.h
+++ b/src/java.desktop/share/native/libfreetype/src/cff/cfferrs.h
@@ -4,7 +4,7 @@
  *
  *   CFF error codes (specification only).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffgload.c b/src/java.desktop/share/native/libfreetype/src/cff/cffgload.c
index c483d1d1a59..cbb071abdfe 100644
--- a/src/java.desktop/share/native/libfreetype/src/cff/cffgload.c
+++ b/src/java.desktop/share/native/libfreetype/src/cff/cffgload.c
@@ -4,7 +4,7 @@
  *
  *   OpenType Glyph Loader (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffgload.h b/src/java.desktop/share/native/libfreetype/src/cff/cffgload.h
index 3b8cf236ddc..346d4b11c31 100644
--- a/src/java.desktop/share/native/libfreetype/src/cff/cffgload.h
+++ b/src/java.desktop/share/native/libfreetype/src/cff/cffgload.h
@@ -4,7 +4,7 @@
  *
  *   OpenType Glyph Loader (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffload.c b/src/java.desktop/share/native/libfreetype/src/cff/cffload.c
index af79082e98c..979fd45f6ca 100644
--- a/src/java.desktop/share/native/libfreetype/src/cff/cffload.c
+++ b/src/java.desktop/share/native/libfreetype/src/cff/cffload.c
@@ -4,7 +4,7 @@
  *
  *   OpenType and CFF data/program tables loader (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -1202,17 +1202,21 @@
         {
           CFF_AxisCoords*  axis = ®ion->axisList[j];
 
-          FT_Int16  start14, peak14, end14;
+          FT_Int  start, peak, end;
 
 
-          if ( FT_READ_SHORT( start14 ) ||
-               FT_READ_SHORT( peak14 )  ||
-               FT_READ_SHORT( end14 )   )
+          if ( FT_READ_SHORT( start ) ||
+               FT_READ_SHORT( peak )  ||
+               FT_READ_SHORT( end )   )
             goto Exit;
 
-          axis->startCoord = FT_fdot14ToFixed( start14 );
-          axis->peakCoord  = FT_fdot14ToFixed( peak14 );
-          axis->endCoord   = FT_fdot14ToFixed( end14 );
+          /* immediately tag invalid ranges with special peak = 0 */
+          if ( ( start < 0 && end > 0 ) || start > peak || peak > end )
+            peak = 0;
+
+          axis->startCoord = FT_fdot14ToFixed( start );
+          axis->peakCoord  = FT_fdot14ToFixed( peak );
+          axis->endCoord   = FT_fdot14ToFixed( end );
         }
       }
 
@@ -1379,10 +1383,10 @@
       /* opcode in both CFF and CFF2 DICTs.  See `cff_parse_num' for    */
       /* decode of this, which rounds to an integer.                    */
       *subFont->blend_top++ = 255;
-      *subFont->blend_top++ = (FT_Byte)( sum >> 24 );
-      *subFont->blend_top++ = (FT_Byte)( sum >> 16 );
-      *subFont->blend_top++ = (FT_Byte)( sum >>  8 );
-      *subFont->blend_top++ = (FT_Byte)sum;
+      *subFont->blend_top++ = (FT_Byte)( (FT_UInt32)sum >> 24 );
+      *subFont->blend_top++ = (FT_Byte)( (FT_UInt32)sum >> 16 );
+      *subFont->blend_top++ = (FT_Byte)( (FT_UInt32)sum >>  8 );
+      *subFont->blend_top++ = (FT_Byte)( (FT_UInt32)sum );
     }
 
     /* leave only numBlends results on parser stack */
@@ -1495,44 +1499,31 @@
       for ( j = 0; j < lenNDV; j++ )
       {
         CFF_AxisCoords*  axis = &varRegion->axisList[j];
-        FT_Fixed         axisScalar;
-
-
-        /* compute the scalar contribution of this axis; */
-        /* ignore invalid ranges                         */
-        if ( axis->startCoord > axis->peakCoord ||
-             axis->peakCoord > axis->endCoord   )
-          axisScalar = FT_FIXED_ONE;
 
-        else if ( axis->startCoord < 0 &&
-                  axis->endCoord > 0   &&
-                  axis->peakCoord != 0 )
-          axisScalar = FT_FIXED_ONE;
 
-        /* peak of 0 means ignore this axis */
-        else if ( axis->peakCoord == 0 )
-          axisScalar = FT_FIXED_ONE;
+        /* compute the scalar contribution of this axis */
+        /* with peak of 0 used for invalid axes         */
+        if ( axis->peakCoord == NDV[j] ||
+             axis->peakCoord == 0      )
+          continue;
 
         /* ignore this region if coords are out of range */
-        else if ( NDV[j] < axis->startCoord ||
-                  NDV[j] > axis->endCoord   )
-          axisScalar = 0;
-
-        /* calculate a proportional factor */
-        else
+        else if ( NDV[j] <= axis->startCoord ||
+                  NDV[j] >= axis->endCoord   )
         {
-          if ( NDV[j] == axis->peakCoord )
-            axisScalar = FT_FIXED_ONE;
-          else if ( NDV[j] < axis->peakCoord )
-            axisScalar = FT_DivFix( NDV[j] - axis->startCoord,
-                                    axis->peakCoord - axis->startCoord );
-          else
-            axisScalar = FT_DivFix( axis->endCoord - NDV[j],
-                                    axis->endCoord - axis->peakCoord );
+          blend->BV[master] = 0;
+          break;
         }
 
-        /* take product of all the axis scalars */
-        blend->BV[master] = FT_MulFix( blend->BV[master], axisScalar );
+        /* adjust proportionally */
+        else if ( NDV[j] < axis->peakCoord )
+          blend->BV[master] = FT_MulDiv( blend->BV[master],
+                                         NDV[j] - axis->startCoord,
+                                         axis->peakCoord - axis->startCoord );
+        else   /* NDV[j] > axis->peakCoord ) */
+          blend->BV[master] = FT_MulDiv( blend->BV[master],
+                                         axis->endCoord - NDV[j],
+                                         axis->endCoord - axis->peakCoord );
       }
 
       FT_TRACE4(( ", %f ",
diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffload.h b/src/java.desktop/share/native/libfreetype/src/cff/cffload.h
index b5286b0c8cb..02209245421 100644
--- a/src/java.desktop/share/native/libfreetype/src/cff/cffload.h
+++ b/src/java.desktop/share/native/libfreetype/src/cff/cffload.h
@@ -4,7 +4,7 @@
  *
  *   OpenType & CFF data/program tables loader (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.c b/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.c
index 6d08620c487..7c6713739a1 100644
--- a/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.c
+++ b/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.c
@@ -4,7 +4,7 @@
  *
  *   OpenType objects manager (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -42,6 +42,8 @@
 #include 
 #include 
 
+#define CFF_fixedToInt( x )                          \
+          ( (FT_Short)( ( (x) + 0x8000U ) >> 16 ) )
 
   /**************************************************************************
    *
@@ -124,19 +126,20 @@
 
     count = priv->num_blue_values = cpriv->num_blue_values;
     for ( n = 0; n < count; n++ )
-      priv->blue_values[n] = (FT_Short)cpriv->blue_values[n];
+      priv->blue_values[n] = CFF_fixedToInt( cpriv->blue_values[n] );
 
     count = priv->num_other_blues = cpriv->num_other_blues;
     for ( n = 0; n < count; n++ )
-      priv->other_blues[n] = (FT_Short)cpriv->other_blues[n];
+      priv->other_blues[n] = CFF_fixedToInt( cpriv->other_blues[n] );
 
     count = priv->num_family_blues = cpriv->num_family_blues;
     for ( n = 0; n < count; n++ )
-      priv->family_blues[n] = (FT_Short)cpriv->family_blues[n];
+      priv->family_blues[n] = CFF_fixedToInt( cpriv->family_blues[n] );
 
     count = priv->num_family_other_blues = cpriv->num_family_other_blues;
     for ( n = 0; n < count; n++ )
-      priv->family_other_blues[n] = (FT_Short)cpriv->family_other_blues[n];
+      priv->family_other_blues[n] =
+        CFF_fixedToInt( cpriv->family_other_blues[n] );
 
     priv->blue_scale = cpriv->blue_scale;
     priv->blue_shift = (FT_Int)cpriv->blue_shift;
@@ -421,32 +424,23 @@
   static void
   remove_subset_prefix( FT_String*  name )
   {
-    FT_Int32  idx             = 0;
-    FT_Int32  length          = (FT_Int32)ft_strlen( name ) + 1;
-    FT_Bool   continue_search = 1;
+    FT_UInt32  i = 0, idx = 0;
 
 
-    while ( continue_search )
+    /* six ASCII uppercase letters followed by a plus sign */
+    while ( 'A' <= name[i] && name[i++] <= 'Z' &&
+            'A' <= name[i] && name[i++] <= 'Z' &&
+            'A' <= name[i] && name[i++] <= 'Z' &&
+            'A' <= name[i] && name[i++] <= 'Z' &&
+            'A' <= name[i] && name[i++] <= 'Z' &&
+            'A' <= name[i] && name[i++] <= 'Z' &&
+                              name[i++] == '+' )
     {
-      if ( length >= 7 && name[6] == '+' )
-      {
-        for ( idx = 0; idx < 6; idx++ )
-        {
-          /* ASCII uppercase letters */
-          if ( !( 'A' <= name[idx] && name[idx] <= 'Z' ) )
-            continue_search = 0;
-        }
-
-        if ( continue_search )
-        {
-          for ( idx = 7; idx < length; idx++ )
-            name[idx - 7] = name[idx];
-          length -= 7;
-        }
-      }
-      else
-        continue_search = 0;
+      idx = i;
     }
+
+    if ( idx )
+      FT_MEM_MOVE( name, name + idx, ft_strlen( name + idx ) + 1 );
   }
 
 
@@ -456,42 +450,20 @@
   remove_style( FT_String*        family_name,
                 const FT_String*  style_name )
   {
-    FT_Int32  family_name_length, style_name_length;
+    FT_String*        f = family_name + ft_strlen( family_name );
+    const FT_String*  s =  style_name + ft_strlen(  style_name );
 
 
-    family_name_length = (FT_Int32)ft_strlen( family_name );
-    style_name_length  = (FT_Int32)ft_strlen( style_name );
+    /* compare strings moving backwards */
+    while ( s > style_name )
+      if ( f == family_name || *--s != *--f )
+        return;
 
-    if ( family_name_length > style_name_length )
-    {
-      FT_Int  idx;
-
-
-      for ( idx = 1; idx <= style_name_length; idx++ )
-      {
-        if ( family_name[family_name_length - idx] !=
-             style_name[style_name_length - idx] )
-          break;
-      }
-
-      if ( idx > style_name_length )
-      {
-        /* family_name ends with style_name; remove it */
-        idx = family_name_length - style_name_length - 1;
-
-        /* also remove special characters     */
-        /* between real family name and style */
-        while ( idx > 0                     &&
-                ( family_name[idx] == '-' ||
-                  family_name[idx] == ' ' ||
-                  family_name[idx] == '_' ||
-                  family_name[idx] == '+' ) )
-          idx--;
-
-        if ( idx > 0 )
-          family_name[idx + 1] = '\0';
-      }
-    }
+    /* terminate and remove special characters */
+    do
+      *f = '\0';
+    while ( f-- > family_name                                    &&
+            ( *f == '-' || *f == ' ' || *f == '_' || *f == '+' ) );
   }
 
 
@@ -722,8 +694,7 @@
         FT_UInt  instance_index = (FT_UInt)face_index >> 16;
 
 
-        if ( FT_HAS_MULTIPLE_MASTERS( cffface ) &&
-             instance_index > 0                 )
+        if ( FT_HAS_MULTIPLE_MASTERS( cffface ) )
         {
           error = FT_Set_Named_Instance( cffface, instance_index );
           if ( error )
diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.h b/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.h
index 8f05f6132bc..91ad83b1cd0 100644
--- a/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.h
+++ b/src/java.desktop/share/native/libfreetype/src/cff/cffobjs.h
@@ -4,7 +4,7 @@
  *
  *   OpenType objects manager (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffparse.c b/src/java.desktop/share/native/libfreetype/src/cff/cffparse.c
index 3b076704cf7..92a69c3b516 100644
--- a/src/java.desktop/share/native/libfreetype/src/cff/cffparse.c
+++ b/src/java.desktop/share/native/libfreetype/src/cff/cffparse.c
@@ -4,7 +4,7 @@
  *
  *   CFF token stream parser (body)
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -501,10 +501,10 @@
       return cff_parse_real( *d, parser->limit, scaling, NULL );
     else if ( **d == 255 )
     {
-      FT_Fixed val = ( ( ( (FT_UInt32)*( d[0] + 1 ) << 24 ) |
-                         ( (FT_UInt32)*( d[0] + 2 ) << 16 ) |
-                         ( (FT_UInt32)*( d[0] + 3 ) <<  8 ) |
-                           (FT_UInt32)*( d[0] + 4 )         ) );
+      FT_Fixed val = (FT_Int32)( ( ( (FT_UInt32)*( d[0] + 1 ) << 24 ) |
+                                   ( (FT_UInt32)*( d[0] + 2 ) << 16 ) |
+                                   ( (FT_UInt32)*( d[0] + 3 ) <<  8 ) |
+                                     (FT_UInt32)*( d[0] + 4 )         ) );
 
       if ( scaling )
       {
@@ -1031,10 +1031,14 @@
           CFF_FIELD( code, name, id, cff_kind_string )
 #define CFF_FIELD_BOOL( code, name, id )             \
           CFF_FIELD( code, name, id, cff_kind_bool )
+#define CFF_FIELD_DELTA( code, name, max, id )                        \
+          CFF_FIELD_DELTA_KIND( code, name, max, id, cff_kind_delta )
+#define CFF_FIELD_DELTA_FIXED( code, name, max, id )                        \
+          CFF_FIELD_DELTA_KIND( code, name, max, id, cff_kind_delta_fixed )
 
 
 #undef  CFF_FIELD
-#undef  CFF_FIELD_DELTA
+#undef  CFF_FIELD_DELTA_KIND
 
 
 #ifndef FT_DEBUG_LEVEL_TRACE
@@ -1064,18 +1068,18 @@
             code | CFFCODE,               \
             FT_FIELD_OFFSET( name ),      \
             FT_FIELD_SIZE( name ),        \
-            0, 0, 0                       \
+            NULL, 0, 0                    \
           },
 
-#define CFF_FIELD_DELTA( code, name, max, id ) \
-          {                                    \
-            cff_kind_delta,                    \
-            code | CFFCODE,                    \
-            FT_FIELD_OFFSET( name ),           \
-            FT_FIELD_SIZE_DELTA( name ),       \
-            0,                                 \
-            max,                               \
-            FT_FIELD_OFFSET( num_ ## name )    \
+#define CFF_FIELD_DELTA_KIND( code, name, max, id, kind ) \
+          {                                               \
+            kind,                                         \
+            code | CFFCODE,                               \
+            FT_FIELD_OFFSET( name ),                      \
+            FT_FIELD_SIZE_DELTA( name ),                  \
+            NULL,                                         \
+            max,                                          \
+            FT_FIELD_OFFSET( num_ ## name )               \
           },
 
   static const CFF_Field_Handler  cff_field_handlers[] =
@@ -1083,7 +1087,7 @@
 
 #include "cfftoken.h"
 
-    { 0, 0, 0, 0, 0, 0, 0 }
+    { 0, 0, 0, 0, NULL, 0, 0 }
   };
 
 
@@ -1117,20 +1121,20 @@
             code | CFFCODE,               \
             FT_FIELD_OFFSET( name ),      \
             FT_FIELD_SIZE( name ),        \
-            0, 0, 0,                      \
+            NULL, 0, 0,                   \
             id                            \
           },
 
-#define CFF_FIELD_DELTA( code, name, max, id ) \
-          {                                    \
-            cff_kind_delta,                    \
-            code | CFFCODE,                    \
-            FT_FIELD_OFFSET( name ),           \
-            FT_FIELD_SIZE_DELTA( name ),       \
-            0,                                 \
-            max,                               \
-            FT_FIELD_OFFSET( num_ ## name ),   \
-            id                                 \
+#define CFF_FIELD_DELTA_KIND( code, name, max, id, kind ) \
+          {                                               \
+            kind,                                         \
+            code | CFFCODE,                               \
+            FT_FIELD_OFFSET( name ),                      \
+            FT_FIELD_SIZE_DELTA( name ),                  \
+            NULL,                                         \
+            max,                                          \
+            FT_FIELD_OFFSET( num_ ## name ),              \
+            id                                            \
           },
 
   static const CFF_Field_Handler  cff_field_handlers[] =
@@ -1138,7 +1142,7 @@
 
 #include "cfftoken.h"
 
-    { 0, 0, 0, 0, 0, 0, 0, 0 }
+    { 0, 0, 0, 0, NULL, 0, 0, NULL }
   };
 
 
@@ -1356,7 +1360,8 @@
 
             /* check that we have enough arguments -- except for */
             /* delta encoded arrays, which can be empty          */
-            if ( field->kind != cff_kind_delta && num_args < 1 )
+            if ( field->kind != cff_kind_delta                       &&
+                 field->kind != cff_kind_delta_fixed && num_args < 1 )
               goto Stack_Underflow;
 
             switch ( field->kind )
@@ -1471,6 +1476,38 @@
               }
               break;
 
+            case cff_kind_delta_fixed:
+              {
+                FT_Byte*   qcount = (FT_Byte*)parser->object +
+                                      field->count_offset;
+
+                FT_Byte**  data = parser->stack;
+
+
+                if ( num_args > field->array_max )
+                  num_args = field->array_max;
+
+                FT_TRACE4(( " [" ));
+
+                /* store count */
+                *qcount = (FT_Byte)num_args;
+
+                val = 0;
+                while ( num_args > 0 )
+                {
+                  val = ADD_LONG( val, cff_parse_fixed( parser, data++ ) );
+                  *(FT_Long*)q = val;
+
+                  FT_TRACE4(( " %f\n", (double)val / 65536 ));
+
+                  q += field->size;
+                  num_args--;
+                }
+
+                FT_TRACE4(( "]\n" ));
+              }
+              break;
+
             default:  /* callback or blend */
               error = field->reader( parser );
               if ( error )
diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cffparse.h b/src/java.desktop/share/native/libfreetype/src/cff/cffparse.h
index 418caacc68c..ca6b18af6aa 100644
--- a/src/java.desktop/share/native/libfreetype/src/cff/cffparse.h
+++ b/src/java.desktop/share/native/libfreetype/src/cff/cffparse.h
@@ -4,7 +4,7 @@
  *
  *   CFF token stream parser (specification)
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -107,6 +107,7 @@ FT_BEGIN_HEADER
     cff_kind_string,
     cff_kind_bool,
     cff_kind_delta,
+    cff_kind_delta_fixed,
     cff_kind_callback,
     cff_kind_blend,
 
diff --git a/src/java.desktop/share/native/libfreetype/src/cff/cfftoken.h b/src/java.desktop/share/native/libfreetype/src/cff/cfftoken.h
index b61cb0e66e8..da45faa7f4e 100644
--- a/src/java.desktop/share/native/libfreetype/src/cff/cfftoken.h
+++ b/src/java.desktop/share/native/libfreetype/src/cff/cfftoken.h
@@ -4,7 +4,7 @@
  *
  *   CFF token definitions (specification only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -80,26 +80,26 @@
 #undef  CFFCODE
 #define CFFCODE       CFF_CODE_PRIVATE
 
-  CFF_FIELD_DELTA     ( 6,     blue_values, 14,        "BlueValues" )
-  CFF_FIELD_DELTA     ( 7,     other_blues, 10,        "OtherBlues" )
-  CFF_FIELD_DELTA     ( 8,     family_blues, 14,       "FamilyBlues" )
-  CFF_FIELD_DELTA     ( 9,     family_other_blues, 10, "FamilyOtherBlues" )
-  CFF_FIELD_FIXED_1000( 0x109, blue_scale,             "BlueScale" )
-  CFF_FIELD_NUM       ( 0x10A, blue_shift,             "BlueShift" )
-  CFF_FIELD_NUM       ( 0x10B, blue_fuzz,              "BlueFuzz" )
-  CFF_FIELD_NUM       ( 10,    standard_width,         "StdHW" )
-  CFF_FIELD_NUM       ( 11,    standard_height,        "StdVW" )
-  CFF_FIELD_DELTA     ( 0x10C, snap_widths, 13,        "StemSnapH" )
-  CFF_FIELD_DELTA     ( 0x10D, snap_heights, 13,       "StemSnapV" )
-  CFF_FIELD_BOOL      ( 0x10E, force_bold,             "ForceBold" )
-  CFF_FIELD_FIXED     ( 0x10F, force_bold_threshold,   "ForceBoldThreshold" )
-  CFF_FIELD_NUM       ( 0x110, lenIV,                  "lenIV" )
-  CFF_FIELD_NUM       ( 0x111, language_group,         "LanguageGroup" )
-  CFF_FIELD_FIXED     ( 0x112, expansion_factor,       "ExpansionFactor" )
-  CFF_FIELD_NUM       ( 0x113, initial_random_seed,    "initialRandomSeed" )
-  CFF_FIELD_NUM       ( 19,    local_subrs_offset,     "Subrs" )
-  CFF_FIELD_NUM       ( 20,    default_width,          "defaultWidthX" )
-  CFF_FIELD_NUM       ( 21,    nominal_width,          "nominalWidthX" )
+  CFF_FIELD_DELTA_FIXED( 6,     blue_values, 14,        "BlueValues" )
+  CFF_FIELD_DELTA_FIXED( 7,     other_blues, 10,        "OtherBlues" )
+  CFF_FIELD_DELTA_FIXED( 8,     family_blues, 14,       "FamilyBlues" )
+  CFF_FIELD_DELTA_FIXED( 9,     family_other_blues, 10, "FamilyOtherBlues" )
+  CFF_FIELD_FIXED_1000 ( 0x109, blue_scale,             "BlueScale" )
+  CFF_FIELD_NUM        ( 0x10A, blue_shift,             "BlueShift" )
+  CFF_FIELD_NUM        ( 0x10B, blue_fuzz,              "BlueFuzz" )
+  CFF_FIELD_NUM        ( 10,    standard_width,         "StdHW" )
+  CFF_FIELD_NUM        ( 11,    standard_height,        "StdVW" )
+  CFF_FIELD_DELTA      ( 0x10C, snap_widths, 13,        "StemSnapH" )
+  CFF_FIELD_DELTA      ( 0x10D, snap_heights, 13,       "StemSnapV" )
+  CFF_FIELD_BOOL       ( 0x10E, force_bold,             "ForceBold" )
+  CFF_FIELD_FIXED      ( 0x10F, force_bold_threshold,   "ForceBoldThreshold" )
+  CFF_FIELD_NUM        ( 0x110, lenIV,                  "lenIV" )
+  CFF_FIELD_NUM        ( 0x111, language_group,         "LanguageGroup" )
+  CFF_FIELD_FIXED      ( 0x112, expansion_factor,       "ExpansionFactor" )
+  CFF_FIELD_NUM        ( 0x113, initial_random_seed,    "initialRandomSeed" )
+  CFF_FIELD_NUM        ( 19,    local_subrs_offset,     "Subrs" )
+  CFF_FIELD_NUM        ( 20,    default_width,          "defaultWidthX" )
+  CFF_FIELD_NUM        ( 21,    nominal_width,          "nominalWidthX" )
 
 
 #undef  FT_STRUCTURE
@@ -129,22 +129,22 @@
 #undef  CFFCODE
 #define CFFCODE       CFF2_CODE_PRIVATE
 
-  CFF_FIELD_DELTA     ( 6,     blue_values, 14,        "BlueValues" )
-  CFF_FIELD_DELTA     ( 7,     other_blues, 10,        "OtherBlues" )
-  CFF_FIELD_DELTA     ( 8,     family_blues, 14,       "FamilyBlues" )
-  CFF_FIELD_DELTA     ( 9,     family_other_blues, 10, "FamilyOtherBlues" )
-  CFF_FIELD_FIXED_1000( 0x109, blue_scale,             "BlueScale" )
-  CFF_FIELD_NUM       ( 0x10A, blue_shift,             "BlueShift" )
-  CFF_FIELD_NUM       ( 0x10B, blue_fuzz,              "BlueFuzz" )
-  CFF_FIELD_NUM       ( 10,    standard_width,         "StdHW" )
-  CFF_FIELD_NUM       ( 11,    standard_height,        "StdVW" )
-  CFF_FIELD_DELTA     ( 0x10C, snap_widths, 13,        "StemSnapH" )
-  CFF_FIELD_DELTA     ( 0x10D, snap_heights, 13,       "StemSnapV" )
-  CFF_FIELD_NUM       ( 0x111, language_group,         "LanguageGroup" )
-  CFF_FIELD_FIXED     ( 0x112, expansion_factor,       "ExpansionFactor" )
-  CFF_FIELD_CALLBACK  ( 22,    vsindex,                "vsindex" )
-  CFF_FIELD_BLEND     ( 23,                            "blend" )
-  CFF_FIELD_NUM       ( 19,    local_subrs_offset,     "Subrs" )
+  CFF_FIELD_DELTA_FIXED( 6,     blue_values, 14,        "BlueValues" )
+  CFF_FIELD_DELTA_FIXED( 7,     other_blues, 10,        "OtherBlues" )
+  CFF_FIELD_DELTA_FIXED( 8,     family_blues, 14,       "FamilyBlues" )
+  CFF_FIELD_DELTA_FIXED( 9,     family_other_blues, 10, "FamilyOtherBlues" )
+  CFF_FIELD_FIXED_1000 ( 0x109, blue_scale,             "BlueScale" )
+  CFF_FIELD_NUM        ( 0x10A, blue_shift,             "BlueShift" )
+  CFF_FIELD_NUM        ( 0x10B, blue_fuzz,              "BlueFuzz" )
+  CFF_FIELD_NUM        ( 10,    standard_width,         "StdHW" )
+  CFF_FIELD_NUM        ( 11,    standard_height,        "StdVW" )
+  CFF_FIELD_DELTA      ( 0x10C, snap_widths, 13,        "StemSnapH" )
+  CFF_FIELD_DELTA      ( 0x10D, snap_heights, 13,       "StemSnapV" )
+  CFF_FIELD_NUM        ( 0x111, language_group,         "LanguageGroup" )
+  CFF_FIELD_FIXED      ( 0x112, expansion_factor,       "ExpansionFactor" )
+  CFF_FIELD_CALLBACK   ( 22,    vsindex,                "vsindex" )
+  CFF_FIELD_BLEND      ( 23,                            "blend" )
+  CFF_FIELD_NUM        ( 19,    local_subrs_offset,     "Subrs" )
 
 
 /* END */
diff --git a/src/java.desktop/share/native/libfreetype/src/cid/ciderrs.h b/src/java.desktop/share/native/libfreetype/src/cid/ciderrs.h
index 40a1097d0ac..c439a8c4a0b 100644
--- a/src/java.desktop/share/native/libfreetype/src/cid/ciderrs.h
+++ b/src/java.desktop/share/native/libfreetype/src/cid/ciderrs.h
@@ -4,7 +4,7 @@
  *
  *   CID error codes (specification only).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidgload.c b/src/java.desktop/share/native/libfreetype/src/cid/cidgload.c
index eaca765ad06..7b571322d45 100644
--- a/src/java.desktop/share/native/libfreetype/src/cid/cidgload.c
+++ b/src/java.desktop/share/native/libfreetype/src/cid/cidgload.c
@@ -4,7 +4,7 @@
  *
  *   CID-keyed Type1 Glyph Loader (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidgload.h b/src/java.desktop/share/native/libfreetype/src/cid/cidgload.h
index edd6229234c..9fdc9db5892 100644
--- a/src/java.desktop/share/native/libfreetype/src/cid/cidgload.h
+++ b/src/java.desktop/share/native/libfreetype/src/cid/cidgload.h
@@ -4,7 +4,7 @@
  *
  *   OpenType Glyph Loader (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidload.c b/src/java.desktop/share/native/libfreetype/src/cid/cidload.c
index a7da8ea39d5..722f5a34ddf 100644
--- a/src/java.desktop/share/native/libfreetype/src/cid/cidload.c
+++ b/src/java.desktop/share/native/libfreetype/src/cid/cidload.c
@@ -4,7 +4,7 @@
  *
  *   CID-keyed Type1 font loader (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -388,7 +388,7 @@
     T1_FIELD_CALLBACK( "ExpansionFactor", parse_expansion_factor, 0 )
     T1_FIELD_CALLBACK( "FontName",        parse_font_name, 0 )
 
-    { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0, 0 }
+    T1_FIELD_ZERO
   };
 
 
@@ -469,36 +469,23 @@
             T1_Field  keyword = (T1_Field)cid_field_records;
 
 
-            for (;;)
+            while ( keyword->len )
             {
-              FT_Byte*  name;
+              FT_Byte*  name = (FT_Byte*)keyword->ident;
 
 
-              name = (FT_Byte*)keyword->ident;
-              if ( !name )
-                break;
-
-              if ( cur[0] == name[0]                     &&
-                   len == ft_strlen( (const char*)name ) )
+              if ( keyword->len == len              &&
+                   ft_memcmp( cur, name, len ) == 0 )
               {
-                FT_UInt  n;
-
-
-                for ( n = 1; n < len; n++ )
-                  if ( cur[n] != name[n] )
-                    break;
-
-                if ( n >= len )
-                {
-                  /* we found it - run the parsing callback */
-                  parser->root.error = cid_load_keyword( face,
-                                                         loader,
-                                                         keyword );
-                  if ( parser->root.error )
-                    return parser->root.error;
-                  break;
-                }
+                /* we found it - run the parsing callback */
+                parser->root.error = cid_load_keyword( face,
+                                                       loader,
+                                                       keyword );
+                if ( parser->root.error )
+                  return parser->root.error;
+                break;
               }
+
               keyword++;
             }
           }
diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidload.h b/src/java.desktop/share/native/libfreetype/src/cid/cidload.h
index d12d2962a68..7f030b32df7 100644
--- a/src/java.desktop/share/native/libfreetype/src/cid/cidload.h
+++ b/src/java.desktop/share/native/libfreetype/src/cid/cidload.h
@@ -4,7 +4,7 @@
  *
  *   CID-keyed Type1 font loader (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.c b/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.c
index f698a419289..8d337c41128 100644
--- a/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.c
+++ b/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.c
@@ -4,7 +4,7 @@
  *
  *   CID objects manager (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.h b/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.h
index 83c0c61c3ca..d371cbe9954 100644
--- a/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.h
+++ b/src/java.desktop/share/native/libfreetype/src/cid/cidobjs.h
@@ -4,7 +4,7 @@
  *
  *   CID objects manager (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidparse.c b/src/java.desktop/share/native/libfreetype/src/cid/cidparse.c
index 171a886215a..73a3ade893b 100644
--- a/src/java.desktop/share/native/libfreetype/src/cid/cidparse.c
+++ b/src/java.desktop/share/native/libfreetype/src/cid/cidparse.c
@@ -4,7 +4,7 @@
  *
  *   CID-keyed Type1 parser (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -90,10 +90,15 @@
     if ( error )
       goto Exit;
 
-  Again:
-    /* now, read the rest of the file until we find */
-    /* `StartData' or `/sfnts'                      */
+    if ( !stream->read ) {
+      /* just parse memory-based streams */
+      offset = stream->size;
+    }
+    else
     {
+      /* Find the last `StartData` or `/sfnts`.  The parser requires */
+      /* contiguous memory; attempt to pin as little as necessary.   */
+
       /*
        * The algorithm is as follows (omitting the case with less than 256
        * bytes to fill for simplicity).
@@ -119,7 +124,8 @@
       FT_Byte*  p           = buffer;
 
 
-      for ( offset = FT_STREAM_POS(); ; offset += 256 )
+      offset = 0;
+      while ( 1 )
       {
         FT_ULong  stream_len;
 
@@ -127,7 +133,7 @@
         stream_len = stream->size - FT_STREAM_POS();
 
         read_len = FT_MIN( read_len, stream_len );
-        if ( FT_STREAM_READ( p, read_len ) )
+        if ( read_len && FT_STREAM_READ( p, read_len ) )
           goto Exit;
 
         /* ensure that we do not compare with data beyond the buffer */
@@ -141,20 +147,23 @@
                ft_strncmp( (char*)p, STARTDATA, STARTDATA_LEN ) == 0 )
           {
             /* save offset of binary data after `StartData' */
-            offset += (FT_ULong)( p - buffer ) + STARTDATA_LEN + 1;
-            goto Found;
+            offset = FT_STREAM_POS() - read_len - read_offset
+                     + (FT_ULong)( p - buffer ) + STARTDATA_LEN + 1;
           }
           else if ( p[1] == 's'                                   &&
                     ft_strncmp( (char*)p, SFNTS, SFNTS_LEN ) == 0 )
           {
-            offset += (FT_ULong)( p - buffer ) + SFNTS_LEN + 1;
-            goto Found;
+            offset = FT_STREAM_POS() - read_len - read_offset
+                     + (FT_ULong)( p - buffer ) + SFNTS_LEN + 1;
           }
         }
 
-        if ( read_offset + read_len < STARTDATA_LEN )
+        if ( read_offset + read_len <= STARTDATA_LEN )
         {
-          FT_TRACE2(( "cid_parser_new: no `StartData' keyword found\n" ));
+          if ( offset )
+            goto Found;
+
+          FT_TRACE2(( "cid_parser_new: no `StartData` keyword found\n" ));
           error = FT_THROW( Invalid_File_Format );
           goto Exit;
         }
@@ -171,9 +180,9 @@
     }
 
   Found:
-    /* We have found the start of the binary data or the `/sfnts' token. */
-    /* Now rewind and extract the frame corresponding to this PostScript */
-    /* section.                                                          */
+    /* We have found an efficient range to look for the binary data or    */
+    /* `/sfnts' token.  Now rewind and extract the frame corresponding to */
+    /* this PostScript section.                                           */
 
     ps_len = offset - base_offset;
     if ( FT_STREAM_SEEK( base_offset )                  ||
@@ -187,8 +196,8 @@
     parser->root.limit     = parser->root.cursor + ps_len;
     parser->num_dict       = FT_UINT_MAX;
 
-    /* Finally, we check whether `StartData' or `/sfnts' was real --  */
-    /* it could be in a comment or string.  We also get the arguments */
+    /* Find the first real `StartData' or `/sfnts' -- the last one    */
+    /* could be in a comment or string.  We also get the arguments    */
     /* of `StartData' to find out whether the data is represented in  */
     /* binary or hex format.                                          */
 
@@ -216,6 +225,7 @@
       {
         T1_TokenRec  type_token;
         FT_Long      binary_length;
+        FT_ULong     found_offset;
 
 
         parser->root.cursor = arg1;
@@ -234,6 +244,24 @@
             parser->binary_length = (FT_ULong)binary_length;
         }
 
+        /* set the real values for the parser, if different */
+        found_offset = (FT_ULong)( cur - parser->postscript )
+                       + STARTDATA_LEN + 1;
+        if ( found_offset != offset )
+        {
+          FT_FRAME_RELEASE( parser->postscript );
+
+          ps_len = found_offset - base_offset;
+          if ( FT_STREAM_SEEK( base_offset )                  ||
+               FT_FRAME_EXTRACT( ps_len, parser->postscript ) )
+            goto Exit;
+
+          parser->data_offset    = found_offset;
+          parser->postscript_len = ps_len;
+          parser->root.base      = parser->postscript;
+          parser->root.cursor    = parser->postscript;
+          parser->root.limit     = parser->root.cursor + ps_len;
+        }
         goto Exit;
       }
       else if ( cur[1] == 's'                                   &&
@@ -251,11 +279,8 @@
       cur  = parser->root.cursor;
     }
 
-    /* we haven't found the correct `StartData'; go back and continue */
-    /* searching                                                      */
-    FT_FRAME_RELEASE( parser->postscript );
-    if ( !FT_STREAM_SEEK( offset ) )
-      goto Again;
+    FT_TRACE2(( "cid_parser_new: no `StartData` token found\n" ));
+    error = FT_THROW( Invalid_File_Format );
 
   Exit:
     return error;
diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidparse.h b/src/java.desktop/share/native/libfreetype/src/cid/cidparse.h
index 2fd4e7a9310..0f5baddcb92 100644
--- a/src/java.desktop/share/native/libfreetype/src/cid/cidparse.h
+++ b/src/java.desktop/share/native/libfreetype/src/cid/cidparse.h
@@ -4,7 +4,7 @@
  *
  *   CID-keyed Type1 parser (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidriver.c b/src/java.desktop/share/native/libfreetype/src/cid/cidriver.c
index 99e7b118395..4be8a5c00d5 100644
--- a/src/java.desktop/share/native/libfreetype/src/cid/cidriver.c
+++ b/src/java.desktop/share/native/libfreetype/src/cid/cidriver.c
@@ -4,7 +4,7 @@
  *
  *   CID driver interface (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidriver.h b/src/java.desktop/share/native/libfreetype/src/cid/cidriver.h
index a6249385c81..7ddce431c5b 100644
--- a/src/java.desktop/share/native/libfreetype/src/cid/cidriver.h
+++ b/src/java.desktop/share/native/libfreetype/src/cid/cidriver.h
@@ -4,7 +4,7 @@
  *
  *   High-level CID driver interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/cid/cidtoken.h b/src/java.desktop/share/native/libfreetype/src/cid/cidtoken.h
index 925951acdbd..160897d1447 100644
--- a/src/java.desktop/share/native/libfreetype/src/cid/cidtoken.h
+++ b/src/java.desktop/share/native/libfreetype/src/cid/cidtoken.h
@@ -4,7 +4,7 @@
  *
  *   CID token definitions (specification only).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.c b/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.c
index db08941def7..e2f6a8e5adb 100644
--- a/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.c
+++ b/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.c
@@ -4,7 +4,7 @@
  *
  *   AFM parser (body).
  *
- * Copyright (C) 2006-2023 by
+ * Copyright (C) 2006-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.h b/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.h
index 2d3b6e6e169..b7766372821 100644
--- a/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.h
+++ b/src/java.desktop/share/native/libfreetype/src/psaux/afmparse.h
@@ -4,7 +4,7 @@
  *
  *   AFM parser (specification).
  *
- * Copyright (C) 2006-2023 by
+ * Copyright (C) 2006-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.c b/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.c
index 562d17d2216..9556e11a586 100644
--- a/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.c
+++ b/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.c
@@ -4,7 +4,7 @@
  *
  *   PostScript CFF (Type 2) decoding routines (body).
  *
- * Copyright (C) 2017-2023 by
+ * Copyright (C) 2017-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -17,6 +17,7 @@
 
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -1752,22 +1753,9 @@
 
           /* without upper limit the loop below might not finish */
           if ( args[0] > 0x7FFFFFFFL )
-            args[0] = 46341;
+            args[0] = 0xB504F4L;    /* sqrt( 32768.0044 ) */
           else if ( args[0] > 0 )
-          {
-            FT_Fixed  root = args[0];
-            FT_Fixed  new_root;
-
-
-            for (;;)
-            {
-              new_root = ( root + FT_DivFix( args[0], root ) + 1 ) >> 1;
-              if ( new_root == root )
-                break;
-              root = new_root;
-            }
-            args[0] = new_root;
-          }
+            args[0] = (FT_Fixed)FT_SqrtFixed( args[0] );
           else
             args[0] = 0;
           args++;
diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.h b/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.h
index e8bb4001cba..038f7235c3d 100644
--- a/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.h
+++ b/src/java.desktop/share/native/libfreetype/src/psaux/cffdecode.h
@@ -4,7 +4,7 @@
  *
  *   PostScript CFF (Type 2) decoding routines (specification).
  *
- * Copyright (C) 2017-2023 by
+ * Copyright (C) 2017-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psauxerr.h b/src/java.desktop/share/native/libfreetype/src/psaux/psauxerr.h
index 895ffa48c2c..18428c40d5a 100644
--- a/src/java.desktop/share/native/libfreetype/src/psaux/psauxerr.h
+++ b/src/java.desktop/share/native/libfreetype/src/psaux/psauxerr.h
@@ -4,7 +4,7 @@
  *
  *   PS auxiliary module error codes (specification only).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.c b/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.c
index 45e35aa53c4..6826f9d8d3e 100644
--- a/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.c
+++ b/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.c
@@ -4,7 +4,7 @@
  *
  *   FreeType auxiliary PostScript module implementation (body).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.h b/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.h
index 94dbf48813c..82d7e348af8 100644
--- a/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.h
+++ b/src/java.desktop/share/native/libfreetype/src/psaux/psauxmod.h
@@ -4,7 +4,7 @@
  *
  *   FreeType auxiliary PostScript module implementation (specification).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psblues.c b/src/java.desktop/share/native/libfreetype/src/psaux/psblues.c
index f9c864fea9a..213b943b465 100644
--- a/src/java.desktop/share/native/libfreetype/src/psaux/psblues.c
+++ b/src/java.desktop/share/native/libfreetype/src/psaux/psblues.c
@@ -54,14 +54,6 @@
 #define FT_COMPONENT  cf2blues
 
 
-  /*
-   * For blue values, the FreeType parser produces an array of integers,
-   * while the Adobe CFF engine produces an array of fixed.
-   * Define a macro to convert FreeType to fixed.
-   */
-#define cf2_blueToFixed( x )  cf2_intToFixed( x )
-
-
   FT_LOCAL_DEF( void )
   cf2_blues_init( CF2_Blues  blues,
                   CF2_Font   font )
@@ -78,10 +70,10 @@
     size_t  numFamilyBlues;
     size_t  numFamilyOtherBlues;
 
-    FT_Pos*  blueValues;
-    FT_Pos*  otherBlues;
-    FT_Pos*  familyBlues;
-    FT_Pos*  familyOtherBlues;
+    FT_Fixed*  blueValues;
+    FT_Fixed*  otherBlues;
+    FT_Fixed*  familyBlues;
+    FT_Fixed*  familyOtherBlues;
 
     size_t     i;
     CF2_Fixed  emBoxBottom, emBoxTop;
@@ -138,13 +130,13 @@
       emBoxTop    = CF2_ICF_Top;
     }
 
-    if ( cf2_getLanguageGroup( decoder ) == 1                   &&
-         ( numBlueValues == 0                                 ||
-           ( numBlueValues == 4                             &&
-             cf2_blueToFixed( blueValues[0] ) < emBoxBottom &&
-             cf2_blueToFixed( blueValues[1] ) < emBoxBottom &&
-             cf2_blueToFixed( blueValues[2] ) > emBoxTop    &&
-             cf2_blueToFixed( blueValues[3] ) > emBoxTop    ) ) )
+    if ( cf2_getLanguageGroup( decoder ) == 1     &&
+         ( numBlueValues == 0                   ||
+           ( numBlueValues == 4               &&
+             blueValues[0] < emBoxBottom      &&
+             blueValues[1] < emBoxBottom      &&
+             blueValues[2] > emBoxTop         &&
+             blueValues[3] > emBoxTop         ) ) )
     {
       /*
        * Construct hint edges suitable for synthetic ghost hints at top
@@ -189,10 +181,8 @@
     /* bottom zones                                                      */
     for ( i = 0; i < numBlueValues; i += 2 )
     {
-      blues->zone[blues->count].csBottomEdge =
-        cf2_blueToFixed( blueValues[i] );
-      blues->zone[blues->count].csTopEdge =
-        cf2_blueToFixed( blueValues[i + 1] );
+      blues->zone[blues->count].csBottomEdge = blueValues[i];
+      blues->zone[blues->count].csTopEdge    = blueValues[i + 1];
 
       zoneHeight = SUB_INT32( blues->zone[blues->count].csTopEdge,
                               blues->zone[blues->count].csBottomEdge );
@@ -238,10 +228,8 @@
 
     for ( i = 0; i < numOtherBlues; i += 2 )
     {
-      blues->zone[blues->count].csBottomEdge =
-        cf2_blueToFixed( otherBlues[i] );
-      blues->zone[blues->count].csTopEdge =
-        cf2_blueToFixed( otherBlues[i + 1] );
+      blues->zone[blues->count].csBottomEdge = otherBlues[i];
+      blues->zone[blues->count].csTopEdge    = otherBlues[i + 1];
 
       zoneHeight = SUB_INT32( blues->zone[blues->count].csTopEdge,
                               blues->zone[blues->count].csBottomEdge );
@@ -299,7 +287,7 @@
         for ( j = 0; j < numFamilyOtherBlues; j += 2 )
         {
           /* top edge */
-          flatFamilyEdge = cf2_blueToFixed( familyOtherBlues[j + 1] );
+          flatFamilyEdge = familyOtherBlues[j + 1];
 
           diff = cf2_fixedAbs( SUB_INT32( flatEdge, flatFamilyEdge ) );
 
@@ -317,7 +305,7 @@
         if ( numFamilyBlues >= 2 )
         {
           /* top edge */
-          flatFamilyEdge = cf2_blueToFixed( familyBlues[1] );
+          flatFamilyEdge = familyBlues[1];
 
           diff = cf2_fixedAbs( SUB_INT32( flatEdge, flatFamilyEdge ) );
 
@@ -337,7 +325,7 @@
         for ( j = 2; j < numFamilyBlues; j += 2 )
         {
           /* bottom edge */
-          flatFamilyEdge = cf2_blueToFixed( familyBlues[j] );
+          flatFamilyEdge = familyBlues[j];
 
           /* adjust edges of top zone upward by twice darkening amount */
           flatFamilyEdge += 2 * font->darkenY;      /* bottom edge */
diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psconv.c b/src/java.desktop/share/native/libfreetype/src/psaux/psconv.c
index b9c7138d846..56c0ecd1d7f 100644
--- a/src/java.desktop/share/native/libfreetype/src/psaux/psconv.c
+++ b/src/java.desktop/share/native/libfreetype/src/psaux/psconv.c
@@ -4,7 +4,7 @@
  *
  *   Some convenience conversions (body).
  *
- * Copyright (C) 2006-2023 by
+ * Copyright (C) 2006-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psconv.h b/src/java.desktop/share/native/libfreetype/src/psaux/psconv.h
index b7c3ee00be8..91fcd15a1c9 100644
--- a/src/java.desktop/share/native/libfreetype/src/psaux/psconv.h
+++ b/src/java.desktop/share/native/libfreetype/src/psaux/psconv.h
@@ -4,7 +4,7 @@
  *
  *   Some convenience conversions (specification).
  *
- * Copyright (C) 2006-2023 by
+ * Copyright (C) 2006-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psft.c b/src/java.desktop/share/native/libfreetype/src/psaux/psft.c
index 618864e6e07..fd0abe17154 100644
--- a/src/java.desktop/share/native/libfreetype/src/psaux/psft.c
+++ b/src/java.desktop/share/native/libfreetype/src/psaux/psft.c
@@ -566,12 +566,12 @@
   FT_LOCAL_DEF( void )
   cf2_getBlueValues( PS_Decoder*  decoder,
                      size_t*      count,
-                     FT_Pos*     *data )
+                     FT_Fixed*   *data )
   {
     FT_ASSERT( decoder && decoder->current_subfont );
 
     *count = decoder->current_subfont->private_dict.num_blue_values;
-    *data  = (FT_Pos*)
+    *data  = (FT_Fixed*)
                &decoder->current_subfont->private_dict.blue_values;
   }
 
@@ -579,12 +579,12 @@
   FT_LOCAL_DEF( void )
   cf2_getOtherBlues( PS_Decoder*  decoder,
                      size_t*      count,
-                     FT_Pos*     *data )
+                     FT_Fixed*   *data )
   {
     FT_ASSERT( decoder && decoder->current_subfont );
 
     *count = decoder->current_subfont->private_dict.num_other_blues;
-    *data  = (FT_Pos*)
+    *data  = (FT_Fixed*)
                &decoder->current_subfont->private_dict.other_blues;
   }
 
@@ -592,12 +592,12 @@
   FT_LOCAL_DEF( void )
   cf2_getFamilyBlues( PS_Decoder*  decoder,
                       size_t*      count,
-                      FT_Pos*     *data )
+                      FT_Fixed*   *data )
   {
     FT_ASSERT( decoder && decoder->current_subfont );
 
     *count = decoder->current_subfont->private_dict.num_family_blues;
-    *data  = (FT_Pos*)
+    *data  = (FT_Fixed*)
                &decoder->current_subfont->private_dict.family_blues;
   }
 
@@ -605,12 +605,12 @@
   FT_LOCAL_DEF( void )
   cf2_getFamilyOtherBlues( PS_Decoder*  decoder,
                            size_t*      count,
-                           FT_Pos*     *data )
+                           FT_Fixed*   *data )
   {
     FT_ASSERT( decoder && decoder->current_subfont );
 
     *count = decoder->current_subfont->private_dict.num_family_other_blues;
-    *data  = (FT_Pos*)
+    *data  = (FT_Fixed*)
                &decoder->current_subfont->private_dict.family_other_blues;
   }
 
diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psft.h b/src/java.desktop/share/native/libfreetype/src/psaux/psft.h
index 3da454e6012..d9082f3a2be 100644
--- a/src/java.desktop/share/native/libfreetype/src/psaux/psft.h
+++ b/src/java.desktop/share/native/libfreetype/src/psaux/psft.h
@@ -92,19 +92,19 @@ FT_BEGIN_HEADER
   FT_LOCAL( void )
   cf2_getBlueValues( PS_Decoder*  decoder,
                      size_t*      count,
-                     FT_Pos*     *data );
+                     FT_Fixed*   *data );
   FT_LOCAL( void )
   cf2_getOtherBlues( PS_Decoder*  decoder,
                      size_t*      count,
-                     FT_Pos*     *data );
+                     FT_Fixed*   *data );
   FT_LOCAL( void )
   cf2_getFamilyBlues( PS_Decoder*  decoder,
                       size_t*      count,
-                      FT_Pos*     *data );
+                      FT_Fixed*   *data );
   FT_LOCAL( void )
   cf2_getFamilyOtherBlues( PS_Decoder*  decoder,
                            size_t*      count,
-                           FT_Pos*     *data );
+                           FT_Fixed*   *data );
 
   FT_LOCAL( CF2_Int )
   cf2_getLanguageGroup( PS_Decoder*  decoder );
diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psintrp.c b/src/java.desktop/share/native/libfreetype/src/psaux/psintrp.c
index 6c640eebd5a..7572e225e37 100644
--- a/src/java.desktop/share/native/libfreetype/src/psaux/psintrp.c
+++ b/src/java.desktop/share/native/libfreetype/src/psaux/psintrp.c
@@ -37,6 +37,7 @@
 
 
 #include "psft.h"
+#include 
 #include 
 #include 
 
@@ -428,6 +429,8 @@
     base  = cf2_stack_count( opStack ) - numOperands;
     delta = base + numBlends;
 
+    FT_TRACE6(( " (" ));
+
     for ( i = 0; i < numBlends; i++ )
     {
       const CF2_Fixed*  weight = &blend->BV[1];
@@ -442,10 +445,14 @@
                                     cf2_stack_getReal( opStack,
                                                        delta++ ) ) );
 
+      FT_TRACE6(( "%f ", (double)sum / 65536 ));
+
       /* store blended result  */
       cf2_stack_setReal( opStack, i + base, sum );
     }
 
+    FT_TRACE6(( "blended)\n" ));
+
     /* leave only `numBlends' results on stack */
     cf2_stack_pop( opStack, numOperands - numBlends );
   }
@@ -734,7 +741,7 @@
           FT_UInt  numBlends;
 
 
-          FT_TRACE4(( " blend\n" ));
+          FT_TRACE4(( " blend" ));
 
           if ( !font->isCFF2 )
             break;    /* clear stack & ignore */
@@ -2275,23 +2282,7 @@
 
                     arg = cf2_stack_popFixed( opStack );
                     if ( arg > 0 )
-                    {
-                      /* use a start value that doesn't make */
-                      /* the algorithm's addition overflow   */
-                      FT_Fixed  root = arg < 10 ? arg : arg >> 1;
-                      FT_Fixed  new_root;
-
-
-                      /* Babylonian method */
-                      for (;;)
-                      {
-                        new_root = ( root + FT_DivFix( arg, root ) + 1 ) >> 1;
-                        if ( new_root == root )
-                          break;
-                        root = new_root;
-                      }
-                      arg = new_root;
-                    }
+                      arg = (CF2_F16Dot16)FT_SqrtFixed( (FT_UInt32)arg );
                     else
                       arg = 0;
 
diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.c b/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.c
index 8da755d0e57..eca465f009e 100644
--- a/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.c
+++ b/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.c
@@ -4,7 +4,7 @@
  *
  *   Auxiliary functions for PostScript fonts (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -23,6 +23,7 @@
 
 #include "psobjs.h"
 #include "psconv.h"
+#include "psft.h"
 
 #include "psauxerr.h"
 #include "psauxmod.h"
@@ -200,7 +201,9 @@
     /* add the object to the base block and adjust offset */
     table->elements[idx] = FT_OFFSET( table->block, table->cursor );
     table->lengths [idx] = length;
-    FT_MEM_COPY( table->block + table->cursor, object, length );
+    /* length == 0 also implies a NULL destination, so skip the copy call */
+    if ( length > 0 )
+      FT_MEM_COPY( table->block + table->cursor, object, length );
 
     table->cursor += length;
     return FT_Err_Ok;
@@ -1624,7 +1627,7 @@
     if ( builder->load_points )
     {
       FT_Vector*  point   = outline->points + outline->n_points;
-      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
+      FT_Byte*    control = outline->tags   + outline->n_points;
 
 
       point->x = FIXED_TO_INT( x );
@@ -1677,8 +1680,7 @@
     if ( !error )
     {
       if ( outline->n_contours > 0 )
-        outline->contours[outline->n_contours - 1] =
-          (short)( outline->n_points - 1 );
+        outline->contours[outline->n_contours - 1] = outline->n_points - 1;
 
       outline->n_contours++;
     }
@@ -1740,7 +1742,7 @@
     {
       FT_Vector*  p1      = outline->points + first;
       FT_Vector*  p2      = outline->points + outline->n_points - 1;
-      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points - 1;
+      FT_Byte*    control = outline->tags   + outline->n_points - 1;
 
 
       /* `delete' last point only if it coincides with the first */
@@ -1760,8 +1762,7 @@
         outline->n_points--;
       }
       else
-        outline->contours[outline->n_contours - 1] =
-          (short)( outline->n_points - 1 );
+        outline->contours[outline->n_contours - 1] = outline->n_points - 1;
     }
   }
 
@@ -1899,7 +1900,7 @@
     if ( builder->load_points )
     {
       FT_Vector*  point   = outline->points + outline->n_points;
-      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
+      FT_Byte*    control = outline->tags   + outline->n_points;
 
 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
       PS_Driver  driver   = (PS_Driver)FT_FACE_DRIVER( builder->face );
@@ -1959,8 +1960,7 @@
     if ( !error )
     {
       if ( outline->n_contours > 0 )
-        outline->contours[outline->n_contours - 1] =
-          (short)( outline->n_points - 1 );
+        outline->contours[outline->n_contours - 1] = outline->n_points - 1;
 
       outline->n_contours++;
     }
@@ -2019,7 +2019,7 @@
     {
       FT_Vector*  p1      = outline->points + first;
       FT_Vector*  p2      = outline->points + outline->n_points - 1;
-      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points - 1;
+      FT_Byte*    control = outline->tags   + outline->n_points - 1;
 
 
       /* `delete' last point only if it coincides with the first    */
@@ -2039,8 +2039,7 @@
         outline->n_points--;
       }
       else
-        outline->contours[outline->n_contours - 1] =
-          (short)( outline->n_points - 1 );
+        outline->contours[outline->n_contours - 1] = outline->n_points - 1;
     }
   }
 
@@ -2188,7 +2187,7 @@
     if ( builder->load_points )
     {
       FT_Vector*  point   = outline->points + outline->n_points;
-      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
+      FT_Byte*    control = outline->tags   + outline->n_points;
 
 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
       PS_Driver  driver   = (PS_Driver)FT_FACE_DRIVER( builder->face );
@@ -2267,8 +2266,7 @@
     if ( !error )
     {
       if ( outline->n_contours > 0 )
-        outline->contours[outline->n_contours - 1] =
-          (short)( outline->n_points - 1 );
+        outline->contours[outline->n_contours - 1] = outline->n_points - 1;
 
       outline->n_contours++;
     }
@@ -2327,7 +2325,7 @@
     {
       FT_Vector*  p1      = outline->points + first;
       FT_Vector*  p2      = outline->points + outline->n_points - 1;
-      FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points - 1;
+      FT_Byte*    control = outline->tags   + outline->n_points - 1;
 
 
       /* `delete' last point only if it coincides with the first */
@@ -2347,8 +2345,7 @@
         outline->n_points--;
       }
       else
-        outline->contours[outline->n_contours - 1] =
-          (short)( outline->n_points - 1 );
+        outline->contours[outline->n_contours - 1] = outline->n_points - 1;
     }
   }
 
@@ -2463,19 +2460,20 @@
 
     count = cpriv->num_blue_values = priv->num_blue_values;
     for ( n = 0; n < count; n++ )
-      cpriv->blue_values[n] = (FT_Pos)priv->blue_values[n];
+      cpriv->blue_values[n] = cf2_intToFixed( priv->blue_values[n] );
 
     count = cpriv->num_other_blues = priv->num_other_blues;
     for ( n = 0; n < count; n++ )
-      cpriv->other_blues[n] = (FT_Pos)priv->other_blues[n];
+      cpriv->other_blues[n] = cf2_intToFixed( priv->other_blues[n] );
 
     count = cpriv->num_family_blues = priv->num_family_blues;
     for ( n = 0; n < count; n++ )
-      cpriv->family_blues[n] = (FT_Pos)priv->family_blues[n];
+      cpriv->family_blues[n] = cf2_intToFixed( priv->family_blues[n] );
 
     count = cpriv->num_family_other_blues = priv->num_family_other_blues;
     for ( n = 0; n < count; n++ )
-      cpriv->family_other_blues[n] = (FT_Pos)priv->family_other_blues[n];
+      cpriv->family_other_blues[n] =
+        cf2_intToFixed( priv->family_other_blues[n] );
 
     cpriv->blue_scale = priv->blue_scale;
     cpriv->blue_shift = (FT_Pos)priv->blue_shift;
diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.h b/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.h
index d5bce541082..345fc8a7335 100644
--- a/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.h
+++ b/src/java.desktop/share/native/libfreetype/src/psaux/psobjs.h
@@ -4,7 +4,7 @@
  *
  *   Auxiliary functions for PostScript fonts (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.c b/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.c
index c4bcf599ea3..5681c3bd0fd 100644
--- a/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.c
+++ b/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.c
@@ -4,7 +4,7 @@
  *
  *   Type 1 character map support (body).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.h b/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.h
index b3702498a55..445e6a2784f 100644
--- a/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.h
+++ b/src/java.desktop/share/native/libfreetype/src/psaux/t1cmap.h
@@ -4,7 +4,7 @@
  *
  *   Type 1 character map support (specification).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.c b/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.c
index 4b6b969bcb9..c74baa8038f 100644
--- a/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.c
+++ b/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.c
@@ -4,7 +4,7 @@
  *
  *   PostScript Type 1 decoding routines (body).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.h b/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.h
index 0970def960b..16203b8f734 100644
--- a/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.h
+++ b/src/java.desktop/share/native/libfreetype/src/psaux/t1decode.h
@@ -4,7 +4,7 @@
  *
  *   PostScript Type 1 decoding routines (specification).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.c b/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.c
index 4f622e1e440..967767b3485 100644
--- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.c
+++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.c
@@ -4,7 +4,7 @@
  *
  *   PostScript hinting algorithm (body).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used
@@ -1118,7 +1118,7 @@
     FT_UInt     n;
     PSH_Point   point = glyph->points;
     FT_Vector*  vec   = glyph->outline->points;
-    char*       tags  = glyph->outline->tags;
+    FT_Byte*    tags  = glyph->outline->tags;
 
 
     for ( n = 0; n < glyph->num_points; n++ )
@@ -1171,8 +1171,8 @@
          FT_QNEW_ARRAY( glyph->contours, outline->n_contours ) )
       goto Exit;
 
-    glyph->num_points   = (FT_UInt)outline->n_points;
-    glyph->num_contours = (FT_UInt)outline->n_contours;
+    glyph->num_points   = outline->n_points;
+    glyph->num_contours = outline->n_contours;
 
     {
       FT_UInt      first = 0, next, n;
@@ -1186,7 +1186,7 @@
         PSH_Point  point;
 
 
-        next  = (FT_UInt)outline->contours[n] + 1;
+        next  = outline->contours[n] + 1;
         count = next - first;
 
         contour->start = points + first;
diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.h b/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.h
index 3f0ba28a693..fb362f061b6 100644
--- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.h
+++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshalgo.h
@@ -4,7 +4,7 @@
  *
  *   PostScript hinting algorithm (specification).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.c b/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.c
index d4c5eb32b1c..435f45838ff 100644
--- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.c
+++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.c
@@ -5,7 +5,7 @@
  *   PostScript hinter global hinting management (body).
  *   Inspired by the new auto-hinter module.
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used
diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.h b/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.h
index 579eb2148a5..c5a5c913168 100644
--- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.h
+++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshglob.h
@@ -4,7 +4,7 @@
  *
  *   PostScript hinter global hinting management.
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.c b/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.c
index 974a99e0186..9965d5b16bf 100644
--- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.c
+++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.c
@@ -4,7 +4,7 @@
  *
  *   FreeType PostScript hinter module implementation (body).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.h b/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.h
index 4bd781a35d7..62ac0a60fdc 100644
--- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.h
+++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshmod.h
@@ -4,7 +4,7 @@
  *
  *   PostScript hinter module interface (specification).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshnterr.h b/src/java.desktop/share/native/libfreetype/src/pshinter/pshnterr.h
index 97624952d8c..e9641340e53 100644
--- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshnterr.h
+++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshnterr.h
@@ -4,7 +4,7 @@
  *
  *   PS Hinter error codes (specification only).
  *
- * Copyright (C) 2003-2023 by
+ * Copyright (C) 2003-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.c b/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.c
index 680e6d01358..0b2b549fc29 100644
--- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.c
+++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.c
@@ -4,7 +4,7 @@
  *
  *   FreeType PostScript hints recorder (body).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -806,7 +806,7 @@
   ps_hints_stem( PS_Hints  hints,
                  FT_UInt   dimension,
                  FT_Int    count,
-                 FT_Long*  stems )
+                 FT_Pos*   stems )
   {
     PS_Dimension  dim;
 
diff --git a/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.h b/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.h
index 0b2484af121..7e375af7ba8 100644
--- a/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.h
+++ b/src/java.desktop/share/native/libfreetype/src/pshinter/pshrec.h
@@ -4,7 +4,7 @@
  *
  *   Postscript (Type1/Type2) hints recorder (specification).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.c b/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.c
index 8203a0465d2..35d054d1cfb 100644
--- a/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.c
+++ b/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.c
@@ -4,7 +4,7 @@
  *
  *   psnames module implementation (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.h b/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.h
index 0904700bfb8..770458316b1 100644
--- a/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.h
+++ b/src/java.desktop/share/native/libfreetype/src/psnames/psmodule.h
@@ -4,7 +4,7 @@
  *
  *   High-level psnames module interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/psnames/psnamerr.h b/src/java.desktop/share/native/libfreetype/src/psnames/psnamerr.h
index 0073f822848..e123eb65e39 100644
--- a/src/java.desktop/share/native/libfreetype/src/psnames/psnamerr.h
+++ b/src/java.desktop/share/native/libfreetype/src/psnames/psnamerr.h
@@ -4,7 +4,7 @@
  *
  *   PS names module error codes (specification only).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/psnames/pstables.h b/src/java.desktop/share/native/libfreetype/src/psnames/pstables.h
index 7f92cce6039..2a941b04609 100644
--- a/src/java.desktop/share/native/libfreetype/src/psnames/pstables.h
+++ b/src/java.desktop/share/native/libfreetype/src/psnames/pstables.h
@@ -4,7 +4,7 @@
  *
  *   PostScript glyph names.
  *
- * Copyright (C) 2005-2023 by
+ * Copyright (C) 2005-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/raster/ftmisc.h b/src/java.desktop/share/native/libfreetype/src/raster/ftmisc.h
index 33dbfd631e9..943f2aa0a50 100644
--- a/src/java.desktop/share/native/libfreetype/src/raster/ftmisc.h
+++ b/src/java.desktop/share/native/libfreetype/src/raster/ftmisc.h
@@ -5,7 +5,7 @@
  *   Miscellaneous macros for stand-alone rasterizer (specification
  *   only).
  *
- * Copyright (C) 2005-2023 by
+ * Copyright (C) 2005-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used
@@ -92,27 +92,6 @@
 #endif
 
 
-  static FT_Long
-  FT_MulDiv( FT_Long  a,
-             FT_Long  b,
-             FT_Long  c )
-  {
-    FT_Int   s;
-    FT_Long  d;
-
-
-    s = 1;
-    if ( a < 0 ) { a = -a; s = -1; }
-    if ( b < 0 ) { b = -b; s = -s; }
-    if ( c < 0 ) { c = -c; s = -s; }
-
-    d = (FT_Long)( c > 0 ? ( (FT_Int64)a * b + ( c >> 1 ) ) / c
-                         : 0x7FFFFFFFL );
-
-    return ( s > 0 ) ? d : -d;
-  }
-
-
   static FT_Long
   FT_MulDiv_No_Round( FT_Long  a,
                       FT_Long  b,
diff --git a/src/java.desktop/share/native/libfreetype/src/raster/ftraster.c b/src/java.desktop/share/native/libfreetype/src/raster/ftraster.c
index 192ca0701a2..e4b7b937d5a 100644
--- a/src/java.desktop/share/native/libfreetype/src/raster/ftraster.c
+++ b/src/java.desktop/share/native/libfreetype/src/raster/ftraster.c
@@ -4,7 +4,7 @@
  *
  *   The FreeType glyph rasterizer (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -63,8 +63,7 @@
 #else /* !STANDALONE_ */
 
 #include "ftraster.h"
-#include  /* for FT_MulDiv and FT_MulDiv_No_Round */
-#include          /* for FT_Outline_Get_CBox              */
+#include  /* for FT_MulDiv_No_Round */
 
 #endif /* !STANDALONE_ */
 
@@ -115,12 +114,12 @@
    *   a change of direction is detected in the outline, a new profile is
    *   generated until the end of the outline.
    *
-   *   Note that when all profiles have been generated, the function
-   *   Finalize_Profile_Table() is used to record, for each profile, its
-   *   bottom-most scanline as well as the scanline above its upmost
-   *   boundary.  These positions are called `y-turns' because they (sort
-   *   of) correspond to local extrema.  They are stored in a sorted list
-   *   built from the top of the render pool as a downwards stack:
+   *   Note that, for all generated profiles, the function End_Profile()
+   *   is used to record all their bottom-most scanlines as well as the
+   *   scanline above their upmost boundary.  These positions are called
+   *   `y-turns' because they (sort of) correspond to local extrema.
+   *   They are stored in a sorted list built from the top of the render
+   *   pool as a downwards stack:
    *
    *     _ _ _______________________________________
    *                           |                    |
@@ -136,7 +135,7 @@
    *   optimize performance (see technical note on the sweep below).
    *
    *   Of course, the raster detects whether the two stacks collide and
-   *   handles the situation properly.
+   *   handles the situation by bisecting the job and restarting.
    *
    */
 
@@ -252,7 +251,6 @@
   /* On the other hand, SMulDiv means `Slow MulDiv', and is used typically */
   /* for clipping computations.  It simply uses the FT_MulDiv() function   */
   /* defined in `ftcalc.h'.                                                */
-#define SMulDiv           FT_MulDiv
 #define SMulDiv_No_Round  FT_MulDiv_No_Round
 
   /* The rasterizer is a very general purpose component; please leave */
@@ -305,16 +303,6 @@
   typedef unsigned char   Byte, *PByte;
   typedef char            Bool;
 
-
-  typedef union  Alignment_
-  {
-    Long    l;
-    void*   p;
-    void  (*f)(void);
-
-  } Alignment, *PAlignment;
-
-
   typedef struct  TPoint_
   {
     Long  x;
@@ -327,6 +315,7 @@
 #define Flow_Up           0x08U
 #define Overshoot_Top     0x10U
 #define Overshoot_Bottom  0x20U
+#define Dropout           0x40U
 
 
   /* States of each line, arc, and profile */
@@ -345,31 +334,28 @@
 
   struct  TProfile_
   {
-    FT_F26Dot6  X;           /* current coordinate during sweep          */
     PProfile    link;        /* link to next profile (various purposes)  */
-    PLong       offset;      /* start of profile's data in render pool   */
+    PProfile    next;        /* next profile in same contour, used       */
+                             /* during drop-out control                  */
+    Int         offset;      /* bottom or currently scanned array index  */
+    Int         height;      /* profile's height in scanlines            */
+    Int         start;       /* profile's starting scanline, also use    */
+                             /* as activation counter                    */
     UShort      flags;       /* Bit 0-2: drop-out mode                   */
                              /* Bit 3: profile orientation (up/down)     */
                              /* Bit 4: is top profile?                   */
                              /* Bit 5: is bottom profile?                */
-    Long        height;      /* profile's height in scanlines            */
-    Long        start;       /* profile's starting scanline              */
+                             /* Bit 6: dropout detected                  */
 
-    Int         countL;      /* number of lines to step before this      */
-                             /* profile becomes drawable                 */
-
-    PProfile    next;        /* next profile in same contour, used       */
-                             /* during drop-out control                  */
+    FT_F26Dot6  X;           /* current coordinate during sweep          */
+    Long        x[1];        /* actually variable array of scanline      */
+                             /* intersections with `height` elements     */
   };
 
   typedef PProfile   TProfileList;
   typedef PProfile*  PProfileList;
 
 
-#define AlignProfileSize \
-  ( ( sizeof ( TProfile ) + sizeof ( Alignment ) - 1 ) / sizeof ( Long ) )
-
-
 #undef RAS_ARG
 #undef RAS_ARGS
 #undef RAS_VAR
@@ -407,15 +393,13 @@
 
   /* prototypes used for sweep function dispatch */
   typedef void
-  Function_Sweep_Init( RAS_ARGS Short  min,
-                                Short  max );
+  Function_Sweep_Init( RAS_ARGS Int  min,
+                                Int  max );
 
   typedef void
-  Function_Sweep_Span( RAS_ARGS Short       y,
+  Function_Sweep_Span( RAS_ARGS Int         y,
                                 FT_F26Dot6  x1,
-                                FT_F26Dot6  x2,
-                                PProfile    left,
-                                PProfile    right );
+                                FT_F26Dot6  x2 );
 
   typedef void
   Function_Sweep_Step( RAS_ARG );
@@ -441,8 +425,7 @@
           (Bool)( x - FLOOR( x ) >= ras.precision_half )
 
   /* Smart dropout rounding to find which pixel is closer to span ends. */
-  /* To mimick Windows, symmetric cases break down indepenently of the  */
-  /* precision.                                                         */
+  /* To mimic Windows, symmetric cases do not depend on the precision.  */
 #define SMART( p, q )  FLOOR( ( (p) + (q) + ras.precision * 63 / 64 ) >> 1 )
 
 #if FT_RENDER_POOL_SIZE > 2048
@@ -462,7 +445,6 @@
     Int         precision_half;
     Int         precision_scale;
     Int         precision_step;
-    Int         precision_jitter;
 
     PLong       buff;               /* The profiles buffer                 */
     PLong       sizeBuff;           /* Render pool size                    */
@@ -471,24 +453,14 @@
 
     FT_Error    error;
 
-    Int         numTurns;           /* number of Y-turns in outline        */
-
     Byte        dropOutControl;     /* current drop_out control method     */
 
-    UShort      bWidth;             /* target bitmap width                 */
-    PByte       bOrigin;            /* target bitmap bottom-left origin    */
-    PByte       bLine;              /* target bitmap current line          */
-
     Long        lastX, lastY;
     Long        minY, maxY;
 
     UShort      num_Profs;          /* current number of profiles          */
+    Int         numTurns;           /* number of Y-turns in outline        */
 
-    Bool        fresh;              /* signals a fresh new profile which   */
-                                    /* `start' field must be completed     */
-    Bool        joint;              /* signals that the last arc ended     */
-                                    /* exactly on a scanline.  Allows      */
-                                    /* removal of doublets                 */
     PProfile    cProfile;           /* current profile                     */
     PProfile    fProfile;           /* head of linked list of profiles     */
     PProfile    gProfile;           /* contour's first profile in case     */
@@ -496,9 +468,14 @@
 
     TStates     state;              /* rendering state                     */
 
-    FT_Bitmap   target;             /* description of target bit/pixmap    */
     FT_Outline  outline;
 
+    Int         bTop;               /* target bitmap max line  index       */
+    Int         bRight;             /* target bitmap rightmost index       */
+    Int         bPitch;             /* target bitmap pitch                 */
+    PByte       bOrigin;            /* target bitmap bottom-left origin    */
+    PByte       bLine;              /* target bitmap current line          */
+
     /* dispatch variables */
 
     Function_Sweep_Init*  Proc_Sweep_Init;
@@ -563,37 +540,82 @@
      *
      *   256 / (1 << 12) = 0.0625 pixels.
      *
-     * `precision_jitter' is an epsilon threshold used in
-     * `Vertical_Sweep_Span' to deal with small imperfections in the Bezier
-     * decomposition (after all, we are working with approximations only);
-     * it avoids switching on additional pixels which would cause artifacts
-     * otherwise.
-     *
-     * The value of `precision_jitter' has been determined heuristically.
-     *
      */
 
     if ( High )
     {
       ras.precision_bits   = 12;
       ras.precision_step   = 256;
-      ras.precision_jitter = 30;
     }
     else
     {
       ras.precision_bits   = 6;
       ras.precision_step   = 32;
-      ras.precision_jitter = 2;
     }
 
-    FT_TRACE6(( "Set_High_Precision(%s)\n", High ? "true" : "false" ));
-
     ras.precision       = 1 << ras.precision_bits;
     ras.precision_half  = ras.precision >> 1;
     ras.precision_scale = ras.precision >> Pixel_Bits;
   }
 
 
+  /**************************************************************************
+   *
+   * @Function:
+   *   Insert_Y_Turn
+   *
+   * @Description:
+   *   Insert a salient into the sorted list placed on top of the render
+   *   pool.
+   *
+   * @Input:
+   *   New y scanline position.
+   *
+   * @Return:
+   *   SUCCESS on success.  FAILURE in case of overflow.
+   */
+  static Bool
+  Insert_Y_Turns( RAS_ARGS Int  y,
+                           Int  top )
+  {
+    Int    n       = ras.numTurns;
+    PLong  y_turns = ras.maxBuff;
+
+
+    /* update top value */
+    if ( n == 0 || top > y_turns[n] )
+      y_turns[n] = top;
+
+    /* look for first y value that is <= */
+    while ( n-- && y < y_turns[n] )
+      ;
+
+    /* if it is <, simply insert it, ignore if == */
+    if ( n < 0 || y > y_turns[n] )
+    {
+      ras.maxBuff--;
+      if ( ras.maxBuff <= ras.top )
+      {
+        ras.error = FT_THROW( Raster_Overflow );
+        return FAILURE;
+      }
+
+      do
+      {
+        Int  y2 = (Int)y_turns[n];
+
+
+        y_turns[n] = y;
+        y = y2;
+      } while ( n-- >= 0 );
+
+      ras.numTurns++;
+    }
+
+    return SUCCESS;
+  }
+
+
   /**************************************************************************
    *
    * @Function:
@@ -606,52 +628,48 @@
    *   aState ::
    *     The state/orientation of the new profile.
    *
-   *   overshoot ::
-   *     Whether the profile's unrounded start position
-   *     differs by at least a half pixel.
-   *
    * @Return:
    *  SUCCESS on success.  FAILURE in case of overflow or of incoherent
    *  profile.
    */
   static Bool
-  New_Profile( RAS_ARGS TStates  aState,
-                        Bool     overshoot )
+  New_Profile( RAS_ARGS TStates  aState )
   {
-    if ( !ras.fProfile )
+    Long  e;
+
+
+    if ( !ras.cProfile || ras.cProfile->height )
     {
       ras.cProfile  = (PProfile)ras.top;
-      ras.fProfile  = ras.cProfile;
-      ras.top      += AlignProfileSize;
-    }
+      ras.top       = ras.cProfile->x;
 
-    if ( ras.top >= ras.maxBuff )
-    {
-      ras.error = FT_THROW( Raster_Overflow );
-      return FAILURE;
+      if ( ras.top >= ras.maxBuff )
+      {
+        FT_TRACE1(( "overflow in New_Profile\n" ));
+        ras.error = FT_THROW( Raster_Overflow );
+        return FAILURE;
+      }
+
+      ras.cProfile->height = 0;
     }
 
-    ras.cProfile->start  = 0;
-    ras.cProfile->height = 0;
-    ras.cProfile->offset = ras.top;
-    ras.cProfile->link   = (PProfile)0;
-    ras.cProfile->next   = (PProfile)0;
     ras.cProfile->flags  = ras.dropOutControl;
 
     switch ( aState )
     {
     case Ascending_State:
       ras.cProfile->flags |= Flow_Up;
-      if ( overshoot )
+      if ( IS_BOTTOM_OVERSHOOT( ras.lastY ) )
         ras.cProfile->flags |= Overshoot_Bottom;
 
-      FT_TRACE6(( "  new ascending profile = %p\n", (void *)ras.cProfile ));
+      e = CEILING( ras.lastY );
       break;
 
     case Descending_State:
-      if ( overshoot )
+      if ( IS_TOP_OVERSHOOT( ras.lastY ) )
         ras.cProfile->flags |= Overshoot_Top;
-      FT_TRACE6(( "  new descending profile = %p\n", (void *)ras.cProfile ));
+
+      e = FLOOR( ras.lastY );
       break;
 
     default:
@@ -660,12 +678,20 @@
       return FAILURE;
     }
 
-    if ( !ras.gProfile )
-      ras.gProfile = ras.cProfile;
+    if ( e > ras.maxY )
+      e = ras.maxY;
+    if ( e < ras.minY )
+      e = ras.minY;
+    ras.cProfile->start = (Int)TRUNC( e );
+
+    FT_TRACE7(( "  new %s profile = %p, start = %d\n",
+                aState == Ascending_State ? "ascending" : "descending",
+                (void *)ras.cProfile, ras.cProfile->start ));
+
+    if ( ras.lastY == e )
+      *ras.top++ = ras.lastX;
 
     ras.state = aState;
-    ras.fresh = TRUE;
-    ras.joint = FALSE;
 
     return SUCCESS;
   }
@@ -677,24 +703,19 @@
    *   End_Profile
    *
    * @Description:
-   *   Finalize the current profile.
-   *
-   * @Input:
-   *   overshoot ::
-   *     Whether the profile's unrounded end position differs
-   *     by at least a half pixel.
+   *   Finalize the current profile and record y-turns.
    *
    * @Return:
    *   SUCCESS on success.  FAILURE in case of overflow or incoherency.
    */
   static Bool
-  End_Profile( RAS_ARGS Bool  overshoot )
+  End_Profile( RAS_ARG )
   {
-    Long  h;
+    PProfile  p = ras.cProfile;
+    Int       h = (Int)( ras.top - p->x );
+    Int       bottom, top;
 
 
-    h = (Long)( ras.top - ras.cProfile->offset );
-
     if ( h < 0 )
     {
       FT_ERROR(( "End_Profile: negative height encountered\n" ));
@@ -704,98 +725,46 @@
 
     if ( h > 0 )
     {
-      PProfile  oldProfile;
+      FT_TRACE7(( "  ending profile %p, start = %2d, height = %+3d\n",
+                  (void *)p, p->start, p->flags & Flow_Up ? h : -h ));
 
+      p->height = h;
 
-      FT_TRACE6(( "  ending profile %p, start = %ld, height = %ld\n",
-                  (void *)ras.cProfile, ras.cProfile->start, h ));
+      if ( p->flags & Flow_Up )
+      {
+        if ( IS_TOP_OVERSHOOT( ras.lastY ) )
+          p->flags |= Overshoot_Top;
 
-      ras.cProfile->height = h;
-      if ( overshoot )
+        bottom    = p->start;
+        top       = bottom + h;
+        p->offset = 0;
+        p->X      = p->x[0];
+      }
+      else
       {
-        if ( ras.cProfile->flags & Flow_Up )
-          ras.cProfile->flags |= Overshoot_Top;
-        else
-          ras.cProfile->flags |= Overshoot_Bottom;
+        if ( IS_BOTTOM_OVERSHOOT( ras.lastY ) )
+          p->flags |= Overshoot_Bottom;
+
+        top       = p->start + 1;
+        bottom    = top - h;
+        p->start  = bottom;
+        p->offset = h - 1;
+        p->X      = p->x[h - 1];
       }
 
-      oldProfile   = ras.cProfile;
-      ras.cProfile = (PProfile)ras.top;
+      if ( Insert_Y_Turns( RAS_VARS bottom, top ) )
+        return FAILURE;
 
-      ras.top += AlignProfileSize;
+      if ( !ras.gProfile )
+        ras.gProfile = p;
 
-      ras.cProfile->height = 0;
-      ras.cProfile->offset = ras.top;
+      /* preliminary values to be finalized */
+      p->next = ras.gProfile;
+      p->link = (PProfile)ras.top;
 
-      oldProfile->next = ras.cProfile;
       ras.num_Profs++;
     }
 
-    if ( ras.top >= ras.maxBuff )
-    {
-      FT_TRACE1(( "overflow in End_Profile\n" ));
-      ras.error = FT_THROW( Raster_Overflow );
-      return FAILURE;
-    }
-
-    ras.joint = FALSE;
-
-    return SUCCESS;
-  }
-
-
-  /**************************************************************************
-   *
-   * @Function:
-   *   Insert_Y_Turn
-   *
-   * @Description:
-   *   Insert a salient into the sorted list placed on top of the render
-   *   pool.
-   *
-   * @Input:
-   *   New y scanline position.
-   *
-   * @Return:
-   *   SUCCESS on success.  FAILURE in case of overflow.
-   */
-  static Bool
-  Insert_Y_Turn( RAS_ARGS Int  y )
-  {
-    PLong  y_turns;
-    Int    n;
-
-
-    n       = ras.numTurns - 1;
-    y_turns = ras.sizeBuff - ras.numTurns;
-
-    /* look for first y value that is <= */
-    while ( n >= 0 && y < y_turns[n] )
-      n--;
-
-    /* if it is <, simply insert it, ignore if == */
-    if ( n >= 0 && y > y_turns[n] )
-      do
-      {
-        Int  y2 = (Int)y_turns[n];
-
-
-        y_turns[n] = y;
-        y = y2;
-      } while ( --n >= 0 );
-
-    if ( n < 0 )
-    {
-      ras.maxBuff--;
-      if ( ras.maxBuff <= ras.top )
-      {
-        ras.error = FT_THROW( Raster_Overflow );
-        return FAILURE;
-      }
-      ras.numTurns++;
-      ras.sizeBuff[-ras.numTurns] = y;
-    }
-
     return SUCCESS;
   }
 
@@ -807,56 +776,29 @@
    *
    * @Description:
    *   Adjust all links in the profiles list.
-   *
-   * @Return:
-   *   SUCCESS on success.  FAILURE in case of overflow.
    */
-  static Bool
+  static void
   Finalize_Profile_Table( RAS_ARG )
   {
-    UShort    n;
-    PProfile  p;
-
+    UShort    n = ras.num_Profs;
+    PProfile  p = ras.fProfile;
+    PProfile  q;
 
-    n = ras.num_Profs;
-    p = ras.fProfile;
 
-    if ( n > 1 && p )
+    /* there should be at least two profiles, up and down */
+    while ( --n )
     {
-      do
-      {
-        Int  bottom, top;
+      q = p->link;
 
+      /* fix the contour loop */
+      if ( q->next == p->next )
+        p->next = q;
 
-        if ( n > 1 )
-          p->link = (PProfile)( p->offset + p->height );
-        else
-          p->link = NULL;
-
-        if ( p->flags & Flow_Up )
-        {
-          bottom = (Int)p->start;
-          top    = (Int)( p->start + p->height - 1 );
-        }
-        else
-        {
-          bottom     = (Int)( p->start - p->height + 1 );
-          top        = (Int)p->start;
-          p->start   = bottom;
-          p->offset += p->height - 1;
-        }
-
-        if ( Insert_Y_Turn( RAS_VARS bottom )  ||
-             Insert_Y_Turn( RAS_VARS top + 1 ) )
-          return FAILURE;
-
-        p = p->link;
-      } while ( --n );
+      p = q;
     }
-    else
-      ras.fProfile = NULL;
 
-    return SUCCESS;
+    /* null-terminate */
+    p->link = NULL;
   }
 
 
@@ -986,107 +928,78 @@
                     Long  miny,
                     Long  maxy )
   {
-    Long   Dx, Dy;
-    Int    e1, e2, f1, f2, size;     /* XXX: is `Short' sufficient? */
-    Long   Ix, Rx, Ax;
+    Long  e, e2, Dx, Dy;
+    Long  Ix, Rx, Ax;
+    Int   size;
 
     PLong  top;
 
 
-    Dx = x2 - x1;
-    Dy = y2 - y1;
-
-    if ( Dy <= 0 || y2 < miny || y1 > maxy )
+    if ( y2 < miny || y1 > maxy )
       return SUCCESS;
 
-    if ( y1 < miny )
-    {
-      /* Take care: miny-y1 can be a very large value; we use     */
-      /*            a slow MulDiv function to avoid clipping bugs */
-      x1 += SMulDiv( Dx, miny - y1, Dy );
-      e1  = (Int)TRUNC( miny );
-      f1  = 0;
-    }
-    else
-    {
-      e1 = (Int)TRUNC( y1 );
-      f1 = (Int)FRAC( y1 );
-    }
+    e2 = y2 > maxy ? maxy : FLOOR( y2 );
+    e  = y1 < miny ? miny : CEILING( y1 );
 
-    if ( y2 > maxy )
-    {
-      /* x2 += FMulDiv( Dx, maxy - y2, Dy );  UNNECESSARY */
-      e2  = (Int)TRUNC( maxy );
-      f2  = 0;
-    }
-    else
-    {
-      e2 = (Int)TRUNC( y2 );
-      f2 = (Int)FRAC( y2 );
-    }
+    if ( y1 == e )
+      e += ras.precision;
 
-    if ( f1 > 0 )
-    {
-      if ( e1 == e2 )
-        return SUCCESS;
-      else
-      {
-        x1 += SMulDiv( Dx, ras.precision - f1, Dy );
-        e1 += 1;
-      }
-    }
-    else
-      if ( ras.joint )
-      {
-        ras.top--;
-        ras.joint = FALSE;
-      }
-
-    ras.joint = (char)( f2 == 0 );
+    if ( e2 < e )  /* nothing to do */
+      return SUCCESS;
 
-    if ( ras.fresh )
-    {
-      ras.cProfile->start = e1;
-      ras.fresh           = FALSE;
-    }
+    size = (Int)TRUNC( e2 - e ) + 1;
+    top  = ras.top;
 
-    size = e2 - e1 + 1;
-    if ( ras.top + size >= ras.maxBuff )
+    if ( top + size >= ras.maxBuff )
     {
       ras.error = FT_THROW( Raster_Overflow );
       return FAILURE;
     }
 
-    if ( Dx > 0 )
-    {
-      Ix = SMulDiv_No_Round( ras.precision, Dx, Dy );
-      Rx = ( ras.precision * Dx ) % Dy;
-      Dx = 1;
-    }
-    else
+    Dx = x2 - x1;
+    Dy = y2 - y1;
+
+    if ( Dx == 0 )  /* very easy */
     {
-      Ix = -SMulDiv_No_Round( ras.precision, -Dx, Dy );
-      Rx = ( ras.precision * -Dx ) % Dy;
-      Dx = -1;
+      do
+        *top++ = x1;
+      while ( --size );
+      goto Fin;
     }
 
-    Ax  = -Dy;
-    top = ras.top;
+    Ix     = SMulDiv_No_Round( e - y1, Dx, Dy );
+    x1    += Ix;
+    *top++ = x1;
 
-    while ( size > 0 )
+    if ( --size )
     {
-      *top++ = x1;
+      Ax = Dx * ( e - y1 )    - Dy * Ix;  /* remainder */
+      Ix = FMulDiv( ras.precision, Dx, Dy );
+      Rx = Dx * ras.precision - Dy * Ix;  /* remainder */
+      Dx = 1;
 
-      x1 += Ix;
-      Ax += Rx;
-      if ( Ax >= 0 )
+      if ( x2 < x1 )
+      {
+        Ax = -Ax;
+        Rx = -Rx;
+        Dx = -Dx;
+      }
+
+      do
       {
-        Ax -= Dy;
-        x1 += Dx;
+        x1 += Ix;
+        Ax += Rx;
+        if ( Ax >= Dy )
+        {
+          Ax -= Dy;
+          x1 += Dx;
+        }
+        *top++ = x1;
       }
-      size--;
+      while ( --size );
     }
 
+  Fin:
     ras.top = top;
     return SUCCESS;
   }
@@ -1131,17 +1044,7 @@
                       Long  miny,
                       Long  maxy )
   {
-    Bool  result, fresh;
-
-
-    fresh  = ras.fresh;
-
-    result = Line_Up( RAS_VARS x1, -y1, x2, -y2, -maxy, -miny );
-
-    if ( fresh && !ras.fresh )
-      ras.cProfile->start = -ras.cProfile->start;
-
-    return result;
+    return Line_Up( RAS_VARS x1, -y1, x2, -y2, -maxy, -miny );
   }
 
 
@@ -1181,105 +1084,73 @@
                       Long       miny,
                       Long       maxy )
   {
-    Long   y1, y2, e, e2, e0;
-    Short  f1;
+    Long  y1, y2, e, e2, dy;
+    Long  dx, x2;
 
-    TPoint*  start_arc;
-
-    PLong top;
+    PLong  top;
 
 
     y1  = arc[degree].y;
     y2  = arc[0].y;
-    top = ras.top;
 
     if ( y2 < miny || y1 > maxy )
-      goto Fin;
-
-    e2 = FLOOR( y2 );
-
-    if ( e2 > maxy )
-      e2 = maxy;
-
-    e0 = miny;
-
-    if ( y1 < miny )
-      e = miny;
-    else
-    {
-      e  = CEILING( y1 );
-      f1 = (Short)( FRAC( y1 ) );
-      e0 = e;
-
-      if ( f1 == 0 )
-      {
-        if ( ras.joint )
-        {
-          top--;
-          ras.joint = FALSE;
-        }
+      return SUCCESS;
 
-        *top++ = arc[degree].x;
+    e2 = y2 > maxy ? maxy : FLOOR( y2 );
+    e  = y1 < miny ? miny : CEILING( y1 );
 
-        e += ras.precision;
-      }
-    }
+    if ( y1 == e )
+      e += ras.precision;
 
-    if ( ras.fresh )
-    {
-      ras.cProfile->start = TRUNC( e0 );
-      ras.fresh = FALSE;
-    }
+    if ( e2 < e )  /* nothing to do */
+      return SUCCESS;
 
-    if ( e2 < e )
-      goto Fin;
+    top = ras.top;
 
     if ( ( top + TRUNC( e2 - e ) + 1 ) >= ras.maxBuff )
     {
-      ras.top   = top;
       ras.error = FT_THROW( Raster_Overflow );
       return FAILURE;
     }
 
-    start_arc = arc;
-
     do
     {
-      ras.joint = FALSE;
-
       y2 = arc[0].y;
+      x2 = arc[0].x;
 
       if ( y2 > e )
       {
-        y1 = arc[degree].y;
-        if ( y2 - y1 >= ras.precision_step )
+        dy = y2 - arc[degree].y;
+        dx = x2 - arc[degree].x;
+
+        /* split condition should be invariant of direction */
+        if (  dy > ras.precision_step ||
+              dx > ras.precision_step ||
+             -dx > ras.precision_step )
         {
           splitter( arc );
           arc += degree;
         }
         else
         {
-          *top++ = arc[degree].x + FMulDiv( arc[0].x - arc[degree].x,
-                                            e - y1, y2 - y1 );
+          *top++ = x2 - FMulDiv( y2 - e, dx, dy );
+          e     += ras.precision;
           arc -= degree;
-          e   += ras.precision;
         }
       }
       else
       {
         if ( y2 == e )
         {
-          ras.joint  = TRUE;
-          *top++     = arc[0].x;
-
-          e += ras.precision;
+          *top++ = x2;
+          e     += ras.precision;
         }
-        arc -= degree;
+        arc   -= degree;
       }
-    } while ( arc >= start_arc && e <= e2 );
+    }
+    while ( e <= e2 );
 
-  Fin:
-    ras.top  = top;
+    ras.top = top;
     return SUCCESS;
   }
 
@@ -1316,7 +1187,7 @@
                         Long       miny,
                         Long       maxy )
   {
-    Bool     result, fresh;
+    Bool  result;
 
 
     arc[0].y = -arc[0].y;
@@ -1325,13 +1196,8 @@
     if ( degree > 2 )
       arc[3].y = -arc[3].y;
 
-    fresh = ras.fresh;
-
     result = Bezier_Up( RAS_VARS degree, arc, splitter, -maxy, -miny );
 
-    if ( fresh && !ras.fresh )
-      ras.cProfile->start = -ras.cProfile->start;
-
     arc[0].y = -arc[0].y;
     return result;
   }
@@ -1362,74 +1228,50 @@
   Line_To( RAS_ARGS Long  x,
                     Long  y )
   {
-    /* First, detect a change of direction */
+    TStates  state;
 
-    switch ( ras.state )
-    {
-    case Unknown_State:
-      if ( y > ras.lastY )
-      {
-        if ( New_Profile( RAS_VARS Ascending_State,
-                                   IS_BOTTOM_OVERSHOOT( ras.lastY ) ) )
-          return FAILURE;
-      }
-      else
-      {
-        if ( y < ras.lastY )
-          if ( New_Profile( RAS_VARS Descending_State,
-                                     IS_TOP_OVERSHOOT( ras.lastY ) ) )
-            return FAILURE;
-      }
-      break;
 
-    case Ascending_State:
-      if ( y < ras.lastY )
-      {
-        if ( End_Profile( RAS_VARS IS_TOP_OVERSHOOT( ras.lastY ) ) ||
-             New_Profile( RAS_VARS Descending_State,
-                                   IS_TOP_OVERSHOOT( ras.lastY ) ) )
-          return FAILURE;
-      }
-      break;
+    if ( y == ras.lastY )
+      goto Fin;
 
-    case Descending_State:
-      if ( y > ras.lastY )
-      {
-        if ( End_Profile( RAS_VARS IS_BOTTOM_OVERSHOOT( ras.lastY ) ) ||
-             New_Profile( RAS_VARS Ascending_State,
-                                   IS_BOTTOM_OVERSHOOT( ras.lastY ) ) )
-          return FAILURE;
-      }
-      break;
+    /* First, detect a change of direction */
 
-    default:
-      ;
+    state = ras.lastY < y ? Ascending_State : Descending_State;
+
+    if ( ras.state != state )
+    {
+      /* finalize current profile if any */
+      if ( ras.state != Unknown_State &&
+           End_Profile( RAS_VAR )     )
+        goto Fail;
+
+      /* create a new profile */
+      if ( New_Profile( RAS_VARS state ) )
+        goto Fail;
     }
 
     /* Then compute the lines */
 
-    switch ( ras.state )
+    if ( state == Ascending_State )
     {
-    case Ascending_State:
       if ( Line_Up( RAS_VARS ras.lastX, ras.lastY,
                              x, y, ras.minY, ras.maxY ) )
-        return FAILURE;
-      break;
-
-    case Descending_State:
+        goto Fail;
+    }
+    else
+    {
       if ( Line_Down( RAS_VARS ras.lastX, ras.lastY,
                                x, y, ras.minY, ras.maxY ) )
-        return FAILURE;
-      break;
-
-    default:
-      ;
+        goto Fail;
     }
 
+  Fin:
     ras.lastX = x;
     ras.lastY = y;
-
     return SUCCESS;
+
+  Fail:
+    return FAILURE;
   }
 
 
@@ -1500,7 +1342,7 @@
         ymax = y1;
       }
 
-      if ( y2 < ymin || y2 > ymax )
+      if ( y2 < FLOOR( ymin ) || y2 > CEILING( ymax ) )
       {
         /* this arc has no given direction, split it! */
         Split_Conic( arc );
@@ -1508,8 +1350,12 @@
       }
       else if ( y1 == y3 )
       {
-        /* this arc is flat, ignore it and pop it from the Bezier stack */
+        /* this arc is flat, advance position */
+        /* and pop it from the Bezier stack   */
         arc -= 2;
+
+        ras.lastX = x3;
+        ras.lastY = y3;
       }
       else
       {
@@ -1518,18 +1364,13 @@
         state_bez = y1 < y3 ? Ascending_State : Descending_State;
         if ( ras.state != state_bez )
         {
-          Bool  o = ( state_bez == Ascending_State )
-                      ? IS_BOTTOM_OVERSHOOT( y1 )
-                      : IS_TOP_OVERSHOOT( y1 );
-
-
           /* finalize current profile if any */
           if ( ras.state != Unknown_State &&
-               End_Profile( RAS_VARS o )  )
+               End_Profile( RAS_VAR )     )
             goto Fail;
 
           /* create a new profile */
-          if ( New_Profile( RAS_VARS state_bez, o ) )
+          if ( New_Profile( RAS_VARS state_bez ) )
             goto Fail;
         }
 
@@ -1545,13 +1386,13 @@
                                      ras.minY, ras.maxY ) )
             goto Fail;
         arc -= 2;
+
+        ras.lastX = x3;
+        ras.lastY = y3;
       }
 
     } while ( arc >= arcs );
 
-    ras.lastX = x3;
-    ras.lastY = y3;
-
     return SUCCESS;
 
   Fail:
@@ -1648,7 +1489,7 @@
         ymax2 = y2;
       }
 
-      if ( ymin2 < ymin1 || ymax2 > ymax1 )
+      if ( ymin2 < FLOOR( ymin1 ) || ymax2 > CEILING( ymax1 ) )
       {
         /* this arc has no given direction, split it! */
         Split_Cubic( arc );
@@ -1656,27 +1497,26 @@
       }
       else if ( y1 == y4 )
       {
-        /* this arc is flat, ignore it and pop it from the Bezier stack */
+        /* this arc is flat, advance position */
+        /* and pop it from the Bezier stack   */
         arc -= 3;
+
+        ras.lastX = x4;
+        ras.lastY = y4;
       }
       else
       {
-        state_bez = ( y1 <= y4 ) ? Ascending_State : Descending_State;
+        state_bez = y1 < y4 ? Ascending_State : Descending_State;
 
         /* detect a change of direction */
         if ( ras.state != state_bez )
         {
-          Bool  o = ( state_bez == Ascending_State )
-                      ? IS_BOTTOM_OVERSHOOT( y1 )
-                      : IS_TOP_OVERSHOOT( y1 );
-
-
           /* finalize current profile if any */
           if ( ras.state != Unknown_State &&
-               End_Profile( RAS_VARS o )  )
+               End_Profile( RAS_VAR )     )
             goto Fail;
 
-          if ( New_Profile( RAS_VARS state_bez, o ) )
+          if ( New_Profile( RAS_VARS state_bez ) )
             goto Fail;
         }
 
@@ -1692,13 +1532,13 @@
                                      ras.minY, ras.maxY ) )
             goto Fail;
         arc -= 3;
+
+        ras.lastX = x4;
+        ras.lastY = y4;
       }
 
     } while ( arc >= arcs );
 
-    ras.lastX = x4;
-    ras.lastY = y4;
-
     return SUCCESS;
 
   Fail:
@@ -1740,6 +1580,11 @@
    *
    * @Return:
    *   SUCCESS on success, FAILURE on error.
+   *
+   * @Note:
+   *   Unlike FT_Outline_Decompose(), this function handles the scanmode
+   *   dropout tags in the individual contours.  Therefore, it cannot be
+   *   replaced.
    */
   static Bool
   Decompose_Curve( RAS_ARGS Int  first,
@@ -1753,7 +1598,7 @@
     FT_Vector*  points;
     FT_Vector*  point;
     FT_Vector*  limit;
-    char*       tags;
+    FT_Byte*    tags;
 
     UInt        tag;       /* current point's state           */
 
@@ -1974,24 +1819,17 @@
 
 
     ras.fProfile = NULL;
-    ras.joint    = FALSE;
-    ras.fresh    = FALSE;
-
-    ras.maxBuff  = ras.sizeBuff - AlignProfileSize;
+    ras.cProfile = NULL;
 
-    ras.numTurns = 0;
+    ras.top      = ras.buff;
+    ras.maxBuff  = ras.sizeBuff - 1;  /* top reserve */
 
-    ras.cProfile         = (PProfile)ras.top;
-    ras.cProfile->offset = ras.top;
-    ras.num_Profs        = 0;
+    ras.numTurns  = 0;
+    ras.num_Profs = 0;
 
     last = -1;
     for ( i = 0; i < ras.outline.n_contours; i++ )
     {
-      PProfile  lastProfile;
-      Bool      o;
-
-
       ras.state    = Unknown_State;
       ras.gProfile = NULL;
 
@@ -2001,35 +1839,30 @@
       if ( Decompose_Curve( RAS_VARS first, last, flipped ) )
         return FAILURE;
 
+      /* Note that ras.gProfile can stay nil if the contour was */
+      /* too small to be drawn or degenerate.                   */
+      if ( !ras.gProfile )
+        continue;
+
       /* we must now check whether the extreme arcs join or not */
       if ( FRAC( ras.lastY ) == 0 &&
            ras.lastY >= ras.minY  &&
            ras.lastY <= ras.maxY  )
-        if ( ras.gProfile                        &&
-             ( ras.gProfile->flags & Flow_Up ) ==
+        if ( ( ras.gProfile->flags & Flow_Up ) ==
                ( ras.cProfile->flags & Flow_Up ) )
           ras.top--;
-        /* Note that ras.gProfile can be nil if the contour was too small */
-        /* to be drawn.                                                   */
 
-      lastProfile = ras.cProfile;
-      if ( ras.top != ras.cProfile->offset &&
-           ( ras.cProfile->flags & Flow_Up ) )
-        o = IS_TOP_OVERSHOOT( ras.lastY );
-      else
-        o = IS_BOTTOM_OVERSHOOT( ras.lastY );
-      if ( End_Profile( RAS_VARS o ) )
+      if ( End_Profile( RAS_VAR ) )
         return FAILURE;
 
-      /* close the `next profile in contour' linked list */
-      if ( ras.gProfile )
-        lastProfile->next = ras.gProfile;
+      if ( !ras.fProfile )
+        ras.fProfile = ras.gProfile;
     }
 
-    if ( Finalize_Profile_Table( RAS_VAR ) )
-      return FAILURE;
+    if ( ras.fProfile )
+      Finalize_Profile_Table( RAS_VAR );
 
-    return (Bool)( ras.top < ras.maxBuff ? SUCCESS : FAILURE );
+    return SUCCESS;
   }
 
 
@@ -2042,24 +1875,11 @@
   /*************************************************************************/
 
 
-  /**************************************************************************
-   *
-   * Init_Linked
-   *
-   *   Initializes an empty linked list.
-   */
-  static void
-  Init_Linked( TProfileList*  l )
-  {
-    *l = NULL;
-  }
-
-
   /**************************************************************************
    *
    * InsNew
    *
-   *   Inserts a new profile in a linked list.
+   *   Inserts a new profile in a linked list, sorted by coordinate.
    */
   static void
   InsNew( PProfileList  list,
@@ -2073,10 +1893,8 @@
     current = *old;
     x       = profile->X;
 
-    while ( current )
+    while ( current && current->X < x )
     {
-      if ( x < current->X )
-        break;
       old     = ¤t->link;
       current = *old;
     }
@@ -2088,79 +1906,51 @@
 
   /**************************************************************************
    *
-   * DelOld
+   * Increment
    *
-   *   Removes an old profile from a linked list.
+   *   Advances all profile in the list to the next scanline.  It also
+   *   sorts the trace list in the unlikely case of profile crossing.
+   *   The profiles are inserted in sorted order.  We might need a single
+   *   swap to fix it when profiles (contours) cross.
+   *   Bubble sort with immediate restart is good enough and simple.
    */
   static void
-  DelOld( PProfileList    list,
-          const PProfile  profile )
+  Increment( PProfileList  list,
+             Int           flow )
   {
-    PProfile  *old, current;
-
+    PProfile  *old, current, next;
 
-    old     = list;
-    current = *old;
 
-    while ( current )
+    /* First, set the new X coordinates and remove exhausted profiles */
+    old = list;
+    while ( *old )
     {
-      if ( current == profile )
+      current = *old;
+      if ( --current->height )
       {
-        *old = current->link;
-        return;
+        current->offset += flow;
+        current->X       = current->x[current->offset];
+        old = ¤t->link;
       }
-
-      old     = ¤t->link;
-      current = *old;
-    }
-
-    /* we should never get there, unless the profile was not part of */
-    /* the list.                                                     */
-  }
-
-
-  /**************************************************************************
-   *
-   * Sort
-   *
-   *   Sorts a trace list.  In 95%, the list is already sorted.  We need
-   *   an algorithm which is fast in this case.  Bubble sort is enough
-   *   and simple.
-   */
-  static void
-  Sort( PProfileList  list )
-  {
-    PProfile  *old, current, next;
-
-
-    /* First, set the new X coordinate of each profile */
-    current = *list;
-    while ( current )
-    {
-      current->X       = *current->offset;
-      current->offset += ( current->flags & Flow_Up ) ? 1 : -1;
-      current->height--;
-      current = current->link;
+      else
+        *old = current->link;  /* remove */
     }
 
-    /* Then sort them */
+    /* Then make sure the list remains sorted */
     old     = list;
     current = *old;
 
     if ( !current )
       return;
 
-    next = current->link;
-
-    while ( next )
+    while ( current->link )
     {
+      next = current->link;
+
       if ( current->X <= next->X )
       {
         old     = ¤t->link;
-        current = *old;
-
-        if ( !current )
-          return;
+        current = next;
       }
       else
       {
@@ -2168,11 +1958,10 @@
         current->link = next->link;
         next->link    = current;
 
+        /* this is likely the only necessary swap -- restart */
         old     = list;
         current = *old;
       }
-
-      next = current->link;
     }
   }
 
@@ -2187,74 +1976,51 @@
    */
 
   static void
-  Vertical_Sweep_Init( RAS_ARGS Short  min,
-                                Short  max )
+  Vertical_Sweep_Init( RAS_ARGS Int  min,
+                                Int  max )
   {
     FT_UNUSED( max );
 
 
-    ras.bLine = ras.bOrigin - min * ras.target.pitch;
+    ras.bLine = ras.bOrigin - min * ras.bPitch;
   }
 
 
   static void
-  Vertical_Sweep_Span( RAS_ARGS Short       y,
+  Vertical_Sweep_Span( RAS_ARGS Int         y,
                                 FT_F26Dot6  x1,
-                                FT_F26Dot6  x2,
-                                PProfile    left,
-                                PProfile    right )
+                                FT_F26Dot6  x2 )
   {
-    Long  e1, e2;
-
-    Int  dropOutControl = left->flags & 7;
+    Int  e1 = (Int)TRUNC( CEILING( x1 ) );
+    Int  e2 = (Int)TRUNC(   FLOOR( x2 ) );
 
     FT_UNUSED( y );
-    FT_UNUSED( left );
-    FT_UNUSED( right );
 
 
-    /* in high-precision mode, we need 12 digits after the comma to */
-    /* represent multiples of 1/(1<<12) = 1/4096                    */
-    FT_TRACE7(( "  y=%d x=[% .12f;% .12f]",
+    FT_TRACE7(( "  y=%d x=[% .*f;% .*f]",
                 y,
-                (double)x1 / (double)ras.precision,
-                (double)x2 / (double)ras.precision ));
-
-    /* Drop-out control */
-
-    e1 = CEILING( x1 );
-    e2 = FLOOR( x2 );
-
-    /* take care of the special case where both the left */
-    /* and right contour lie exactly on pixel centers    */
-    if ( dropOutControl != 2                             &&
-         x2 - x1 - ras.precision <= ras.precision_jitter &&
-         e1 != x1 && e2 != x2                            )
-      e2 = e1;
+                ras.precision_bits, (double)x1 / (double)ras.precision,
+                ras.precision_bits, (double)x2 / (double)ras.precision ));
 
-    e1 = TRUNC( e1 );
-    e2 = TRUNC( e2 );
-
-    if ( e2 >= 0 && e1 < ras.bWidth )
+    if ( e2 >= 0 && e1 <= ras.bRight )
     {
-      Byte*  target;
+      PByte  target;
 
-      Int   c1, c2;
-      Byte  f1, f2;
+      Int   c1, f1, c2, f2;
 
 
       if ( e1 < 0 )
         e1 = 0;
-      if ( e2 >= ras.bWidth )
-        e2 = ras.bWidth - 1;
+      if ( e2 > ras.bRight )
+        e2 = ras.bRight;
 
-      FT_TRACE7(( " -> x=[%ld;%ld]", e1, e2 ));
+      FT_TRACE7(( " -> x=[%d;%d]", e1, e2 ));
 
-      c1 = (Short)( e1 >> 3 );
-      c2 = (Short)( e2 >> 3 );
+      c1 = e1 >> 3;
+      c2 = e2 >> 3;
 
-      f1 = (Byte)  ( 0xFF >> ( e1 & 7 ) );
-      f2 = (Byte) ~( 0x7F >> ( e2 & 7 ) );
+      f1 =  0xFF >> ( e1 & 7 );
+      f2 = ~0x7F >> ( e2 & 7 );
 
       target = ras.bLine + c1;
       c2 -= c1;
@@ -2280,163 +2046,50 @@
 
 
   static void
-  Vertical_Sweep_Drop( RAS_ARGS Short       y,
+  Vertical_Sweep_Drop( RAS_ARGS Int         y,
                                 FT_F26Dot6  x1,
-                                FT_F26Dot6  x2,
-                                PProfile    left,
-                                PProfile    right )
+                                FT_F26Dot6  x2 )
   {
-    Long   e1, e2, pxl;
-    Short  c1, f1;
-
-
-    FT_TRACE7(( "  y=%d x=[% .12f;% .12f]",
-                y,
-                (double)x1 / (double)ras.precision,
-                (double)x2 / (double)ras.precision ));
-
-    /* Drop-out control */
-
-    /*   e2            x2                    x1           e1   */
-    /*                                                         */
-    /*                 ^                     |                 */
-    /*                 |                     |                 */
-    /*   +-------------+---------------------+------------+    */
-    /*                 |                     |                 */
-    /*                 |                     v                 */
-    /*                                                         */
-    /* pixel         contour              contour       pixel  */
-    /* center                                           center */
-
-    /* drop-out mode    scan conversion rules (as defined in OpenType) */
-    /* --------------------------------------------------------------- */
-    /*  0                1, 2, 3                                       */
-    /*  1                1, 2, 4                                       */
-    /*  2                1, 2                                          */
-    /*  3                same as mode 2                                */
-    /*  4                1, 2, 5                                       */
-    /*  5                1, 2, 6                                       */
-    /*  6, 7             same as mode 2                                */
-
-    e1  = CEILING( x1 );
-    e2  = FLOOR  ( x2 );
-    pxl = e1;
-
-    if ( e1 > e2 )
-    {
-      Int  dropOutControl = left->flags & 7;
-
-
-      if ( e1 == e2 + ras.precision )
-      {
-        switch ( dropOutControl )
-        {
-        case 0: /* simple drop-outs including stubs */
-          pxl = e2;
-          break;
-
-        case 4: /* smart drop-outs including stubs */
-          pxl = SMART( x1, x2 );
-          break;
-
-        case 1: /* simple drop-outs excluding stubs */
-        case 5: /* smart drop-outs excluding stubs  */
-
-          /* Drop-out Control Rules #4 and #6 */
-
-          /* The specification neither provides an exact definition */
-          /* of a `stub' nor gives exact rules to exclude them.     */
-          /*                                                        */
-          /* Here the constraints we use to recognize a stub.       */
-          /*                                                        */
-          /*  upper stub:                                           */
-          /*                                                        */
-          /*   - P_Left and P_Right are in the same contour         */
-          /*   - P_Right is the successor of P_Left in that contour */
-          /*   - y is the top of P_Left and P_Right                 */
-          /*                                                        */
-          /*  lower stub:                                           */
-          /*                                                        */
-          /*   - P_Left and P_Right are in the same contour         */
-          /*   - P_Left is the successor of P_Right in that contour */
-          /*   - y is the bottom of P_Left                          */
-          /*                                                        */
-          /* We draw a stub if the following constraints are met.   */
-          /*                                                        */
-          /*   - for an upper or lower stub, there is top or bottom */
-          /*     overshoot, respectively                            */
-          /*   - the covered interval is greater or equal to a half */
-          /*     pixel                                              */
-
-          /* upper stub test */
-          if ( left->next == right                &&
-               left->height <= 0                  &&
-               !( left->flags & Overshoot_Top   &&
-                  x2 - x1 >= ras.precision_half ) )
-            goto Exit;
-
-          /* lower stub test */
-          if ( right->next == left                 &&
-               left->start == y                    &&
-               !( left->flags & Overshoot_Bottom &&
-                  x2 - x1 >= ras.precision_half  ) )
-            goto Exit;
-
-          if ( dropOutControl == 1 )
-            pxl = e2;
-          else
-            pxl = SMART( x1, x2 );
-          break;
-
-        default: /* modes 2, 3, 6, 7 */
-          goto Exit;  /* no drop-out control */
-        }
+    Int  e1 = (Int)TRUNC( x1 );
+    Int  e2 = (Int)TRUNC( x2 );
+    Int  c1, f1;
 
-        /* undocumented but confirmed: If the drop-out would result in a  */
-        /* pixel outside of the bounding box, use the pixel inside of the */
-        /* bounding box instead                                           */
-        if ( pxl < 0 )
-          pxl = e1;
-        else if ( TRUNC( pxl ) >= ras.bWidth )
-          pxl = e2;
+    FT_UNUSED( y );
 
-        /* check that the other pixel isn't set */
-        e1 = ( pxl == e1 ) ? e2 : e1;
 
-        e1 = TRUNC( e1 );
+    /* undocumented but confirmed: If the drop-out would result in a  */
+    /* pixel outside of the bounding box, use the pixel inside of the */
+    /* bounding box instead                                           */
+    if ( e1 < 0 || e1 > ras.bRight )
+      e1 = e2;
 
-        c1 = (Short)( e1 >> 3 );
-        f1 = (Short)( e1 &  7 );
+    /* otherwise check that the other pixel isn't set */
+    else if ( e2 >=0 && e2 <= ras.bRight )
+    {
+      c1 = e2 >> 3;
+      f1 = 0x80 >> ( e2 & 7 );
 
-        if ( e1 >= 0 && e1 < ras.bWidth     &&
-             ras.bLine[c1] & ( 0x80 >> f1 ) )
-          goto Exit;
-      }
-      else
-        goto Exit;
+      if ( ras.bLine[c1] & f1 )
+        return;
     }
 
-    e1 = TRUNC( pxl );
-
-    if ( e1 >= 0 && e1 < ras.bWidth )
+    if ( e1 >= 0 && e1 <= ras.bRight )
     {
-      FT_TRACE7(( " -> x=%ld", e1 ));
+      c1 = e1 >> 3;
+      f1 = 0x80 >> ( e1 & 7 );
 
-      c1 = (Short)( e1 >> 3 );
-      f1 = (Short)( e1 & 7 );
+      FT_TRACE7(( "  y=%d x=%d%s\n", y, e1,
+                  ras.bLine[c1] & f1 ? " redundant" : "" ));
 
-      ras.bLine[c1] |= (char)( 0x80 >> f1 );
+      ras.bLine[c1] |= f1;
     }
-
-  Exit:
-    FT_TRACE7(( " dropout=%d\n", left->flags & 7 ));
   }
 
 
   static void
   Vertical_Sweep_Step( RAS_ARG )
   {
-    ras.bLine -= ras.target.pitch;
+    ras.bLine -= ras.bPitch;
   }
 
 
@@ -2450,8 +2103,8 @@
    */
 
   static void
-  Horizontal_Sweep_Init( RAS_ARGS Short  min,
-                                  Short  max )
+  Horizontal_Sweep_Init( RAS_ARGS Int  min,
+                                  Int  max )
   {
     /* nothing, really */
     FT_UNUSED_RASTER;
@@ -2461,22 +2114,18 @@
 
 
   static void
-  Horizontal_Sweep_Span( RAS_ARGS Short       y,
+  Horizontal_Sweep_Span( RAS_ARGS Int         y,
                                   FT_F26Dot6  x1,
-                                  FT_F26Dot6  x2,
-                                  PProfile    left,
-                                  PProfile    right )
+                                  FT_F26Dot6  x2 )
   {
-    Long  e1, e2;
+    Long  e1 = CEILING( x1 );
+    Long  e2 =   FLOOR( x2 );
 
-    FT_UNUSED( left );
-    FT_UNUSED( right );
 
-
-    FT_TRACE7(( "  x=%d y=[% .12f;% .12f]",
+    FT_TRACE7(( "  x=%d y=[% .*f;% .*f]",
                 y,
-                (double)x1 / (double)ras.precision,
-                (double)x2 / (double)ras.precision ));
+                ras.precision_bits, (double)x1 / (double)ras.precision,
+                ras.precision_bits, (double)x2 / (double)ras.precision ));
 
     /* We should not need this procedure but the vertical sweep   */
     /* mishandles horizontal lines through pixel centers.  So we  */
@@ -2484,20 +2133,18 @@
     /*                                                            */
     /* XXX: Can we handle horizontal lines better and drop this?  */
 
-    e1 = CEILING( x1 );
-
     if ( x1 == e1 )
     {
       e1 = TRUNC( e1 );
 
-      if ( e1 >= 0 && (ULong)e1 < ras.target.rows )
+      if ( e1 >= 0 && e1 <= ras.bTop )
       {
-        Byte   f1;
+        Int    f1;
         PByte  bits;
 
 
-        bits = ras.bOrigin + ( y >> 3 ) - e1 * ras.target.pitch;
-        f1   = (Byte)( 0x80 >> ( y & 7 ) );
+        bits = ras.bOrigin + ( y >> 3 ) - e1 * ras.bPitch;
+        f1   = 0x80 >> ( y & 7 );
 
         FT_TRACE7(( bits[0] & f1 ? " redundant"
                                  : " -> y=%ld edge", e1 ));
@@ -2506,20 +2153,18 @@
       }
     }
 
-    e2 = FLOOR  ( x2 );
-
     if ( x2 == e2 )
     {
       e2 = TRUNC( e2 );
 
-      if ( e2 >= 0 && (ULong)e2 < ras.target.rows )
+      if ( e2 >= 0 && e2 <= ras.bTop )
       {
-        Byte   f1;
+        Int    f1;
         PByte  bits;
 
 
-        bits = ras.bOrigin + ( y >> 3 ) - e2 * ras.target.pitch;
-        f1   = (Byte)( 0x80 >> ( y & 7 ) );
+        bits = ras.bOrigin + ( y >> 3 ) - e2 * ras.bPitch;
+        f1   = 0x80 >> ( y & 7 );
 
         FT_TRACE7(( bits[0] & f1 ? " redundant"
                                  : " -> y=%ld edge", e2 ));
@@ -2533,122 +2178,42 @@
 
 
   static void
-  Horizontal_Sweep_Drop( RAS_ARGS Short       y,
+  Horizontal_Sweep_Drop( RAS_ARGS Int         y,
                                   FT_F26Dot6  x1,
-                                  FT_F26Dot6  x2,
-                                  PProfile    left,
-                                  PProfile    right )
+                                  FT_F26Dot6  x2 )
   {
-    Long   e1, e2, pxl;
+    Int    e1 = (Int)TRUNC( x1 );
+    Int    e2 = (Int)TRUNC( x2 );
     PByte  bits;
-    Byte   f1;
-
-
-    FT_TRACE7(( "  x=%d y=[% .12f;% .12f]",
-                y,
-                (double)x1 / (double)ras.precision,
-                (double)x2 / (double)ras.precision ));
-
-    /* During the horizontal sweep, we only take care of drop-outs */
-
-    /* e1     +       <-- pixel center */
-    /*        |                        */
-    /* x1  ---+-->    <-- contour      */
-    /*        |                        */
-    /*        |                        */
-    /* x2  <--+---    <-- contour      */
-    /*        |                        */
-    /*        |                        */
-    /* e2     +       <-- pixel center */
-
-    e1  = CEILING( x1 );
-    e2  = FLOOR  ( x2 );
-    pxl = e1;
-
-    if ( e1 > e2 )
-    {
-      Int  dropOutControl = left->flags & 7;
-
+    Int    f1;
 
-      if ( e1 == e2 + ras.precision )
-      {
-        switch ( dropOutControl )
-        {
-        case 0: /* simple drop-outs including stubs */
-          pxl = e2;
-          break;
-
-        case 4: /* smart drop-outs including stubs */
-          pxl = SMART( x1, x2 );
-          break;
-
-        case 1: /* simple drop-outs excluding stubs */
-        case 5: /* smart drop-outs excluding stubs  */
-          /* see Vertical_Sweep_Drop for details */
-
-          /* rightmost stub test */
-          if ( left->next == right                &&
-               left->height <= 0                  &&
-               !( left->flags & Overshoot_Top   &&
-                  x2 - x1 >= ras.precision_half ) )
-            goto Exit;
-
-          /* leftmost stub test */
-          if ( right->next == left                 &&
-               left->start == y                    &&
-               !( left->flags & Overshoot_Bottom &&
-                  x2 - x1 >= ras.precision_half  ) )
-            goto Exit;
-
-          if ( dropOutControl == 1 )
-            pxl = e2;
-          else
-            pxl = SMART( x1, x2 );
-          break;
 
-        default: /* modes 2, 3, 6, 7 */
-          goto Exit;  /* no drop-out control */
-        }
-
-        /* undocumented but confirmed: If the drop-out would result in a  */
-        /* pixel outside of the bounding box, use the pixel inside of the */
-        /* bounding box instead                                           */
-        if ( pxl < 0 )
-          pxl = e1;
-        else if ( (ULong)( TRUNC( pxl ) ) >= ras.target.rows )
-          pxl = e2;
-
-        /* check that the other pixel isn't set */
-        e1 = ( pxl == e1 ) ? e2 : e1;
-
-        e1 = TRUNC( e1 );
+    /* undocumented but confirmed: If the drop-out would result in a  */
+    /* pixel outside of the bounding box, use the pixel inside of the */
+    /* bounding box instead                                           */
+    if ( e1 < 0 || e1 > ras.bTop )
+      e1 = e2;
 
-        bits = ras.bOrigin + ( y >> 3 ) - e1 * ras.target.pitch;
-        f1   = (Byte)( 0x80 >> ( y & 7 ) );
+    /* otherwise check that the other pixel isn't set */
+    else if ( e2 >=0 && e2 <= ras.bTop )
+    {
+      bits = ras.bOrigin + ( y >> 3 ) - e2 * ras.bPitch;
+      f1   = 0x80 >> ( y & 7 );
 
-        if ( e1 >= 0                     &&
-             (ULong)e1 < ras.target.rows &&
-             *bits & f1                  )
-          goto Exit;
-      }
-      else
-        goto Exit;
+      if ( *bits & f1 )
+        return;
     }
 
-    e1 = TRUNC( pxl );
-
-    if ( e1 >= 0 && (ULong)e1 < ras.target.rows )
+    if ( e1 >= 0 && e1 <= ras.bTop )
     {
-      FT_TRACE7(( " -> y=%ld", e1 ));
+      bits  = ras.bOrigin + ( y >> 3 ) - e1 * ras.bPitch;
+      f1    = 0x80 >> ( y & 7 );
 
-      bits  = ras.bOrigin + ( y >> 3 ) - e1 * ras.target.pitch;
-      f1    = (Byte)( 0x80 >> ( y & 7 ) );
+      FT_TRACE7(( "  x=%d y=%d%s\n", y, e1,
+                  *bits & f1 ? " redundant" : "" ));
 
-      bits[0] |= f1;
+      *bits |= f1;
     }
-
-  Exit:
-    FT_TRACE7(( " dropout=%d\n", left->flags & 7 ));
   }
 
 
@@ -2664,116 +2229,61 @@
    *
    * Generic Sweep Drawing routine
    *
+   * Note that this routine is executed with the pool containing at least
+   * two valid profiles (up and down) and two y-turns (top and bottom).
+   *
    */
 
-  static Bool
+  static void
   Draw_Sweep( RAS_ARG )
   {
-    Short         y, y_change, y_height;
-
-    PProfile      P, Q, P_Left, P_Right;
-
-    Short         min_Y, max_Y, top, bottom, dropouts;
-
-    Long          x1, x2, xs, e1, e2;
-
-    TProfileList  waiting;
-    TProfileList  draw_left, draw_right;
-
-
-    /* initialize empty linked lists */
-
-    Init_Linked( &waiting );
-
-    Init_Linked( &draw_left  );
-    Init_Linked( &draw_right );
-
-    /* first, compute min and max Y */
-
-    P     = ras.fProfile;
-    max_Y = (Short)TRUNC( ras.minY );
-    min_Y = (Short)TRUNC( ras.maxY );
-
-    while ( P )
-    {
-      Q = P->link;
+    Int           min_Y, max_Y, dropouts;
+    Int           y, y_turn;
 
-      bottom = (Short)P->start;
-      top    = (Short)( P->start + P->height - 1 );
+    PProfile      *Q, P, P_Left, P_Right;
 
-      if ( min_Y > bottom )
-        min_Y = bottom;
-      if ( max_Y < top )
-        max_Y = top;
+    TProfileList  waiting    = ras.fProfile;
+    TProfileList  draw_left  = NULL;
+    TProfileList  draw_right = NULL;
 
-      P->X = 0;
-      InsNew( &waiting, P );
 
-      P = Q;
-    }
+    /* use y_turns to set the drawing range */
 
-    /* check the Y-turns */
-    if ( ras.numTurns == 0 )
-    {
-      ras.error = FT_THROW( Invalid_Outline );
-      return FAILURE;
-    }
+    min_Y = (Int)ras.maxBuff[0];
+    max_Y = (Int)ras.maxBuff[ras.numTurns] - 1;
 
     /* now initialize the sweep */
 
     ras.Proc_Sweep_Init( RAS_VARS min_Y, max_Y );
 
-    /* then compute the distance of each profile from min_Y */
-
-    P = waiting;
-
-    while ( P )
-    {
-      P->countL = P->start - min_Y;
-      P = P->link;
-    }
-
     /* let's go */
 
-    y        = min_Y;
-    y_height = 0;
-
-    if ( ras.numTurns > 0                     &&
-         ras.sizeBuff[-ras.numTurns] == min_Y )
-      ras.numTurns--;
-
-    while ( ras.numTurns > 0 )
+    for ( y = min_Y; y <= max_Y; )
     {
-      /* check waiting list for new activations */
-
-      P = waiting;
+      /* check waiting list for new profile activations */
 
-      while ( P )
+      Q = &waiting;
+      while ( *Q )
       {
-        Q = P->link;
-        P->countL -= y_height;
-        if ( P->countL == 0 )
+        P = *Q;
+        if ( P->start == y )
         {
-          DelOld( &waiting, P );
+          *Q = P->link;  /* remove */
 
+          /* each active list contains profiles with the same flow */
+          /* left and right are arbitrary, correspond to TrueType  */
           if ( P->flags & Flow_Up )
             InsNew( &draw_left,  P );
           else
             InsNew( &draw_right, P );
         }
-
-        P = Q;
+        else
+          Q = &P->link;
       }
 
-      /* sort the drawing lists */
+      y_turn = (Int)*++ras.maxBuff;
 
-      Sort( &draw_left );
-      Sort( &draw_right );
-
-      y_change = (Short)ras.sizeBuff[-ras.numTurns--];
-      y_height = (Short)( y_change - y );
-
-      while ( y < y_change )
+      do
       {
         /* let's trace */
 
@@ -2784,9 +2294,13 @@
 
         while ( P_Left && P_Right )
         {
-          x1 = P_Left ->X;
-          x2 = P_Right->X;
+          Long  x1 = P_Left ->X;
+          Long  x2 = P_Right->X;
+          Long  xs;
+
 
+          /* TrueType should have x2 > x1, but can be opposite */
+          /* by mistake or in CFF/Type1, fix it then           */
           if ( x1 > x2 )
           {
             xs = x1;
@@ -2794,205 +2308,130 @@
             x2 = xs;
           }
 
-          e1 = FLOOR( x1 );
-          e2 = CEILING( x2 );
+          if ( CEILING( x1 ) <= FLOOR( x2 ) )
+            ras.Proc_Sweep_Span( RAS_VARS y, x1, x2 );
 
-          if ( x2 - x1 <= ras.precision &&
-               e1 != x1 && e2 != x2     )
+          /* otherwise, bottom ceiling > top floor, it is a drop-out */
+          else
           {
-            if ( e1 > e2 || e2 == e1 + ras.precision )
+            Int  dropOutControl = P_Left->flags & 7;
+
+
+            /* Drop-out control */
+
+            /*   e2            x2                    x1           e1   */
+            /*                                                         */
+            /*                 ^                     |                 */
+            /*                 |                     |                 */
+            /*   +-------------+---------------------+------------+    */
+            /*                 |                     |                 */
+            /*                 |                     v                 */
+            /*                                                         */
+            /* pixel         contour              contour       pixel  */
+            /* center                                           center */
+
+            /* drop-out mode   scan conversion rules (OpenType specs)  */
+            /* ------------------------------------------------------- */
+            /*  bit 0          exclude stubs if set                    */
+            /*  bit 1          ignore drop-outs if set                 */
+            /*  bit 2          smart rounding if set                   */
+
+            if ( dropOutControl & 2 )
+              goto Next_Pair;
+
+            /* The specification neither provides an exact definition */
+            /* of a `stub' nor gives exact rules to exclude them.     */
+            /*                                                        */
+            /* Here the constraints we use to recognize a stub.       */
+            /*                                                        */
+            /*  upper stub:                                           */
+            /*                                                        */
+            /*   - P_Left and P_Right are in the same contour         */
+            /*   - P_Right is the successor of P_Left in that contour */
+            /*   - y is the top of P_Left and P_Right                 */
+            /*                                                        */
+            /*  lower stub:                                           */
+            /*                                                        */
+            /*   - P_Left and P_Right are in the same contour         */
+            /*   - P_Left is the successor of P_Right in that contour */
+            /*   - y is the bottom of P_Left                          */
+            /*                                                        */
+            /* We draw a stub if the following constraints are met.   */
+            /*                                                        */
+            /*   - for an upper or lower stub, there is top or bottom */
+            /*     overshoot, respectively                            */
+            /*   - the covered interval is greater or equal to a half */
+            /*     pixel                                              */
+
+            if ( dropOutControl & 1 )
             {
-              Int  dropOutControl = P_Left->flags & 7;
-
-
-              if ( dropOutControl != 2 )
-              {
-                /* a drop-out was detected */
-
-                P_Left ->X = x1;
-                P_Right->X = x2;
-
-                /* mark profile for drop-out processing */
-                P_Left->countL = 1;
-                dropouts++;
-              }
+              /* upper stub test */
+              if ( P_Left->height == 1                &&
+                   P_Left->next == P_Right            &&
+                   !( P_Left->flags & Overshoot_Top   &&
+                      x2 - x1 >= ras.precision_half   ) )
+                goto Next_Pair;
+
+              /* lower stub test */
+              if ( P_Left->offset == 0                 &&
+                   P_Right->next == P_Left             &&
+                   !( P_Left->flags & Overshoot_Bottom &&
+                      x2 - x1 >= ras.precision_half    ) )
+                goto Next_Pair;
+            }
 
-              goto Skip_To_Next;
+            /* select the pixel to set and the other pixel */
+            if ( dropOutControl & 4 )
+            {
+              x2 = SMART( x1, x2 );
+              x1 = x1 > x2 ? x2 + ras.precision : x2 - ras.precision;
+            }
+            else
+            {
+              x2 = FLOOR  ( x2 );
+              x1 = CEILING( x1 );
             }
-          }
 
-          ras.Proc_Sweep_Span( RAS_VARS y, x1, x2, P_Left, P_Right );
+            P_Left ->X = x2;
+            P_Right->X = x1;
 
-        Skip_To_Next:
+            /* mark profile for drop-out processing */
+            P_Left->flags |= Dropout;
+            dropouts++;
+          }
 
+        Next_Pair:
           P_Left  = P_Left->link;
           P_Right = P_Right->link;
         }
 
-        /* handle drop-outs _after_ the span drawing --       */
-        /* drop-out processing has been moved out of the loop */
-        /* for performance tuning                             */
-        if ( dropouts > 0 )
-          goto Scan_DropOuts;
-
-      Next_Line:
-
-        ras.Proc_Sweep_Step( RAS_VAR );
-
-        y++;
+        /* handle drop-outs _after_ the span drawing */
+        P_Left  = draw_left;
+        P_Right = draw_right;
 
-        if ( y < y_change )
+        while ( dropouts )
         {
-          Sort( &draw_left  );
-          Sort( &draw_right );
-        }
-      }
-
-      /* now finalize the profiles that need it */
-
-      P = draw_left;
-      while ( P )
-      {
-        Q = P->link;
-        if ( P->height == 0 )
-          DelOld( &draw_left, P );
-        P = Q;
-      }
-
-      P = draw_right;
-      while ( P )
-      {
-        Q = P->link;
-        if ( P->height == 0 )
-          DelOld( &draw_right, P );
-        P = Q;
-      }
-    }
-
-    /* for gray-scaling, flush the bitmap scanline cache */
-    while ( y <= max_Y )
-    {
-      ras.Proc_Sweep_Step( RAS_VAR );
-      y++;
-    }
-
-    return SUCCESS;
-
-  Scan_DropOuts:
-
-    P_Left  = draw_left;
-    P_Right = draw_right;
-
-    while ( P_Left && P_Right )
-    {
-      if ( P_Left->countL )
-      {
-        P_Left->countL = 0;
-#if 0
-        dropouts--;  /* -- this is useful when debugging only */
-#endif
-        ras.Proc_Sweep_Drop( RAS_VARS y,
-                                      P_Left->X,
-                                      P_Right->X,
-                                      P_Left,
-                                      P_Right );
-      }
-
-      P_Left  = P_Left->link;
-      P_Right = P_Right->link;
-    }
-
-    goto Next_Line;
-  }
-
-
-#ifdef STANDALONE_
-
-  /**************************************************************************
-   *
-   * The following functions should only compile in stand-alone mode,
-   * i.e., when building this component without the rest of FreeType.
-   *
-   */
-
-  /**************************************************************************
-   *
-   * @Function:
-   *   FT_Outline_Get_CBox
-   *
-   * @Description:
-   *   Return an outline's `control box'.  The control box encloses all
-   *   the outline's points, including Bézier control points.  Though it
-   *   coincides with the exact bounding box for most glyphs, it can be
-   *   slightly larger in some situations (like when rotating an outline
-   *   that contains Bézier outside arcs).
-   *
-   *   Computing the control box is very fast, while getting the bounding
-   *   box can take much more time as it needs to walk over all segments
-   *   and arcs in the outline.  To get the latter, you can use the
-   *   `ftbbox' component, which is dedicated to this single task.
-   *
-   * @Input:
-   *   outline ::
-   *     A pointer to the source outline descriptor.
-   *
-   * @Output:
-   *   acbox ::
-   *     The outline's control box.
-   *
-   * @Note:
-   *   See @FT_Glyph_Get_CBox for a discussion of tricky fonts.
-   */
-
-  static void
-  FT_Outline_Get_CBox( const FT_Outline*  outline,
-                       FT_BBox           *acbox )
-  {
-    if ( outline && acbox )
-    {
-      Long  xMin, yMin, xMax, yMax;
-
-
-      if ( outline->n_points == 0 )
-      {
-        xMin = 0;
-        yMin = 0;
-        xMax = 0;
-        yMax = 0;
-      }
-      else
-      {
-        FT_Vector*  vec   = outline->points;
-        FT_Vector*  limit = vec + outline->n_points;
-
-
-        xMin = xMax = vec->x;
-        yMin = yMax = vec->y;
-        vec++;
+          if ( P_Left->flags & Dropout )
+          {
+            ras.Proc_Sweep_Drop( RAS_VARS y, P_Left->X, P_Right->X );
 
-        for ( ; vec < limit; vec++ )
-        {
-          Long  x, y;
+            P_Left->flags &= ~Dropout;
+            dropouts--;
+          }
 
+          P_Left  = P_Left->link;
+          P_Right = P_Right->link;
+        }
 
-          x = vec->x;
-          if ( x < xMin ) xMin = x;
-          if ( x > xMax ) xMax = x;
+        ras.Proc_Sweep_Step( RAS_VAR );
 
-          y = vec->y;
-          if ( y < yMin ) yMin = y;
-          if ( y > yMax ) yMax = y;
-        }
+        Increment( &draw_left,   1 );
+        Increment( &draw_right, -1 );
       }
-      acbox->xMin = xMin;
-      acbox->xMax = xMax;
-      acbox->yMin = yMin;
-      acbox->yMax = yMax;
+      while ( ++y < y_turn );
     }
   }
 
-#endif /* STANDALONE_ */
-
 
   /**************************************************************************
    *
@@ -3019,13 +2458,15 @@
     Int  band_stack[32];  /* enough to bisect 32-bit int bands */
 
 
+    FT_TRACE6(( "%s pass [%d..%d]\n",
+                flipped ? "Horizontal" : "Vertical",
+                y_min, y_max ));
+
     while ( 1 )
     {
       ras.minY = (Long)y_min * ras.precision;
       ras.maxY = (Long)y_max * ras.precision;
 
-      ras.top = ras.buff;
-
       ras.error = Raster_Err_Ok;
 
       if ( Convert_Glyph( RAS_VARS flipped ) )
@@ -3038,6 +2479,9 @@
         if ( y_min == y_max )
           return ras.error;  /* still Raster_Overflow */
 
+        FT_TRACE6(( "band [%d..%d]: to be bisected\n",
+                    y_min, y_max ));
+
         y_mid = ( y_min + y_max ) >> 1;
 
         band_stack[band_top++] = y_min;
@@ -3045,9 +2489,12 @@
       }
       else
       {
+        FT_TRACE6(( "band [%d..%d]: %hd profiles; %td bytes remaining\n",
+                    y_min, y_max, ras.num_Profs,
+                    (char*)ras.maxBuff - (char*)ras.top ));
+
         if ( ras.fProfile )
-          if ( Draw_Sweep( RAS_VAR ) )
-             return ras.error;
+          Draw_Sweep( RAS_VAR );
 
         if ( --band_top < 0 )
           break;
@@ -3076,53 +2523,48 @@
   Render_Glyph( RAS_ARG )
   {
     FT_Error  error;
+    Long      buffer[FT_MAX_BLACK_POOL];
 
 
+    ras.buff     = buffer;
+    ras.sizeBuff = (&buffer)[1]; /* Points to right after buffer. */
+
     Set_High_Precision( RAS_VARS ras.outline.flags &
                                  FT_OUTLINE_HIGH_PRECISION );
 
+    ras.dropOutControl = 0;
+
     if ( ras.outline.flags & FT_OUTLINE_IGNORE_DROPOUTS )
-      ras.dropOutControl = 2;
-    else
-    {
-      if ( ras.outline.flags & FT_OUTLINE_SMART_DROPOUTS )
-        ras.dropOutControl = 4;
-      else
-        ras.dropOutControl = 0;
+      ras.dropOutControl |= 2;
 
-      if ( !( ras.outline.flags & FT_OUTLINE_INCLUDE_STUBS ) )
-        ras.dropOutControl += 1;
-    }
+    if ( ras.outline.flags & FT_OUTLINE_SMART_DROPOUTS )
+      ras.dropOutControl |= 4;
 
-    /* Vertical Sweep */
-    FT_TRACE7(( "Vertical pass (ftraster)\n" ));
+    if ( !( ras.outline.flags & FT_OUTLINE_INCLUDE_STUBS ) )
+      ras.dropOutControl |= 1;
+
+    FT_TRACE6(( "BW Raster: precision 1/%d, dropout mode %d\n",
+                ras.precision, ras.dropOutControl ));
 
+    /* Vertical Sweep */
     ras.Proc_Sweep_Init = Vertical_Sweep_Init;
     ras.Proc_Sweep_Span = Vertical_Sweep_Span;
     ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
     ras.Proc_Sweep_Step = Vertical_Sweep_Step;
 
-    ras.bWidth  = (UShort)ras.target.width;
-    ras.bOrigin = (Byte*)ras.target.buffer;
-
-    if ( ras.target.pitch > 0 )
-      ras.bOrigin += (Long)( ras.target.rows - 1 ) * ras.target.pitch;
-
-    error = Render_Single_Pass( RAS_VARS 0, 0, (Int)ras.target.rows - 1 );
+    error = Render_Single_Pass( RAS_VARS 0, 0, ras.bTop );
     if ( error )
       return error;
 
     /* Horizontal Sweep */
     if ( !( ras.outline.flags & FT_OUTLINE_SINGLE_PASS ) )
     {
-      FT_TRACE7(( "Horizontal pass (ftraster)\n" ));
-
       ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
       ras.Proc_Sweep_Span = Horizontal_Sweep_Span;
       ras.Proc_Sweep_Drop = Horizontal_Sweep_Drop;
       ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
 
-      error = Render_Single_Pass( RAS_VARS 1, 0, (Int)ras.target.width - 1 );
+      error = Render_Single_Pass( RAS_VARS 1, 0, ras.bRight );
       if ( error )
         return error;
     }
@@ -3233,8 +2675,6 @@
     black_TWorker  worker[1];
 #endif
 
-    Long  buffer[FT_MAX_BLACK_POOL];
-
 
     if ( !raster )
       return FT_THROW( Raster_Uninitialized );
@@ -3243,7 +2683,7 @@
       return FT_THROW( Invalid_Outline );
 
     /* return immediately if the outline is empty */
-    if ( outline->n_points == 0 || outline->n_contours <= 0 )
+    if ( outline->n_points == 0 || outline->n_contours == 0 )
       return Raster_Err_Ok;
 
     if ( !outline->contours || !outline->points )
@@ -3269,10 +2709,14 @@
       return FT_THROW( Invalid_Argument );
 
     ras.outline = *outline;
-    ras.target  = *target_map;
 
-    ras.buff     = buffer;
-    ras.sizeBuff = (&buffer)[1]; /* Points to right after buffer. */
+    ras.bTop    =   (Int)target_map->rows - 1;
+    ras.bRight  =   (Int)target_map->width - 1;
+    ras.bPitch  =   (Int)target_map->pitch;
+    ras.bOrigin = (PByte)target_map->buffer;
+
+    if ( ras.bPitch > 0 )
+      ras.bOrigin += ras.bTop * ras.bPitch;
 
     return Render_Glyph( RAS_VAR );
   }
diff --git a/src/java.desktop/share/native/libfreetype/src/raster/ftraster.h b/src/java.desktop/share/native/libfreetype/src/raster/ftraster.h
index b511b3a99e9..ad9cb1b9fe0 100644
--- a/src/java.desktop/share/native/libfreetype/src/raster/ftraster.h
+++ b/src/java.desktop/share/native/libfreetype/src/raster/ftraster.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType glyph rasterizer (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used
diff --git a/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.c b/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.c
index 6d442b1ff8c..fd9f174f2e1 100644
--- a/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.c
+++ b/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.c
@@ -4,7 +4,7 @@
  *
  *   The FreeType glyph rasterizer interface (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.h b/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.h
index cec35c8528a..cf3e73c0a24 100644
--- a/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.h
+++ b/src/java.desktop/share/native/libfreetype/src/raster/ftrend1.h
@@ -4,7 +4,7 @@
  *
  *   The FreeType glyph rasterizer interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/raster/rasterrs.h b/src/java.desktop/share/native/libfreetype/src/raster/rasterrs.h
index 989d8b44be1..326d42e0438 100644
--- a/src/java.desktop/share/native/libfreetype/src/raster/rasterrs.h
+++ b/src/java.desktop/share/native/libfreetype/src/raster/rasterrs.h
@@ -4,7 +4,7 @@
  *
  *   monochrome renderer error codes (specification only).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.c b/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.c
index 33712162e00..76181568af9 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.c
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.c
@@ -4,7 +4,7 @@
  *
  *   PNG Bitmap glyph support.
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * Google, Inc.
  * Written by Stuart Gill and Behdad Esfahbod.
  *
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.h b/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.h
index 903bd2bc348..6e7a5c08e71 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.h
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/pngshim.h
@@ -4,7 +4,7 @@
  *
  *   PNG Bitmap glyph support.
  *
- * Copyright (C) 2013-2023 by
+ * Copyright (C) 2013-2024 by
  * Google, Inc.
  * Written by Stuart Gill and Behdad Esfahbod.
  *
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.c b/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.c
index 0925940b03f..81072207b49 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.c
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.c
@@ -4,7 +4,7 @@
  *
  *   High-level SFNT driver interface (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -49,6 +49,10 @@
 #include 
 #endif
 
+#ifdef TT_CONFIG_OPTION_GPOS_KERNING
+#include "ttgpos.h"
+#endif
+
 #include "ttcmap.h"
 #include "ttkern.h"
 #include "ttmtx.h"
@@ -1249,6 +1253,12 @@
 #define PUT_PS_NAMES( a )  a
 #else
 #define PUT_PS_NAMES( a )  NULL
+#endif
+
+#ifdef TT_CONFIG_OPTION_GPOS_KERNING
+#define PUT_GPOS_KERNING( a )  a
+#else
+#define PUT_GPOS_KERNING( a )  NULL
 #endif
 
   FT_DEFINE_SFNT_INTERFACE(
@@ -1274,6 +1284,8 @@
     tt_face_free_name,      /* TT_Free_Table_Func      free_name       */
 
     tt_face_load_kern,      /* TT_Load_Table_Func      load_kern       */
+    PUT_GPOS_KERNING( tt_face_load_gpos ),
+                            /* TT_Load_Table_Func      load_gpos       */
     tt_face_load_gasp,      /* TT_Load_Table_Func      load_gasp       */
     tt_face_load_pclt,      /* TT_Load_Table_Func      load_init       */
 
@@ -1292,6 +1304,9 @@
     /* since version 2.1.8 */
     tt_face_get_kerning,    /* TT_Face_GetKerningFunc  get_kerning     */
 
+    PUT_GPOS_KERNING( tt_face_get_gpos_kerning ),
+                           /* TT_Face_GetKerningFunc  get_gpos_kerning */
+
     /* since version 2.2 */
     tt_face_load_font_dir,  /* TT_Load_Table_Func      load_font_dir   */
     tt_face_load_hmtx,      /* TT_Load_Metrics_Func    load_hmtx       */
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.h b/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.h
index 2445958b69f..6f71489fdc1 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.h
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfdriver.h
@@ -4,7 +4,7 @@
  *
  *   High-level SFNT driver interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sferrors.h b/src/java.desktop/share/native/libfreetype/src/sfnt/sferrors.h
index e7a8eb04bb8..d3ca1d9aa8b 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/sferrors.h
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sferrors.h
@@ -4,7 +4,7 @@
  *
  *   SFNT error codes (specification only).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.c b/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.c
index f5d66ef8403..6ee4e5e939b 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.c
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.c
@@ -4,7 +4,7 @@
  *
  *   SFNT object management (base).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -40,6 +40,10 @@
 #include "ttbdf.h"
 #endif
 
+#ifdef TT_CONFIG_OPTION_GPOS_KERNING
+#include "ttgpos.h"
+#endif
+
 
   /**************************************************************************
    *
@@ -1026,6 +1030,10 @@
     LOAD_( gasp );
     LOAD_( kern );
 
+#ifdef TT_CONFIG_OPTION_GPOS_KERNING
+    LOAD_( gpos );
+#endif
+
     face->root.num_glyphs = face->max_profile.numGlyphs;
 
     /* Bit 8 of the `fsSelection' field in the `OS/2' table denotes  */
@@ -1119,7 +1127,11 @@
         flags |= FT_FACE_FLAG_VERTICAL;
 
       /* kerning available ? */
-      if ( TT_FACE_HAS_KERNING( face ) )
+      if ( TT_FACE_HAS_KERNING( face )
+#ifdef TT_CONFIG_OPTION_GPOS_KERNING
+           || face->gpos_kerning_available
+#endif
+         )
         flags |= FT_FACE_FLAG_KERNING;
 
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
@@ -1470,6 +1482,11 @@
     /* freeing the kerning table */
     tt_face_done_kern( face );
 
+#ifdef TT_CONFIG_OPTION_GPOS_KERNING
+    /* freeing the GPOS table */
+    tt_face_done_gpos( face );
+#endif
+
     /* freeing the collection table */
     FT_FREE( face->ttc_header.offsets );
     face->ttc_header.count = 0;
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.h b/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.h
index 906aebbf904..90847d95732 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.h
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfobjs.h
@@ -4,7 +4,7 @@
  *
  *   SFNT object management (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.c b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.c
index 7c0ce2205e6..14514bf9574 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.c
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.c
@@ -4,7 +4,7 @@
  *
  *   WOFF format management (base).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -18,6 +18,7 @@
 
 #include "sfwoff.h"
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -149,6 +150,7 @@
     /* Miscellaneous checks. */
     if ( woff.length != stream->size                              ||
          woff.num_tables == 0                                     ||
+         woff.num_tables >  0xFFFU                                ||
          44 + woff.num_tables * 20UL >= woff.length               ||
          12 + woff.num_tables * 16UL >= woff.totalSfntSize        ||
          ( woff.totalSfntSize & 3 ) != 0                          ||
@@ -169,21 +171,11 @@
 
     /* Write sfnt header. */
     {
-      FT_UInt  searchRange, entrySelector, rangeShift, x;
+      FT_Int  entrySelector = FT_MSB( woff.num_tables );
+      FT_Int  searchRange   = ( 1 << entrySelector ) * 16;
+      FT_Int  rangeShift    = woff.num_tables * 16 - searchRange;
 
 
-      x             = woff.num_tables;
-      entrySelector = 0;
-      while ( x )
-      {
-        x            >>= 1;
-        entrySelector += 1;
-      }
-      entrySelector--;
-
-      searchRange = ( 1 << entrySelector ) * 16;
-      rangeShift  = woff.num_tables * 16 - searchRange;
-
       WRITE_ULONG ( sfnt_header, woff.flavor );
       WRITE_USHORT( sfnt_header, woff.num_tables );
       WRITE_USHORT( sfnt_header, searchRange );
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.h b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.h
index d4384227376..a04735ffe28 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.h
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff.h
@@ -4,7 +4,7 @@
  *
  *   WOFFF format management (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.c b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.c
index 2be44a347ad..589b3e0c6b7 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.c
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.c
@@ -4,7 +4,7 @@
  *
  *   WOFF2 format management (base).
  *
- * Copyright (C) 2019-2023 by
+ * Copyright (C) 2019-2024 by
  * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -18,6 +18,7 @@
 #include "sfwoff2.h"
 #include "woff2tags.h"
 #include 
+#include 
 #include 
 #include 
 
@@ -289,23 +290,15 @@
     FT_ULong  checksum     = 0;
     FT_ULong  aligned_size = size & ~3UL;
     FT_ULong  i;
-    FT_ULong  v;
+    FT_Int    shift;
 
 
     for ( i = 0; i < aligned_size; i += 4 )
-      checksum += ( (FT_ULong)buf[i    ] << 24 ) |
-                  ( (FT_ULong)buf[i + 1] << 16 ) |
-                  ( (FT_ULong)buf[i + 2] <<  8 ) |
-                  ( (FT_ULong)buf[i + 3] <<  0 );
+      checksum += FT_NEXT_ULONG( buf );
 
-    /* If size is not aligned to 4, treat as if it is padded with 0s. */
-    if ( size != aligned_size )
-    {
-      v = 0;
-      for ( i = aligned_size ; i < size; ++i )
-        v |= (FT_ULong)buf[i] << ( 24 - 8 * ( i & 3 ) );
-      checksum += v;
-    }
+    /* remaining bytes can be shifted and added one at a time */
+    for ( shift = 24; i < size; i++, shift -= 8 )
+      checksum += (FT_UInt32)FT_NEXT_BYTE( buf ) << shift;
 
     return checksum;
   }
@@ -1799,7 +1792,6 @@
 
     FT_Byte*   sfnt        = NULL;
     FT_Stream  sfnt_stream = NULL;
-    FT_Byte*   sfnt_header;
     FT_ULong   sfnt_size;
 
     FT_Byte*  uncompressed_buf = NULL;
@@ -1853,6 +1845,7 @@
     /* Miscellaneous checks. */
     if ( woff2.length != stream->size                               ||
          woff2.num_tables == 0                                      ||
+         woff2.num_tables >  0xFFFU                                 ||
          48 + woff2.num_tables * 20UL >= woff2.length               ||
          ( woff2.metaOffset == 0 && ( woff2.metaLength != 0     ||
                                       woff2.metaOrigLength != 0 ) ) ||
@@ -2143,6 +2136,13 @@
       WOFF2_TtcFont  ttc_font = woff2.ttc_fonts + face_index;
 
 
+      if ( ttc_font->num_tables == 0 || ttc_font->num_tables > 0xFFFU )
+      {
+        FT_ERROR(( "woff2_open_font: invalid WOFF2 CollectionFontEntry\n" ));
+        error = FT_THROW( Invalid_Table );
+        goto Exit;
+      }
+
       /* Create a temporary array. */
       if ( FT_QNEW_ARRAY( temp_indices,
                           ttc_font->num_tables ) )
@@ -2198,27 +2198,15 @@
          FT_NEW( sfnt_stream )        )
       goto Exit;
 
-    sfnt_header = sfnt;
-
-    WRITE_ULONG( sfnt_header, woff2.flavor );
-
-    if ( woff2.num_tables )
     {
-      FT_UInt  searchRange, entrySelector, rangeShift, x;
+      FT_Byte*  sfnt_header = sfnt;
 
+      FT_Int  entrySelector = FT_MSB( woff2.num_tables );
+      FT_Int  searchRange   = ( 1 << entrySelector ) * 16;
+      FT_Int  rangeShift    = woff2.num_tables * 16 - searchRange;
 
-      x             = woff2.num_tables;
-      entrySelector = 0;
-      while ( x )
-      {
-        x            >>= 1;
-        entrySelector += 1;
-      }
-      entrySelector--;
-
-      searchRange = ( 1 << entrySelector ) * 16;
-      rangeShift  = ( woff2.num_tables * 16 ) - searchRange;
 
+      WRITE_ULONG ( sfnt_header, woff2.flavor );
       WRITE_USHORT( sfnt_header, woff2.num_tables );
       WRITE_USHORT( sfnt_header, searchRange );
       WRITE_USHORT( sfnt_header, entrySelector );
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.h b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.h
index 4901286ee08..f41140648dc 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.h
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/sfwoff2.h
@@ -4,7 +4,7 @@
  *
  *   WOFFF2 format management (specification).
  *
- * Copyright (C) 2019-2023 by
+ * Copyright (C) 2019-2024 by
  * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.c
index 9ba25dcbc13..28f4d1173c0 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.c
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.c
@@ -4,7 +4,7 @@
  *
  *   TrueType character mapping table (cmap) support (body).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.h
index ff52917ed5b..e2c5e72bf02 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.h
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmap.h
@@ -4,7 +4,7 @@
  *
  *   TrueType character mapping table (cmap) support (specification).
  *
- * Copyright (C) 2002-2023 by
+ * Copyright (C) 2002-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmapc.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmapc.h
index 0af48c2478a..370898363f3 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmapc.h
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcmapc.h
@@ -4,7 +4,7 @@
  *
  *   TT CMAP classes definitions (specification only).
  *
- * Copyright (C) 2009-2023 by
+ * Copyright (C) 2009-2024 by
  * Oran Agra and Mickey Gabel.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.c
index 281e7135eea..b37658dde9e 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.c
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.c
@@ -4,7 +4,7 @@
  *
  *   TrueType and OpenType colored glyph layer support (body).
  *
- * Copyright (C) 2018-2023 by
+ * Copyright (C) 2018-2024 by
  * David Turner, Robert Wilhelm, Dominik Röttsches, and Werner Lemberg.
  *
  * Originally written by Shao Yu Zhang .
@@ -208,18 +208,19 @@
     colr->num_base_glyphs = FT_NEXT_USHORT( p );
     base_glyph_offset     = FT_NEXT_ULONG( p );
 
-    if ( base_glyph_offset >= table_size )
+    if ( table_size <= base_glyph_offset )
       goto InvalidTable;
-    if ( colr->num_base_glyphs * BASE_GLYPH_SIZE >
-           table_size - base_glyph_offset )
+    if ( ( table_size - base_glyph_offset ) / BASE_GLYPH_SIZE
+             < colr->num_base_glyphs )
       goto InvalidTable;
 
     layer_offset     = FT_NEXT_ULONG( p );
     colr->num_layers = FT_NEXT_USHORT( p );
 
-    if ( layer_offset >= table_size )
+    if ( table_size <= layer_offset )
       goto InvalidTable;
-    if ( colr->num_layers * LAYER_SIZE > table_size - layer_offset )
+    if ( ( table_size - layer_offset ) / LAYER_SIZE
+             < colr->num_layers )
       goto InvalidTable;
 
     if ( colr->version == 1 )
@@ -229,14 +230,14 @@
 
       base_glyphs_offset_v1 = FT_NEXT_ULONG( p );
 
-      if ( base_glyphs_offset_v1 >= table_size - 4 )
+      if ( table_size - 4 <= base_glyphs_offset_v1 )
         goto InvalidTable;
 
       p1                 = (FT_Byte*)( table + base_glyphs_offset_v1 );
       num_base_glyphs_v1 = FT_PEEK_ULONG( p1 );
 
-      if ( num_base_glyphs_v1 * BASE_GLYPH_PAINT_RECORD_SIZE >
-             table_size - base_glyphs_offset_v1 )
+      if ( ( table_size - base_glyphs_offset_v1 ) / BASE_GLYPH_PAINT_RECORD_SIZE
+               < num_base_glyphs_v1 )
         goto InvalidTable;
 
       colr->num_base_glyphs_v1 = num_base_glyphs_v1;
@@ -244,19 +245,19 @@
 
       layer_offset_v1 = FT_NEXT_ULONG( p );
 
-      if ( layer_offset_v1 >= table_size )
+      if ( table_size <= layer_offset_v1 )
         goto InvalidTable;
 
       if ( layer_offset_v1 )
       {
-        if ( layer_offset_v1 >= table_size - 4 )
+        if ( table_size - 4 <= layer_offset_v1 )
           goto InvalidTable;
 
         p1            = (FT_Byte*)( table + layer_offset_v1 );
         num_layers_v1 = FT_PEEK_ULONG( p1 );
 
-        if ( num_layers_v1 * LAYER_V1_LIST_PAINT_OFFSET_SIZE >
-               table_size - layer_offset_v1 )
+        if ( ( table_size - layer_offset_v1 ) / LAYER_V1_LIST_PAINT_OFFSET_SIZE
+                < num_layers_v1 )
           goto InvalidTable;
 
         colr->num_layers_v1 = num_layers_v1;
@@ -279,7 +280,7 @@
 
       clip_list_offset = FT_NEXT_ULONG( p );
 
-      if ( clip_list_offset >= table_size )
+      if ( table_size <= clip_list_offset )
         goto InvalidTable;
 
       if ( clip_list_offset )
@@ -311,7 +312,7 @@
           goto InvalidTable;
 
         var_store_offset = FT_NEXT_ULONG( p );
-        if ( var_store_offset >= table_size )
+        if ( table_size <= var_store_offset )
           goto InvalidTable;
 
         if ( var_store_offset )
@@ -661,6 +662,7 @@
       FT_UInt32  first_layer_index;
 
 
+      ENSURE_READ_BYTES( 5 );
       num_layers = FT_NEXT_BYTE( p );
       if ( num_layers > colr->num_layers_v1 )
         return 0;
@@ -1278,7 +1280,8 @@
 
     while ( min < max )
     {
-      FT_UInt  mid = min + ( max - min ) / 2;
+      FT_UInt    mid = min + ( max - min ) / 2;
+      FT_UShort  gid;
 
       /*
        * `base_glyph_begin` is the beginning of `BaseGlyphV1List`;
@@ -1287,8 +1290,7 @@
        */
       FT_Byte  *p = base_glyph_begin + 4 + mid * BASE_GLYPH_PAINT_RECORD_SIZE;
 
-      FT_UShort  gid = FT_NEXT_USHORT( p );
-
+      gid = FT_NEXT_USHORT( p );
 
       if ( gid < glyph_id )
         min = mid + 1;
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.h
index 20c85f0359f..30031464c73 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.h
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcolr.h
@@ -4,7 +4,7 @@
  *
  *   TrueType and OpenType colored glyph layer support (specification).
  *
- * Copyright (C) 2018-2023 by
+ * Copyright (C) 2018-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * Originally written by Shao Yu Zhang .
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.c
index 46ae08596f3..997eb869ffc 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.c
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.c
@@ -4,7 +4,7 @@
  *
  *   TrueType and OpenType color palette support (body).
  *
- * Copyright (C) 2018-2023 by
+ * Copyright (C) 2018-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * Originally written by Shao Yu Zhang .
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.h
index 8e9913f0ccd..bb301ae88b6 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.h
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttcpal.h
@@ -4,7 +4,7 @@
  *
  *   TrueType and OpenType color palette support (specification).
  *
- * Copyright (C) 2018-2023 by
+ * Copyright (C) 2018-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * Originally written by Shao Yu Zhang .
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.c
index a47d08bd6de..f0411366af4 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.c
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.c
@@ -5,7 +5,7 @@
  *   Load the basic TrueType kerning table.  This doesn't handle
  *   kerning data within the GPOS table at the moment.
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.h
index 960c7da4946..a54e51df12d 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.h
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttkern.h
@@ -5,7 +5,7 @@
  *   Load the basic TrueType kerning table.  This doesn't handle
  *   kerning data within the GPOS table at the moment.
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.c
index 7b44e9cd2e7..c3a5fae2cb9 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.c
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.c
@@ -5,7 +5,7 @@
  *   Load the basic TrueType tables, i.e., tables that can be either in
  *   TTF or OTF fonts (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -1046,7 +1046,7 @@
   FT_LOCAL_DEF( void )
   tt_face_free_name( TT_Face  face )
   {
-    FT_Memory     memory = face->root.driver->root.memory;
+    FT_Memory     memory = face->root.memory;
     TT_NameTable  table  = &face->name_table;
 
 
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.h
index 1499dd5735f..2b1d62d9bd9 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.h
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttload.h
@@ -5,7 +5,7 @@
  *   Load the basic TrueType tables, i.e., tables that can be either in
  *   TTF or OTF fonts (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.c
index 38ee9ae728a..27884118563 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.c
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.c
@@ -4,7 +4,7 @@
  *
  *   Load the metrics tables common to TTF and OTF fonts (body).
  *
- * Copyright (C) 2006-2023 by
+ * Copyright (C) 2006-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.h
index 56d2b627661..34b3c0e18f2 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.h
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttmtx.h
@@ -4,7 +4,7 @@
  *
  *   Load the metrics tables common to TTF and OTF fonts (specification).
  *
- * Copyright (C) 2006-2023 by
+ * Copyright (C) 2006-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.c
index 1dfad4298bd..5698a62c8d1 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.c
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.c
@@ -5,7 +5,7 @@
  *   PostScript name table processing for TrueType and OpenType fonts
  *   (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -204,8 +204,8 @@
     /* now load the name strings */
     if ( num_names )
     {
-      FT_ULong   p;
-      FT_Byte*   strings;
+      FT_Byte*   p;
+      FT_Byte*   p_end;
 
 
       post_len -= (FT_ULong)num_glyphs * 2;
@@ -214,36 +214,36 @@
                                     post_len + 1 ) )
         goto Fail;
 
-      strings = (FT_Byte*)( name_strings + num_names );
-      if ( FT_STREAM_READ( strings, post_len ) )
+      p = (FT_Byte*)( name_strings + num_names );
+      if ( FT_STREAM_READ( p, post_len ) )
         goto Fail;
 
+      p_end = p + post_len;
+
       /* convert from Pascal- to C-strings and set pointers */
-      for ( p = 0, n = 0; p < post_len && n < num_names; n++ )
+      for ( n = 0; p < p_end && n < num_names; n++ )
       {
-        FT_UInt  len = strings[p];
+        FT_UInt  len = *p;
 
 
-        if ( len > 63U )
-        {
-          error = FT_THROW( Invalid_File_Format );
-          goto Fail;
-        }
+        /* names in the Adobe Glyph List are shorter than 40 characters */
+        if ( len >= 40U )
+          FT_TRACE4(( "load_format_20: unusual %u-char name found\n", len ));
 
-        strings[p]      = 0;
-        name_strings[n] = strings + p + 1;
-        p              += len + 1;
+        *p++            = 0;
+        name_strings[n] = p;
+        p              += len;
       }
-      strings[post_len] = 0;
+      *p_end = 0;
 
       /* deal with missing or insufficient string data */
       if ( n < num_names )
       {
         FT_TRACE4(( "load_format_20: %hu PostScript names are truncated\n",
-                    num_names - n ));
+                    (FT_UShort)( num_names - n ) ));
 
         for ( ; n < num_names; n++ )
-          name_strings[n] = strings + post_len;
+          name_strings[n] = p_end;
       }
     }
 
@@ -436,13 +436,8 @@
 
     format = face->postscript.FormatType;
 
-    if ( format == 0x00010000L )
-    {
-      if ( idx < 258 )                    /* paranoid checking */
-        *PSname = MAC_NAME( idx );
-    }
-    else if ( format == 0x00020000L ||
-              format == 0x00025000L )
+    if ( format == 0x00020000L ||
+         format == 0x00025000L )
     {
       TT_Post_Names  names = &face->postscript_names;
 
@@ -466,6 +461,11 @@
       }
     }
 
+    /* version 1.0 is only valid with 258 glyphs */
+    else if ( format == 0x00010000L              &&
+              face->max_profile.numGlyphs == 258 )
+      *PSname = MAC_NAME( idx );
+
     /* nothing to do for format == 0x00030000L */
 
   End:
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.h
index 528f1c5f2f2..150db6c3981 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.h
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttpost.h
@@ -5,7 +5,7 @@
  *   PostScript name table processing for TrueType and OpenType fonts
  *   (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.c b/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.c
index 03f90a628d6..cb3a8abf182 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.c
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.c
@@ -4,7 +4,7 @@
  *
  *   TrueType and OpenType embedded bitmap support (body).
  *
- * Copyright (C) 2005-2023 by
+ * Copyright (C) 2005-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * Copyright 2013 by Google, Inc.
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.h b/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.h
index 07e2db461a5..96f80a58424 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.h
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/ttsbit.h
@@ -4,7 +4,7 @@
  *
  *   TrueType and OpenType embedded bitmap support (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.c b/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.c
index eeedd9906be..532ccfa1737 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.c
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.c
@@ -4,7 +4,7 @@
  *
  *   WOFF2 Font table tags (base).
  *
- * Copyright (C) 2019-2023 by
+ * Copyright (C) 2019-2024 by
  * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.h b/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.h
index 1201848e5ec..d03b4b41bc9 100644
--- a/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.h
+++ b/src/java.desktop/share/native/libfreetype/src/sfnt/woff2tags.h
@@ -4,7 +4,7 @@
  *
  *   WOFF2 Font table tags (specification).
  *
- * Copyright (C) 2019-2023 by
+ * Copyright (C) 2019-2024 by
  * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.c b/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.c
index 0918272f870..b7c0632a6fa 100644
--- a/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.c
+++ b/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.c
@@ -4,7 +4,7 @@
  *
  *   A new `perfect' anti-aliasing renderer (body).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -489,7 +489,7 @@ typedef ptrdiff_t  FT_PtrDist;
 
   typedef struct  gray_TWorker_
   {
-    ft_jmp_buf  jump_buffer;
+    FT_BBox     cbox;
 
     TCoord  min_ex, max_ex;  /* min and max integer pixel coordinates */
     TCoord  min_ey, max_ey;
@@ -510,6 +510,8 @@ typedef ptrdiff_t  FT_PtrDist;
     FT_Raster_Span_Func  render_span;
     void*                render_span_data;
 
+    ft_jmp_buf  jump_buffer;
+
   } gray_TWorker, *gray_PWorker;
 
 #if defined( _MSC_VER )
@@ -997,49 +999,12 @@ typedef ptrdiff_t  FT_PtrDist;
 #endif
 
   /*
-   * Benchmarking shows that using DDA to flatten the quadratic Bézier arcs
-   * is slightly faster in the following cases:
-   *
-   *   - When the host CPU is 64-bit.
-   *   - When SSE2 SIMD registers and instructions are available (even on
-   *     x86).
-   *
-   * For other cases, using binary splits is actually slightly faster.
-   */
-#if ( defined( __SSE2__ )                          ||   \
-      defined( __x86_64__ )                        ||   \
-      defined( _M_AMD64 )                          ||   \
-      ( defined( _M_IX86_FP ) && _M_IX86_FP >= 2 ) ) && \
-    !defined( __VMS )
-#  define FT_SSE2 1
-#else
-#  define FT_SSE2 0
-#endif
-
-#if FT_SSE2                || \
-    defined( __aarch64__ ) || \
-    defined( _M_ARM64 )
-#  define BEZIER_USE_DDA  1
-#else
-#  define BEZIER_USE_DDA  0
-#endif
-
-  /*
-   * For now, the code that depends on `BEZIER_USE_DDA` requires `FT_Int64`
-   * to be defined.  If `FT_INT64` is not defined, meaning there is no
-   * 64-bit type available, disable it to avoid compilation errors.  See for
-   * example https://gitlab.freedesktop.org/freetype/freetype/-/issues/1071.
+   * For now, the code that uses DDA to render conic curves requires
+   * `FT_Int64` to be defined.  See for example
+   *    https://gitlab.freedesktop.org/freetype/freetype/-/issues/1071.
    */
-#if !defined( FT_INT64 )
-#  undef BEZIER_USE_DDA
-#  define BEZIER_USE_DDA  0
-#endif
-
-#if BEZIER_USE_DDA
 
-#if FT_SSE2
-#  include 
-#endif
+#ifdef FT_INT64
 
 #define LEFT_SHIFT( a, b )  (FT_Int64)( (FT_UInt64)(a) << (b) )
 
@@ -1095,16 +1060,17 @@ typedef ptrdiff_t  FT_PtrDist;
       return;
     }
 
-    /* We can calculate the number of necessary bisections because  */
+    /* We can calculate the number of necessary segments because    */
     /* each bisection predictably reduces deviation exactly 4-fold. */
     /* Even 32-bit deviation would vanish after 16 bisections.      */
-    shift = 0;
+    shift = 16;
     do
     {
-      dx   >>= 2;
-      shift += 1;
+      dx >>= 2;
+      shift--;
 
     } while ( dx > ONE_PIXEL / 4 );
+    count = 0x10000U >> shift;
 
     /*
      * The (P0,P1,P2) arc equation, for t in [0,1] range:
@@ -1150,75 +1116,19 @@ typedef ptrdiff_t  FT_PtrDist;
      *             = (B << (33 - N)) + (A << (32 - 2*N))
      */
 
-#if FT_SSE2
-    /* Experience shows that for small shift values, */
-    /* SSE2 is actually slower.                      */
-    if ( shift > 2 )
-    {
-      union
-      {
-        struct { FT_Int64  ax, ay, bx, by; }  i;
-        struct { __m128i  a, b; }  vec;
-
-      } u;
-
-      union
-      {
-        struct { FT_Int32  px_lo, px_hi, py_lo, py_hi; }  i;
-        __m128i  vec;
-
-      } v;
-
-      __m128i  a, b;
-      __m128i  r, q, q2;
-      __m128i  p;
-
-
-      u.i.ax = ax;
-      u.i.ay = ay;
-      u.i.bx = bx;
-      u.i.by = by;
-
-      a = _mm_load_si128( &u.vec.a );
-      b = _mm_load_si128( &u.vec.b );
-
-      r  = _mm_slli_epi64( a, 33 - 2 * shift );
-      q  = _mm_slli_epi64( b, 33 - shift );
-      q2 = _mm_slli_epi64( a, 32 - 2 * shift );
-
-      q = _mm_add_epi64( q2, q );
-
-      v.i.px_lo = 0;
-      v.i.px_hi = p0.x;
-      v.i.py_lo = 0;
-      v.i.py_hi = p0.y;
-
-      p = _mm_load_si128( &v.vec );
-
-      for ( count = 1U << shift; count > 0; count-- )
-      {
-        p = _mm_add_epi64( p, q );
-        q = _mm_add_epi64( q, r );
-
-        _mm_store_si128( &v.vec, p );
-
-        gray_render_line( RAS_VAR_ v.i.px_hi, v.i.py_hi );
-      }
-
-      return;
-    }
-#endif  /* FT_SSE2 */
+    rx = LEFT_SHIFT( ax, shift + shift );
+    ry = LEFT_SHIFT( ay, shift + shift );
 
-    rx = LEFT_SHIFT( ax, 33 - 2 * shift );
-    ry = LEFT_SHIFT( ay, 33 - 2 * shift );
+    qx = LEFT_SHIFT( bx, shift + 17 ) + rx;
+    qy = LEFT_SHIFT( by, shift + 17 ) + ry;
 
-    qx = LEFT_SHIFT( bx, 33 - shift ) + LEFT_SHIFT( ax, 32 - 2 * shift );
-    qy = LEFT_SHIFT( by, 33 - shift ) + LEFT_SHIFT( ay, 32 - 2 * shift );
+    rx *= 2;
+    ry *= 2;
 
     px = LEFT_SHIFT( p0.x, 32 );
     py = LEFT_SHIFT( p0.y, 32 );
 
-    for ( count = 1U << shift; count > 0; count-- )
+    do
     {
       px += qx;
       py += qy;
@@ -1227,10 +1137,10 @@ typedef ptrdiff_t  FT_PtrDist;
 
       gray_render_line( RAS_VAR_ (FT_Pos)( px >> 32 ),
                                  (FT_Pos)( py >> 32 ) );
-    }
+    } while ( --count );
   }
 
-#else  /* !BEZIER_USE_DDA */
+#else  /* !FT_INT64 */
 
   /*
    * Note that multiple attempts to speed up the function below
@@ -1324,7 +1234,7 @@ typedef ptrdiff_t  FT_PtrDist;
     } while ( --draw );
   }
 
-#endif  /* !BEZIER_USE_DDA */
+#endif  /* !FT_INT64 */
 
 
   /*
@@ -1486,139 +1396,6 @@ typedef ptrdiff_t  FT_PtrDist;
   }
 
 
-  static void
-  gray_sweep( RAS_ARG )
-  {
-    int  fill = ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) ? 0x100
-                                                                 : INT_MIN;
-    int  coverage;
-    int  y;
-
-
-    for ( y = ras.min_ey; y < ras.max_ey; y++ )
-    {
-      PCell   cell  = ras.ycells[y - ras.min_ey];
-      TCoord  x     = ras.min_ex;
-      TArea   cover = 0;
-
-      unsigned char*  line = ras.target.origin - ras.target.pitch * y;
-
-
-      for ( ; cell != ras.cell_null; cell = cell->next )
-      {
-        TArea  area;
-
-
-        if ( cover != 0 && cell->x > x )
-        {
-          FT_FILL_RULE( coverage, cover, fill );
-          FT_GRAY_SET( line + x, coverage, cell->x - x );
-        }
-
-        cover += (TArea)cell->cover * ( ONE_PIXEL * 2 );
-        area   = cover - cell->area;
-
-        if ( area != 0 && cell->x >= ras.min_ex )
-        {
-          FT_FILL_RULE( coverage, area, fill );
-          line[cell->x] = (unsigned char)coverage;
-        }
-
-        x = cell->x + 1;
-      }
-
-      if ( cover != 0 )  /* only if cropped */
-      {
-        FT_FILL_RULE( coverage, cover, fill );
-        FT_GRAY_SET( line + x, coverage, ras.max_ex - x );
-      }
-    }
-  }
-
-
-  static void
-  gray_sweep_direct( RAS_ARG )
-  {
-    int  fill = ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) ? 0x100
-                                                                 : INT_MIN;
-    int  coverage;
-    int  y;
-
-    FT_Span  span[FT_MAX_GRAY_SPANS];
-    int      n = 0;
-
-
-    for ( y = ras.min_ey; y < ras.max_ey; y++ )
-    {
-      PCell   cell  = ras.ycells[y - ras.min_ey];
-      TCoord  x     = ras.min_ex;
-      TArea   cover = 0;
-
-
-      for ( ; cell != ras.cell_null; cell = cell->next )
-      {
-        TArea  area;
-
-
-        if ( cover != 0 && cell->x > x )
-        {
-          FT_FILL_RULE( coverage, cover, fill );
-
-          span[n].coverage = (unsigned char)coverage;
-          span[n].x        = (short)x;
-          span[n].len      = (unsigned short)( cell->x - x );
-
-          if ( ++n == FT_MAX_GRAY_SPANS )
-          {
-            /* flush the span buffer and reset the count */
-            ras.render_span( y, n, span, ras.render_span_data );
-            n = 0;
-          }
-        }
-
-        cover += (TArea)cell->cover * ( ONE_PIXEL * 2 );
-        area   = cover - cell->area;
-
-        if ( area != 0 && cell->x >= ras.min_ex )
-        {
-          FT_FILL_RULE( coverage, area, fill );
-
-          span[n].coverage = (unsigned char)coverage;
-          span[n].x        = (short)cell->x;
-          span[n].len      = 1;
-
-          if ( ++n == FT_MAX_GRAY_SPANS )
-          {
-            /* flush the span buffer and reset the count */
-            ras.render_span( y, n, span, ras.render_span_data );
-            n = 0;
-          }
-        }
-
-        x = cell->x + 1;
-      }
-
-      if ( cover != 0 )  /* only if cropped */
-      {
-        FT_FILL_RULE( coverage, cover, fill );
-
-        span[n].coverage = (unsigned char)coverage;
-        span[n].x        = (short)x;
-        span[n].len      = (unsigned short)( ras.max_ex - x );
-
-        ++n;
-      }
-
-      if ( n )
-      {
-        /* flush the span buffer and reset the count */
-        ras.render_span( y, n, span, ras.render_span_data );
-        n = 0;
-      }
-    }
-  }
-
-
 #ifdef STANDALONE_
 
   /**************************************************************************
@@ -1934,7 +1711,7 @@ typedef ptrdiff_t  FT_PtrDist;
       if ( continued )
         FT_Trace_Enable();
 
-      FT_TRACE7(( "band [%d..%d]: %td cell%s remaining/\n",
+      FT_TRACE7(( "band [%d..%d]: %td cell%s remaining\n",
                   ras.min_ey,
                   ras.max_ey,
                   ras.cell_null - ras.cell_free,
@@ -1952,14 +1729,144 @@ typedef ptrdiff_t  FT_PtrDist;
   }
 
 
+  static void
+  gray_sweep( RAS_ARG )
+  {
+    int  fill = ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) ? 0x100
+                                                                 : INT_MIN;
+    int  coverage;
+    int  y;
+
+
+    for ( y = ras.min_ey; y < ras.max_ey; y++ )
+    {
+      PCell   cell  = ras.ycells[y - ras.min_ey];
+      TCoord  x     = ras.min_ex;
+      TArea   cover = 0;
+
+      unsigned char*  line = ras.target.origin - ras.target.pitch * y;
+
+
+      for ( ; cell != ras.cell_null; cell = cell->next )
+      {
+        TArea  area;
+
+
+        if ( cover != 0 && cell->x > x )
+        {
+          FT_FILL_RULE( coverage, cover, fill );
+          FT_GRAY_SET( line + x, coverage, cell->x - x );
+        }
+
+        cover += (TArea)cell->cover * ( ONE_PIXEL * 2 );
+        area   = cover - cell->area;
+
+        if ( area != 0 && cell->x >= ras.min_ex )
+        {
+          FT_FILL_RULE( coverage, area, fill );
+          line[cell->x] = (unsigned char)coverage;
+        }
+
+        x = cell->x + 1;
+      }
+
+      if ( cover != 0 )  /* only if cropped */
+      {
+        FT_FILL_RULE( coverage, cover, fill );
+        FT_GRAY_SET( line + x, coverage, ras.max_ex - x );
+      }
+    }
+  }
+
+
+  static void
+  gray_sweep_direct( RAS_ARG )
+  {
+    int  fill = ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL ) ? 0x100
+                                                                 : INT_MIN;
+    int  coverage;
+    int  y;
+
+    FT_Span  span[FT_MAX_GRAY_SPANS];
+    int      n = 0;
+
+
+    for ( y = ras.min_ey; y < ras.max_ey; y++ )
+    {
+      PCell   cell  = ras.ycells[y - ras.min_ey];
+      TCoord  x     = ras.min_ex;
+      TArea   cover = 0;
+
+
+      for ( ; cell != ras.cell_null; cell = cell->next )
+      {
+        TArea  area;
+
+
+        if ( cover != 0 && cell->x > x )
+        {
+          FT_FILL_RULE( coverage, cover, fill );
+
+          span[n].coverage = (unsigned char)coverage;
+          span[n].x        = (short)x;
+          span[n].len      = (unsigned short)( cell->x - x );
+
+          if ( ++n == FT_MAX_GRAY_SPANS )
+          {
+            /* flush the span buffer and reset the count */
+            ras.render_span( y, n, span, ras.render_span_data );
+            n = 0;
+          }
+        }
+
+        cover += (TArea)cell->cover * ( ONE_PIXEL * 2 );
+        area   = cover - cell->area;
+
+        if ( area != 0 && cell->x >= ras.min_ex )
+        {
+          FT_FILL_RULE( coverage, area, fill );
+
+          span[n].coverage = (unsigned char)coverage;
+          span[n].x        = (short)cell->x;
+          span[n].len      = 1;
+
+          if ( ++n == FT_MAX_GRAY_SPANS )
+          {
+            /* flush the span buffer and reset the count */
+            ras.render_span( y, n, span, ras.render_span_data );
+            n = 0;
+          }
+        }
+
+        x = cell->x + 1;
+      }
+
+      if ( cover != 0 )  /* only if cropped */
+      {
+        FT_FILL_RULE( coverage, cover, fill );
+
+        span[n].coverage = (unsigned char)coverage;
+        span[n].x        = (short)x;
+        span[n].len      = (unsigned short)( ras.max_ex - x );
+
+        ++n;
+      }
+
+      if ( n )
+      {
+        /* flush the span buffer and reset the count */
+        ras.render_span( y, n, span, ras.render_span_data );
+        n = 0;
+      }
+    }
+  }
+
+
   static int
   gray_convert_glyph( RAS_ARG )
   {
-    const TCoord  yMin = ras.min_ey;
-    const TCoord  yMax = ras.max_ey;
-
     TCell    buffer[FT_MAX_GRAY_POOL];
-    size_t   height = (size_t)( yMax - yMin );
+    size_t   height = (size_t)( ras.cbox.yMax - ras.cbox.yMin );
     size_t   n = FT_MAX_GRAY_POOL / 8;
     TCoord   y;
     TCoord   bands[32];  /* enough to accommodate bisections */
@@ -1985,35 +1892,36 @@ typedef ptrdiff_t  FT_PtrDist;
       height  = ( height + n - 1 ) / n;
     }
 
-    for ( y = yMin; y < yMax; )
+    for ( y = ras.cbox.yMin; y < ras.cbox.yMax; )
     {
       ras.min_ey = y;
       y         += height;
-      ras.max_ey = FT_MIN( y, yMax );
+      ras.max_ey = FT_MIN( y, ras.cbox.yMax );
+
+      ras.count_ey = ras.max_ey - ras.min_ey;
 
       band    = bands;
-      band[1] = ras.min_ey;
-      band[0] = ras.max_ey;
+      band[1] = ras.cbox.xMin;
+      band[0] = ras.cbox.xMax;
 
       do
       {
-        TCoord  width = band[0] - band[1];
-        TCoord  w;
+        TCoord  i;
         int     error;
 
 
-        for ( w = 0; w < width; ++w )
-          ras.ycells[w] = ras.cell_null;
+        ras.min_ex = band[1];
+        ras.max_ex = band[0];
+
+        /* memory management: zero out and skip ycells */
+        for ( i = 0; i < ras.count_ey; ++i )
+          ras.ycells[i] = ras.cell_null;
 
-        /* memory management: skip ycells */
-        n = ( (size_t)width * sizeof ( PCell ) + sizeof ( TCell ) - 1 ) /
-              sizeof ( TCell );
+        n = ( (size_t)ras.count_ey * sizeof ( PCell ) + sizeof ( TCell ) - 1 )
+              / sizeof ( TCell );
 
         ras.cell_free = buffer + n;
         ras.cell      = ras.cell_null;
-        ras.min_ey    = band[1];
-        ras.max_ey    = band[0];
-        ras.count_ey  = width;
 
         error     = gray_convert_glyph_inner( RAS_VAR_ continued );
         continued = 1;
@@ -2031,10 +1939,10 @@ typedef ptrdiff_t  FT_PtrDist;
           return error;
 
         /* render pool overflow; we will reduce the render band by half */
-        width >>= 1;
+        i = ( band[0] - band[1] ) >> 1;
 
         /* this should never happen even with tiny rendering pool */
-        if ( width == 0 )
+        if ( i == 0 )
         {
           FT_TRACE7(( "gray_convert_glyph: rotten glyph\n" ));
           return FT_THROW( Raster_Overflow );
@@ -2042,7 +1950,7 @@ typedef ptrdiff_t  FT_PtrDist;
 
         band++;
         band[1]  = band[0];
-        band[0] += width;
+        band[0] += i;
       } while ( band >= bands );
     }
 
@@ -2073,7 +1981,7 @@ typedef ptrdiff_t  FT_PtrDist;
       return FT_THROW( Invalid_Outline );
 
     /* return immediately if the outline is empty */
-    if ( outline->n_points == 0 || outline->n_contours <= 0 )
+    if ( outline->n_points == 0 || outline->n_contours == 0 )
       return Smooth_Err_Ok;
 
     if ( !outline->contours || !outline->points )
@@ -2093,10 +2001,7 @@ typedef ptrdiff_t  FT_PtrDist;
       ras.render_span      = (FT_Raster_Span_Func)params->gray_spans;
       ras.render_span_data = params->user;
 
-      ras.min_ex = params->clip_box.xMin;
-      ras.min_ey = params->clip_box.yMin;
-      ras.max_ex = params->clip_box.xMax;
-      ras.max_ey = params->clip_box.yMax;
+      ras.cbox = params->clip_box;
     }
     else
     {
@@ -2122,14 +2027,14 @@ typedef ptrdiff_t  FT_PtrDist;
       ras.render_span      = (FT_Raster_Span_Func)NULL;
       ras.render_span_data = NULL;
 
-      ras.min_ex = 0;
-      ras.min_ey = 0;
-      ras.max_ex = (FT_Pos)target_map->width;
-      ras.max_ey = (FT_Pos)target_map->rows;
+      ras.cbox.xMin = 0;
+      ras.cbox.yMin = 0;
+      ras.cbox.xMax = (FT_Pos)target_map->width;
+      ras.cbox.yMax = (FT_Pos)target_map->rows;
     }
 
     /* exit if nothing to do */
-    if ( ras.max_ex <= ras.min_ex || ras.max_ey <= ras.min_ey )
+    if ( ras.cbox.xMin >= ras.cbox.xMax || ras.cbox.yMin >= ras.cbox.yMax )
       return Smooth_Err_Ok;
 
     return gray_convert_glyph( RAS_VAR );
diff --git a/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.h b/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.h
index a5001bf40d3..940fbe8c79b 100644
--- a/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.h
+++ b/src/java.desktop/share/native/libfreetype/src/smooth/ftgrays.h
@@ -4,7 +4,7 @@
  *
  *   FreeType smooth renderer declaration
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmerrs.h b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmerrs.h
index f4ac93dc410..6d41fb8e0fd 100644
--- a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmerrs.h
+++ b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmerrs.h
@@ -4,7 +4,7 @@
  *
  *   smooth renderer error codes (specification only).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.c b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.c
index 9b0e8886cb3..f0acc1ea4a6 100644
--- a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.c
+++ b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.c
@@ -4,7 +4,7 @@
  *
  *   Anti-aliasing renderer interface (body).
  *
- * Copyright (C) 2000-2023 by
+ * Copyright (C) 2000-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.h b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.h
index f8bdc9938b3..d7b61a9e60e 100644
--- a/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.h
+++ b/src/java.desktop/share/native/libfreetype/src/smooth/ftsmooth.h
@@ -4,7 +4,7 @@
  *
  *   Anti-aliasing renderer interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.c
index d1496fec7fa..4ab68eb9a12 100644
--- a/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.c
+++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.c
@@ -4,7 +4,7 @@
  *
  *   TrueType font driver implementation (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -217,7 +217,20 @@
     kerning->y = 0;
 
     if ( sfnt )
-      kerning->x = sfnt->get_kerning( ttface, left_glyph, right_glyph );
+    {
+      /* Use 'kern' table if available since that can be faster; otherwise */
+      /* use GPOS kerning pairs if available.                              */
+      if ( ttface->kern_avail_bits != 0 )
+        kerning->x = sfnt->get_kerning( ttface,
+                                        left_glyph,
+                                        right_glyph );
+#ifdef TT_CONFIG_OPTION_GPOS_KERNING
+      else if ( ttface->gpos_kerning_available )
+        kerning->x = sfnt->get_gpos_kerning( ttface,
+                                             left_glyph,
+                                             right_glyph );
+#endif
+    }
 
     return 0;
   }
diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.h
index 757a66f425d..3e1cf234fcf 100644
--- a/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.h
+++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttdriver.h
@@ -4,7 +4,7 @@
  *
  *   High-level TrueType driver interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/tterrors.h b/src/java.desktop/share/native/libfreetype/src/truetype/tterrors.h
index 008ee99853c..7ad937bd04d 100644
--- a/src/java.desktop/share/native/libfreetype/src/truetype/tterrors.h
+++ b/src/java.desktop/share/native/libfreetype/src/truetype/tterrors.h
@@ -4,7 +4,7 @@
  *
  *   TrueType error codes (specification only).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.c
index dc427e8a116..b656ccf04e3 100644
--- a/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.c
+++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.c
@@ -4,7 +4,7 @@
  *
  *   TrueType Glyph Loader (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -353,7 +353,8 @@
     FT_Byte         c, count;
     FT_Vector       *vec, *vec_limit;
     FT_Pos          x, y;
-    FT_Short        *cont, *cont_limit, last;
+    FT_UShort       *cont, *cont_limit;
+    FT_Int          last;
 
 
     /* check that we can add the contours to the glyph */
@@ -372,7 +373,7 @@
     last = -1;
     for ( ; cont < cont_limit; cont++ )
     {
-      *cont = FT_NEXT_SHORT( p );
+      *cont = FT_NEXT_USHORT( p );
 
       if ( *cont <= last )
         goto Invalid_Outline;
@@ -418,11 +419,9 @@
       /* and thus allocate the bytecode array size by ourselves     */
       if ( n_ins )
       {
-        if ( FT_QNEW_ARRAY( exec->glyphIns, n_ins ) )
+        if ( FT_DUP( exec->glyphIns, p, n_ins ) )
           return error;
 
-        FT_MEM_COPY( exec->glyphIns, p, (FT_Long)n_ins );
-
         exec->glyphSize  = n_ins;
       }
     }
@@ -432,7 +431,7 @@
     p += n_ins;
 
     /* reading the point tags */
-    flag       = (FT_Byte*)outline->tags;
+    flag       = outline->tags;
     flag_limit = flag + n_points;
 
     FT_ASSERT( flag );
@@ -465,7 +464,7 @@
 
     vec       = outline->points;
     vec_limit = vec + n_points;
-    flag      = (FT_Byte*)outline->tags;
+    flag      = outline->tags;
     x         = 0;
 
     for ( ; vec < vec_limit; vec++, flag++ )
@@ -499,7 +498,7 @@
 
     vec       = outline->points;
     vec_limit = vec + n_points;
-    flag      = (FT_Byte*)outline->tags;
+    flag      = outline->tags;
     y         = 0;
 
     for ( ; vec < vec_limit; vec++, flag++ )
@@ -532,8 +531,8 @@
       *flag  = (FT_Byte)( f & ON_CURVE_POINT );
     }
 
-    outline->n_points   = (FT_Short)n_points;
-    outline->n_contours = (FT_Short)n_contours;
+    outline->n_points   = (FT_UShort)n_points;
+    outline->n_contours = (FT_UShort)n_contours;
 
     load->cursor = p;
 
@@ -754,15 +753,13 @@
                    FT_UInt       start_point,
                    FT_UInt       start_contour )
   {
-    zone->n_points    = (FT_UShort)load->outline.n_points + 4 -
-                          (FT_UShort)start_point;
-    zone->n_contours  = load->outline.n_contours -
-                          (FT_Short)start_contour;
+    zone->n_points    = load->outline.n_points + 4 - (FT_UShort)start_point;
+    zone->n_contours  = load->outline.n_contours - (FT_UShort)start_contour;
     zone->org         = load->extra_points + start_point;
     zone->cur         = load->outline.points + start_point;
     zone->orus        = load->extra_points2 + start_point;
-    zone->tags        = (FT_Byte*)load->outline.tags + start_point;
-    zone->contours    = (FT_UShort*)load->outline.contours + start_contour;
+    zone->tags        = load->outline.tags + start_point;
+    zone->contours    = load->outline.contours + start_contour;
     zone->first_point = (FT_UShort)start_point;
   }
 
@@ -1046,7 +1043,7 @@
     current.points   = gloader->base.outline.points +
                          num_base_points;
     current.n_points = gloader->base.outline.n_points -
-                         (short)num_base_points;
+                         (FT_UShort)num_base_points;
 
     have_scale = FT_BOOL( subglyph->flags & ( WE_HAVE_A_SCALE     |
                                               WE_HAVE_AN_XY_SCALE |
@@ -1059,7 +1056,7 @@
     /* get offset */
     if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
     {
-      FT_UInt     num_points = (FT_UInt)gloader->base.outline.n_points;
+      FT_UInt     num_points = gloader->base.outline.n_points;
       FT_UInt     k = (FT_UInt)subglyph->arg1;
       FT_UInt     l = (FT_UInt)subglyph->arg2;
       FT_Vector*  p1;
@@ -1721,8 +1718,8 @@
         FT_List_Add( &loader->composites, node );
       }
 
-      start_point   = (FT_UInt)gloader->base.outline.n_points;
-      start_contour = (FT_UInt)gloader->base.outline.n_contours;
+      start_point   = gloader->base.outline.n_points;
+      start_contour = gloader->base.outline.n_contours;
 
       /* for each subglyph, read composite header */
       error = face->read_composite_glyph( loader );
@@ -1741,14 +1738,14 @@
       if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) ||
            FT_IS_VARIATION( FT_FACE( face ) )      )
       {
-        short        i, limit;
+        FT_UShort    i, limit;
         FT_SubGlyph  subglyph;
 
         FT_Outline  outline = { 0, 0, NULL, NULL, NULL, 0 };
         FT_Vector*  unrounded = NULL;
 
 
-        limit = (short)gloader->current.num_subglyphs;
+        limit = (FT_UShort)gloader->current.num_subglyphs;
 
         /* construct an outline structure for              */
         /* communication with `TT_Vary_Apply_Glyph_Deltas' */
@@ -1874,7 +1871,7 @@
           linear_hadvance = loader->linear;
           linear_vadvance = loader->vadvance;
 
-          num_base_points = (FT_UInt)gloader->base.outline.n_points;
+          num_base_points = gloader->base.outline.n_points;
 
           error = load_truetype_glyph( loader,
                                        (FT_UInt)subglyph->index,
@@ -1898,7 +1895,7 @@
             loader->vadvance = linear_vadvance;
           }
 
-          num_points = (FT_UInt)gloader->base.outline.n_points;
+          num_points = gloader->base.outline.n_points;
 
           if ( num_points == num_base_points )
             continue;
@@ -2313,7 +2310,7 @@
        *
        * 1) we have a `tricky' font that heavily relies on the interpreter to
        *    render glyphs correctly, for example DFKai-SB, or
-       * 2) FT_RENDER_MODE_MONO (i.e, monochome rendering) is requested.
+       * 2) FT_RENDER_MODE_MONO (i.e, monochrome rendering) is requested.
        *
        * In those cases, backward compatibility needs to be turned off to get
        * correct rendering.  The rendering is then completely up to the
@@ -2719,7 +2716,7 @@
          size->metrics->y_ppem < 24         )
       glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION;
 
-    FT_TRACE1(( "  subglyphs = %u, contours = %hd, points = %hd,"
+    FT_TRACE1(( "  subglyphs = %u, contours = %hu, points = %hu,"
                 " flags = 0x%.3x\n",
                 loader.gloader->base.num_subglyphs,
                 glyph->outline.n_contours,
diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.h
index f18637dce33..22ea967f301 100644
--- a/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.h
+++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttgload.h
@@ -4,7 +4,7 @@
  *
  *   TrueType Glyph Loader (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.c
index 9d149ea365c..4f0083c96b7 100644
--- a/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.c
+++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.c
@@ -4,7 +4,7 @@
  *
  *   TrueType GX Font Variation loader
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * David Turner, Robert Wilhelm, Werner Lemberg, and George Williams.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -129,9 +129,6 @@
    *   stream ::
    *     The data stream.
    *
-   *   size ::
-   *     The size of the table holding the data.
-   *
    * @Output:
    *   point_cnt ::
    *     The number of points read.  A zero value means that
@@ -144,14 +141,14 @@
    */
   static FT_UShort*
   ft_var_readpackedpoints( FT_Stream  stream,
-                           FT_ULong   size,
                            FT_UInt   *point_cnt )
   {
     FT_UShort *points = NULL;
     FT_UInt    n;
-    FT_UInt    runcnt;
+    FT_UInt    runcnt, cnt;
     FT_UInt    i, j;
     FT_UShort  first;
+    FT_Byte*   p;
     FT_Memory  memory = stream->memory;
     FT_Error   error;
 
@@ -169,56 +166,60 @@
       n  |= FT_GET_BYTE();
     }
 
-    if ( n > size )
-    {
-      FT_TRACE1(( "ft_var_readpackedpoints: number of points too large\n" ));
+    if ( FT_QNEW_ARRAY( points, n ) )
       return NULL;
-    }
-
-    /* in the nested loops below we increase `i' twice; */
-    /* it is faster to simply allocate one more slot    */
-    /* than to add another test within the loop         */
-    if ( FT_QNEW_ARRAY( points, n + 1 ) )
-      return NULL;
-
-    *point_cnt = n;
 
+    p     = stream->cursor;
     first = 0;
     i     = 0;
     while ( i < n )
     {
-      runcnt = FT_GET_BYTE();
+      if ( p >= stream->limit )
+        goto Fail;
+
+      runcnt = FT_NEXT_BYTE( p );
+      cnt    = runcnt & GX_PT_POINT_RUN_COUNT_MASK;
+
+      /* first point not included in run count */
+      cnt++;
+      if ( cnt > n - i )
+        cnt = n - i;
+
       if ( runcnt & GX_PT_POINTS_ARE_WORDS )
       {
-        runcnt     &= GX_PT_POINT_RUN_COUNT_MASK;
-        first      += FT_GET_USHORT();
-        points[i++] = first;
+        if ( 2 * cnt > (FT_UInt)( stream->limit - p ) )
+          goto Fail;
 
-        /* first point not included in run count */
-        for ( j = 0; j < runcnt; j++ )
+        for ( j = 0; j < cnt; j++ )
         {
-          first      += FT_GET_USHORT();
+          first      += FT_NEXT_USHORT( p );
           points[i++] = first;
-          if ( i >= n )
-            break;
         }
       }
       else
       {
-        first      += FT_GET_BYTE();
-        points[i++] = first;
+        if ( cnt > (FT_UInt)( stream->limit - p ) )
+          goto Fail;
 
-        for ( j = 0; j < runcnt; j++ )
+        for ( j = 0; j < cnt; j++ )
         {
-          first      += FT_GET_BYTE();
+          first      += FT_NEXT_BYTE( p );
           points[i++] = first;
-          if ( i >= n )
-            break;
         }
       }
     }
 
+    stream->cursor = p;
+
+    *point_cnt = n;
+
     return points;
+
+  Fail:
+    FT_TRACE1(( "ft_var_readpackedpoints: invalid table\n" ));
+
+    FT_FREE( points );
+    return NULL;
   }
 
 
@@ -240,9 +241,6 @@
    *   stream ::
    *     The data stream.
    *
-   *   size ::
-   *     The size of the table holding the data.
-   *
    *   delta_cnt ::
    *     The number of deltas to be read.
    *
@@ -258,13 +256,12 @@
    */
   static FT_Fixed*
   ft_var_readpackeddeltas( FT_Stream  stream,
-                           FT_ULong   size,
                            FT_UInt    delta_cnt )
   {
     FT_Fixed  *deltas = NULL;
     FT_UInt    runcnt, cnt;
     FT_UInt    i, j;
-    FT_UInt    bytes_used;
+    FT_Byte*   p;
     FT_Memory  memory = stream->memory;
     FT_Error   error;
 
@@ -272,68 +269,51 @@
     if ( FT_QNEW_ARRAY( deltas, delta_cnt ) )
       return NULL;
 
-    i          = 0;
-    bytes_used = 0;
-
-    while ( i < delta_cnt && bytes_used < size )
+    p = stream->cursor;
+    i = 0;
+    while ( i < delta_cnt )
     {
-      runcnt = FT_GET_BYTE();
+      if ( p >= stream->limit )
+        goto Fail;
+
+      runcnt = FT_NEXT_BYTE( p );
       cnt    = runcnt & GX_DT_DELTA_RUN_COUNT_MASK;
 
-      bytes_used++;
+      /* first point not included in run count */
+      cnt++;
+      if ( cnt > delta_cnt - i )
+        cnt = delta_cnt - i;
 
       if ( runcnt & GX_DT_DELTAS_ARE_ZERO )
       {
-        /* `cnt` + 1 zeroes get added */
-        for ( j = 0; j <= cnt && i < delta_cnt; j++ )
+        for ( j = 0; j < cnt; j++ )
           deltas[i++] = 0;
       }
       else if ( runcnt & GX_DT_DELTAS_ARE_WORDS )
       {
-        /* `cnt` + 1 shorts from the stack */
-        bytes_used += 2 * ( cnt + 1 );
-        if ( bytes_used > size )
-        {
-          FT_TRACE1(( "ft_var_readpackeddeltas:"
-                      " number of short deltas too large\n" ));
+        if ( 2 * cnt > (FT_UInt)( stream->limit - p ) )
           goto Fail;
-        }
 
-        for ( j = 0; j <= cnt && i < delta_cnt; j++ )
-          deltas[i++] = FT_intToFixed( FT_GET_SHORT() );
+        for ( j = 0; j < cnt; j++ )
+          deltas[i++] = FT_intToFixed( FT_NEXT_SHORT( p ) );
       }
       else
       {
-        /* `cnt` + 1 signed bytes from the stack */
-        bytes_used += cnt + 1;
-        if ( bytes_used > size )
-        {
-          FT_TRACE1(( "ft_var_readpackeddeltas:"
-                      " number of byte deltas too large\n" ));
+        if ( cnt > (FT_UInt)( stream->limit - p ) )
           goto Fail;
-        }
 
-        for ( j = 0; j <= cnt && i < delta_cnt; j++ )
-          deltas[i++] = FT_intToFixed( FT_GET_CHAR() );
-      }
-
-      if ( j <= cnt )
-      {
-        FT_TRACE1(( "ft_var_readpackeddeltas:"
-                    " number of deltas too large\n" ));
-        goto Fail;
+        for ( j = 0; j < cnt; j++ )
+          deltas[i++] = FT_intToFixed( FT_NEXT_CHAR( p ) );
       }
     }
 
-    if ( i < delta_cnt )
-    {
-      FT_TRACE1(( "ft_var_readpackeddeltas: not enough deltas\n" ));
-      goto Fail;
-    }
+    stream->cursor = p;
 
     return deltas;
 
   Fail:
+    FT_TRACE1(( "ft_var_readpackeddeltas: invalid table\n" ));
+
     FT_FREE( deltas );
     return NULL;
   }
@@ -596,7 +576,7 @@
 
       for ( j = 0; j < itemStore->axisCount; j++ )
       {
-        FT_Short  start, peak, end;
+        FT_Int  start, peak, end;
 
 
         if ( FT_READ_SHORT( start ) ||
@@ -604,6 +584,10 @@
              FT_READ_SHORT( end )   )
           goto Exit;
 
+        /* immediately tag invalid ranges with special peak = 0 */
+        if ( ( start < 0 && end > 0 ) || start > peak || peak > end )
+          peak = 0;
+
         axisCoords[j].startCoord = FT_fdot14ToFixed( start );
         axisCoords[j].peakCoord  = FT_fdot14ToFixed( peak );
         axisCoords[j].endCoord   = FT_fdot14ToFixed( end );
@@ -1024,6 +1008,9 @@
     if ( innerIndex >= varData->itemCount )
       return 0; /* Out of range. */
 
+    if ( varData->regionIdxCount == 0 )
+      return 0; /* Avoid "applying zero offset to null pointer". */
+
     if ( varData->regionIdxCount < 16 )
     {
       deltaSet = deltaSetStack;
@@ -1074,43 +1061,32 @@
       /* inner loop steps through axes in this region */
       for ( j = 0; j < itemStore->axisCount; j++, axis++ )
       {
-        /* compute the scalar contribution of this axis; */
-        /* ignore invalid ranges                         */
-        if ( axis->startCoord > axis->peakCoord ||
-             axis->peakCoord > axis->endCoord   )
-          continue;
+        FT_Fixed  ncv = ttface->blend->normalizedcoords[j];
 
-        else if ( axis->startCoord < 0 &&
-                  axis->endCoord > 0   &&
-                  axis->peakCoord != 0 )
-          continue;
 
-        /* peak of 0 means ignore this axis */
-        else if ( axis->peakCoord == 0 )
-          continue;
-
-        else if ( ttface->blend->normalizedcoords[j] == axis->peakCoord )
+        /* compute the scalar contribution of this axis */
+        /* with peak of 0 used for invalid axes         */
+        if ( axis->peakCoord == ncv ||
+             axis->peakCoord == 0   )
           continue;
 
         /* ignore this region if coords are out of range */
-        else if ( ttface->blend->normalizedcoords[j] <= axis->startCoord ||
-                  ttface->blend->normalizedcoords[j] >= axis->endCoord   )
+        else if ( ncv <= axis->startCoord ||
+                  ncv >= axis->endCoord   )
         {
           scalar = 0;
           break;
         }
 
         /* cumulative product of all the axis scalars */
-        else if ( ttface->blend->normalizedcoords[j] < axis->peakCoord )
-          scalar =
-            FT_MulDiv( scalar,
-                       ttface->blend->normalizedcoords[j] - axis->startCoord,
-                       axis->peakCoord - axis->startCoord );
-        else
-          scalar =
-            FT_MulDiv( scalar,
-                       axis->endCoord - ttface->blend->normalizedcoords[j],
-                       axis->endCoord - axis->peakCoord );
+        else if ( ncv < axis->peakCoord )
+          scalar = FT_MulDiv( scalar,
+                              ncv - axis->startCoord,
+                              axis->peakCoord - axis->startCoord );
+        else   /* ncv > axis->peakCoord */
+          scalar = FT_MulDiv( scalar,
+                              axis->endCoord - ncv,
+                              axis->endCoord - axis->peakCoord );
 
       } /* per-axis loop */
 
@@ -1920,32 +1896,27 @@
 
     for ( i = 0; i < blend->num_axis; i++ )
     {
-      FT_TRACE6(( "    axis %d coordinate %.5f:\n",
-                  i, (double)blend->normalizedcoords[i] / 65536 ));
+      FT_Fixed  ncv = blend->normalizedcoords[i];
+
+
+      FT_TRACE6(( "    axis %d coordinate %.5f:\n", i, (double)ncv / 65536 ));
 
       /* It's not clear why (for intermediate tuples) we don't need     */
       /* to check against start/end -- the documentation says we don't. */
       /* Similarly, it's unclear why we don't need to scale along the   */
       /* axis.                                                          */
 
-      if ( tuple_coords[i] == 0 )
+      if ( tuple_coords[i] == ncv )
       {
-        FT_TRACE6(( "      tuple coordinate is zero, ignore\n" ));
+        FT_TRACE6(( "      tuple coordinate %.5f fits perfectly\n",
+                    (double)tuple_coords[i] / 65536 ));
+        /* `apply' does not change */
         continue;
       }
 
-      if ( blend->normalizedcoords[i] == 0 )
-      {
-        FT_TRACE6(( "      axis coordinate is zero, stop\n" ));
-        apply = 0;
-        break;
-      }
-
-      if ( blend->normalizedcoords[i] == tuple_coords[i] )
+      if ( tuple_coords[i] == 0 )
       {
-        FT_TRACE6(( "      tuple coordinate %.5f fits perfectly\n",
-                    (double)tuple_coords[i] / 65536 ));
-        /* `apply' does not change */
+        FT_TRACE6(( "      tuple coordinate is zero, ignore\n" ));
         continue;
       }
 
@@ -1953,27 +1924,27 @@
       {
         /* not an intermediate tuple */
 
-        if ( blend->normalizedcoords[i] < FT_MIN( 0, tuple_coords[i] ) ||
-             blend->normalizedcoords[i] > FT_MAX( 0, tuple_coords[i] ) )
+        if ( ( tuple_coords[i] > ncv && ncv > 0 ) ||
+             ( tuple_coords[i] < ncv && ncv < 0 ) )
+        {
+          FT_TRACE6(( "      tuple coordinate %.5f fits\n",
+                      (double)tuple_coords[i] / 65536 ));
+          apply = FT_MulDiv( apply, ncv, tuple_coords[i] );
+        }
+        else
         {
           FT_TRACE6(( "      tuple coordinate %.5f is exceeded, stop\n",
                       (double)tuple_coords[i] / 65536 ));
           apply = 0;
           break;
         }
-
-        FT_TRACE6(( "      tuple coordinate %.5f fits\n",
-                    (double)tuple_coords[i] / 65536 ));
-        apply = FT_MulDiv( apply,
-                           blend->normalizedcoords[i],
-                           tuple_coords[i] );
       }
       else
       {
         /* intermediate tuple */
 
-        if ( blend->normalizedcoords[i] <= im_start_coords[i] ||
-             blend->normalizedcoords[i] >= im_end_coords[i]   )
+        if ( ncv <= im_start_coords[i] ||
+             ncv >= im_end_coords[i]   )
         {
           FT_TRACE6(( "      intermediate tuple range ]%.5f;%.5f[ is exceeded,"
                       " stop\n",
@@ -1986,13 +1957,13 @@
         FT_TRACE6(( "      intermediate tuple range ]%.5f;%.5f[ fits\n",
                     (double)im_start_coords[i] / 65536,
                     (double)im_end_coords[i] / 65536 ));
-        if ( blend->normalizedcoords[i] < tuple_coords[i] )
+        if ( ncv < tuple_coords[i] )
           apply = FT_MulDiv( apply,
-                             blend->normalizedcoords[i] - im_start_coords[i],
+                             ncv - im_start_coords[i],
                              tuple_coords[i] - im_start_coords[i] );
-        else
+        else /* ncv > tuple_coords[i] */
           apply = FT_MulDiv( apply,
-                             im_end_coords[i] - blend->normalizedcoords[i],
+                             im_end_coords[i] - ncv,
                              im_end_coords[i] - tuple_coords[i] );
       }
     }
@@ -2141,11 +2112,12 @@
                                          outerIndex,
                                          innerIndex );
 
-      v += delta << 2;
+          /* Convert delta in F2DOT14 to 16.16 before adding. */
+          v += MUL_INT( delta, 4 );
 
-      /* Clamp value range. */
-      v = v >=  0x10000L ?  0x10000 : v;
-      v = v <= -0x10000L ? -0x10000 : v;
+          /* Clamp value to range [-1, 1]. */
+          v = v >=  0x10000L ?  0x10000 : v;
+          v = v <= -0x10000L ? -0x10000 : v;
 
           new_normalized[i] = v;
         }
@@ -2721,9 +2693,8 @@
       FT_UInt  n;
 
 
-      if ( FT_ALLOC( mmvar, ttface->blend->mmvar_len ) )
+      if ( FT_DUP( mmvar, ttface->blend->mmvar, ttface->blend->mmvar_len ) )
         goto Exit;
-      FT_MEM_COPY( mmvar, ttface->blend->mmvar, ttface->blend->mmvar_len );
 
       axis_flags =
         (FT_UShort*)( (char*)mmvar + mmvar_size );
@@ -3533,9 +3504,10 @@
     FT_ULong  here;
     FT_UInt   i, j;
 
-    FT_Fixed*  tuple_coords    = NULL;
-    FT_Fixed*  im_start_coords = NULL;
-    FT_Fixed*  im_end_coords   = NULL;
+    FT_Fixed*  peak_coords = NULL;
+    FT_Fixed*  tuple_coords;
+    FT_Fixed*  im_start_coords;
+    FT_Fixed*  im_end_coords;
 
     GX_Blend  blend = face->blend;
 
@@ -3556,16 +3528,16 @@
     {
       FT_TRACE2(( "\n" ));
       FT_TRACE2(( "tt_face_vary_cvt: no blend specified\n" ));
-      error = FT_Err_Ok;
-      goto Exit;
+
+      return FT_Err_Ok;
     }
 
     if ( !face->cvt )
     {
       FT_TRACE2(( "\n" ));
       FT_TRACE2(( "tt_face_vary_cvt: no `cvt ' table\n" ));
-      error = FT_Err_Ok;
-      goto Exit;
+
+      return FT_Err_Ok;
     }
 
     error = face->goto_table( face, TTAG_cvar, stream, &table_len );
@@ -3573,15 +3545,11 @@
     {
       FT_TRACE2(( "is missing\n" ));
 
-      error = FT_Err_Ok;
-      goto Exit;
+      return FT_Err_Ok;
     }
 
     if ( FT_FRAME_ENTER( table_len ) )
-    {
-      error = FT_Err_Ok;
-      goto Exit;
-    }
+      return FT_Err_Ok;
 
     table_start = FT_Stream_FTell( stream );
     if ( FT_GET_LONG() != 0x00010000L )
@@ -3594,11 +3562,6 @@
 
     FT_TRACE2(( "loaded\n" ));
 
-    if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis )    ||
-         FT_NEW_ARRAY( im_start_coords, blend->num_axis ) ||
-         FT_NEW_ARRAY( im_end_coords, blend->num_axis )   )
-      goto FExit;
-
     tupleCount   = FT_GET_USHORT();
     offsetToData = FT_GET_USHORT();
 
@@ -3621,9 +3584,8 @@
 
       FT_Stream_SeekSet( stream, offsetToData );
 
-      sharedpoints = ft_var_readpackedpoints( stream,
-                                              table_len,
-                                              &spoint_count );
+      sharedpoints = ft_var_readpackedpoints( stream, &spoint_count );
+
       offsetToData = FT_Stream_FTell( stream );
 
       FT_Stream_SeekSet( stream, here );
@@ -3634,8 +3596,12 @@
                 tupleCount & GX_TC_TUPLE_COUNT_MASK,
                 ( tupleCount & GX_TC_TUPLE_COUNT_MASK ) == 1 ? "" : "s" ));
 
-    if ( FT_NEW_ARRAY( cvt_deltas, face->cvt_size ) )
-      goto FExit;
+    if ( FT_QNEW_ARRAY( peak_coords, 3 * blend->num_axis ) ||
+         FT_NEW_ARRAY( cvt_deltas, face->cvt_size )        )
+      goto Exit;
+
+    im_start_coords = peak_coords + blend->num_axis;
+    im_end_coords = im_start_coords + blend->num_axis;
 
     for ( i = 0; i < ( tupleCount & GX_TC_TUPLE_COUNT_MASK ); i++ )
     {
@@ -3652,32 +3618,19 @@
       if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD )
       {
         for ( j = 0; j < blend->num_axis; j++ )
-          tuple_coords[j] = FT_fdot14ToFixed( FT_GET_SHORT() );
+          peak_coords[j] = FT_fdot14ToFixed( FT_GET_SHORT() );
+        tuple_coords = peak_coords;
       }
-      else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) >= blend->tuplecount )
+      else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) < blend->tuplecount )
+        tuple_coords = blend->tuplecoords +
+            ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) * blend->num_axis;
+      else
       {
         FT_TRACE2(( "tt_face_vary_cvt:"
                     " invalid tuple index\n" ));
 
         error = FT_THROW( Invalid_Table );
-        goto FExit;
-      }
-      else
-      {
-        if ( !blend->tuplecoords )
-        {
-          FT_TRACE2(( "tt_face_vary_cvt:"
-                      " no valid tuple coordinates available\n" ));
-
-          error = FT_THROW( Invalid_Table );
-          goto FExit;
-        }
-
-        FT_MEM_COPY(
-          tuple_coords,
-          blend->tuplecoords +
-            ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) * blend->num_axis,
-          blend->num_axis * sizeof ( FT_Fixed ) );
+        goto Exit;
       }
 
       if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
@@ -3706,9 +3659,7 @@
 
       if ( tupleIndex & GX_TI_PRIVATE_POINT_NUMBERS )
       {
-        localpoints = ft_var_readpackedpoints( stream,
-                                               table_len,
-                                               &point_count );
+        localpoints = ft_var_readpackedpoints( stream, &point_count );
         points      = localpoints;
       }
       else
@@ -3719,7 +3670,6 @@
       }
 
       deltas = ft_var_readpackeddeltas( stream,
-                                        table_len,
                                         point_count == 0 ? face->cvt_size
                                                          : point_count );
 
@@ -3820,22 +3770,20 @@
     for ( i = 0; i < face->cvt_size; i++ )
       face->cvt[i] += FT_fixedToFdot6( cvt_deltas[i] );
 
-  FExit:
-    FT_FRAME_EXIT();
+    /* Iterate over all `FT_Size` objects and set `cvt_ready` to -1 */
+    /* to trigger rescaling of all CVT values.                      */
+    FT_List_Iterate( &root->sizes_list,
+                     tt_cvt_ready_iterator,
+                     NULL );
 
   Exit:
     if ( sharedpoints != ALL_POINTS )
       FT_FREE( sharedpoints );
-    FT_FREE( tuple_coords );
-    FT_FREE( im_start_coords );
-    FT_FREE( im_end_coords );
     FT_FREE( cvt_deltas );
+    FT_FREE( peak_coords );
 
-    /* iterate over all FT_Size objects and set `cvt_ready' to -1 */
-    /* to trigger rescaling of all CVT values                     */
-    FT_List_Iterate( &root->sizes_list,
-                     tt_cvt_ready_iterator,
-                     NULL );
+  FExit:
+    FT_FRAME_EXIT();
 
     return error;
 
@@ -4099,9 +4047,10 @@
     FT_ULong  here;
     FT_UInt   i, j;
 
-    FT_Fixed*  tuple_coords    = NULL;
-    FT_Fixed*  im_start_coords = NULL;
-    FT_Fixed*  im_end_coords   = NULL;
+    FT_Fixed*  peak_coords = NULL;
+    FT_Fixed*  tuple_coords;
+    FT_Fixed*  im_start_coords;
+    FT_Fixed*  im_end_coords;
 
     GX_Blend  blend = face->blend;
 
@@ -4136,27 +4085,17 @@
       return FT_Err_Ok;
     }
 
-    if ( FT_NEW_ARRAY( points_org, n_points ) ||
-         FT_NEW_ARRAY( points_out, n_points ) ||
-         FT_NEW_ARRAY( has_delta, n_points )  )
-      goto Fail1;
-
     dataSize = blend->glyphoffsets[glyph_index + 1] -
                  blend->glyphoffsets[glyph_index];
 
     if ( FT_STREAM_SEEK( blend->glyphoffsets[glyph_index] ) ||
          FT_FRAME_ENTER( dataSize )                         )
-      goto Fail1;
+      return error;
 
     glyph_start = FT_Stream_FTell( stream );
 
     /* each set of glyph variation data is formatted similarly to `cvar' */
 
-    if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis )    ||
-         FT_NEW_ARRAY( im_start_coords, blend->num_axis ) ||
-         FT_NEW_ARRAY( im_end_coords, blend->num_axis )   )
-      goto Fail2;
-
     tupleCount   = FT_GET_USHORT();
     offsetToData = FT_GET_USHORT();
 
@@ -4168,7 +4107,7 @@
                   " invalid glyph variation array header\n" ));
 
       error = FT_THROW( Invalid_Table );
-      goto Fail2;
+      goto FExit;
     }
 
     offsetToData += glyph_start;
@@ -4179,9 +4118,8 @@
 
       FT_Stream_SeekSet( stream, offsetToData );
 
-      sharedpoints = ft_var_readpackedpoints( stream,
-                                              blend->gvar_size,
-                                              &spoint_count );
+      sharedpoints = ft_var_readpackedpoints( stream, &spoint_count );
+
       offsetToData = FT_Stream_FTell( stream );
 
       FT_Stream_SeekSet( stream, here );
@@ -4192,9 +4130,16 @@
                 tupleCount & GX_TC_TUPLE_COUNT_MASK,
                 ( tupleCount & GX_TC_TUPLE_COUNT_MASK ) == 1 ? "" : "s" ));
 
-    if ( FT_NEW_ARRAY( point_deltas_x, n_points ) ||
-         FT_NEW_ARRAY( point_deltas_y, n_points ) )
-      goto Fail3;
+    if ( FT_QNEW_ARRAY( peak_coords, 3 * blend->num_axis ) ||
+         FT_NEW_ARRAY( point_deltas_x, 2 * n_points )      ||
+         FT_QNEW_ARRAY( points_org, n_points )             ||
+         FT_QNEW_ARRAY( points_out, n_points )             ||
+         FT_QNEW_ARRAY( has_delta, n_points )              )
+      goto Exit;
+
+    im_start_coords = peak_coords + blend->num_axis;
+    im_end_coords   = im_start_coords + blend->num_axis;
+    point_deltas_y  = point_deltas_x + n_points;
 
     for ( j = 0; j < n_points; j++ )
     {
@@ -4217,22 +4162,20 @@
       if ( tupleIndex & GX_TI_EMBEDDED_TUPLE_COORD )
       {
         for ( j = 0; j < blend->num_axis; j++ )
-          tuple_coords[j] = FT_fdot14ToFixed( FT_GET_SHORT() );
+          peak_coords[j] = FT_fdot14ToFixed( FT_GET_SHORT() );
+        tuple_coords = peak_coords;
       }
-      else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) >= blend->tuplecount )
+      else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) < blend->tuplecount )
+        tuple_coords = blend->tuplecoords +
+            ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) * blend->num_axis;
+      else
       {
         FT_TRACE2(( "TT_Vary_Apply_Glyph_Deltas:"
                     " invalid tuple index\n" ));
 
         error = FT_THROW( Invalid_Table );
-        goto Fail3;
+        goto Exit;
       }
-      else
-        FT_MEM_COPY(
-          tuple_coords,
-          blend->tuplecoords +
-            ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) * blend->num_axis,
-          blend->num_axis * sizeof ( FT_Fixed ) );
 
       if ( tupleIndex & GX_TI_INTERMEDIATE_TUPLE )
       {
@@ -4260,9 +4203,7 @@
 
       if ( tupleIndex & GX_TI_PRIVATE_POINT_NUMBERS )
       {
-        localpoints = ft_var_readpackedpoints( stream,
-                                               blend->gvar_size,
-                                               &point_count );
+        localpoints = ft_var_readpackedpoints( stream, &point_count );
         points      = localpoints;
       }
       else
@@ -4272,11 +4213,9 @@
       }
 
       deltas_x = ft_var_readpackeddeltas( stream,
-                                          blend->gvar_size,
                                           point_count == 0 ? n_points
                                                            : point_count );
       deltas_y = ft_var_readpackeddeltas( stream,
-                                          blend->gvar_size,
                                           point_count == 0 ? n_points
                                                            : point_count );
 
@@ -4460,23 +4399,17 @@
                                        unrounded[n_points - 2].y ) / 64;
     }
 
-  Fail3:
-    FT_FREE( point_deltas_x );
-    FT_FREE( point_deltas_y );
-
-  Fail2:
+  Exit:
     if ( sharedpoints != ALL_POINTS )
       FT_FREE( sharedpoints );
-    FT_FREE( tuple_coords );
-    FT_FREE( im_start_coords );
-    FT_FREE( im_end_coords );
-
-    FT_FRAME_EXIT();
-
-  Fail1:
     FT_FREE( points_org );
     FT_FREE( points_out );
     FT_FREE( has_delta );
+    FT_FREE( peak_coords );
+    FT_FREE( point_deltas_x );
+
+  FExit:
+    FT_FRAME_EXIT();
 
     return error;
   }
diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.h
index e3da6d1705c..9326011e3a2 100644
--- a/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.h
+++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttgxvar.h
@@ -4,7 +4,7 @@
  *
  *   TrueType GX Font Variation loader (specification)
  *
- * Copyright (C) 2004-2023 by
+ * Copyright (C) 2004-2024 by
  * David Turner, Robert Wilhelm, Werner Lemberg and George Williams.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.c
index 79df4555d94..951891dbf51 100644
--- a/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.c
+++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.c
@@ -4,7 +4,7 @@
  *
  *   TrueType bytecode interpreter (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -5270,11 +5270,11 @@
     FT_UShort        refp;
     FT_F26Dot6       dx, dy;
 
-    FT_Short         contour, bounds;
+    FT_UShort        contour, bounds;
     FT_UShort        start, limit, i;
 
 
-    contour = (FT_Short)args[0];
+    contour = (FT_UShort)args[0];
     bounds  = ( exc->GS.gep2 == 0 ) ? 1 : exc->zp2.n_contours;
 
     if ( BOUNDS( contour, bounds ) )
@@ -5290,15 +5290,13 @@
     if ( contour == 0 )
       start = 0;
     else
-      start = (FT_UShort)( exc->zp2.contours[contour - 1] + 1 -
-                           exc->zp2.first_point );
+      start = exc->zp2.contours[contour - 1] + 1 - exc->zp2.first_point;
 
     /* we use the number of points if in the twilight zone */
     if ( exc->GS.gep2 == 0 )
       limit = exc->zp2.n_points;
     else
-      limit = (FT_UShort)( exc->zp2.contours[contour] -
-                           exc->zp2.first_point + 1 );
+      limit = exc->zp2.contours[contour] + 1 - exc->zp2.first_point;
 
     for ( i = start; i < limit; i++ )
     {
@@ -5341,9 +5339,9 @@
     /*      Normal zone's `n_points' includes phantoms, so must    */
     /*      use end of last contour.                               */
     if ( exc->GS.gep2 == 0 )
-      limit = (FT_UShort)exc->zp2.n_points;
+      limit = exc->zp2.n_points;
     else if ( exc->GS.gep2 == 1 && exc->zp2.n_contours > 0 )
-      limit = (FT_UShort)( exc->zp2.contours[exc->zp2.n_contours - 1] + 1 );
+      limit = exc->zp2.contours[exc->zp2.n_contours - 1] + 1;
     else
       limit = 0;
 
diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.h
index e98e258fe7e..4f1a9bbc679 100644
--- a/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.h
+++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttinterp.h
@@ -4,7 +4,7 @@
  *
  *   TrueType bytecode interpreter (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.c
index 5b56af711df..d0ac3181204 100644
--- a/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.c
+++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.c
@@ -4,7 +4,7 @@
  *
  *   Objects manager (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -115,7 +115,7 @@
   FT_LOCAL_DEF( FT_Error )
   tt_glyphzone_new( FT_Memory     memory,
                     FT_UShort     maxPoints,
-                    FT_Short      maxContours,
+                    FT_UShort     maxContours,
                     TT_GlyphZone  zone )
   {
     FT_Error  error;
@@ -152,18 +152,20 @@
   static const FT_String*
   tt_skip_pdffont_random_tag( const FT_String*  name )
   {
-    unsigned int  i;
-
-
-    if ( ft_strlen( name ) < 8 || name[6] != '+' )
-      return name;
-
-    for ( i = 0; i < 6; i++ )
-      if ( !ft_isupper( name[i] ) )
-        return name;
+    if ( ft_isupper( name[0] ) &&
+         ft_isupper( name[1] ) &&
+         ft_isupper( name[2] ) &&
+         ft_isupper( name[3] ) &&
+         ft_isupper( name[4] ) &&
+         ft_isupper( name[5] ) &&
+              '+' == name[6]   &&
+                     name[7]   )
+    {
+      FT_TRACE7(( "name without randomization tag: %s\n", name + 7 ));
+      return name + 7;
+    }
 
-    FT_TRACE7(( "name without randomization tag: %s\n", name + 7 ));
-    return name + 7;
+    return name;
   }
 
 
@@ -254,17 +256,20 @@
   {
     FT_Error   error;
     FT_UInt32  checksum = 0;
-    FT_UInt    i;
+    FT_Byte*   p;
+    FT_Int     shift;
 
 
     if ( FT_FRAME_ENTER( length ) )
       return 0;
 
+    p = (FT_Byte*)stream->cursor;
+
     for ( ; length > 3; length -= 4 )
-      checksum += (FT_UInt32)FT_GET_ULONG();
+      checksum += FT_NEXT_ULONG( p );
 
-    for ( i = 3; length > 0; length--, i-- )
-      checksum += (FT_UInt32)FT_GET_BYTE() << ( i * 8 );
+    for ( shift = 24; length > 0; length--, shift -=8 )
+      checksum += (FT_UInt32)FT_NEXT_BYTE( p ) << shift;
 
     FT_FRAME_EXIT();
 
@@ -782,8 +787,7 @@
       FT_UInt  instance_index = (FT_UInt)face_index >> 16;
 
 
-      if ( FT_HAS_MULTIPLE_MASTERS( ttface ) &&
-           instance_index > 0                )
+      if ( FT_HAS_MULTIPLE_MASTERS( ttface ) )
       {
         error = FT_Set_Named_Instance( ttface, instance_index );
         if ( error )
@@ -990,16 +994,16 @@
     FT_Error        error;
     FT_UInt         i;
 
-    /* unscaled CVT values are already stored in 26.6 format */
-    FT_Fixed  scale = size->ttmetrics.scale >> 6;
-
 
     /* Scale the cvt values to the new ppem.            */
     /* By default, we use the y ppem value for scaling. */
     FT_TRACE6(( "CVT values:\n" ));
     for ( i = 0; i < size->cvt_size; i++ )
     {
-      size->cvt[i] = FT_MulFix( face->cvt[i], scale );
+      /* Unscaled CVT values are already stored in 26.6 format.            */
+      /* Note that this scaling operation is very sensitive to rounding;   */
+      /* the integer division by 64 must be applied to the first argument. */
+      size->cvt[i] = FT_MulFix( face->cvt[i] / 64, size->ttmetrics.scale );
       FT_TRACE6(( "  %3d: %f (%f)\n",
                   i, (double)face->cvt[i] / 64, (double)size->cvt[i] / 64 ));
     }
diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.h
index 40eb37b4c43..9c36ca78362 100644
--- a/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.h
+++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttobjs.h
@@ -4,7 +4,7 @@
  *
  *   Objects manager (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -105,7 +105,7 @@ FT_BEGIN_HEADER
   FT_LOCAL( FT_Error )
   tt_glyphzone_new( FT_Memory     memory,
                     FT_UShort     maxPoints,
-                    FT_Short      maxContours,
+                    FT_UShort     maxContours,
                     TT_GlyphZone  zone );
 
 #endif /* TT_USE_BYTECODE_INTERPRETER */
diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.c b/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.c
index 54a64c7b462..9505b5f179f 100644
--- a/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.c
+++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.c
@@ -4,7 +4,7 @@
  *
  *   TrueType-specific tables loader (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.h b/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.h
index ed229fa4616..bc32b58020c 100644
--- a/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.h
+++ b/src/java.desktop/share/native/libfreetype/src/truetype/ttpload.h
@@ -4,7 +4,7 @@
  *
  *   TrueType-specific tables loader (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1afm.c b/src/java.desktop/share/native/libfreetype/src/type1/t1afm.c
index d9b9398b013..a63cd4dc48a 100644
--- a/src/java.desktop/share/native/libfreetype/src/type1/t1afm.c
+++ b/src/java.desktop/share/native/libfreetype/src/type1/t1afm.c
@@ -4,7 +4,7 @@
  *
  *   AFM support for Type 1 fonts (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1afm.h b/src/java.desktop/share/native/libfreetype/src/type1/t1afm.h
index e0d5aa5a882..7f5cdda191f 100644
--- a/src/java.desktop/share/native/libfreetype/src/type1/t1afm.h
+++ b/src/java.desktop/share/native/libfreetype/src/type1/t1afm.h
@@ -4,7 +4,7 @@
  *
  *   AFM support for Type 1 fonts (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1driver.c b/src/java.desktop/share/native/libfreetype/src/type1/t1driver.c
index a4cdf372a9e..8ed01914a5a 100644
--- a/src/java.desktop/share/native/libfreetype/src/type1/t1driver.c
+++ b/src/java.desktop/share/native/libfreetype/src/type1/t1driver.c
@@ -4,7 +4,7 @@
  *
  *   Type 1 driver interface (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -312,10 +312,7 @@
       {
         retval = ft_strlen( type1->glyph_names[idx] ) + 1;
         if ( value && value_len >= retval )
-        {
           ft_memcpy( value, (void *)( type1->glyph_names[idx] ), retval );
-          ((FT_Char *)value)[retval - 1] = (FT_Char)'\0';
-        }
       }
       break;
 
@@ -344,11 +341,8 @@
       {
         retval = ft_strlen( type1->encoding.char_name[idx] ) + 1;
         if ( value && value_len >= retval )
-        {
           ft_memcpy( value, (void *)( type1->encoding.char_name[idx] ),
-                     retval - 1 );
-          ((FT_Char *)value)[retval - 1] = (FT_Char)'\0';
-        }
+                     retval );
       }
       break;
 
diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1driver.h b/src/java.desktop/share/native/libfreetype/src/type1/t1driver.h
index ee7fcf43e01..5ff52b55b1a 100644
--- a/src/java.desktop/share/native/libfreetype/src/type1/t1driver.h
+++ b/src/java.desktop/share/native/libfreetype/src/type1/t1driver.h
@@ -4,7 +4,7 @@
  *
  *   High-level Type 1 driver interface (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1errors.h b/src/java.desktop/share/native/libfreetype/src/type1/t1errors.h
index 2fbd1e513f3..8aeb24ae188 100644
--- a/src/java.desktop/share/native/libfreetype/src/type1/t1errors.h
+++ b/src/java.desktop/share/native/libfreetype/src/type1/t1errors.h
@@ -4,7 +4,7 @@
  *
  *   Type 1 error codes (specification only).
  *
- * Copyright (C) 2001-2023 by
+ * Copyright (C) 2001-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1gload.c b/src/java.desktop/share/native/libfreetype/src/type1/t1gload.c
index a32a4649d6d..c29e682510c 100644
--- a/src/java.desktop/share/native/libfreetype/src/type1/t1gload.c
+++ b/src/java.desktop/share/native/libfreetype/src/type1/t1gload.c
@@ -4,7 +4,7 @@
  *
  *   Type 1 Glyph Loader (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1gload.h b/src/java.desktop/share/native/libfreetype/src/type1/t1gload.h
index c06484758a5..17a6a5941e3 100644
--- a/src/java.desktop/share/native/libfreetype/src/type1/t1gload.h
+++ b/src/java.desktop/share/native/libfreetype/src/type1/t1gload.h
@@ -4,7 +4,7 @@
  *
  *   Type 1 Glyph Loader (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1load.c b/src/java.desktop/share/native/libfreetype/src/type1/t1load.c
index be7cd0fd5e9..ee7fb42a517 100644
--- a/src/java.desktop/share/native/libfreetype/src/type1/t1load.c
+++ b/src/java.desktop/share/native/libfreetype/src/type1/t1load.c
@@ -4,7 +4,7 @@
  *
  *   Type 1 font loader (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
@@ -751,6 +751,7 @@
         PS_DesignMap  dmap = blend->design_map + n;
 
 
+        FT_FREE( dmap->blend_points );
         FT_FREE( dmap->design_points );
         dmap->num_points = 0;
       }
@@ -1043,9 +1044,9 @@
       }
 
       /* allocate design map data */
-      if ( FT_QNEW_ARRAY( map->design_points, num_points * 2 ) )
+      if ( FT_QNEW_ARRAY( map->design_points, num_points ) ||
+           FT_QNEW_ARRAY( map->blend_points,  num_points ) )
         goto Exit;
-      map->blend_points = map->design_points + num_points;
       map->num_points   = (FT_Byte)num_points;
 
       for ( p = 0; p < num_points; p++ )
@@ -1876,9 +1877,8 @@
         }
 
         /* t1_decrypt() shouldn't write to base -- make temporary copy */
-        if ( FT_QALLOC( temp, size ) )
+        if ( FT_DUP( temp, base, size ) )
           goto Fail;
-        FT_MEM_COPY( temp, base, size );
         psaux->t1_decrypt( temp, size, 4330 );
         size -= (FT_ULong)t1face->type1.private_dict.lenIV;
         error = T1_Add_Table( table,
@@ -2090,9 +2090,8 @@
           }
 
           /* t1_decrypt() shouldn't write to base -- make temporary copy */
-          if ( FT_QALLOC( temp, size ) )
+          if ( FT_DUP( temp, base, size ) )
             goto Fail;
-          FT_MEM_COPY( temp, base, size );
           psaux->t1_decrypt( temp, size, 4330 );
           size -= (FT_ULong)t1face->type1.private_dict.lenIV;
           error = T1_Add_Table( code_table,
@@ -2284,7 +2283,7 @@
                        T1_FIELD_DICT_PRIVATE )
 #endif
 
-    { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0, 0 }
+    T1_FIELD_ZERO
   };
 
 
@@ -2392,18 +2391,13 @@
           T1_Field  keyword = (T1_Field)t1_keywords;
 
 
-          for (;;)
+          while ( keyword->len )
           {
-            FT_Byte*  name;
+            FT_Byte*  name = (FT_Byte*)keyword->ident;
 
 
-            name = (FT_Byte*)keyword->ident;
-            if ( !name )
-              break;
-
-            if ( cur[0] == name[0]                      &&
-                 len == ft_strlen( (const char *)name ) &&
-                 ft_memcmp( cur, name, len ) == 0       )
+            if ( keyword->len == len              &&
+                 ft_memcmp( cur, name, len ) == 0 )
             {
               /* We found it -- run the parsing callback!     */
               /* We record every instance of every field      */
diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1load.h b/src/java.desktop/share/native/libfreetype/src/type1/t1load.h
index d8c9d2d8abe..a45efa7cb7b 100644
--- a/src/java.desktop/share/native/libfreetype/src/type1/t1load.h
+++ b/src/java.desktop/share/native/libfreetype/src/type1/t1load.h
@@ -4,7 +4,7 @@
  *
  *   Type 1 font loader (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1objs.c b/src/java.desktop/share/native/libfreetype/src/type1/t1objs.c
index 69e4fd5065e..b1b27c31fe3 100644
--- a/src/java.desktop/share/native/libfreetype/src/type1/t1objs.c
+++ b/src/java.desktop/share/native/libfreetype/src/type1/t1objs.c
@@ -4,7 +4,7 @@
  *
  *   Type 1 objects manager (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1objs.h b/src/java.desktop/share/native/libfreetype/src/type1/t1objs.h
index 03847b27e96..3809370c1e0 100644
--- a/src/java.desktop/share/native/libfreetype/src/type1/t1objs.h
+++ b/src/java.desktop/share/native/libfreetype/src/type1/t1objs.h
@@ -4,7 +4,7 @@
  *
  *   Type 1 objects manager (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1parse.c b/src/java.desktop/share/native/libfreetype/src/type1/t1parse.c
index 6dec6c16c3e..3717ea7c572 100644
--- a/src/java.desktop/share/native/libfreetype/src/type1/t1parse.c
+++ b/src/java.desktop/share/native/libfreetype/src/type1/t1parse.c
@@ -4,7 +4,7 @@
  *
  *   Type 1 parser (body).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1parse.h b/src/java.desktop/share/native/libfreetype/src/type1/t1parse.h
index 0d9a2865df0..a0a2134d45c 100644
--- a/src/java.desktop/share/native/libfreetype/src/type1/t1parse.h
+++ b/src/java.desktop/share/native/libfreetype/src/type1/t1parse.h
@@ -4,7 +4,7 @@
  *
  *   Type 1 parser (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/libfreetype/src/type1/t1tokens.h b/src/java.desktop/share/native/libfreetype/src/type1/t1tokens.h
index 40f36092622..5a3d2f1ef08 100644
--- a/src/java.desktop/share/native/libfreetype/src/type1/t1tokens.h
+++ b/src/java.desktop/share/native/libfreetype/src/type1/t1tokens.h
@@ -4,7 +4,7 @@
  *
  *   Type 1 tokenizer (specification).
  *
- * Copyright (C) 1996-2023 by
+ * Copyright (C) 1996-2024 by
  * David Turner, Robert Wilhelm, and Werner Lemberg.
  *
  * This file is part of the FreeType project, and may only be used,
diff --git a/src/java.desktop/share/native/liblcms/cmsalpha.c b/src/java.desktop/share/native/liblcms/cmsalpha.c
index 78d3ca6b671..2e50b65be24 100644
--- a/src/java.desktop/share/native/liblcms/cmsalpha.c
+++ b/src/java.desktop/share/native/liblcms/cmsalpha.c
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -612,8 +612,8 @@ void _cmsHandleExtraChannels(_cmsTRANSFORM* p, const void* in,
         cmsUInt8Number* SourcePtr;
         cmsUInt8Number* DestPtr;
 
-        cmsUInt32Number SourceStrideIncrement = 0;
-        cmsUInt32Number DestStrideIncrement = 0;
+        size_t SourceStrideIncrement = 0;
+        size_t DestStrideIncrement = 0;
 
         // The loop itself
         for (i = 0; i < LineCount; i++) {
@@ -640,8 +640,8 @@ void _cmsHandleExtraChannels(_cmsTRANSFORM* p, const void* in,
         cmsUInt8Number* SourcePtr[cmsMAXCHANNELS];
         cmsUInt8Number* DestPtr[cmsMAXCHANNELS];
 
-        cmsUInt32Number SourceStrideIncrements[cmsMAXCHANNELS];
-        cmsUInt32Number DestStrideIncrements[cmsMAXCHANNELS];
+        size_t SourceStrideIncrements[cmsMAXCHANNELS];
+        size_t DestStrideIncrements[cmsMAXCHANNELS];
 
         memset(SourceStrideIncrements, 0, sizeof(SourceStrideIncrements));
         memset(DestStrideIncrements, 0, sizeof(DestStrideIncrements));
diff --git a/src/java.desktop/share/native/liblcms/cmscam02.c b/src/java.desktop/share/native/liblcms/cmscam02.c
index 71a48d43de4..45ef4eef970 100644
--- a/src/java.desktop/share/native/liblcms/cmscam02.c
+++ b/src/java.desktop/share/native/liblcms/cmscam02.c
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -117,17 +117,16 @@ cmsFloat64Number computeFL(cmsCIECAM02* pMod)
     return FL;
 }
 
-static
-cmsFloat64Number computeD(cmsCIECAM02* pMod)
+static cmsFloat64Number computeD(cmsCIECAM02* pMod)
 {
-    cmsFloat64Number D;
+    cmsFloat64Number D, temp;
 
-    D = pMod->F - (1.0/3.6)*(exp(((-pMod ->LA-42) / 92.0)));
+    temp = 1.0 - ((1.0 / 3.6) * exp((-pMod->LA - 42) / 92.0));
 
+    D = pMod->F * temp;
     return D;
 }
 
-
 static
 CAM02COLOR XYZtoCAT02(CAM02COLOR clr)
 {
diff --git a/src/java.desktop/share/native/liblcms/cmscgats.c b/src/java.desktop/share/native/liblcms/cmscgats.c
index 57725ae4731..3e62d064c3f 100644
--- a/src/java.desktop/share/native/liblcms/cmscgats.c
+++ b/src/java.desktop/share/native/liblcms/cmscgats.c
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -444,10 +444,11 @@ static
 void StringClear(string* s)
 {
     s->len = 0;
+    s->begin[0] = 0;
 }
 
 static
-void StringAppend(string* s, char c)
+cmsBool StringAppend(string* s, char c)
 {
     if (s->len + 1 >= s->max)
     {
@@ -455,6 +456,8 @@ void StringAppend(string* s, char c)
 
         s->max *= 10;
         new_ptr = (char*) AllocChunk(s->it8, s->max);
+        if (new_ptr == NULL) return FALSE;
+
         if (new_ptr != NULL && s->begin != NULL)
             memcpy(new_ptr, s->begin, s->len);
 
@@ -466,6 +469,8 @@ void StringAppend(string* s, char c)
         s->begin[s->len++] = c;
         s->begin[s->len] = 0;
     }
+
+    return TRUE;
 }
 
 static
@@ -475,13 +480,15 @@ char* StringPtr(string* s)
 }
 
 static
-void StringCat(string* s, const char* c)
+cmsBool StringCat(string* s, const char* c)
 {
     while (*c)
     {
-        StringAppend(s, *c);
+        if (!StringAppend(s, *c)) return FALSE;
         c++;
     }
+
+    return TRUE;
 }
 
 
@@ -830,7 +837,12 @@ void InStringSymbol(cmsIT8* it8)
 
             if (it8->ch == '\n' || it8->ch == '\r' || it8->ch == 0) break;
             else {
-                StringAppend(it8->str, (char)it8->ch);
+                if (!StringAppend(it8->str, (char)it8->ch)) {
+
+                    SynError(it8, "Out of memory");
+                    return;
+                }
+
                 NextCh(it8);
             }
         }
@@ -860,7 +872,11 @@ void InSymbol(cmsIT8* it8)
 
             do {
 
-                StringAppend(it8->id, (char) it8->ch);
+                if (!StringAppend(it8->id, (char)it8->ch)) {
+
+                    SynError(it8, "Out of memory");
+                    return;
+                }
 
                 NextCh(it8);
 
@@ -904,7 +920,6 @@ void InSymbol(cmsIT8* it8)
                             if ((cmsFloat64Number) it8->inum * 16.0 + (cmsFloat64Number) j > (cmsFloat64Number)+2147483647.0)
                             {
                                 SynError(it8, "Invalid hexadecimal number");
-                                it8->sy = SEOF;
                                 return;
                             }
 
@@ -926,7 +941,6 @@ void InSymbol(cmsIT8* it8)
                             if ((cmsFloat64Number) it8->inum * 2.0 + j > (cmsFloat64Number)+2147483647.0)
                             {
                                 SynError(it8, "Invalid binary number");
-                                it8->sy = SEOF;
                                 return;
                             }
 
@@ -979,11 +993,19 @@ void InSymbol(cmsIT8* it8)
                     }
 
                     StringClear(it8->id);
-                    StringCat(it8->id, buffer);
+                    if (!StringCat(it8->id, buffer)) {
+
+                        SynError(it8, "Out of memory");
+                        return;
+                    }
 
                     do {
 
-                        StringAppend(it8->id, (char) it8->ch);
+                        if (!StringAppend(it8->id, (char)it8->ch)) {
+
+                            SynError(it8, "Out of memory");
+                            return;
+                        }
 
                         NextCh(it8);
 
@@ -1038,7 +1060,6 @@ void InSymbol(cmsIT8* it8)
 
         default:
             SynError(it8, "Unrecognized character: 0x%x", it8 ->ch);
-            it8->sy = SEOF;
             return;
             }
 
@@ -1053,24 +1074,21 @@ void InSymbol(cmsIT8* it8)
                 if(it8 -> IncludeSP >= (MAXINCLUDE-1)) {
 
                     SynError(it8, "Too many recursion levels");
-                    it8->sy = SEOF;
                     return;
                 }
 
                 InStringSymbol(it8);
                 if (!Check(it8, SSTRING, "Filename expected"))
-                {
-                    it8->sy = SEOF;
                     return;
-                }
+
 
                 FileNest = it8 -> FileStack[it8 -> IncludeSP + 1];
                 if(FileNest == NULL) {
 
                     FileNest = it8 ->FileStack[it8 -> IncludeSP + 1] = (FILECTX*)AllocChunk(it8, sizeof(FILECTX));
                     if (FileNest == NULL) {
+
                         SynError(it8, "Out of memory");
-                        it8->sy = SEOF;
                         return;
                     }
                 }
@@ -1078,8 +1096,8 @@ void InSymbol(cmsIT8* it8)
                 if (BuildAbsolutePath(StringPtr(it8->str),
                                       it8->FileStack[it8->IncludeSP]->FileName,
                                       FileNest->FileName, cmsMAX_PATH-1) == FALSE) {
+
                     SynError(it8, "File path too long");
-                    it8->sy = SEOF;
                     return;
                 }
 
@@ -1087,7 +1105,6 @@ void InSymbol(cmsIT8* it8)
                 if (FileNest->Stream == NULL) {
 
                         SynError(it8, "File %s not found", FileNest->FileName);
-                        it8->sy = SEOF;
                         return;
                 }
                 it8->IncludeSP++;
@@ -1102,10 +1119,10 @@ void InSymbol(cmsIT8* it8)
 static
 cmsBool CheckEOLN(cmsIT8* it8)
 {
-        if (!Check(it8, SEOLN, "Expected separator")) return FALSE;
-        while (it8 -> sy == SEOLN)
-                        InSymbol(it8);
-        return TRUE;
+    if (!Check(it8, SEOLN, "Expected separator")) return FALSE;
+    while (it8->sy == SEOLN)
+        InSymbol(it8);
+    return TRUE;
 
 }
 
@@ -1114,8 +1131,8 @@ cmsBool CheckEOLN(cmsIT8* it8)
 static
 void Skip(cmsIT8* it8, SYMBOL sy)
 {
-        if (it8->sy == sy && it8->sy != SEOF)
-                        InSymbol(it8);
+    if (it8->sy == sy && it8->sy != SEOF && it8->sy != SSYNERROR)
+        InSymbol(it8);
 }
 
 
@@ -1124,7 +1141,7 @@ static
 void SkipEOLN(cmsIT8* it8)
 {
     while (it8->sy == SEOLN) {
-             InSymbol(it8);
+        InSymbol(it8);
     }
 }
 
@@ -1235,9 +1252,12 @@ void* AllocChunk(cmsIT8* it8, cmsUInt32Number size)
     cmsUInt8Number* ptr;
 
     size = _cmsALIGNMEM(size);
+    if (size == 0) return NULL;
 
     if (size > Free) {
 
+        cmsUInt8Number* new_block;
+
         if (it8 -> Allocator.BlockSize == 0)
 
                 it8 -> Allocator.BlockSize = 20*1024;
@@ -1248,7 +1268,11 @@ void* AllocChunk(cmsIT8* it8, cmsUInt32Number size)
                 it8 ->Allocator.BlockSize = size;
 
         it8 ->Allocator.Used = 0;
-        it8 ->Allocator.Block = (cmsUInt8Number*) AllocBigBlock(it8, it8 ->Allocator.BlockSize);
+        new_block = (cmsUInt8Number*)AllocBigBlock(it8, it8->Allocator.BlockSize);
+        if (new_block == NULL)
+            return NULL;
+
+        it8->Allocator.Block = new_block;
     }
 
     if (it8->Allocator.Block == NULL)
@@ -1258,7 +1282,6 @@ void* AllocChunk(cmsIT8* it8, cmsUInt32Number size)
     it8 ->Allocator.Used += size;
 
     return (void*) ptr;
-
 }
 
 
@@ -1266,9 +1289,12 @@ void* AllocChunk(cmsIT8* it8, cmsUInt32Number size)
 static
 char *AllocString(cmsIT8* it8, const char* str)
 {
-    cmsUInt32Number Size = (cmsUInt32Number) strlen(str)+1;
+    cmsUInt32Number Size;
     char *ptr;
 
+    if (str == NULL) return NULL;
+
+    Size = (cmsUInt32Number)strlen(str) + 1;
 
     ptr = (char *) AllocChunk(it8, Size);
     if (ptr) memcpy(ptr, str, Size-1);
@@ -1404,10 +1430,13 @@ KEYVALUE* AddAvailableSampleID(cmsIT8* it8, const char* Key)
 
 
 static
-void AllocTable(cmsIT8* it8)
+cmsBool AllocTable(cmsIT8* it8)
 {
     TABLE* t;
 
+    if (it8->TablesCount >= (MAXTABLES-1))
+        return FALSE;
+
     t = it8 ->Tab + it8 ->TablesCount;
 
     t->HeaderList = NULL;
@@ -1415,6 +1444,7 @@ void AllocTable(cmsIT8* it8)
     t->Data       = NULL;
 
     it8 ->TablesCount++;
+    return TRUE;
 }
 
 
@@ -1426,7 +1456,10 @@ cmsInt32Number CMSEXPORT cmsIT8SetTable(cmsHANDLE  IT8, cmsUInt32Number nTable)
 
          if (nTable == it8 ->TablesCount) {
 
-             AllocTable(it8);
+             if (!AllocTable(it8)) {
+                 SynError(it8, "Too many tables");
+                 return -1;
+             }
          }
          else {
              SynError(it8, "Table %d is out of sequence", nTable);
@@ -1610,8 +1643,8 @@ cmsInt32Number satoi(const char* b)
     if (b == NULL) return 0;
 
     n = atoi(b);
-    if (n > 0x7fffffffL) return 0x7fffffffL;
-    if (n < -0x7ffffffeL) return -0x7ffffffeL;
+    if (n > 0x7ffffff0L) return 0x7ffffff0L;
+    if (n < -0x7ffffff0L) return -0x7ffffff0L;
 
     return (cmsInt32Number)n;
 }
@@ -1620,22 +1653,26 @@ cmsInt32Number satoi(const char* b)
 static
 cmsBool AllocateDataFormat(cmsIT8* it8)
 {
+    cmsUInt32Number size;
+
     TABLE* t = GetTable(it8);
 
-    if (t -> DataFormat) return TRUE;    // Already allocated
+    if (t->DataFormat) return TRUE;    // Already allocated
 
-    t -> nSamples  = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS"));
+    t->nSamples = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS"));
 
-    if (t -> nSamples <= 0) {
+    if (t->nSamples <= 0 || t->nSamples > 0x7ffe) {
 
-        SynError(it8, "AllocateDataFormat: Unknown NUMBER_OF_FIELDS");
+        SynError(it8, "Wrong NUMBER_OF_FIELDS");
         return FALSE;
-        }
+    }
+
+    size = ((cmsUInt32Number)t->nSamples + 1) * sizeof(char*);
 
-    t -> DataFormat = (char**) AllocChunk (it8, ((cmsUInt32Number) t->nSamples + 1) * sizeof(char *));
+    t->DataFormat = (char**)AllocChunk(it8, size);
     if (t->DataFormat == NULL) {
 
-        SynError(it8, "AllocateDataFormat: Unable to allocate dataFormat array");
+        SynError(it8, "Unable to allocate dataFormat array");
         return FALSE;
     }
 
@@ -1664,7 +1701,7 @@ cmsBool SetDataFormat(cmsIT8* it8, int n, const char *label)
             return FALSE;
     }
 
-    if (n > t -> nSamples) {
+    if (n >= t -> nSamples) {
         SynError(it8, "More than NUMBER_OF_FIELDS fields.");
         return FALSE;
     }
@@ -1713,13 +1750,14 @@ cmsBool AllocateDataSet(cmsIT8* it8)
     t-> nSamples   = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS"));
     t-> nPatches   = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_SETS"));
 
-    if (t -> nSamples < 0 || t->nSamples > 0x7ffe || t->nPatches < 0 || t->nPatches > 0x7ffe)
+    if (t -> nSamples < 0 || t->nSamples > 0x7ffe || t->nPatches < 0 || t->nPatches > 0x7ffe ||
+        (t->nPatches * t->nSamples) > 200000)
     {
         SynError(it8, "AllocateDataSet: too much data");
         return FALSE;
     }
     else {
-        // Some dumb analizers warns of possible overflow here, just take a look couple of lines above.
+        // Some dumb analyzers warns of possible overflow here, just take a look couple of lines above.
         t->Data = (char**)AllocChunk(it8, ((cmsUInt32Number)t->nSamples + 1) * ((cmsUInt32Number)t->nPatches + 1) * sizeof(char*));
         if (t->Data == NULL) {
 
@@ -1748,8 +1786,11 @@ char* GetData(cmsIT8* it8, int nSet, int nField)
 static
 cmsBool SetData(cmsIT8* it8, int nSet, int nField, const char *Val)
 {
+    char* ptr;
+
     TABLE* t = GetTable(it8);
 
+
     if (!t->Data) {
         if (!AllocateDataSet(it8)) return FALSE;
     }
@@ -1766,7 +1807,11 @@ cmsBool SetData(cmsIT8* it8, int nSet, int nField, const char *Val)
 
     }
 
-    t->Data [nSet * t -> nSamples + nField] = AllocString(it8, Val);
+    ptr = AllocString(it8, Val);
+    if (ptr == NULL)
+        return FALSE;
+
+    t->Data [nSet * t -> nSamples + nField] = ptr;
     return TRUE;
 }
 
@@ -2121,7 +2166,7 @@ cmsBool DataSection (cmsIT8* it8)
         if (!AllocateDataSet(it8)) return FALSE;
     }
 
-    while (it8->sy != SEND_DATA && it8->sy != SEOF)
+    while (it8->sy != SEND_DATA && it8->sy != SEOF && it8->sy != SSYNERROR)
     {
         if (iField >= t -> nSamples) {
             iField = 0;
@@ -2129,7 +2174,7 @@ cmsBool DataSection (cmsIT8* it8)
 
         }
 
-        if (it8->sy != SEND_DATA && it8->sy != SEOF) {
+        if (it8->sy != SEND_DATA && it8->sy != SEOF && it8->sy != SSYNERROR) {
 
             switch (it8->sy)
             {
@@ -2225,8 +2270,8 @@ cmsBool HeaderSection(cmsIT8* it8)
             if (!GetVal(it8, Buffer, MAXSTR - 1, "Property data expected")) return FALSE;
 
             if (Key->WriteAs != WRITE_PAIR) {
-                AddToList(it8, &GetTable(it8)->HeaderList, VarName, NULL, Buffer,
-                    (it8->sy == SSTRING) ? WRITE_STRINGIFY : WRITE_UNCOOKED);
+                if (AddToList(it8, &GetTable(it8)->HeaderList, VarName, NULL, Buffer,
+                    (it8->sy == SSTRING) ? WRITE_STRINGIFY : WRITE_UNCOOKED) == NULL) return FALSE;
             }
             else {
                 const char *Subkey;
@@ -2332,9 +2377,10 @@ cmsBool ParseIT8(cmsIT8* it8, cmsBool nosheet)
 
                     if (!DataSection(it8)) return FALSE;
 
-                    if (it8 -> sy != SEOF) {
+                    if (it8 -> sy != SEOF && it8->sy != SSYNERROR) {
+
+                            if (!AllocTable(it8)) return FALSE;
 
-                            AllocTable(it8);
                             it8 ->nTable = it8 ->TablesCount - 1;
 
                             // Read sheet type if present. We only support identifier and string.
@@ -3064,7 +3110,8 @@ cmsBool ParseCube(cmsIT8* cube, cmsStage** Shaper, cmsStage** CLUT, char title[]
 
     InSymbol(cube);
 
-    while (cube->sy != SEOF) {
+    while (cube->sy != SEOF && cube->sy != SSYNERROR) {
+
         switch (cube->sy)
         {
         // Set profile description
diff --git a/src/java.desktop/share/native/liblcms/cmscnvrt.c b/src/java.desktop/share/native/liblcms/cmscnvrt.c
index d18865b15b9..9f8619cb9da 100644
--- a/src/java.desktop/share/native/liblcms/cmscnvrt.c
+++ b/src/java.desktop/share/native/liblcms/cmscnvrt.c
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -750,7 +750,6 @@ static
 cmsBool is_cmyk_devicelink(cmsHPROFILE hProfile)
 {
     return cmsGetDeviceClass(hProfile) == cmsSigLinkClass &&
-            cmsGetColorSpace(hProfile) == cmsSigCmykData &&
             cmsGetColorSpace(hProfile) == cmsSigCmykData;
 }
 
diff --git a/src/java.desktop/share/native/liblcms/cmserr.c b/src/java.desktop/share/native/liblcms/cmserr.c
index 9fb7db89c9a..d421c550d32 100644
--- a/src/java.desktop/share/native/liblcms/cmserr.c
+++ b/src/java.desktop/share/native/liblcms/cmserr.c
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
diff --git a/src/java.desktop/share/native/liblcms/cmsgamma.c b/src/java.desktop/share/native/liblcms/cmsgamma.c
index 8e489a43c55..773858b0c1f 100644
--- a/src/java.desktop/share/native/liblcms/cmsgamma.c
+++ b/src/java.desktop/share/native/liblcms/cmsgamma.c
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
diff --git a/src/java.desktop/share/native/liblcms/cmsgmt.c b/src/java.desktop/share/native/liblcms/cmsgmt.c
index e9ee73b52cd..03ac70202a5 100644
--- a/src/java.desktop/share/native/liblcms/cmsgmt.c
+++ b/src/java.desktop/share/native/liblcms/cmsgmt.c
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2021 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -327,8 +327,9 @@ cmsPipeline* _cmsCreateGamutCheckPipeline(cmsContext ContextID,
     cmsUInt32Number dwFormat;
     GAMUTCHAIN Chain;
     cmsUInt32Number nGridpoints;
-    cmsInt32Number nChannels;
+    cmsInt32Number nChannels, nInputChannels;
     cmsColorSpaceSignature ColorSpace;
+    cmsColorSpaceSignature InputColorSpace;
     cmsUInt32Number i;
     cmsHPROFILE ProfileList[256];
     cmsBool     BPCList[256];
@@ -374,11 +375,13 @@ cmsPipeline* _cmsCreateGamutCheckPipeline(cmsContext ContextID,
     AdaptationList[nGamutPCSposition] = 1.0;
     IntentList[nGamutPCSposition] = INTENT_RELATIVE_COLORIMETRIC;
 
-
     ColorSpace  = cmsGetColorSpace(hGamut);
     nChannels   = cmsChannelsOfColorSpace(ColorSpace);
     nGridpoints = _cmsReasonableGridpointsByColorspace(ColorSpace, cmsFLAGS_HIGHRESPRECALC);
-    dwFormat    = (CHANNELS_SH(nChannels)|BYTES_SH(2));
+
+    InputColorSpace = cmsGetColorSpace(ProfileList[0]);
+    nInputChannels  = cmsChannelsOfColorSpace(InputColorSpace);
+    dwFormat        = (CHANNELS_SH(nInputChannels)|BYTES_SH(2));
 
     // 16 bits to Lab double
     Chain.hInput = cmsCreateExtendedTransform(ContextID,
diff --git a/src/java.desktop/share/native/liblcms/cmshalf.c b/src/java.desktop/share/native/liblcms/cmshalf.c
index 5babb063eb0..7e5f7a3c7e0 100644
--- a/src/java.desktop/share/native/liblcms/cmshalf.c
+++ b/src/java.desktop/share/native/liblcms/cmshalf.c
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
diff --git a/src/java.desktop/share/native/liblcms/cmsintrp.c b/src/java.desktop/share/native/liblcms/cmsintrp.c
index 9837454df0b..43c47429c3c 100644
--- a/src/java.desktop/share/native/liblcms/cmsintrp.c
+++ b/src/java.desktop/share/native/liblcms/cmsintrp.c
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -524,7 +524,7 @@ void TrilinearInterpFloat(const cmsFloat32Number Input[],
     py = fclamp(Input[1]) * p->Domain[1];
     pz = fclamp(Input[2]) * p->Domain[2];
 
-    x0 = (int) floor(px); fx = px - (cmsFloat32Number) x0;  // We need full floor funcionality here
+    x0 = (int) floor(px); fx = px - (cmsFloat32Number) x0;  // We need full floor functionality here
     y0 = (int) floor(py); fy = py - (cmsFloat32Number) y0;
     z0 = (int) floor(pz); fz = pz - (cmsFloat32Number) z0;
 
diff --git a/src/java.desktop/share/native/liblcms/cmsio0.c b/src/java.desktop/share/native/liblcms/cmsio0.c
index 05baa9392e2..5258b7939d2 100644
--- a/src/java.desktop/share/native/liblcms/cmsio0.c
+++ b/src/java.desktop/share/native/liblcms/cmsio0.c
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -306,6 +306,11 @@ cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromMem(cmsContext ContextID, void *Buff
         fm = (FILEMEM*) _cmsMallocZero(ContextID, sizeof(FILEMEM));
         if (fm == NULL) goto Error;
 
+        if (Buffer == NULL) {
+            cmsSignalError(ContextID, cmsERROR_WRITE, "Couldn't write profile to NULL pointer");
+            goto Error;
+        }
+
         fm ->Block = (cmsUInt8Number*) Buffer;
         fm ->FreeBlockOnClose = FALSE;
         fm ->Size    = size;
diff --git a/src/java.desktop/share/native/liblcms/cmsio1.c b/src/java.desktop/share/native/liblcms/cmsio1.c
index e42d4d38987..48772c7cbde 100644
--- a/src/java.desktop/share/native/liblcms/cmsio1.c
+++ b/src/java.desktop/share/native/liblcms/cmsio1.c
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
diff --git a/src/java.desktop/share/native/liblcms/cmslut.c b/src/java.desktop/share/native/liblcms/cmslut.c
index b544c948625..3cf4e8cac5a 100644
--- a/src/java.desktop/share/native/liblcms/cmslut.c
+++ b/src/java.desktop/share/native/liblcms/cmslut.c
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -1109,7 +1109,7 @@ cmsStage* _cmsStageNormalizeFromLabFloat(cmsContext ContextID)
     return mpe;
 }
 
-// Fom XYZ to floating point PCS
+// From XYZ to floating point PCS
 cmsStage* _cmsStageNormalizeFromXyzFloat(cmsContext ContextID)
 {
 #define n (32768.0/65535.0)
diff --git a/src/java.desktop/share/native/liblcms/cmsmd5.c b/src/java.desktop/share/native/liblcms/cmsmd5.c
index 01aa44de85a..d9b9a4e5260 100644
--- a/src/java.desktop/share/native/liblcms/cmsmd5.c
+++ b/src/java.desktop/share/native/liblcms/cmsmd5.c
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -280,8 +280,8 @@ void CMSEXPORT cmsMD5finish(cmsProfileID* ProfileID,  cmsHANDLE Handle)
 
 
 // Assuming io points to an ICC profile, compute and store MD5 checksum
-// In the header, rendering intentent, attributes and ID should be set to zero
-// before computing MD5 checksum (per 6.1.13 in ICC spec)
+// In the header, rendering intentent, flags and ID should be set to zero
+// before computing MD5 checksum (per 7.2.18 of ICC spec 4.4)
 
 cmsBool CMSEXPORT cmsMD5computeID(cmsHPROFILE hProfile)
 {
@@ -299,8 +299,8 @@ cmsBool CMSEXPORT cmsMD5computeID(cmsHPROFILE hProfile)
     // Save a copy of the profile header
     memmove(&Keep, Icc, sizeof(_cmsICCPROFILE));
 
-    // Set RI, attributes and ID
-    memset(&Icc ->attributes, 0, sizeof(Icc ->attributes));
+    // Set RI, flags and ID
+    Icc ->flags = 0;
     Icc ->RenderingIntent = 0;
     memset(&Icc ->ProfileID, 0, sizeof(Icc ->ProfileID));
 
diff --git a/src/java.desktop/share/native/liblcms/cmsmtrx.c b/src/java.desktop/share/native/liblcms/cmsmtrx.c
index 599c290bd70..841da662a10 100644
--- a/src/java.desktop/share/native/liblcms/cmsmtrx.c
+++ b/src/java.desktop/share/native/liblcms/cmsmtrx.c
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
diff --git a/src/java.desktop/share/native/liblcms/cmsnamed.c b/src/java.desktop/share/native/liblcms/cmsnamed.c
index d3cd97d4aea..451bfe9f34d 100644
--- a/src/java.desktop/share/native/liblcms/cmsnamed.c
+++ b/src/java.desktop/share/native/liblcms/cmsnamed.c
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -598,7 +598,7 @@ cmsUInt32Number CMSEXPORT cmsMLUgetASCII(const cmsMLU* mlu,
     if (BufferSize < ASCIIlen + 1)
         ASCIIlen = BufferSize - 1;
 
-    // Precess each character
+    // Process each character
     for (i=0; i < ASCIIlen; i++) {
 
         wchar_t wc = Wide[i];
diff --git a/src/java.desktop/share/native/liblcms/cmsopt.c b/src/java.desktop/share/native/liblcms/cmsopt.c
index 421a4f4a701..767008e68c5 100644
--- a/src/java.desktop/share/native/liblcms/cmsopt.c
+++ b/src/java.desktop/share/native/liblcms/cmsopt.c
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
diff --git a/src/java.desktop/share/native/liblcms/cmspack.c b/src/java.desktop/share/native/liblcms/cmspack.c
index fc875995a80..d430e73051d 100644
--- a/src/java.desktop/share/native/liblcms/cmspack.c
+++ b/src/java.desktop/share/native/liblcms/cmspack.c
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -217,7 +217,7 @@ cmsUInt8Number* UnrollPlanarBytes(CMSREGISTER _cmsTRANSFORM* info,
     else
     {
         if (Premul && Extra)
-            alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(accum[(nChan) * Stride]));
+            alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(accum[nChan * Stride]));
     }
 
     for (i=0; i < nChan; i++) {
@@ -606,8 +606,8 @@ cmsUInt8Number* UnrollAnyWordsPremul(CMSREGISTER _cmsTRANSFORM* info,
    cmsUInt32Number ExtraFirst  = DoSwap ^ SwapFirst;
    cmsUInt32Number i;
 
-   cmsUInt16Number alpha = (ExtraFirst ? accum[0] : accum[nChan - 1]);
-   cmsUInt32Number alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(alpha));
+   cmsUInt16Number alpha = (ExtraFirst ? ((cmsUInt16Number*)accum)[0] : ((cmsUInt16Number*)accum)[nChan]);
+   cmsUInt32Number alpha_factor = _cmsToFixedDomain(alpha);
 
     if (ExtraFirst) {
         accum += sizeof(cmsUInt16Number);
@@ -691,8 +691,8 @@ cmsUInt8Number* UnrollPlanarWordsPremul(CMSREGISTER _cmsTRANSFORM* info,
     cmsUInt32Number ExtraFirst = DoSwap ^ SwapFirst;
     cmsUInt8Number* Init = accum;
 
-    cmsUInt16Number  alpha = (ExtraFirst ? accum[0] : accum[(nChan - 1) * Stride]);
-    cmsUInt32Number alpha_factor = _cmsToFixedDomain(FROM_8_TO_16(alpha));
+    cmsUInt16Number alpha = (ExtraFirst ? ((cmsUInt16Number*)accum)[0] : ((cmsUInt16Number*)accum)[nChan * Stride / 2]);
+    cmsUInt32Number alpha_factor = _cmsToFixedDomain(alpha);
 
     if (ExtraFirst) {
         accum += Stride;
@@ -1107,8 +1107,7 @@ cmsINLINE cmsBool IsInkSpace(cmsUInt32Number Type)
 }
 
 // Return the size in bytes of a given formatter
-static
-cmsUInt32Number PixelSize(cmsUInt32Number Format)
+cmsINLINE cmsUInt32Number PixelSize(cmsUInt32Number Format)
 {
     cmsUInt32Number fmt_bytes = T_BYTES(Format);
 
@@ -1454,7 +1453,7 @@ cmsUInt8Number* UnrollDoublesToFloat(_cmsTRANSFORM* info,
     if (Premul && Extra)
     {
         if (Planar)
-            alpha_factor = (ExtraFirst ? ptr[0] : ptr[(nChan) * Stride]) / maximum;
+            alpha_factor = (ExtraFirst ? ptr[0] : ptr[nChan * Stride]) / maximum;
         else
             alpha_factor = (ExtraFirst ? ptr[0] : ptr[nChan]) / maximum;
     }
@@ -3052,6 +3051,7 @@ cmsUInt8Number* PackWordsFromFloat(_cmsTRANSFORM* info,
     if (ExtraFirst)
         start = Extra;
 
+    Stride /= 2;
     for (i = 0; i < nChan; i++) {
 
         cmsUInt32Number index = DoSwap ? (nChan - i - 1) : i;
@@ -3115,7 +3115,7 @@ cmsUInt8Number* PackFloatsFromFloat(_cmsTRANSFORM* info,
                      v = maximum - v;
 
               if (Planar)
-                     ((cmsFloat32Number*)output)[(i + start)* Stride] = (cmsFloat32Number)v;
+                     ((cmsFloat32Number*)output)[(i + start) * Stride] = (cmsFloat32Number)v;
               else
                      ((cmsFloat32Number*)output)[i + start] = (cmsFloat32Number)v;
        }
@@ -3455,7 +3455,7 @@ cmsUInt8Number* UnrollHalfToFloat(_cmsTRANSFORM* info,
     cmsUInt32Number i, start = 0;
     cmsFloat32Number maximum = IsInkSpace(info ->InputFormat) ? 100.0F : 1.0F;
 
-    Stride /= PixelSize(info->OutputFormat);
+    Stride /= PixelSize(info->InputFormat);
 
     if (ExtraFirst)
             start = Extra;
@@ -4062,6 +4062,9 @@ cmsUInt32Number CMSEXPORT cmsFormatterForColorspaceOfProfile(cmsHPROFILE hProfil
     // Unsupported color space?
     if (nOutputChans < 0) return 0;
 
+    // Fix float spaces
+    nBytes &= 7;
+
     // Create a fake formatter for result
     return FLOAT_SH(Float) | COLORSPACE_SH(ColorSpaceBits) | BYTES_SH(nBytes) | CHANNELS_SH(nOutputChans);
 }
@@ -4079,6 +4082,9 @@ cmsUInt32Number CMSEXPORT cmsFormatterForPCSOfProfile(cmsHPROFILE hProfile, cmsU
     // Unsupported color space?
     if (nOutputChans < 0) return 0;
 
+    // Fix float spaces
+    nBytes &= 7;
+
     // Create a fake formatter for result
     return FLOAT_SH(Float) | COLORSPACE_SH(ColorSpaceBits) | BYTES_SH(nBytes) | CHANNELS_SH(nOutputChans);
 }
diff --git a/src/java.desktop/share/native/liblcms/cmspcs.c b/src/java.desktop/share/native/liblcms/cmspcs.c
index c4739840053..5f1b1f0d8e6 100644
--- a/src/java.desktop/share/native/liblcms/cmspcs.c
+++ b/src/java.desktop/share/native/liblcms/cmspcs.c
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
diff --git a/src/java.desktop/share/native/liblcms/cmsplugin.c b/src/java.desktop/share/native/liblcms/cmsplugin.c
index f84e0172c81..aaad39f52b0 100644
--- a/src/java.desktop/share/native/liblcms/cmsplugin.c
+++ b/src/java.desktop/share/native/liblcms/cmsplugin.c
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -935,7 +935,10 @@ cmsContext CMSEXPORT cmsDupContext(cmsContext ContextID, void* NewUserData)
     if (!InitContextMutex()) return NULL;
 
     // Setup default memory allocators
-    memcpy(&ctx->DefaultMemoryManager, &src->DefaultMemoryManager, sizeof(ctx->DefaultMemoryManager));
+    if (ContextID == NULL)
+        _cmsInstallAllocFunctions(NULL, &ctx->DefaultMemoryManager);
+    else
+        memcpy(&ctx->DefaultMemoryManager, &src->DefaultMemoryManager, sizeof(ctx->DefaultMemoryManager));
 
     // Maintain the linked list
     _cmsEnterCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);
diff --git a/src/java.desktop/share/native/liblcms/cmsps2.c b/src/java.desktop/share/native/liblcms/cmsps2.c
index 9a2ab464f31..476817e9c1a 100644
--- a/src/java.desktop/share/native/liblcms/cmsps2.c
+++ b/src/java.desktop/share/native/liblcms/cmsps2.c
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -494,7 +494,7 @@ void Emit1Gamma(cmsIOHANDLER* m, cmsToneCurve* Table)
     // Bounds check
     EmitRangeCheck(m);
 
-    // Emit intepolation code
+    // Emit interpolation code
 
     // PostScript code                      Stack
     // ===============                      ========================
@@ -618,7 +618,7 @@ int OutputValueSampler(CMSREGISTER const cmsUInt16Number In[], CMSREGISTER cmsUI
     }
 
 
-    // Hadle the parenthesis on rows
+    // Handle the parenthesis on rows
 
     if (In[0] != sc ->FirstComponent) {
 
@@ -694,8 +694,10 @@ void WriteCLUT(cmsIOHANDLER* m, cmsStage* mpe, const char* PreMaj,
 
         _cmsIOPrintf(m, "[");
 
-        for (i = 0; i < sc.Pipeline->Params->nInputs; i++)
-            _cmsIOPrintf(m, " %d ", sc.Pipeline->Params->nSamples[i]);
+        for (i = 0; i < sc.Pipeline->Params->nInputs; i++) {
+            if (i < MAX_INPUT_DIMENSIONS)
+                _cmsIOPrintf(m, " %d ", sc.Pipeline->Params->nSamples[i]);
+        }
 
         _cmsIOPrintf(m, " [\n");
 
@@ -869,13 +871,13 @@ cmsToneCurve* ExtractGray2Y(cmsContext ContextID, cmsHPROFILE hProfile, cmsUInt3
 // a more perceptually uniform space... I do choose Lab.
 
 static
-int WriteInputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags)
+cmsBool WriteInputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags)
 {
     cmsHPROFILE hLab;
     cmsHTRANSFORM xform;
     cmsUInt32Number nChannels;
     cmsUInt32Number InputFormat;
-    int rc;
+
     cmsHPROFILE Profiles[2];
     cmsCIEXYZ BlackPointAdaptedToD50;
 
@@ -900,7 +902,7 @@ int WriteInputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent,
     if (xform == NULL) {
 
         cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Cannot create transform Profile -> Lab");
-        return 0;
+        return FALSE;
     }
 
     // Only 1, 3 and 4 channels are allowed
@@ -919,29 +921,35 @@ int WriteInputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent,
             cmsUInt32Number OutFrm = TYPE_Lab_16;
             cmsPipeline* DeviceLink;
             _cmsTRANSFORM* v = (_cmsTRANSFORM*) xform;
+            cmsBool rc;
 
             DeviceLink = cmsPipelineDup(v ->Lut);
-            if (DeviceLink == NULL) return 0;
+            if (DeviceLink == NULL) {
+                cmsDeleteTransform(xform);
+                return FALSE;
+            }
 
             dwFlags |= cmsFLAGS_FORCE_CLUT;
             _cmsOptimizePipeline(m->ContextID, &DeviceLink, Intent, &InputFormat, &OutFrm, &dwFlags);
 
             rc = EmitCIEBasedDEF(m, DeviceLink, Intent, &BlackPointAdaptedToD50);
             cmsPipelineFree(DeviceLink);
-            if (rc == 0) return 0;
+            if (!rc) {
+                cmsDeleteTransform(xform);
+                return FALSE;
+            }
             }
             break;
 
     default:
 
+        cmsDeleteTransform(xform);
         cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Only 3, 4 channels are supported for CSA. This profile has %d channels.", nChannels);
-        return 0;
+        return FALSE;
     }
 
-
     cmsDeleteTransform(xform);
-
-    return 1;
+    return TRUE;
 }
 
 static
@@ -1284,7 +1292,7 @@ void EmitXYZ2Lab(cmsIOHANDLER* m)
 // 8 bits.
 
 static
-int WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags)
+cmsBool WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags)
 {
     cmsHPROFILE hLab;
     cmsHTRANSFORM xform;
@@ -1302,7 +1310,7 @@ int WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent
     cmsStage* first;
 
     hLab = cmsCreateLab4ProfileTHR(m ->ContextID, NULL);
-    if (hLab == NULL) return 0;
+    if (hLab == NULL) return FALSE;
 
     OutputFormat = cmsFormatterForColorspaceOfProfile(hProfile, 2, FALSE);
     nChannels    = T_CHANNELS(OutputFormat);
@@ -1327,7 +1335,7 @@ int WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent
 
     if (xform == NULL) {
         cmsSignalError(m ->ContextID, cmsERROR_COLORSPACE_CHECK, "Cannot create transform Lab -> Profile in CRD creation");
-        return 0;
+        return FALSE;
     }
 
     // Get a copy of the internal devicelink
@@ -1335,17 +1343,22 @@ int WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent
     DeviceLink = cmsPipelineDup(v ->Lut);
     if (DeviceLink == NULL) {
         cmsDeleteTransform(xform);
-        return 0;
+        cmsSignalError(m->ContextID, cmsERROR_CORRUPTION_DETECTED, "Cannot access link for CRD");
+        return FALSE;
     }
 
      // We need a CLUT
     dwFlags |= cmsFLAGS_FORCE_CLUT;
-    _cmsOptimizePipeline(m->ContextID, &DeviceLink, RelativeEncodingIntent, &InFrm, &OutputFormat, &dwFlags);
+    if (!_cmsOptimizePipeline(m->ContextID, &DeviceLink, RelativeEncodingIntent, &InFrm, &OutputFormat, &dwFlags)) {
+        cmsPipelineFree(DeviceLink);
+        cmsDeleteTransform(xform);
+        cmsSignalError(m->ContextID, cmsERROR_CORRUPTION_DETECTED, "Cannot create CLUT table for CRD");
+        return FALSE;
+    }
 
     _cmsIOPrintf(m, "<<\n");
     _cmsIOPrintf(m, "/ColorRenderingType 1\n");
 
-
     cmsDetectBlackPoint(&BlackPointAdaptedToD50, hProfile, Intent, 0);
 
     // Emit headers, etc.
@@ -1367,6 +1380,13 @@ int WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent
 
     first = cmsPipelineGetPtrToFirstStage(DeviceLink);
     if (first != NULL) {
+        if (first->Type != cmsSigCLutElemType) {
+            cmsPipelineFree(DeviceLink);
+            cmsDeleteTransform(xform);
+            cmsSignalError(m->ContextID, cmsERROR_CORRUPTION_DETECTED, "Cannot create CLUT, revise your flags!");
+            return FALSE;
+        }
+
         WriteCLUT(m, first, "<", ">\n", "", "", lFixWhite, ColorSpace);
     }
 
@@ -1389,7 +1409,7 @@ int WriteOutputLUT(cmsIOHANDLER* m, cmsHPROFILE hProfile, cmsUInt32Number Intent
     cmsPipelineFree(DeviceLink);
     cmsDeleteTransform(xform);
 
-    return 1;
+    return TRUE;
 }
 
 
diff --git a/src/java.desktop/share/native/liblcms/cmssamp.c b/src/java.desktop/share/native/liblcms/cmssamp.c
index 74f5f4bff29..ca5c4a9d693 100644
--- a/src/java.desktop/share/native/liblcms/cmssamp.c
+++ b/src/java.desktop/share/native/liblcms/cmssamp.c
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
diff --git a/src/java.desktop/share/native/liblcms/cmssm.c b/src/java.desktop/share/native/liblcms/cmssm.c
index 3e1486ae3ae..e2a810a2669 100644
--- a/src/java.desktop/share/native/liblcms/cmssm.c
+++ b/src/java.desktop/share/native/liblcms/cmssm.c
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
diff --git a/src/java.desktop/share/native/liblcms/cmstypes.c b/src/java.desktop/share/native/liblcms/cmstypes.c
index 862f393497a..22514f88226 100644
--- a/src/java.desktop/share/native/liblcms/cmstypes.c
+++ b/src/java.desktop/share/native/liblcms/cmstypes.c
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -599,6 +599,178 @@ void Type_ColorantOrderType_Free(struct _cms_typehandler_struct* self, void* Ptr
     _cmsFree(self ->ContextID, Ptr);
 }
 
+// ********************************************************************************
+// Type cmsSigUInt8ArrayType
+// ********************************************************************************
+// This type represents an array of generic 1-byte/8-bit quantity.
+
+static
+void* Type_UInt8_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
+{
+    cmsUInt8Number* array;
+    cmsUInt32Number i, n;
+
+    *nItems = 0;
+    n = SizeOfTag / sizeof(cmsUInt8Number);
+    array = (cmsUInt8Number*)_cmsCalloc(self->ContextID, n, sizeof(cmsUInt8Number));
+    if (array == NULL) return NULL;
+
+    for (i = 0; i < n; i++) {
+
+        if (!_cmsReadUInt8Number(io, &array[i])) {
+
+            _cmsFree(self->ContextID, array);
+            return NULL;
+        }
+    }
+
+    *nItems = n;
+    return (void*)array;
+}
+
+static
+cmsBool Type_UInt8_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
+{
+    cmsUInt8Number* Value = (cmsUInt8Number*)Ptr;
+    cmsUInt32Number i;
+
+    for (i = 0; i < nItems; i++) {
+
+        if (!_cmsWriteUInt8Number(io, Value[i])) return FALSE;
+    }
+
+    return TRUE;
+
+    cmsUNUSED_PARAMETER(self);
+}
+
+static
+void* Type_UInt8_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n)
+{
+    return _cmsDupMem(self->ContextID, Ptr, n * sizeof(cmsUInt8Number));
+}
+
+
+static
+void Type_UInt8_Free(struct _cms_typehandler_struct* self, void* Ptr)
+{
+    _cmsFree(self->ContextID, Ptr);
+}
+
+// ********************************************************************************
+// Type cmsSigUInt32ArrayType
+// ********************************************************************************
+// This type represents an array of generic 4-byte/32-bit quantity.
+static
+void* Type_UInt32_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
+{
+    cmsUInt32Number* array;
+    cmsUInt32Number i, n;
+
+    *nItems = 0;
+    n = SizeOfTag / sizeof(cmsUInt32Number);
+    array = (cmsUInt32Number*)_cmsCalloc(self->ContextID, n, sizeof(cmsUInt32Number));
+    if (array == NULL) return NULL;
+
+    for (i = 0; i < n; i++) {
+
+        if (!_cmsReadUInt32Number(io, &array[i])) {
+
+            _cmsFree(self->ContextID, array);
+            return NULL;
+        }
+    }
+
+    *nItems = n;
+    return (void*)array;
+}
+
+static
+cmsBool Type_UInt32_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
+{
+    cmsUInt32Number* Value = (cmsUInt32Number*)Ptr;
+    cmsUInt32Number i;
+
+    for (i = 0; i < nItems; i++) {
+
+        if (!_cmsWriteUInt32Number(io, Value[i])) return FALSE;
+    }
+
+    return TRUE;
+
+    cmsUNUSED_PARAMETER(self);
+}
+
+static
+void* Type_UInt32_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n)
+{
+    return _cmsDupMem(self->ContextID, Ptr, n * sizeof(cmsUInt32Number));
+}
+
+
+static
+void Type_UInt32_Free(struct _cms_typehandler_struct* self, void* Ptr)
+{
+    _cmsFree(self->ContextID, Ptr);
+}
+
+// ********************************************************************************
+// Type cmsSigUInt64ArrayType
+// ********************************************************************************
+// This type represents an array of generic 8-byte/64-bit quantity.
+static
+void* Type_UInt64_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
+{
+    cmsUInt64Number* array;
+    cmsUInt32Number i, n;
+
+    *nItems = 0;
+    n = SizeOfTag / sizeof(cmsUInt64Number);
+    array = (cmsUInt64Number*)_cmsCalloc(self->ContextID, n, sizeof(cmsUInt64Number));
+    if (array == NULL) return NULL;
+
+    for (i = 0; i < n; i++) {
+
+        if (!_cmsReadUInt64Number(io, &array[i])) {
+
+            _cmsFree(self->ContextID, array);
+            return NULL;
+        }
+    }
+
+    *nItems = n;
+    return (void*)array;
+}
+
+static
+cmsBool Type_UInt64_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
+{
+    cmsUInt64Number* Value = (cmsUInt64Number*)Ptr;
+    cmsUInt32Number i;
+
+    for (i = 0; i < nItems; i++) {
+
+        if (!_cmsWriteUInt64Number(io, &Value[i])) return FALSE;
+    }
+
+    return TRUE;
+
+    cmsUNUSED_PARAMETER(self);
+}
+
+static
+void* Type_UInt64_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n)
+{
+    return _cmsDupMem(self->ContextID, Ptr, n * sizeof(cmsUInt64Number));
+}
+
+
+static
+void Type_UInt64_Free(struct _cms_typehandler_struct* self, void* Ptr)
+{
+    _cmsFree(self->ContextID, Ptr);
+}
+
 // ********************************************************************************
 // Type cmsSigS15Fixed16ArrayType
 // ********************************************************************************
@@ -968,6 +1140,8 @@ void *Type_Text_Description_Read(struct _cms_typehandler_struct* self, cmsIOHAND
 
     // Read len of ASCII
     if (!_cmsReadUInt32Number(io, &AsciiCount)) return NULL;
+    if (AsciiCount > 0x7ffff) return NULL;
+
     SizeOfTag -= sizeof(cmsUInt32Number);
 
     // Check for size
@@ -999,7 +1173,8 @@ void *Type_Text_Description_Read(struct _cms_typehandler_struct* self, cmsIOHAND
     if (!_cmsReadUInt32Number(io, &UnicodeCount)) goto Done;
     SizeOfTag -= 2* sizeof(cmsUInt32Number);
 
-    if (UnicodeCount == 0 || SizeOfTag < UnicodeCount*sizeof(cmsUInt16Number)) goto Done;
+    if (UnicodeCount == 0 || UnicodeCount > 0x7ffff ||
+        SizeOfTag < UnicodeCount*sizeof(cmsUInt16Number)) goto Done;
 
     UnicodeString = (wchar_t*)_cmsMallocZero(self->ContextID, (UnicodeCount + 1) * sizeof(wchar_t));
     if (UnicodeString == NULL) goto Done;
@@ -1129,7 +1304,7 @@ cmsBool  Type_Text_Description_Write(struct _cms_typehandler_struct* self, cmsIO
     if (!io ->Write(io, 67, Filler)) goto Error;
 
     // possibly add pad at the end of tag
-    if(len_aligned - len_tag_requirement > 0)
+    if (len_aligned > len_tag_requirement)
       if (!io ->Write(io, len_aligned - len_tag_requirement, Filler)) goto Error;
 
     rc = TRUE;
@@ -5191,7 +5366,7 @@ cmsBool ReadOneWChar(cmsIOHANDLER* io,  _cmsDICelem* e, cmsUInt32Number i, wchar
       if (!io -> Seek(io, e -> Offsets[i])) return FALSE;
 
       nChars = e ->Sizes[i] / sizeof(cmsUInt16Number);
-
+      if (nChars > 0x7ffff) return FALSE;
 
       *wcstr = (wchar_t*) _cmsMallocZero(e ->ContextID, (nChars + 1) * sizeof(wchar_t));
       if (*wcstr == NULL) return FALSE;
@@ -5772,7 +5947,10 @@ static const _cmsTagTypeLinkedList SupportedTagTypes[] = {
 {TYPE_HANDLER(cmsSigDictType,                  Dictionary),         (_cmsTagTypeLinkedList*) &SupportedTagTypes[30] },
 {TYPE_HANDLER(cmsSigcicpType,                  VideoSignal),        (_cmsTagTypeLinkedList*) &SupportedTagTypes[31] },
 {TYPE_HANDLER(cmsSigVcgtType,                  vcgt),               (_cmsTagTypeLinkedList*) &SupportedTagTypes[32] },
-{TYPE_HANDLER(cmsSigMHC2Type,                  MHC2),                NULL }
+{TYPE_HANDLER(cmsSigMHC2Type,                  MHC2),               (_cmsTagTypeLinkedList*) &SupportedTagTypes[33] },
+{TYPE_HANDLER(cmsSigUInt8ArrayType,            UInt8),              (_cmsTagTypeLinkedList*) &SupportedTagTypes[34] },
+{TYPE_HANDLER(cmsSigUInt32ArrayType,           UInt32),             (_cmsTagTypeLinkedList*) &SupportedTagTypes[35] },
+{TYPE_HANDLER(cmsSigUInt64ArrayType,           UInt64),             NULL }
 };
 
 
diff --git a/src/java.desktop/share/native/liblcms/cmsvirt.c b/src/java.desktop/share/native/liblcms/cmsvirt.c
index e8d18d4ca9f..1ef86dae054 100644
--- a/src/java.desktop/share/native/liblcms/cmsvirt.c
+++ b/src/java.desktop/share/native/liblcms/cmsvirt.c
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -412,7 +412,7 @@ int InkLimitingSampler(CMSREGISTER const cmsUInt16Number In[], CMSREGISTER cmsUI
     Out[1] = _cmsQuickSaturateWord(In[1] * Ratio);     // M
     Out[2] = _cmsQuickSaturateWord(In[2] * Ratio);     // Y
 
-    Out[3] = In[3];                                 // K (untouched)
+    Out[3] = In[3];                                    // K (untouched)
 
     return TRUE;
 }
@@ -433,7 +433,7 @@ cmsHPROFILE CMSEXPORT cmsCreateInkLimitingDeviceLinkTHR(cmsContext ContextID,
         return NULL;
     }
 
-    if (Limit < 0.0 || Limit > 400) {
+    if (Limit < 1.0 || Limit > 400) {
 
         cmsSignalError(ContextID, cmsERROR_RANGE, "InkLimiting: Limit should be between 1..400");
         if (Limit < 1) Limit = 1;
@@ -705,7 +705,7 @@ cmsHPROFILE CMSEXPORT cmsCreate_sRGBProfile(void)
 *
 * This virtual profile cannot be saved as an ICC file
 */
-cmsHPROFILE cmsCreate_OkLabProfile(cmsContext ctx)
+cmsHPROFILE CMSEXPORT cmsCreate_OkLabProfile(cmsContext ctx)
 {
     cmsStage* XYZPCS = _cmsStageNormalizeFromXyzFloat(ctx);
     cmsStage* PCSXYZ = _cmsStageNormalizeToXyzFloat(ctx);
@@ -774,6 +774,8 @@ cmsHPROFILE cmsCreate_OkLabProfile(cmsContext ctx)
     cmsPipeline* BToA = cmsPipelineAlloc(ctx, 3, 3);
 
     cmsHPROFILE hProfile = cmsCreateProfilePlaceholder(ctx);
+    if (!hProfile)            // can't allocate
+        goto error;
 
     cmsSetProfileVersion(hProfile, 4.4);
 
diff --git a/src/java.desktop/share/native/liblcms/cmswtpnt.c b/src/java.desktop/share/native/liblcms/cmswtpnt.c
index 27d71803531..ebba2cd6a97 100644
--- a/src/java.desktop/share/native/liblcms/cmswtpnt.c
+++ b/src/java.desktop/share/native/liblcms/cmswtpnt.c
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
diff --git a/src/java.desktop/share/native/liblcms/cmsxform.c b/src/java.desktop/share/native/liblcms/cmsxform.c
index 86afd7202fd..1eb3eecbf18 100644
--- a/src/java.desktop/share/native/liblcms/cmsxform.c
+++ b/src/java.desktop/share/native/liblcms/cmsxform.c
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -295,7 +295,7 @@ void FloatXFORM(_cmsTRANSFORM* p,
     cmsUInt8Number* output;
     cmsFloat32Number fIn[cmsMAXCHANNELS], fOut[cmsMAXCHANNELS];
     cmsFloat32Number OutOfGamut;
-    cmsUInt32Number i, j, c, strideIn, strideOut;
+    size_t i, j, c, strideIn, strideOut;
 
     _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
 
@@ -322,9 +322,11 @@ void FloatXFORM(_cmsTRANSFORM* p,
                 // Is current color out of gamut?
                 if (OutOfGamut > 0.0) {
 
+                    _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*)_cmsContextGetClientChunk(p->ContextID, AlarmCodesContext);
+
                     // Certainly, out of gamut
                     for (c = 0; c < cmsMAXCHANNELS; c++)
-                        fOut[c] = -1.0;
+                        fOut[c] = ContextAlarmCodes->AlarmCodes[c] / 65535.0F;
 
                 }
                 else {
@@ -361,7 +363,7 @@ void NullFloatXFORM(_cmsTRANSFORM* p,
     cmsUInt8Number* accum;
     cmsUInt8Number* output;
     cmsFloat32Number fIn[cmsMAXCHANNELS];
-    cmsUInt32Number i, j, strideIn, strideOut;
+    size_t i, j, strideIn, strideOut;
 
     _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
 
@@ -399,7 +401,7 @@ void NullXFORM(_cmsTRANSFORM* p,
     cmsUInt8Number* accum;
     cmsUInt8Number* output;
     cmsUInt16Number wIn[cmsMAXCHANNELS];
-    cmsUInt32Number i, j, strideIn, strideOut;
+    size_t i, j, strideIn, strideOut;
 
     _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
 
@@ -409,17 +411,17 @@ void NullXFORM(_cmsTRANSFORM* p,
 
     for (i = 0; i < LineCount; i++) {
 
-           accum = (cmsUInt8Number*)in + strideIn;
-           output = (cmsUInt8Number*)out + strideOut;
+        accum = (cmsUInt8Number*)in + strideIn;
+        output = (cmsUInt8Number*)out + strideOut;
 
-           for (j = 0; j < PixelsPerLine; j++) {
+        for (j = 0; j < PixelsPerLine; j++) {
 
-                  accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn);
-                  output = p->ToOutput(p, wIn, output, Stride->BytesPerPlaneOut);
-    }
+            accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn);
+            output = p->ToOutput(p, wIn, output, Stride->BytesPerPlaneOut);
+        }
 
-           strideIn += Stride->BytesPerLineIn;
-           strideOut += Stride->BytesPerLineOut;
+        strideIn += Stride->BytesPerLineIn;
+        strideOut += Stride->BytesPerLineOut;
     }
 
 }
@@ -437,7 +439,7 @@ void PrecalculatedXFORM(_cmsTRANSFORM* p,
     CMSREGISTER cmsUInt8Number* accum;
     CMSREGISTER cmsUInt8Number* output;
     cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
-    cmsUInt32Number i, j, strideIn, strideOut;
+    size_t i, j, strideIn, strideOut;
 
     _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
 
@@ -500,7 +502,7 @@ void PrecalculatedXFORMGamutCheck(_cmsTRANSFORM* p,
     cmsUInt8Number* accum;
     cmsUInt8Number* output;
     cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
-    cmsUInt32Number i, j, strideIn, strideOut;
+    size_t i, j, strideIn, strideOut;
 
     _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
 
@@ -511,18 +513,18 @@ void PrecalculatedXFORMGamutCheck(_cmsTRANSFORM* p,
 
     for (i = 0; i < LineCount; i++) {
 
-           accum = (cmsUInt8Number*)in + strideIn;
-           output = (cmsUInt8Number*)out + strideOut;
+        accum = (cmsUInt8Number*)in + strideIn;
+        output = (cmsUInt8Number*)out + strideOut;
 
-           for (j = 0; j < PixelsPerLine; j++) {
+        for (j = 0; j < PixelsPerLine; j++) {
 
-                  accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn);
-                  TransformOnePixelWithGamutCheck(p, wIn, wOut);
-                  output = p->ToOutput(p, wOut, output, Stride->BytesPerPlaneOut);
-           }
+            accum = p->FromInput(p, wIn, accum, Stride->BytesPerPlaneIn);
+            TransformOnePixelWithGamutCheck(p, wIn, wOut);
+            output = p->ToOutput(p, wOut, output, Stride->BytesPerPlaneOut);
+        }
 
-           strideIn += Stride->BytesPerLineIn;
-           strideOut += Stride->BytesPerLineOut;
+        strideIn += Stride->BytesPerLineIn;
+        strideOut += Stride->BytesPerLineOut;
     }
 }
 
@@ -540,7 +542,7 @@ void CachedXFORM(_cmsTRANSFORM* p,
     cmsUInt8Number* output;
     cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
     _cmsCACHE Cache;
-    cmsUInt32Number i, j, strideIn, strideOut;
+    size_t i, j, strideIn, strideOut;
 
     _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
 
@@ -595,7 +597,7 @@ void CachedXFORMGamutCheck(_cmsTRANSFORM* p,
     cmsUInt8Number* output;
     cmsUInt16Number wIn[cmsMAXCHANNELS], wOut[cmsMAXCHANNELS];
     _cmsCACHE Cache;
-    cmsUInt32Number i, j, strideIn, strideOut;
+    size_t i, j, strideIn, strideOut;
 
     _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);
 
@@ -712,7 +714,7 @@ void _cmsTransform2toTransformAdaptor(struct _cmstransform_struct *CMMcargo,
                                       const cmsStride* Stride)
 {
 
-       cmsUInt32Number i, strideIn, strideOut;
+       size_t i, strideIn, strideOut;
 
        _cmsHandleExtraChannels(CMMcargo, InputBuffer, OutputBuffer, PixelsPerLine, LineCount, Stride);
 
@@ -1099,7 +1101,7 @@ cmsBool  IsProperColorSpace(cmsColorSpaceSignature Check, cmsUInt32Number dwForm
     int Space1 = (int) T_COLORSPACE(dwFormat);
     int Space2 = _cmsLCMScolorSpace(Check);
 
-    if (Space1 == PT_ANY) return TRUE;
+    if (Space1 == PT_ANY) return (T_CHANNELS(dwFormat) == cmsChannelsOf(Check));
     if (Space1 == Space2) return TRUE;
 
     if (Space1 == PT_LabV2 && Space2 == PT_Lab) return TRUE;
@@ -1160,7 +1162,15 @@ cmsHTRANSFORM CMSEXPORT cmsCreateExtendedTransform(cmsContext ContextID,
     cmsColorSpaceSignature EntryColorSpace;
     cmsColorSpaceSignature ExitColorSpace;
     cmsPipeline* Lut;
-    cmsUInt32Number LastIntent = Intents[nProfiles-1];
+    cmsUInt32Number LastIntent;
+
+    // Safeguard
+    if (nProfiles <= 0 || nProfiles > 255) {
+        cmsSignalError(ContextID, cmsERROR_RANGE, "Wrong number of profiles. 1..255 expected, %d found.", nProfiles);
+        return NULL;
+    }
+
+    LastIntent = Intents[nProfiles - 1];
 
     // If it is a fake transform
     if (dwFlags & cmsFLAGS_NULLTRANSFORM)
diff --git a/src/java.desktop/share/native/liblcms/lcms2.h b/src/java.desktop/share/native/liblcms/lcms2.h
index 2d9a8b1248f..5ba09661308 100644
--- a/src/java.desktop/share/native/liblcms/lcms2.h
+++ b/src/java.desktop/share/native/liblcms/lcms2.h
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2025 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -52,7 +52,7 @@
 //
 //---------------------------------------------------------------------------------
 //
-// Version 2.16
+// Version 2.17
 //
 
 #ifndef _lcms2_H
@@ -93,6 +93,9 @@
 // Uncomment this to remove the "register" storage class
 // #define CMS_NO_REGISTER_KEYWORD 1
 
+// Uncomment this to remove visibility attribute when building shared objects
+// #define CMS_NO_VISIBILITY 1
+
 // ********** End of configuration toggles ******************************
 
 // Needed for streams
@@ -113,7 +116,7 @@ extern "C" {
 #endif
 
 // Version/release
-#define LCMS_VERSION        2160
+#define LCMS_VERSION        2170
 
 // I will give the chance of redefining basic types for compilers that are not fully C99 compliant
 #ifndef CMS_BASIC_TYPES_ALREADY_DEFINED
@@ -277,7 +280,7 @@ typedef int                  cmsBool;
 #     define CMSAPI
 #  endif
 #else  // not Windows
-#  ifdef HAVE_FUNC_ATTRIBUTE_VISIBILITY
+#  if defined(HAVE_FUNC_ATTRIBUTE_VISIBILITY) && !defined(CMS_NO_VISIBILITY)
 #     define CMSEXPORT
 #     define CMSAPI    __attribute__((visibility("default")))
 #  else
@@ -987,7 +990,6 @@ typedef void* cmsHTRANSFORM;
 // IEEE 754-2008 "half"
 #define TYPE_GRAY_HALF_FLT    (FLOAT_SH(1)|COLORSPACE_SH(PT_GRAY)|CHANNELS_SH(1)|BYTES_SH(2))
 #define TYPE_RGB_HALF_FLT     (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(2))
-#define TYPE_RGBA_HALF_FLT    (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2))
 #define TYPE_CMYK_HALF_FLT    (FLOAT_SH(1)|COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(2))
 
 #define TYPE_RGBA_HALF_FLT    (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(2))
diff --git a/src/java.desktop/share/native/liblcms/lcms2_internal.h b/src/java.desktop/share/native/liblcms/lcms2_internal.h
index 75973edad0d..d14c0dd823e 100644
--- a/src/java.desktop/share/native/liblcms/lcms2_internal.h
+++ b/src/java.desktop/share/native/liblcms/lcms2_internal.h
@@ -27,9 +27,10 @@
 // However, the following notice accompanied the original version of this
 // file:
 //
+
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
@@ -467,7 +468,7 @@ cmsBool  _cmsRegisterTransformPlugin(cmsContext ContextID, cmsPluginBase* Plugin
 // Mutex
 cmsBool _cmsRegisterMutexPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
 
-// Paralellization
+// Parallelization
 cmsBool _cmsRegisterParallelizationPlugin(cmsContext ContextID, cmsPluginBase* Plugin);
 
 // ---------------------------------------------------------------------------------------------------------
@@ -1000,7 +1001,7 @@ cmsBool           _cmsReadCHAD(cmsMAT3* Dest, cmsHPROFILE hProfile);
 
 // Link several profiles to obtain a single LUT modelling the whole color transform. Intents, Black point
 // compensation and Adaptation parameters may vary across profiles. BPC and Adaptation refers to the PCS
-// after the profile. I.e, BPC[0] refers to connexion between profile(0) and profile(1)
+// after the profile. I.e, BPC[0] refers to connetion between profile(0) and profile(1)
 cmsPipeline* _cmsLinkProfiles(cmsContext         ContextID,
                               cmsUInt32Number    nProfiles,
                               cmsUInt32Number    TheIntents[],
diff --git a/src/java.desktop/share/native/liblcms/lcms2_plugin.h b/src/java.desktop/share/native/liblcms/lcms2_plugin.h
index e7e7bd1f0ce..bdfc76f6bf5 100644
--- a/src/java.desktop/share/native/liblcms/lcms2_plugin.h
+++ b/src/java.desktop/share/native/liblcms/lcms2_plugin.h
@@ -30,7 +30,7 @@
 //---------------------------------------------------------------------------------
 //
 //  Little Color Management System
-//  Copyright (c) 1998-2023 Marti Maria Saguer
+//  Copyright (c) 1998-2024 Marti Maria Saguer
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the "Software"),
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/CHANGES b/src/java.desktop/share/native/libsplashscreen/libpng/CHANGES
index 441b57ecf1a..834b5e19277 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/CHANGES
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/CHANGES
@@ -6196,6 +6196,61 @@ Version 1.6.43 [February 23, 2024]
     consistency verification and text linting.
   Added version consistency verification to pngtest.c also.
 
+Version 1.6.44 [September 12, 2024]
+  Hardened calculations in chroma handling to prevent overflows, and
+    relaxed a constraint in cHRM validation to accomodate the standard
+    ACES AP1 set of color primaries.
+    (Contributed by John Bowler)
+  Removed the ASM implementation of ARM Neon optimizations and updated
+    the build accordingly. Only the remaining C implementation shall be
+    used from now on, thus ensuring the support of the PAC/BTI security
+    features on ARM64.
+    (Contributed by Ross Burton and John Bowler)
+  Fixed the pickup of the PNG_HARDWARE_OPTIMIZATIONS option in the
+    CMake build on FreeBSD/amd64. This is an important performance fix
+    on this platform.
+  Applied various fixes and improvements to the CMake build.
+    (Contributed by Eric Riff, Benjamin Buch and Erik Scholz)
+  Added fuzzing targets for the simplified read API.
+    (Contributed by Mikhail Khachayants)
+  Fixed a build error involving pngtest.c under a custom config.
+    This was a regression introduced in a code cleanup in libpng-1.6.43.
+    (Contributed by Ben Wagner)
+  Fixed and improved the config files for AppVeyor CI and Travis CI.
+
+Version 1.6.45 [January 7, 2025]
+  Added support for the cICP chunk.
+    (Contributed by Lucas Chollet and John Bowler)
+  Adjusted and improved various checks in colorspace calculations.
+    (Contributed by John Bowler)
+  Rearranged the write order of colorspace chunks for better conformance
+    with the PNG v3 draft specification.
+    (Contributed by John Bowler)
+  Raised the minimum required CMake version from 3.6 to 3.14.
+  Forked off a development branch for libpng version 1.8.
+
+Version 1.6.46 [January 23, 2025]
+  Added support for the mDCV and cLLI chunks.
+    (Contributed by John Bowler)
+  Fixed a build issue affecting C89 compilers.
+    This was a regression introduced in libpng-1.6.45.
+    (Contributed by John Bowler)
+  Added makefile.c89, specifically for testing C89 compilers.
+  Cleaned up contrib/pngminus: corrected an old typo, removed an old
+    workaround, and updated the CMake file.
+
+Version 1.6.47 [February 18, 2025]
+  Modified the behaviour of colorspace chunks in order to adhere
+    to the new precedence rules formulated in the latest draft of
+    the PNG Specification.
+    (Contributed by John Bowler)
+  Fixed a latent bug in `png_write_iCCP`.
+    This would have been a read-beyond-end-of-malloc vulnerability,
+    introduced early in the libpng-1.6.0 development, yet (fortunately!)
+    it was inaccessible before the above-mentioned modification of the
+    colorspace precedence rules, due to pre-existing colorspace checks.
+    (Reported by Bob Friesenhahn; fixed by John Bowler)
+
 Send comments/corrections/commendations to png-mng-implement at lists.sf.net.
 Subscription is required; visit
 https://lists.sourceforge.net/lists/listinfo/png-mng-implement
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/LICENSE b/src/java.desktop/share/native/libsplashscreen/libpng/LICENSE
index 25f298f0fcf..ea6df986cb6 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/LICENSE
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/LICENSE
@@ -4,8 +4,8 @@ COPYRIGHT NOTICE, DISCLAIMER, and LICENSE
 PNG Reference Library License version 2
 ---------------------------------------
 
- * Copyright (c) 1995-2024 The PNG Reference Library Authors.
- * Copyright (c) 2018-2024 Cosmin Truta.
+ * Copyright (c) 1995-2025 The PNG Reference Library Authors.
+ * Copyright (c) 2018-2025 Cosmin Truta.
  * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
  * Copyright (c) 1996-1997 Andreas Dilger.
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/README b/src/java.desktop/share/native/libsplashscreen/libpng/README
index a6ca3ae9f94..57952fb215a 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/README
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/README
@@ -1,4 +1,4 @@
-README for libpng version 1.6.43
+README for libpng version 1.6.47
 ================================
 
 See the note about version numbers near the top of `png.h`.
@@ -157,8 +157,6 @@ Files included in this distribution
                           "PNG: The Definitive Guide" by Greg Roelofs,
                           O'Reilly, 1999
         libtests/     =>  Test programs
-        oss-fuzz/     =>  Files used by the OSS-Fuzz project for fuzz-testing
-                          libpng
         pngexif/      =>  Program to inspect the EXIF information in PNG files
         pngminim/     =>  Minimal decoder, encoder, and progressive decoder
                           programs demonstrating the use of pngusr.dfa
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/png.c b/src/java.desktop/share/native/libsplashscreen/libpng/png.c
index 232dff876c7..7b6de2f8ec3 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/png.c
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/png.c
@@ -29,7 +29,7 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * Copyright (c) 2018-2024 Cosmin Truta
+ * Copyright (c) 2018-2025 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -42,7 +42,34 @@
 #include "pngpriv.h"
 
 /* Generate a compiler error if there is an old png.h in the search path. */
-typedef png_libpng_version_1_6_43 Your_png_h_is_not_version_1_6_43;
+typedef png_libpng_version_1_6_47 Your_png_h_is_not_version_1_6_47;
+
+/* Sanity check the chunks definitions - PNG_KNOWN_CHUNKS from pngpriv.h and the
+ * corresponding macro definitions.  This causes a compile time failure if
+ * something is wrong but generates no code.
+ *
+ * (1) The first check is that the PNG_CHUNK(cHNK, index) 'index' values must
+ * increment from 0 to the last value.
+ */
+#define PNG_CHUNK(cHNK, index) != (index) || ((index)+1)
+
+#if 0 PNG_KNOWN_CHUNKS < 0
+#  error PNG_KNOWN_CHUNKS chunk definitions are not in order
+#endif
+
+#undef PNG_CHUNK
+
+/* (2) The chunk name macros, png_cHNK, must all be valid and defined.  Since
+ * this is a preprocessor test undefined pp-tokens come out as zero and will
+ * fail this test.
+ */
+#define PNG_CHUNK(cHNK, index) !PNG_CHUNK_NAME_VALID(png_ ## cHNK) ||
+
+#if PNG_KNOWN_CHUNKS 0
+#  error png_cHNK not defined for some known cHNK
+#endif
+
+#undef PNG_CHUNK
 
 /* Tells libpng that we have already handled the first "num_bytes" bytes
  * of the PNG file signature.  If the PNG data is embedded into another
@@ -270,21 +297,23 @@ png_create_png_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
     */
    memset(&create_struct, 0, (sizeof create_struct));
 
-   /* Added at libpng-1.2.6 */
 #  ifdef PNG_USER_LIMITS_SUPPORTED
       create_struct.user_width_max = PNG_USER_WIDTH_MAX;
       create_struct.user_height_max = PNG_USER_HEIGHT_MAX;
 
 #     ifdef PNG_USER_CHUNK_CACHE_MAX
-      /* Added at libpng-1.2.43 and 1.4.0 */
       create_struct.user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX;
 #     endif
 
-#     ifdef PNG_USER_CHUNK_MALLOC_MAX
-      /* Added at libpng-1.2.43 and 1.4.1, required only for read but exists
-       * in png_struct regardless.
-       */
+#     if PNG_USER_CHUNK_MALLOC_MAX > 0 /* default to compile-time limit */
       create_struct.user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX;
+
+      /* No compile-time limit, so initialize to the system limit: */
+#     elif defined PNG_MAX_MALLOC_64K /* legacy system limit */
+      create_struct.user_chunk_malloc_max = 65536U;
+
+#     else /* modern system limit SIZE_MAX (C99) */
+      create_struct.user_chunk_malloc_max = PNG_SIZE_MAX;
 #     endif
 #  endif
 
@@ -626,13 +655,6 @@ png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask,
    /* Free any eXIf entry */
    if (((mask & PNG_FREE_EXIF) & info_ptr->free_me) != 0)
    {
-# ifdef PNG_READ_eXIf_SUPPORTED
-      if (info_ptr->eXIf_buf)
-      {
-         png_free(png_ptr, info_ptr->eXIf_buf);
-         info_ptr->eXIf_buf = NULL;
-      }
-# endif
       if (info_ptr->exif)
       {
          png_free(png_ptr, info_ptr->exif);
@@ -822,8 +844,8 @@ png_get_copyright(png_const_structrp png_ptr)
    return PNG_STRING_COPYRIGHT
 #else
    return PNG_STRING_NEWLINE \
-      "libpng version 1.6.43" PNG_STRING_NEWLINE \
-      "Copyright (c) 2018-2024 Cosmin Truta" PNG_STRING_NEWLINE \
+      "libpng version 1.6.47" PNG_STRING_NEWLINE \
+      "Copyright (c) 2018-2025 Cosmin Truta" PNG_STRING_NEWLINE \
       "Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson" \
       PNG_STRING_NEWLINE \
       "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
@@ -1067,210 +1089,132 @@ png_zstream_error(png_structrp png_ptr, int ret)
    }
 }
 
-/* png_convert_size: a PNGAPI but no longer in png.h, so deleted
- * at libpng 1.5.5!
- */
-
-/* Added at libpng version 1.2.34 and 1.4.0 (moved from pngset.c) */
-#ifdef PNG_GAMMA_SUPPORTED /* always set if COLORSPACE */
-static int
-png_colorspace_check_gamma(png_const_structrp png_ptr,
-    png_colorspacerp colorspace, png_fixed_point gAMA, int from)
-   /* This is called to check a new gamma value against an existing one.  The
-    * routine returns false if the new gamma value should not be written.
-    *
-    * 'from' says where the new gamma value comes from:
-    *
-    *    0: the new gamma value is the libpng estimate for an ICC profile
-    *    1: the new gamma value comes from a gAMA chunk
-    *    2: the new gamma value comes from an sRGB chunk
-    */
+#ifdef PNG_COLORSPACE_SUPPORTED
+static png_int_32
+png_fp_add(png_int_32 addend0, png_int_32 addend1, int *error)
 {
-   png_fixed_point gtest;
-
-   if ((colorspace->flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 &&
-       (png_muldiv(>est, colorspace->gamma, PNG_FP_1, gAMA) == 0  ||
-      png_gamma_significant(gtest) != 0))
+   /* Safely add two fixed point values setting an error flag and returning 0.5
+    * on overflow.
+    * IMPLEMENTATION NOTE: ANSI requires signed overflow not to occur, therefore
+    * relying on addition of two positive values producing a negative one is not
+    * safe.
+    */
+   if (addend0 > 0)
    {
-      /* Either this is an sRGB image, in which case the calculated gamma
-       * approximation should match, or this is an image with a profile and the
-       * value libpng calculates for the gamma of the profile does not match the
-       * value recorded in the file.  The former, sRGB, case is an error, the
-       * latter is just a warning.
-       */
-      if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0 || from == 2)
-      {
-         png_chunk_report(png_ptr, "gamma value does not match sRGB",
-             PNG_CHUNK_ERROR);
-         /* Do not overwrite an sRGB value */
-         return from == 2;
-      }
-
-      else /* sRGB tag not involved */
-      {
-         png_chunk_report(png_ptr, "gamma value does not match libpng estimate",
-             PNG_CHUNK_WARNING);
-         return from == 1;
-      }
+      if (0x7fffffff - addend0 >= addend1)
+         return addend0+addend1;
    }
-
-   return 1;
-}
-
-void /* PRIVATE */
-png_colorspace_set_gamma(png_const_structrp png_ptr,
-    png_colorspacerp colorspace, png_fixed_point gAMA)
-{
-   /* Changed in libpng-1.5.4 to limit the values to ensure overflow can't
-    * occur.  Since the fixed point representation is asymmetrical it is
-    * possible for 1/gamma to overflow the limit of 21474 and this means the
-    * gamma value must be at least 5/100000 and hence at most 20000.0.  For
-    * safety the limits here are a little narrower.  The values are 0.00016 to
-    * 6250.0, which are truly ridiculous gamma values (and will produce
-    * displays that are all black or all white.)
-    *
-    * In 1.6.0 this test replaces the ones in pngrutil.c, in the gAMA chunk
-    * handling code, which only required the value to be >0.
-    */
-   png_const_charp errmsg;
-
-   if (gAMA < 16 || gAMA > 625000000)
-      errmsg = "gamma value out of range";
-
-#  ifdef PNG_READ_gAMA_SUPPORTED
-   /* Allow the application to set the gamma value more than once */
-   else if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
-      (colorspace->flags & PNG_COLORSPACE_FROM_gAMA) != 0)
-      errmsg = "duplicate";
-#  endif
-
-   /* Do nothing if the colorspace is already invalid */
-   else if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0)
-      return;
-
-   else
+   else if (addend0 < 0)
    {
-      if (png_colorspace_check_gamma(png_ptr, colorspace, gAMA,
-          1/*from gAMA*/) != 0)
-      {
-         /* Store this gamma value. */
-         colorspace->gamma = gAMA;
-         colorspace->flags |=
-            (PNG_COLORSPACE_HAVE_GAMMA | PNG_COLORSPACE_FROM_gAMA);
-      }
-
-      /* At present if the check_gamma test fails the gamma of the colorspace is
-       * not updated however the colorspace is not invalidated.  This
-       * corresponds to the case where the existing gamma comes from an sRGB
-       * chunk or profile.  An error message has already been output.
-       */
-      return;
+      if (-0x7fffffff - addend0 <= addend1)
+         return addend0+addend1;
    }
+   else
+      return addend1;
 
-   /* Error exit - errmsg has been set. */
-   colorspace->flags |= PNG_COLORSPACE_INVALID;
-   png_chunk_report(png_ptr, errmsg, PNG_CHUNK_WRITE_ERROR);
+   *error = 1;
+   return PNG_FP_1/2;
 }
 
-void /* PRIVATE */
-png_colorspace_sync_info(png_const_structrp png_ptr, png_inforp info_ptr)
+static png_int_32
+png_fp_sub(png_int_32 addend0, png_int_32 addend1, int *error)
 {
-   if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) != 0)
+   /* As above but calculate addend0-addend1. */
+   if (addend1 > 0)
    {
-      /* Everything is invalid */
-      info_ptr->valid &= ~(PNG_INFO_gAMA|PNG_INFO_cHRM|PNG_INFO_sRGB|
-         PNG_INFO_iCCP);
-
-#     ifdef PNG_COLORSPACE_SUPPORTED
-      /* Clean up the iCCP profile now if it won't be used. */
-      png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, -1/*not used*/);
-#     else
-      PNG_UNUSED(png_ptr)
-#     endif
+      if (-0x7fffffff + addend1 <= addend0)
+         return addend0-addend1;
    }
-
-   else
+   else if (addend1 < 0)
    {
-#     ifdef PNG_COLORSPACE_SUPPORTED
-      /* Leave the INFO_iCCP flag set if the pngset.c code has already set
-       * it; this allows a PNG to contain a profile which matches sRGB and
-       * yet still have that profile retrievable by the application.
-       */
-      if ((info_ptr->colorspace.flags & PNG_COLORSPACE_MATCHES_sRGB) != 0)
-         info_ptr->valid |= PNG_INFO_sRGB;
-
-      else
-         info_ptr->valid &= ~PNG_INFO_sRGB;
-
-      if ((info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
-         info_ptr->valid |= PNG_INFO_cHRM;
-
-      else
-         info_ptr->valid &= ~PNG_INFO_cHRM;
-#     endif
-
-      if ((info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) != 0)
-         info_ptr->valid |= PNG_INFO_gAMA;
-
-      else
-         info_ptr->valid &= ~PNG_INFO_gAMA;
+      if (0x7fffffff + addend1 >= addend0)
+         return addend0-addend1;
    }
+   else
+      return addend0;
+
+   *error = 1;
+   return PNG_FP_1/2;
 }
 
-#ifdef PNG_READ_SUPPORTED
-void /* PRIVATE */
-png_colorspace_sync(png_const_structrp png_ptr, png_inforp info_ptr)
+static int
+png_safe_add(png_int_32 *addend0_and_result, png_int_32 addend1,
+      png_int_32 addend2)
 {
-   if (info_ptr == NULL) /* reduce code size; check here not in the caller */
-      return;
-
-   info_ptr->colorspace = png_ptr->colorspace;
-   png_colorspace_sync_info(png_ptr, info_ptr);
+   /* Safely add three integers.  Returns 0 on success, 1 on overflow.  Does not
+    * set the result on overflow.
+    */
+   int error = 0;
+   int result = png_fp_add(*addend0_and_result,
+                           png_fp_add(addend1, addend2, &error),
+                           &error);
+   if (!error) *addend0_and_result = result;
+   return error;
 }
-#endif
-#endif /* GAMMA */
 
-#ifdef PNG_COLORSPACE_SUPPORTED
 /* Added at libpng-1.5.5 to support read and write of true CIEXYZ values for
  * cHRM, as opposed to using chromaticities.  These internal APIs return
  * non-zero on a parameter error.  The X, Y and Z values are required to be
  * positive and less than 1.0.
  */
-static int
+int /* PRIVATE */
 png_xy_from_XYZ(png_xy *xy, const png_XYZ *XYZ)
 {
-   png_int_32 d, dwhite, whiteX, whiteY;
+   /* NOTE: returns 0 on success, 1 means error. */
+   png_int_32 d, dred, dgreen, dblue, dwhite, whiteX, whiteY;
 
-   d = XYZ->red_X + XYZ->red_Y + XYZ->red_Z;
-   if (png_muldiv(&xy->redx, XYZ->red_X, PNG_FP_1, d) == 0)
+   /* 'd' in each of the blocks below is just X+Y+Z for each component,
+    * x, y and z are X,Y,Z/(X+Y+Z).
+    */
+   d = XYZ->red_X;
+   if (png_safe_add(&d, XYZ->red_Y, XYZ->red_Z))
       return 1;
-   if (png_muldiv(&xy->redy, XYZ->red_Y, PNG_FP_1, d) == 0)
+   dred = d;
+   if (png_muldiv(&xy->redx, XYZ->red_X, PNG_FP_1, dred) == 0)
+      return 1;
+   if (png_muldiv(&xy->redy, XYZ->red_Y, PNG_FP_1, dred) == 0)
       return 1;
-   dwhite = d;
-   whiteX = XYZ->red_X;
-   whiteY = XYZ->red_Y;
 
-   d = XYZ->green_X + XYZ->green_Y + XYZ->green_Z;
-   if (png_muldiv(&xy->greenx, XYZ->green_X, PNG_FP_1, d) == 0)
+   d = XYZ->green_X;
+   if (png_safe_add(&d, XYZ->green_Y, XYZ->green_Z))
       return 1;
-   if (png_muldiv(&xy->greeny, XYZ->green_Y, PNG_FP_1, d) == 0)
+   dgreen = d;
+   if (png_muldiv(&xy->greenx, XYZ->green_X, PNG_FP_1, dgreen) == 0)
+      return 1;
+   if (png_muldiv(&xy->greeny, XYZ->green_Y, PNG_FP_1, dgreen) == 0)
       return 1;
-   dwhite += d;
-   whiteX += XYZ->green_X;
-   whiteY += XYZ->green_Y;
 
-   d = XYZ->blue_X + XYZ->blue_Y + XYZ->blue_Z;
-   if (png_muldiv(&xy->bluex, XYZ->blue_X, PNG_FP_1, d) == 0)
+   d = XYZ->blue_X;
+   if (png_safe_add(&d, XYZ->blue_Y, XYZ->blue_Z))
+      return 1;
+   dblue = d;
+   if (png_muldiv(&xy->bluex, XYZ->blue_X, PNG_FP_1, dblue) == 0)
       return 1;
-   if (png_muldiv(&xy->bluey, XYZ->blue_Y, PNG_FP_1, d) == 0)
+   if (png_muldiv(&xy->bluey, XYZ->blue_Y, PNG_FP_1, dblue) == 0)
       return 1;
-   dwhite += d;
-   whiteX += XYZ->blue_X;
-   whiteY += XYZ->blue_Y;
 
-   /* The reference white is simply the sum of the end-point (X,Y,Z) vectors,
-    * thus:
+   /* The reference white is simply the sum of the end-point (X,Y,Z) vectors so
+    * the fillowing calculates (X+Y+Z) of the reference white (media white,
+    * encoding white) itself:
     */
+   d = dblue;
+   if (png_safe_add(&d, dred, dgreen))
+      return 1;
+   dwhite = d;
+
+   /* Find the white X,Y values from the sum of the red, green and blue X,Y
+    * values.
+    */
+   d = XYZ->red_X;
+   if (png_safe_add(&d, XYZ->green_X, XYZ->blue_X))
+      return 1;
+   whiteX = d;
+
+   d = XYZ->red_Y;
+   if (png_safe_add(&d, XYZ->green_Y, XYZ->blue_Y))
+      return 1;
+   whiteY = d;
+
    if (png_muldiv(&xy->whitex, whiteX, PNG_FP_1, dwhite) == 0)
       return 1;
    if (png_muldiv(&xy->whitey, whiteY, PNG_FP_1, dwhite) == 0)
@@ -1279,9 +1223,10 @@ png_xy_from_XYZ(png_xy *xy, const png_XYZ *XYZ)
    return 0;
 }
 
-static int
+int /* PRIVATE */
 png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy)
 {
+   /* NOTE: returns 0 on success, 1 means error. */
    png_fixed_point red_inverse, green_inverse, blue_scale;
    png_fixed_point left, right, denominator;
 
@@ -1289,15 +1234,24 @@ png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy)
     * have end points with 0 tristimulus values (these are impossible end
     * points, but they are used to cover the possible colors).  We check
     * xy->whitey against 5, not 0, to avoid a possible integer overflow.
+    *
+    * The limits here will *not* accept ACES AP0, where bluey is -7700
+    * (-0.0770) because the PNG spec itself requires the xy values to be
+    * unsigned.  whitey is also required to be 5 or more to avoid overflow.
+    *
+    * Instead the upper limits have been relaxed to accomodate ACES AP1 where
+    * redz ends up as -600 (-0.006).  ProPhotoRGB was already "in range."
+    * The new limit accomodates the AP0 and AP1 ranges for z but not AP0 redy.
     */
-   if (xy->redx   < 0 || xy->redx > PNG_FP_1) return 1;
-   if (xy->redy   < 0 || xy->redy > PNG_FP_1-xy->redx) return 1;
-   if (xy->greenx < 0 || xy->greenx > PNG_FP_1) return 1;
-   if (xy->greeny < 0 || xy->greeny > PNG_FP_1-xy->greenx) return 1;
-   if (xy->bluex  < 0 || xy->bluex > PNG_FP_1) return 1;
-   if (xy->bluey  < 0 || xy->bluey > PNG_FP_1-xy->bluex) return 1;
-   if (xy->whitex < 0 || xy->whitex > PNG_FP_1) return 1;
-   if (xy->whitey < 5 || xy->whitey > PNG_FP_1-xy->whitex) return 1;
+   const png_fixed_point fpLimit = PNG_FP_1+(PNG_FP_1/10);
+   if (xy->redx   < 0 || xy->redx > fpLimit) return 1;
+   if (xy->redy   < 0 || xy->redy > fpLimit-xy->redx) return 1;
+   if (xy->greenx < 0 || xy->greenx > fpLimit) return 1;
+   if (xy->greeny < 0 || xy->greeny > fpLimit-xy->greenx) return 1;
+   if (xy->bluex  < 0 || xy->bluex > fpLimit) return 1;
+   if (xy->bluey  < 0 || xy->bluey > fpLimit-xy->bluex) return 1;
+   if (xy->whitex < 0 || xy->whitex > fpLimit) return 1;
+   if (xy->whitey < 5 || xy->whitey > fpLimit-xy->whitex) return 1;
 
    /* The reverse calculation is more difficult because the original tristimulus
     * value had 9 independent values (red,green,blue)x(X,Y,Z) however only 8
@@ -1442,18 +1396,23 @@ png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy)
     *  (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x)
     *
     * Accuracy:
-    * The input values have 5 decimal digits of accuracy.  The values are all in
-    * the range 0 < value < 1, so simple products are in the same range but may
-    * need up to 10 decimal digits to preserve the original precision and avoid
-    * underflow.  Because we are using a 32-bit signed representation we cannot
-    * match this; the best is a little over 9 decimal digits, less than 10.
+    * The input values have 5 decimal digits of accuracy.
+    *
+    * In the previous implementation the values were all in the range 0 < value
+    * < 1, so simple products are in the same range but may need up to 10
+    * decimal digits to preserve the original precision and avoid underflow.
+    * Because we are using a 32-bit signed representation we cannot match this;
+    * the best is a little over 9 decimal digits, less than 10.
+    *
+    * This range has now been extended to allow values up to 1.1, or 110,000 in
+    * fixed point.
     *
     * The approach used here is to preserve the maximum precision within the
     * signed representation.  Because the red-scale calculation above uses the
-    * difference between two products of values that must be in the range -1..+1
-    * it is sufficient to divide the product by 7; ceil(100,000/32767*2).  The
-    * factor is irrelevant in the calculation because it is applied to both
-    * numerator and denominator.
+    * difference between two products of values that must be in the range
+    * -1.1..+1.1 it is sufficient to divide the product by 8;
+    * ceil(121,000/32767*2).  The factor is irrelevant in the calculation
+    * because it is applied to both numerator and denominator.
     *
     * Note that the values of the differences of the products of the
     * chromaticities in the above equations tend to be small, for example for
@@ -1475,49 +1434,64 @@ png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy)
     *  Adobe Wide Gamut RGB
     *    0.258728243040113 0.724682314948566 0.016589442011321
     */
-   /* By the argument, above overflow should be impossible here. The return
-    * value of 2 indicates an internal error to the caller.
-    */
-   if (png_muldiv(&left, xy->greenx-xy->bluex, xy->redy - xy->bluey, 7) == 0)
-      return 2;
-   if (png_muldiv(&right, xy->greeny-xy->bluey, xy->redx - xy->bluex, 7) == 0)
-      return 2;
-   denominator = left - right;
-
-   /* Now find the red numerator. */
-   if (png_muldiv(&left, xy->greenx-xy->bluex, xy->whitey-xy->bluey, 7) == 0)
-      return 2;
-   if (png_muldiv(&right, xy->greeny-xy->bluey, xy->whitex-xy->bluex, 7) == 0)
-      return 2;
-
-   /* Overflow is possible here and it indicates an extreme set of PNG cHRM
-    * chunk values.  This calculation actually returns the reciprocal of the
-    * scale value because this allows us to delay the multiplication of white-y
-    * into the denominator, which tends to produce a small number.
-    */
-   if (png_muldiv(&red_inverse, xy->whitey, denominator, left-right) == 0 ||
-       red_inverse <= xy->whitey /* r+g+b scales = white scale */)
-      return 1;
+   {
+      int error = 0;
 
-   /* Similarly for green_inverse: */
-   if (png_muldiv(&left, xy->redy-xy->bluey, xy->whitex-xy->bluex, 7) == 0)
-      return 2;
-   if (png_muldiv(&right, xy->redx-xy->bluex, xy->whitey-xy->bluey, 7) == 0)
-      return 2;
-   if (png_muldiv(&green_inverse, xy->whitey, denominator, left-right) == 0 ||
-       green_inverse <= xy->whitey)
-      return 1;
+      /* By the argument above overflow should be impossible here, however the
+       * code now simply returns a failure code.  The xy subtracts in the
+       * arguments to png_muldiv are *not* checked for overflow because the
+       * checks at the start guarantee they are in the range 0..110000 and
+       * png_fixed_point is a 32-bit signed number.
+       */
+      if (png_muldiv(&left, xy->greenx-xy->bluex, xy->redy - xy->bluey, 8) == 0)
+         return 1;
+      if (png_muldiv(&right, xy->greeny-xy->bluey, xy->redx - xy->bluex, 8) ==
+            0)
+         return 1;
+      denominator = png_fp_sub(left, right, &error);
+      if (error) return 1;
 
-   /* And the blue scale, the checks above guarantee this can't overflow but it
-    * can still produce 0 for extreme cHRM values.
-    */
-   blue_scale = png_reciprocal(xy->whitey) - png_reciprocal(red_inverse) -
-       png_reciprocal(green_inverse);
-   if (blue_scale <= 0)
-      return 1;
+      /* Now find the red numerator. */
+      if (png_muldiv(&left, xy->greenx-xy->bluex, xy->whitey-xy->bluey, 8) == 0)
+         return 1;
+      if (png_muldiv(&right, xy->greeny-xy->bluey, xy->whitex-xy->bluex, 8) ==
+            0)
+         return 1;
 
+      /* Overflow is possible here and it indicates an extreme set of PNG cHRM
+       * chunk values.  This calculation actually returns the reciprocal of the
+       * scale value because this allows us to delay the multiplication of
+       * white-y into the denominator, which tends to produce a small number.
+       */
+      if (png_muldiv(&red_inverse, xy->whitey, denominator,
+                     png_fp_sub(left, right, &error)) == 0 || error ||
+          red_inverse <= xy->whitey /* r+g+b scales = white scale */)
+         return 1;
 
-   /* And fill in the png_XYZ: */
+      /* Similarly for green_inverse: */
+      if (png_muldiv(&left, xy->redy-xy->bluey, xy->whitex-xy->bluex, 8) == 0)
+         return 1;
+      if (png_muldiv(&right, xy->redx-xy->bluex, xy->whitey-xy->bluey, 8) == 0)
+         return 1;
+      if (png_muldiv(&green_inverse, xy->whitey, denominator,
+                     png_fp_sub(left, right, &error)) == 0 || error ||
+          green_inverse <= xy->whitey)
+         return 1;
+
+      /* And the blue scale, the checks above guarantee this can't overflow but
+       * it can still produce 0 for extreme cHRM values.
+       */
+      blue_scale = png_fp_sub(png_fp_sub(png_reciprocal(xy->whitey),
+                                         png_reciprocal(red_inverse), &error),
+                              png_reciprocal(green_inverse), &error);
+      if (error || blue_scale <= 0)
+         return 1;
+   }
+
+   /* And fill in the png_XYZ.  Again the subtracts are safe because of the
+    * checks on the xy values at the start (the subtracts just calculate the
+    * corresponding z values.)
+    */
    if (png_muldiv(&XYZ->red_X, xy->redx, PNG_FP_1, red_inverse) == 0)
       return 1;
    if (png_muldiv(&XYZ->red_Y, xy->redy, PNG_FP_1, red_inverse) == 0)
@@ -1544,250 +1518,9 @@ png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy)
 
    return 0; /*success*/
 }
+#endif /* COLORSPACE */
 
-static int
-png_XYZ_normalize(png_XYZ *XYZ)
-{
-   png_int_32 Y;
-
-   if (XYZ->red_Y < 0 || XYZ->green_Y < 0 || XYZ->blue_Y < 0 ||
-      XYZ->red_X < 0 || XYZ->green_X < 0 || XYZ->blue_X < 0 ||
-      XYZ->red_Z < 0 || XYZ->green_Z < 0 || XYZ->blue_Z < 0)
-      return 1;
-
-   /* Normalize by scaling so the sum of the end-point Y values is PNG_FP_1.
-    * IMPLEMENTATION NOTE: ANSI requires signed overflow not to occur, therefore
-    * relying on addition of two positive values producing a negative one is not
-    * safe.
-    */
-   Y = XYZ->red_Y;
-   if (0x7fffffff - Y < XYZ->green_X)
-      return 1;
-   Y += XYZ->green_Y;
-   if (0x7fffffff - Y < XYZ->blue_X)
-      return 1;
-   Y += XYZ->blue_Y;
-
-   if (Y != PNG_FP_1)
-   {
-      if (png_muldiv(&XYZ->red_X, XYZ->red_X, PNG_FP_1, Y) == 0)
-         return 1;
-      if (png_muldiv(&XYZ->red_Y, XYZ->red_Y, PNG_FP_1, Y) == 0)
-         return 1;
-      if (png_muldiv(&XYZ->red_Z, XYZ->red_Z, PNG_FP_1, Y) == 0)
-         return 1;
-
-      if (png_muldiv(&XYZ->green_X, XYZ->green_X, PNG_FP_1, Y) == 0)
-         return 1;
-      if (png_muldiv(&XYZ->green_Y, XYZ->green_Y, PNG_FP_1, Y) == 0)
-         return 1;
-      if (png_muldiv(&XYZ->green_Z, XYZ->green_Z, PNG_FP_1, Y) == 0)
-         return 1;
-
-      if (png_muldiv(&XYZ->blue_X, XYZ->blue_X, PNG_FP_1, Y) == 0)
-         return 1;
-      if (png_muldiv(&XYZ->blue_Y, XYZ->blue_Y, PNG_FP_1, Y) == 0)
-         return 1;
-      if (png_muldiv(&XYZ->blue_Z, XYZ->blue_Z, PNG_FP_1, Y) == 0)
-         return 1;
-   }
-
-   return 0;
-}
-
-static int
-png_colorspace_endpoints_match(const png_xy *xy1, const png_xy *xy2, int delta)
-{
-   /* Allow an error of +/-0.01 (absolute value) on each chromaticity */
-   if (PNG_OUT_OF_RANGE(xy1->whitex, xy2->whitex,delta) ||
-       PNG_OUT_OF_RANGE(xy1->whitey, xy2->whitey,delta) ||
-       PNG_OUT_OF_RANGE(xy1->redx,   xy2->redx,  delta) ||
-       PNG_OUT_OF_RANGE(xy1->redy,   xy2->redy,  delta) ||
-       PNG_OUT_OF_RANGE(xy1->greenx, xy2->greenx,delta) ||
-       PNG_OUT_OF_RANGE(xy1->greeny, xy2->greeny,delta) ||
-       PNG_OUT_OF_RANGE(xy1->bluex,  xy2->bluex, delta) ||
-       PNG_OUT_OF_RANGE(xy1->bluey,  xy2->bluey, delta))
-      return 0;
-   return 1;
-}
-
-/* Added in libpng-1.6.0, a different check for the validity of a set of cHRM
- * chunk chromaticities.  Earlier checks used to simply look for the overflow
- * condition (where the determinant of the matrix to solve for XYZ ends up zero
- * because the chromaticity values are not all distinct.)  Despite this it is
- * theoretically possible to produce chromaticities that are apparently valid
- * but that rapidly degrade to invalid, potentially crashing, sets because of
- * arithmetic inaccuracies when calculations are performed on them.  The new
- * check is to round-trip xy -> XYZ -> xy and then check that the result is
- * within a small percentage of the original.
- */
-static int
-png_colorspace_check_xy(png_XYZ *XYZ, const png_xy *xy)
-{
-   int result;
-   png_xy xy_test;
-
-   /* As a side-effect this routine also returns the XYZ endpoints. */
-   result = png_XYZ_from_xy(XYZ, xy);
-   if (result != 0)
-      return result;
-
-   result = png_xy_from_XYZ(&xy_test, XYZ);
-   if (result != 0)
-      return result;
-
-   if (png_colorspace_endpoints_match(xy, &xy_test,
-       5/*actually, the math is pretty accurate*/) != 0)
-      return 0;
-
-   /* Too much slip */
-   return 1;
-}
-
-/* This is the check going the other way.  The XYZ is modified to normalize it
- * (another side-effect) and the xy chromaticities are returned.
- */
-static int
-png_colorspace_check_XYZ(png_xy *xy, png_XYZ *XYZ)
-{
-   int result;
-   png_XYZ XYZtemp;
-
-   result = png_XYZ_normalize(XYZ);
-   if (result != 0)
-      return result;
-
-   result = png_xy_from_XYZ(xy, XYZ);
-   if (result != 0)
-      return result;
-
-   XYZtemp = *XYZ;
-   return png_colorspace_check_xy(&XYZtemp, xy);
-}
-
-/* Used to check for an endpoint match against sRGB */
-static const png_xy sRGB_xy = /* From ITU-R BT.709-3 */
-{
-   /* color      x       y */
-   /* red   */ 64000, 33000,
-   /* green */ 30000, 60000,
-   /* blue  */ 15000,  6000,
-   /* white */ 31270, 32900
-};
-
-static int
-png_colorspace_set_xy_and_XYZ(png_const_structrp png_ptr,
-    png_colorspacerp colorspace, const png_xy *xy, const png_XYZ *XYZ,
-    int preferred)
-{
-   if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0)
-      return 0;
-
-   /* The consistency check is performed on the chromaticities; this factors out
-    * variations because of the normalization (or not) of the end point Y
-    * values.
-    */
-   if (preferred < 2 &&
-       (colorspace->flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
-   {
-      /* The end points must be reasonably close to any we already have.  The
-       * following allows an error of up to +/-.001
-       */
-      if (png_colorspace_endpoints_match(xy, &colorspace->end_points_xy,
-          100) == 0)
-      {
-         colorspace->flags |= PNG_COLORSPACE_INVALID;
-         png_benign_error(png_ptr, "inconsistent chromaticities");
-         return 0; /* failed */
-      }
-
-      /* Only overwrite with preferred values */
-      if (preferred == 0)
-         return 1; /* ok, but no change */
-   }
-
-   colorspace->end_points_xy = *xy;
-   colorspace->end_points_XYZ = *XYZ;
-   colorspace->flags |= PNG_COLORSPACE_HAVE_ENDPOINTS;
-
-   /* The end points are normally quoted to two decimal digits, so allow +/-0.01
-    * on this test.
-    */
-   if (png_colorspace_endpoints_match(xy, &sRGB_xy, 1000) != 0)
-      colorspace->flags |= PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB;
-
-   else
-      colorspace->flags &= PNG_COLORSPACE_CANCEL(
-         PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB);
-
-   return 2; /* ok and changed */
-}
-
-int /* PRIVATE */
-png_colorspace_set_chromaticities(png_const_structrp png_ptr,
-    png_colorspacerp colorspace, const png_xy *xy, int preferred)
-{
-   /* We must check the end points to ensure they are reasonable - in the past
-    * color management systems have crashed as a result of getting bogus
-    * colorant values, while this isn't the fault of libpng it is the
-    * responsibility of libpng because PNG carries the bomb and libpng is in a
-    * position to protect against it.
-    */
-   png_XYZ XYZ;
-
-   switch (png_colorspace_check_xy(&XYZ, xy))
-   {
-      case 0: /* success */
-         return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, xy, &XYZ,
-             preferred);
-
-      case 1:
-         /* We can't invert the chromaticities so we can't produce value XYZ
-          * values.  Likely as not a color management system will fail too.
-          */
-         colorspace->flags |= PNG_COLORSPACE_INVALID;
-         png_benign_error(png_ptr, "invalid chromaticities");
-         break;
-
-      default:
-         /* libpng is broken; this should be a warning but if it happens we
-          * want error reports so for the moment it is an error.
-          */
-         colorspace->flags |= PNG_COLORSPACE_INVALID;
-         png_error(png_ptr, "internal error checking chromaticities");
-   }
-
-   return 0; /* failed */
-}
-
-int /* PRIVATE */
-png_colorspace_set_endpoints(png_const_structrp png_ptr,
-    png_colorspacerp colorspace, const png_XYZ *XYZ_in, int preferred)
-{
-   png_XYZ XYZ = *XYZ_in;
-   png_xy xy;
-
-   switch (png_colorspace_check_XYZ(&xy, &XYZ))
-   {
-      case 0:
-         return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, &xy, &XYZ,
-             preferred);
-
-      case 1:
-         /* End points are invalid. */
-         colorspace->flags |= PNG_COLORSPACE_INVALID;
-         png_benign_error(png_ptr, "invalid end points");
-         break;
-
-      default:
-         colorspace->flags |= PNG_COLORSPACE_INVALID;
-         png_error(png_ptr, "internal error checking chromaticities");
-   }
-
-   return 0; /* failed */
-}
-
-#if defined(PNG_sRGB_SUPPORTED) || defined(PNG_iCCP_SUPPORTED)
+#ifdef PNG_iCCP_SUPPORTED
 /* Error message generation */
 static char
 png_icc_tag_char(png_uint_32 byte)
@@ -1827,15 +1560,12 @@ is_ICC_signature(png_alloc_size_t it)
 }
 
 static int
-png_icc_profile_error(png_const_structrp png_ptr, png_colorspacerp colorspace,
-    png_const_charp name, png_alloc_size_t value, png_const_charp reason)
+png_icc_profile_error(png_const_structrp png_ptr, png_const_charp name,
+   png_alloc_size_t value, png_const_charp reason)
 {
    size_t pos;
    char message[196]; /* see below for calculation */
 
-   if (colorspace != NULL)
-      colorspace->flags |= PNG_COLORSPACE_INVALID;
-
    pos = png_safecat(message, (sizeof message), 0, "profile '"); /* 9 chars */
    pos = png_safecat(message, pos+79, pos, name); /* Truncate to 79 chars */
    pos = png_safecat(message, (sizeof message), pos, "': "); /* +2 = 90 */
@@ -1862,109 +1592,13 @@ png_icc_profile_error(png_const_structrp png_ptr, png_colorspacerp colorspace,
    pos = png_safecat(message, (sizeof message), pos, reason);
    PNG_UNUSED(pos)
 
-   /* This is recoverable, but make it unconditionally an app_error on write to
-    * avoid writing invalid ICC profiles into PNG files (i.e., we handle them
-    * on read, with a warning, but on write unless the app turns off
-    * application errors the PNG won't be written.)
-    */
-   png_chunk_report(png_ptr, message,
-       (colorspace != NULL) ? PNG_CHUNK_ERROR : PNG_CHUNK_WRITE_ERROR);
+   png_chunk_benign_error(png_ptr, message);
 
    return 0;
 }
-#endif /* sRGB || iCCP */
-
-#ifdef PNG_sRGB_SUPPORTED
-int /* PRIVATE */
-png_colorspace_set_sRGB(png_const_structrp png_ptr, png_colorspacerp colorspace,
-    int intent)
-{
-   /* sRGB sets known gamma, end points and (from the chunk) intent. */
-   /* IMPORTANT: these are not necessarily the values found in an ICC profile
-    * because ICC profiles store values adapted to a D50 environment; it is
-    * expected that the ICC profile mediaWhitePointTag will be D50; see the
-    * checks and code elsewhere to understand this better.
-    *
-    * These XYZ values, which are accurate to 5dp, produce rgb to gray
-    * coefficients of (6968,23435,2366), which are reduced (because they add up
-    * to 32769 not 32768) to (6968,23434,2366).  These are the values that
-    * libpng has traditionally used (and are the best values given the 15bit
-    * algorithm used by the rgb to gray code.)
-    */
-   static const png_XYZ sRGB_XYZ = /* D65 XYZ (*not* the D50 adapted values!) */
-   {
-      /* color      X      Y      Z */
-      /* red   */ 41239, 21264,  1933,
-      /* green */ 35758, 71517, 11919,
-      /* blue  */ 18048,  7219, 95053
-   };
-
-   /* Do nothing if the colorspace is already invalidated. */
-   if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0)
-      return 0;
-
-   /* Check the intent, then check for existing settings.  It is valid for the
-    * PNG file to have cHRM or gAMA chunks along with sRGB, but the values must
-    * be consistent with the correct values.  If, however, this function is
-    * called below because an iCCP chunk matches sRGB then it is quite
-    * conceivable that an older app recorded incorrect gAMA and cHRM because of
-    * an incorrect calculation based on the values in the profile - this does
-    * *not* invalidate the profile (though it still produces an error, which can
-    * be ignored.)
-    */
-   if (intent < 0 || intent >= PNG_sRGB_INTENT_LAST)
-      return png_icc_profile_error(png_ptr, colorspace, "sRGB",
-          (png_alloc_size_t)intent, "invalid sRGB rendering intent");
-
-   if ((colorspace->flags & PNG_COLORSPACE_HAVE_INTENT) != 0 &&
-       colorspace->rendering_intent != intent)
-      return png_icc_profile_error(png_ptr, colorspace, "sRGB",
-         (png_alloc_size_t)intent, "inconsistent rendering intents");
-
-   if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0)
-   {
-      png_benign_error(png_ptr, "duplicate sRGB information ignored");
-      return 0;
-   }
-
-   /* If the standard sRGB cHRM chunk does not match the one from the PNG file
-    * warn but overwrite the value with the correct one.
-    */
-   if ((colorspace->flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0 &&
-       !png_colorspace_endpoints_match(&sRGB_xy, &colorspace->end_points_xy,
-       100))
-      png_chunk_report(png_ptr, "cHRM chunk does not match sRGB",
-         PNG_CHUNK_ERROR);
-
-   /* This check is just done for the error reporting - the routine always
-    * returns true when the 'from' argument corresponds to sRGB (2).
-    */
-   (void)png_colorspace_check_gamma(png_ptr, colorspace, PNG_GAMMA_sRGB_INVERSE,
-       2/*from sRGB*/);
-
-   /* intent: bugs in GCC force 'int' to be used as the parameter type. */
-   colorspace->rendering_intent = (png_uint_16)intent;
-   colorspace->flags |= PNG_COLORSPACE_HAVE_INTENT;
-
-   /* endpoints */
-   colorspace->end_points_xy = sRGB_xy;
-   colorspace->end_points_XYZ = sRGB_XYZ;
-   colorspace->flags |=
-      (PNG_COLORSPACE_HAVE_ENDPOINTS|PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB);
-
-   /* gamma */
-   colorspace->gamma = PNG_GAMMA_sRGB_INVERSE;
-   colorspace->flags |= PNG_COLORSPACE_HAVE_GAMMA;
-
-   /* Finally record that we have an sRGB profile */
-   colorspace->flags |=
-      (PNG_COLORSPACE_MATCHES_sRGB|PNG_COLORSPACE_FROM_sRGB);
-
-   return 1; /* set */
-}
-#endif /* sRGB */
+#endif /* iCCP */
 
-#ifdef PNG_iCCP_SUPPORTED
+#ifdef PNG_READ_iCCP_SUPPORTED
 /* Encoded value of D50 as an ICC XYZNumber.  From the ICC 2010 spec the value
  * is XYZ(0.9642,1.0,0.8249), which scales to:
  *
@@ -1974,21 +1608,19 @@ static const png_byte D50_nCIEXYZ[12] =
    { 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d };
 
 static int /* bool */
-icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace,
-    png_const_charp name, png_uint_32 profile_length)
+icc_check_length(png_const_structrp png_ptr, png_const_charp name,
+   png_uint_32 profile_length)
 {
    if (profile_length < 132)
-      return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
-          "too short");
+      return png_icc_profile_error(png_ptr, name, profile_length, "too short");
    return 1;
 }
 
-#ifdef PNG_READ_iCCP_SUPPORTED
 int /* PRIVATE */
-png_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace,
-    png_const_charp name, png_uint_32 profile_length)
+png_icc_check_length(png_const_structrp png_ptr, png_const_charp name,
+   png_uint_32 profile_length)
 {
-   if (!icc_check_length(png_ptr, colorspace, name, profile_length))
+   if (!icc_check_length(png_ptr, name, profile_length))
       return 0;
 
    /* This needs to be here because the 'normal' check is in
@@ -1997,30 +1629,17 @@ png_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace,
     * the caller supplies the profile buffer so libpng doesn't allocate it.  See
     * the call to icc_check_length below (the write case).
     */
-#  ifdef PNG_SET_USER_LIMITS_SUPPORTED
-      else if (png_ptr->user_chunk_malloc_max > 0 &&
-               png_ptr->user_chunk_malloc_max < profile_length)
-         return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
-             "exceeds application limits");
-#  elif PNG_USER_CHUNK_MALLOC_MAX > 0
-      else if (PNG_USER_CHUNK_MALLOC_MAX < profile_length)
-         return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
-             "exceeds libpng limits");
-#  else /* !SET_USER_LIMITS */
-      /* This will get compiled out on all 32-bit and better systems. */
-      else if (PNG_SIZE_MAX < profile_length)
-         return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
-             "exceeds system limits");
-#  endif /* !SET_USER_LIMITS */
+   if (profile_length > png_chunk_max(png_ptr))
+      return png_icc_profile_error(png_ptr, name, profile_length,
+            "profile too long");
 
    return 1;
 }
-#endif /* READ_iCCP */
 
 int /* PRIVATE */
-png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace,
-    png_const_charp name, png_uint_32 profile_length,
-    png_const_bytep profile/* first 132 bytes only */, int color_type)
+png_icc_check_header(png_const_structrp png_ptr, png_const_charp name,
+   png_uint_32 profile_length,
+   png_const_bytep profile/* first 132 bytes only */, int color_type)
 {
    png_uint_32 temp;
 
@@ -2031,18 +1650,18 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace,
     */
    temp = png_get_uint_32(profile);
    if (temp != profile_length)
-      return png_icc_profile_error(png_ptr, colorspace, name, temp,
+      return png_icc_profile_error(png_ptr, name, temp,
           "length does not match profile");
 
    temp = (png_uint_32) (*(profile+8));
    if (temp > 3 && (profile_length & 3))
-      return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
+      return png_icc_profile_error(png_ptr, name, profile_length,
           "invalid length");
 
    temp = png_get_uint_32(profile+128); /* tag count: 12 bytes/tag */
    if (temp > 357913930 || /* (2^32-4-132)/12: maximum possible tag count */
       profile_length < 132+12*temp) /* truncated tag table */
-      return png_icc_profile_error(png_ptr, colorspace, name, temp,
+      return png_icc_profile_error(png_ptr, name, temp,
           "tag count too large");
 
    /* The 'intent' must be valid or we can't store it, ICC limits the intent to
@@ -2050,14 +1669,14 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace,
     */
    temp = png_get_uint_32(profile+64);
    if (temp >= 0xffff) /* The ICC limit */
-      return png_icc_profile_error(png_ptr, colorspace, name, temp,
+      return png_icc_profile_error(png_ptr, name, temp,
           "invalid rendering intent");
 
    /* This is just a warning because the profile may be valid in future
     * versions.
     */
    if (temp >= PNG_sRGB_INTENT_LAST)
-      (void)png_icc_profile_error(png_ptr, NULL, name, temp,
+      (void)png_icc_profile_error(png_ptr, name, temp,
           "intent outside defined range");
 
    /* At this point the tag table can't be checked because it hasn't necessarily
@@ -2074,7 +1693,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace,
     */
    temp = png_get_uint_32(profile+36); /* signature 'ascp' */
    if (temp != 0x61637370)
-      return png_icc_profile_error(png_ptr, colorspace, name, temp,
+      return png_icc_profile_error(png_ptr, name, temp,
           "invalid signature");
 
    /* Currently the PCS illuminant/adopted white point (the computational
@@ -2085,7 +1704,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace,
     * following is just a warning.
     */
    if (memcmp(profile+68, D50_nCIEXYZ, 12) != 0)
-      (void)png_icc_profile_error(png_ptr, NULL, name, 0/*no tag value*/,
+      (void)png_icc_profile_error(png_ptr, name, 0/*no tag value*/,
           "PCS illuminant is not D50");
 
    /* The PNG spec requires this:
@@ -2113,18 +1732,18 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace,
    {
       case 0x52474220: /* 'RGB ' */
          if ((color_type & PNG_COLOR_MASK_COLOR) == 0)
-            return png_icc_profile_error(png_ptr, colorspace, name, temp,
+            return png_icc_profile_error(png_ptr, name, temp,
                 "RGB color space not permitted on grayscale PNG");
          break;
 
       case 0x47524159: /* 'GRAY' */
          if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
-            return png_icc_profile_error(png_ptr, colorspace, name, temp,
+            return png_icc_profile_error(png_ptr, name, temp,
                 "Gray color space not permitted on RGB PNG");
          break;
 
       default:
-         return png_icc_profile_error(png_ptr, colorspace, name, temp,
+         return png_icc_profile_error(png_ptr, name, temp,
              "invalid ICC profile color space");
    }
 
@@ -2149,7 +1768,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace,
 
       case 0x61627374: /* 'abst' */
          /* May not be embedded in an image */
-         return png_icc_profile_error(png_ptr, colorspace, name, temp,
+         return png_icc_profile_error(png_ptr, name, temp,
              "invalid embedded Abstract ICC profile");
 
       case 0x6c696e6b: /* 'link' */
@@ -2159,7 +1778,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace,
           * therefore a DeviceLink profile should not be found embedded in a
           * PNG.
           */
-         return png_icc_profile_error(png_ptr, colorspace, name, temp,
+         return png_icc_profile_error(png_ptr, name, temp,
              "unexpected DeviceLink ICC profile class");
 
       case 0x6e6d636c: /* 'nmcl' */
@@ -2167,7 +1786,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace,
           * contain an AToB0 tag that is open to misinterpretation.  Almost
           * certainly it will fail the tests below.
           */
-         (void)png_icc_profile_error(png_ptr, NULL, name, temp,
+         (void)png_icc_profile_error(png_ptr, name, temp,
              "unexpected NamedColor ICC profile class");
          break;
 
@@ -2177,7 +1796,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace,
           * tag content to ensure they are backward compatible with one of the
           * understood profiles.
           */
-         (void)png_icc_profile_error(png_ptr, NULL, name, temp,
+         (void)png_icc_profile_error(png_ptr, name, temp,
              "unrecognized ICC profile class");
          break;
    }
@@ -2193,7 +1812,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace,
          break;
 
       default:
-         return png_icc_profile_error(png_ptr, colorspace, name, temp,
+         return png_icc_profile_error(png_ptr, name, temp,
              "unexpected ICC PCS encoding");
    }
 
@@ -2201,9 +1820,9 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace,
 }
 
 int /* PRIVATE */
-png_icc_check_tag_table(png_const_structrp png_ptr, png_colorspacerp colorspace,
-    png_const_charp name, png_uint_32 profile_length,
-    png_const_bytep profile /* header plus whole tag table */)
+png_icc_check_tag_table(png_const_structrp png_ptr, png_const_charp name,
+   png_uint_32 profile_length,
+   png_const_bytep profile /* header plus whole tag table */)
 {
    png_uint_32 tag_count = png_get_uint_32(profile+128);
    png_uint_32 itag;
@@ -2229,7 +1848,7 @@ png_icc_check_tag_table(png_const_structrp png_ptr, png_colorspacerp colorspace,
        * profile.
        */
       if (tag_start > profile_length || tag_length > profile_length - tag_start)
-         return png_icc_profile_error(png_ptr, colorspace, name, tag_id,
+         return png_icc_profile_error(png_ptr, name, tag_id,
              "ICC profile tag outside profile");
 
       if ((tag_start & 3) != 0)
@@ -2238,307 +1857,132 @@ png_icc_check_tag_table(png_const_structrp png_ptr, png_colorspacerp colorspace,
           * only a warning here because libpng does not care about the
           * alignment.
           */
-         (void)png_icc_profile_error(png_ptr, NULL, name, tag_id,
+         (void)png_icc_profile_error(png_ptr, name, tag_id,
              "ICC profile tag start not a multiple of 4");
       }
    }
 
    return 1; /* success, maybe with warnings */
 }
+#endif /* READ_iCCP */
 
-#ifdef PNG_sRGB_SUPPORTED
-#if PNG_sRGB_PROFILE_CHECKS >= 0
-/* Information about the known ICC sRGB profiles */
-static const struct
-{
-   png_uint_32 adler, crc, length;
-   png_uint_32 md5[4];
-   png_byte    have_md5;
-   png_byte    is_broken;
-   png_uint_16 intent;
-
-#  define PNG_MD5(a,b,c,d) { a, b, c, d }, (a!=0)||(b!=0)||(c!=0)||(d!=0)
-#  define PNG_ICC_CHECKSUM(adler, crc, md5, intent, broke, date, length, fname)\
-      { adler, crc, length, md5, broke, intent },
-
-} png_sRGB_checks[] =
-{
-   /* This data comes from contrib/tools/checksum-icc run on downloads of
-    * all four ICC sRGB profiles from www.color.org.
-    */
-   /* adler32, crc32, MD5[4], intent, date, length, file-name */
-   PNG_ICC_CHECKSUM(0x0a3fd9f6, 0x3b8772b9,
-       PNG_MD5(0x29f83dde, 0xaff255ae, 0x7842fae4, 0xca83390d), 0, 0,
-       "2009/03/27 21:36:31", 3048, "sRGB_IEC61966-2-1_black_scaled.icc")
-
-   /* ICC sRGB v2 perceptual no black-compensation: */
-   PNG_ICC_CHECKSUM(0x4909e5e1, 0x427ebb21,
-       PNG_MD5(0xc95bd637, 0xe95d8a3b, 0x0df38f99, 0xc1320389), 1, 0,
-       "2009/03/27 21:37:45", 3052, "sRGB_IEC61966-2-1_no_black_scaling.icc")
-
-   PNG_ICC_CHECKSUM(0xfd2144a1, 0x306fd8ae,
-       PNG_MD5(0xfc663378, 0x37e2886b, 0xfd72e983, 0x8228f1b8), 0, 0,
-       "2009/08/10 17:28:01", 60988, "sRGB_v4_ICC_preference_displayclass.icc")
-
-   /* ICC sRGB v4 perceptual */
-   PNG_ICC_CHECKSUM(0x209c35d2, 0xbbef7812,
-       PNG_MD5(0x34562abf, 0x994ccd06, 0x6d2c5721, 0xd0d68c5d), 0, 0,
-       "2007/07/25 00:05:37", 60960, "sRGB_v4_ICC_preference.icc")
-
-   /* The following profiles have no known MD5 checksum. If there is a match
-    * on the (empty) MD5 the other fields are used to attempt a match and
-    * a warning is produced.  The first two of these profiles have a 'cprt' tag
-    * which suggests that they were also made by Hewlett Packard.
-    */
-   PNG_ICC_CHECKSUM(0xa054d762, 0x5d5129ce,
-       PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 0,
-       "2004/07/21 18:57:42", 3024, "sRGB_IEC61966-2-1_noBPC.icc")
-
-   /* This is a 'mntr' (display) profile with a mediaWhitePointTag that does not
-    * match the D50 PCS illuminant in the header (it is in fact the D65 values,
-    * so the white point is recorded as the un-adapted value.)  The profiles
-    * below only differ in one byte - the intent - and are basically the same as
-    * the previous profile except for the mediaWhitePointTag error and a missing
-    * chromaticAdaptationTag.
-    */
-   PNG_ICC_CHECKSUM(0xf784f3fb, 0x182ea552,
-       PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 0, 1/*broken*/,
-       "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 perceptual")
-
-   PNG_ICC_CHECKSUM(0x0398f3fc, 0xf29e526d,
-       PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 1/*broken*/,
-       "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 media-relative")
-};
-
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+#if (defined PNG_READ_mDCV_SUPPORTED) || (defined PNG_READ_cHRM_SUPPORTED)
 static int
-png_compare_ICC_profile_with_sRGB(png_const_structrp png_ptr,
-    png_const_bytep profile, uLong adler)
+have_chromaticities(png_const_structrp png_ptr)
 {
-   /* The quick check is to verify just the MD5 signature and trust the
-    * rest of the data.  Because the profile has already been verified for
-    * correctness this is safe.  png_colorspace_set_sRGB will check the 'intent'
-    * field too, so if the profile has been edited with an intent not defined
-    * by sRGB (but maybe defined by a later ICC specification) the read of
-    * the profile will fail at that point.
+   /* Handle new PNGv3 chunks and the precedence rules to determine whether
+    * png_struct::chromaticities must be processed.  Only required for RGB to
+    * gray.
+    *
+    * mDCV: this is the mastering colour space and it is independent of the
+    *       encoding so it needs to be used regardless of the encoded space.
+    *
+    * cICP: first in priority but not yet implemented - the chromaticities come
+    *       from the 'primaries'.
+    *
+    * iCCP: not supported by libpng (so ignored)
+    *
+    * sRGB: the defaults match sRGB
+    *
+    * cHRM: calculate the coefficients
     */
+#  ifdef PNG_READ_mDCV_SUPPORTED
+      if (png_has_chunk(png_ptr, mDCV))
+         return 1;
+#     define check_chromaticities 1
+#  endif /*mDCV*/
 
-   png_uint_32 length = 0;
-   png_uint_32 intent = 0x10000; /* invalid */
-#if PNG_sRGB_PROFILE_CHECKS > 1
-   uLong crc = 0; /* the value for 0 length data */
-#endif
-   unsigned int i;
-
-#ifdef PNG_SET_OPTION_SUPPORTED
-   /* First see if PNG_SKIP_sRGB_CHECK_PROFILE has been set to "on" */
-   if (((png_ptr->options >> PNG_SKIP_sRGB_CHECK_PROFILE) & 3) ==
-               PNG_OPTION_ON)
-      return 0;
-#endif
-
-   for (i=0; i < (sizeof png_sRGB_checks) / (sizeof png_sRGB_checks[0]); ++i)
-   {
-      if (png_get_uint_32(profile+84) == png_sRGB_checks[i].md5[0] &&
-         png_get_uint_32(profile+88) == png_sRGB_checks[i].md5[1] &&
-         png_get_uint_32(profile+92) == png_sRGB_checks[i].md5[2] &&
-         png_get_uint_32(profile+96) == png_sRGB_checks[i].md5[3])
-      {
-         /* This may be one of the old HP profiles without an MD5, in that
-          * case we can only use the length and Adler32 (note that these
-          * are not used by default if there is an MD5!)
-          */
-#        if PNG_sRGB_PROFILE_CHECKS == 0
-            if (png_sRGB_checks[i].have_md5 != 0)
-               return 1+png_sRGB_checks[i].is_broken;
-#        endif
-
-         /* Profile is unsigned or more checks have been configured in. */
-         if (length == 0)
-         {
-            length = png_get_uint_32(profile);
-            intent = png_get_uint_32(profile+64);
-         }
-
-         /* Length *and* intent must match */
-         if (length == (png_uint_32) png_sRGB_checks[i].length &&
-            intent == (png_uint_32) png_sRGB_checks[i].intent)
-         {
-            /* Now calculate the adler32 if not done already. */
-            if (adler == 0)
-            {
-               adler = adler32(0, NULL, 0);
-               adler = adler32(adler, profile, length);
-            }
-
-            if (adler == png_sRGB_checks[i].adler)
-            {
-               /* These basic checks suggest that the data has not been
-                * modified, but if the check level is more than 1 perform
-                * our own crc32 checksum on the data.
-                */
-#              if PNG_sRGB_PROFILE_CHECKS > 1
-                  if (crc == 0)
-                  {
-                     crc = crc32(0, NULL, 0);
-                     crc = crc32(crc, profile, length);
-                  }
-
-                  /* So this check must pass for the 'return' below to happen.
-                   */
-                  if (crc == png_sRGB_checks[i].crc)
-#              endif
-               {
-                  if (png_sRGB_checks[i].is_broken != 0)
-                  {
-                     /* These profiles are known to have bad data that may cause
-                      * problems if they are used, therefore attempt to
-                      * discourage their use, skip the 'have_md5' warning below,
-                      * which is made irrelevant by this error.
-                      */
-                     png_chunk_report(png_ptr, "known incorrect sRGB profile",
-                         PNG_CHUNK_ERROR);
-                  }
-
-                  /* Warn that this being done; this isn't even an error since
-                   * the profile is perfectly valid, but it would be nice if
-                   * people used the up-to-date ones.
-                   */
-                  else if (png_sRGB_checks[i].have_md5 == 0)
-                  {
-                     png_chunk_report(png_ptr,
-                         "out-of-date sRGB profile with no signature",
-                         PNG_CHUNK_WARNING);
-                  }
+#  ifdef PNG_READ_sRGB_SUPPORTED
+      if (png_has_chunk(png_ptr, sRGB))
+         return 0;
+#  endif /*sRGB*/
 
-                  return 1+png_sRGB_checks[i].is_broken;
-               }
-            }
-
-# if PNG_sRGB_PROFILE_CHECKS > 0
-         /* The signature matched, but the profile had been changed in some
-          * way.  This probably indicates a data error or uninformed hacking.
-          * Fall through to "no match".
-          */
-         png_chunk_report(png_ptr,
-             "Not recognizing known sRGB profile that has been edited",
-             PNG_CHUNK_WARNING);
-         break;
-# endif
-         }
-      }
-   }
+#  ifdef PNG_READ_cHRM_SUPPORTED
+      if (png_has_chunk(png_ptr, cHRM))
+         return 1;
+#     define check_chromaticities 1
+#  endif /*cHRM*/
 
-   return 0; /* no match */
+   return 0; /* sRGB defaults */
 }
+#endif /* READ_mDCV || READ_cHRM */
 
 void /* PRIVATE */
-png_icc_set_sRGB(png_const_structrp png_ptr,
-    png_colorspacerp colorspace, png_const_bytep profile, uLong adler)
+png_set_rgb_coefficients(png_structrp png_ptr)
 {
-   /* Is this profile one of the known ICC sRGB profiles?  If it is, just set
-    * the sRGB information.
+   /* Set the rgb_to_gray coefficients from the colorspace if available.  Note
+    * that '_set' means that png_rgb_to_gray was called **and** it successfully
+    * set up the coefficients.
     */
-   if (png_compare_ICC_profile_with_sRGB(png_ptr, profile, adler) != 0)
-      (void)png_colorspace_set_sRGB(png_ptr, colorspace,
-         (int)/*already checked*/png_get_uint_32(profile+64));
-}
-#endif /* PNG_sRGB_PROFILE_CHECKS >= 0 */
-#endif /* sRGB */
-
-int /* PRIVATE */
-png_colorspace_set_ICC(png_const_structrp png_ptr, png_colorspacerp colorspace,
-    png_const_charp name, png_uint_32 profile_length, png_const_bytep profile,
-    int color_type)
-{
-   if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0)
-      return 0;
-
-   if (icc_check_length(png_ptr, colorspace, name, profile_length) != 0 &&
-       png_icc_check_header(png_ptr, colorspace, name, profile_length, profile,
-           color_type) != 0 &&
-       png_icc_check_tag_table(png_ptr, colorspace, name, profile_length,
-           profile) != 0)
+   if (png_ptr->rgb_to_gray_coefficients_set == 0)
    {
-#     if defined(PNG_sRGB_SUPPORTED) && PNG_sRGB_PROFILE_CHECKS >= 0
-         /* If no sRGB support, don't try storing sRGB information */
-         png_icc_set_sRGB(png_ptr, colorspace, profile, 0);
-#     endif
-      return 1;
-   }
+#  if check_chromaticities
+      png_XYZ xyz;
 
-   /* Failure case */
-   return 0;
-}
-#endif /* iCCP */
-
-#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
-void /* PRIVATE */
-png_colorspace_set_rgb_coefficients(png_structrp png_ptr)
-{
-   /* Set the rgb_to_gray coefficients from the colorspace. */
-   if (png_ptr->rgb_to_gray_coefficients_set == 0 &&
-      (png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
-   {
-      /* png_set_background has not been called, get the coefficients from the Y
-       * values of the colorspace colorants.
-       */
-      png_fixed_point r = png_ptr->colorspace.end_points_XYZ.red_Y;
-      png_fixed_point g = png_ptr->colorspace.end_points_XYZ.green_Y;
-      png_fixed_point b = png_ptr->colorspace.end_points_XYZ.blue_Y;
-      png_fixed_point total = r+g+b;
-
-      if (total > 0 &&
-         r >= 0 && png_muldiv(&r, r, 32768, total) && r >= 0 && r <= 32768 &&
-         g >= 0 && png_muldiv(&g, g, 32768, total) && g >= 0 && g <= 32768 &&
-         b >= 0 && png_muldiv(&b, b, 32768, total) && b >= 0 && b <= 32768 &&
-         r+g+b <= 32769)
+      if (have_chromaticities(png_ptr) &&
+          png_XYZ_from_xy(&xyz, &png_ptr->chromaticities) == 0)
       {
-         /* We allow 0 coefficients here.  r+g+b may be 32769 if two or
-          * all of the coefficients were rounded up.  Handle this by
-          * reducing the *largest* coefficient by 1; this matches the
-          * approach used for the default coefficients in pngrtran.c
+         /* png_set_rgb_to_gray has not set the coefficients, get them from the
+          * Y * values of the colorspace colorants.
           */
-         int add = 0;
+         png_fixed_point r = xyz.red_Y;
+         png_fixed_point g = xyz.green_Y;
+         png_fixed_point b = xyz.blue_Y;
+         png_fixed_point total = r+g+b;
+
+         if (total > 0 &&
+            r >= 0 && png_muldiv(&r, r, 32768, total) && r >= 0 && r <= 32768 &&
+            g >= 0 && png_muldiv(&g, g, 32768, total) && g >= 0 && g <= 32768 &&
+            b >= 0 && png_muldiv(&b, b, 32768, total) && b >= 0 && b <= 32768 &&
+            r+g+b <= 32769)
+         {
+            /* We allow 0 coefficients here.  r+g+b may be 32769 if two or
+             * all of the coefficients were rounded up.  Handle this by
+             * reducing the *largest* coefficient by 1; this matches the
+             * approach used for the default coefficients in pngrtran.c
+             */
+            int add = 0;
 
-         if (r+g+b > 32768)
-            add = -1;
-         else if (r+g+b < 32768)
-            add = 1;
+            if (r+g+b > 32768)
+               add = -1;
+            else if (r+g+b < 32768)
+               add = 1;
 
-         if (add != 0)
-         {
-            if (g >= r && g >= b)
-               g += add;
-            else if (r >= g && r >= b)
-               r += add;
-            else
-               b += add;
-         }
+            if (add != 0)
+            {
+               if (g >= r && g >= b)
+                  g += add;
+               else if (r >= g && r >= b)
+                  r += add;
+               else
+                  b += add;
+            }
 
-         /* Check for an internal error. */
-         if (r+g+b != 32768)
-            png_error(png_ptr,
-                "internal error handling cHRM coefficients");
+            /* Check for an internal error. */
+            if (r+g+b != 32768)
+               png_error(png_ptr,
+                   "internal error handling cHRM coefficients");
 
-         else
-         {
-            png_ptr->rgb_to_gray_red_coeff   = (png_uint_16)r;
-            png_ptr->rgb_to_gray_green_coeff = (png_uint_16)g;
+            else
+            {
+               png_ptr->rgb_to_gray_red_coeff   = (png_uint_16)r;
+               png_ptr->rgb_to_gray_green_coeff = (png_uint_16)g;
+            }
          }
       }
-
-      /* This is a png_error at present even though it could be ignored -
-       * it should never happen, but it is important that if it does, the
-       * bug is fixed.
-       */
       else
-         png_error(png_ptr, "internal error handling cHRM->XYZ");
+#  endif /* check_chromaticities */
+      {
+         /* Use the historical REC 709 (etc) values: */
+         png_ptr->rgb_to_gray_red_coeff   = 6968;
+         png_ptr->rgb_to_gray_green_coeff = 23434;
+         /* png_ptr->rgb_to_gray_blue_coeff  = 2366; */
+      }
    }
 }
 #endif /* READ_RGB_TO_GRAY */
 
-#endif /* COLORSPACE */
-
 void /* PRIVATE */
 png_check_IHDR(png_const_structrp png_ptr,
     png_uint_32 width, png_uint_32 height, int bit_depth,
@@ -3320,7 +2764,27 @@ png_fixed(png_const_structrp png_ptr, double fp, png_const_charp text)
 }
 #endif
 
-#if defined(PNG_GAMMA_SUPPORTED) || defined(PNG_COLORSPACE_SUPPORTED) ||\
+#if defined(PNG_FLOATING_POINT_SUPPORTED) && \
+   !defined(PNG_FIXED_POINT_MACRO_SUPPORTED) && \
+   (defined(PNG_cLLI_SUPPORTED) || defined(PNG_mDCV_SUPPORTED))
+png_uint_32
+png_fixed_ITU(png_const_structrp png_ptr, double fp, png_const_charp text)
+{
+   double r = floor(10000 * fp + .5);
+
+   if (r > 2147483647. || r < 0)
+      png_fixed_error(png_ptr, text);
+
+#  ifndef PNG_ERROR_TEXT_SUPPORTED
+   PNG_UNUSED(text)
+#  endif
+
+   return (png_uint_32)r;
+}
+#endif
+
+
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_COLORSPACE_SUPPORTED) ||\
     defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG_READ_pHYs_SUPPORTED)
 /* muldiv functions */
 /* This API takes signed arguments and rounds the result to the nearest
@@ -3328,7 +2792,7 @@ png_fixed(png_const_structrp png_ptr, double fp, png_const_charp text)
  * the nearest .00001).  Overflow and divide by zero are signalled in
  * the result, a boolean - true on success, false on overflow.
  */
-int
+int /* PRIVATE */
 png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times,
     png_int_32 divisor)
 {
@@ -3442,27 +2906,7 @@ png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times,
 
    return 0;
 }
-#endif /* READ_GAMMA || INCH_CONVERSIONS */
-
-#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED)
-/* The following is for when the caller doesn't much care about the
- * result.
- */
-png_fixed_point
-png_muldiv_warn(png_const_structrp png_ptr, png_fixed_point a, png_int_32 times,
-    png_int_32 divisor)
-{
-   png_fixed_point result;
-
-   if (png_muldiv(&result, a, times, divisor) != 0)
-      return result;
-
-   png_warning(png_ptr, "fixed point overflow ignored");
-   return 0;
-}
-#endif
 
-#ifdef PNG_GAMMA_SUPPORTED /* more fixed point functions for gamma */
 /* Calculate a reciprocal, return 0 on div-by-zero or overflow. */
 png_fixed_point
 png_reciprocal(png_fixed_point a)
@@ -3481,26 +2925,38 @@ png_reciprocal(png_fixed_point a)
 
    return 0; /* error/overflow */
 }
+#endif /* READ_GAMMA || COLORSPACE || INCH_CONVERSIONS || READ_pHYS */
 
+#ifdef PNG_READ_GAMMA_SUPPORTED
 /* This is the shared test on whether a gamma value is 'significant' - whether
  * it is worth doing gamma correction.
  */
 int /* PRIVATE */
 png_gamma_significant(png_fixed_point gamma_val)
 {
+   /* sRGB:       1/2.2 == 0.4545(45)
+    * AdobeRGB:   1/(2+51/256) ~= 0.45471 5dp
+    *
+    * So the correction from AdobeRGB to sRGB (output) is:
+    *
+    *    2.2/(2+51/256) == 1.00035524
+    *
+    * I.e. vanishly small (<4E-4) but still detectable in 16-bit linear (+/-
+    * 23).  Note that the Adobe choice seems to be something intended to give an
+    * exact number with 8 binary fractional digits - it is the closest to 2.2
+    * that is possible a base 2 .8p representation.
+    */
    return gamma_val < PNG_FP_1 - PNG_GAMMA_THRESHOLD_FIXED ||
        gamma_val > PNG_FP_1 + PNG_GAMMA_THRESHOLD_FIXED;
 }
-#endif
 
-#ifdef PNG_READ_GAMMA_SUPPORTED
-#ifdef PNG_16BIT_SUPPORTED
+#ifndef PNG_FLOATING_ARITHMETIC_SUPPORTED
 /* A local convenience routine. */
 static png_fixed_point
 png_product2(png_fixed_point a, png_fixed_point b)
 {
-   /* The required result is 1/a * 1/b; the following preserves accuracy. */
-#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
+   /* The required result is a * b; the following preserves accuracy. */
+#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED /* Should now be unused */
    double r = a * 1E-5;
    r *= b;
    r = floor(r+.5);
@@ -3516,9 +2972,8 @@ png_product2(png_fixed_point a, png_fixed_point b)
 
    return 0; /* overflow */
 }
-#endif /* 16BIT */
+#endif /* FLOATING_ARITHMETIC */
 
-/* The inverse of the above. */
 png_fixed_point
 png_reciprocal2(png_fixed_point a, png_fixed_point b)
 {
@@ -4171,10 +3626,27 @@ png_destroy_gamma_table(png_structrp png_ptr)
  * tables, we don't make a full table if we are reducing to 8-bit in
  * the future.  Note also how the gamma_16 tables are segmented so that
  * we don't need to allocate > 64K chunks for a full 16-bit table.
+ *
+ * TODO: move this to pngrtran.c and make it static.  Better yet create
+ * pngcolor.c and put all the PNG_COLORSPACE stuff in there.
  */
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
+   defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
+   defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+#  define GAMMA_TRANSFORMS 1 /* #ifdef CSE */
+#else
+#  define GAMMA_TRANSFORMS 0
+#endif
+
 void /* PRIVATE */
 png_build_gamma_table(png_structrp png_ptr, int bit_depth)
 {
+   png_fixed_point file_gamma, screen_gamma;
+   png_fixed_point correction;
+#  if GAMMA_TRANSFORMS
+      png_fixed_point file_to_linear, linear_to_screen;
+#  endif
+
    png_debug(1, "in png_build_gamma_table");
 
    /* Remove any existing table; this copes with multiple calls to
@@ -4189,27 +3661,44 @@ png_build_gamma_table(png_structrp png_ptr, int bit_depth)
       png_destroy_gamma_table(png_ptr);
    }
 
+   /* The following fields are set, finally, in png_init_read_transformations.
+    * If file_gamma is 0 (unset) nothing can be done otherwise if screen_gamma
+    * is 0 (unset) there is no gamma correction but to/from linear is possible.
+    */
+   file_gamma = png_ptr->file_gamma;
+   screen_gamma = png_ptr->screen_gamma;
+#  if GAMMA_TRANSFORMS
+      file_to_linear = png_reciprocal(file_gamma);
+#  endif
+
+   if (screen_gamma > 0)
+   {
+#     if GAMMA_TRANSFORMS
+         linear_to_screen = png_reciprocal(screen_gamma);
+#     endif
+      correction = png_reciprocal2(screen_gamma, file_gamma);
+   }
+   else /* screen gamma unknown */
+   {
+#     if GAMMA_TRANSFORMS
+         linear_to_screen = file_gamma;
+#     endif
+      correction = PNG_FP_1;
+   }
+
    if (bit_depth <= 8)
    {
-      png_build_8bit_table(png_ptr, &png_ptr->gamma_table,
-          png_ptr->screen_gamma > 0 ?
-          png_reciprocal2(png_ptr->colorspace.gamma,
-          png_ptr->screen_gamma) : PNG_FP_1);
+      png_build_8bit_table(png_ptr, &png_ptr->gamma_table, correction);
 
-#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
-   defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
-   defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+#if GAMMA_TRANSFORMS
       if ((png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) != 0)
       {
-         png_build_8bit_table(png_ptr, &png_ptr->gamma_to_1,
-             png_reciprocal(png_ptr->colorspace.gamma));
+         png_build_8bit_table(png_ptr, &png_ptr->gamma_to_1, file_to_linear);
 
          png_build_8bit_table(png_ptr, &png_ptr->gamma_from_1,
-             png_ptr->screen_gamma > 0 ?
-             png_reciprocal(png_ptr->screen_gamma) :
-             png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */);
+            linear_to_screen);
       }
-#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
+#endif /* GAMMA_TRANSFORMS */
    }
 #ifdef PNG_16BIT_SUPPORTED
    else
@@ -4275,32 +3764,26 @@ png_build_gamma_table(png_structrp png_ptr, int bit_depth)
        * reduced to 8 bits.
        */
       if ((png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) != 0)
-          png_build_16to8_table(png_ptr, &png_ptr->gamma_16_table, shift,
-          png_ptr->screen_gamma > 0 ? png_product2(png_ptr->colorspace.gamma,
-          png_ptr->screen_gamma) : PNG_FP_1);
-
+         png_build_16to8_table(png_ptr, &png_ptr->gamma_16_table, shift,
+            png_reciprocal(correction));
       else
-          png_build_16bit_table(png_ptr, &png_ptr->gamma_16_table, shift,
-          png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->colorspace.gamma,
-          png_ptr->screen_gamma) : PNG_FP_1);
+         png_build_16bit_table(png_ptr, &png_ptr->gamma_16_table, shift,
+            correction);
 
-#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
-   defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
-   defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+#  if GAMMA_TRANSFORMS
       if ((png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) != 0)
       {
          png_build_16bit_table(png_ptr, &png_ptr->gamma_16_to_1, shift,
-             png_reciprocal(png_ptr->colorspace.gamma));
+            file_to_linear);
 
          /* Notice that the '16 from 1' table should be full precision, however
           * the lookup on this table still uses gamma_shift, so it can't be.
           * TODO: fix this.
           */
          png_build_16bit_table(png_ptr, &png_ptr->gamma_16_from_1, shift,
-             png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) :
-             png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */);
+            linear_to_screen);
       }
-#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
+#endif /* GAMMA_TRANSFORMS */
    }
 #endif /* 16BIT */
 }
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/png.h b/src/java.desktop/share/native/libsplashscreen/libpng/png.h
index 9f61a773c1d..ede12c34fe6 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/png.h
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/png.h
@@ -29,9 +29,9 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * libpng version 1.6.43
+ * libpng version 1.6.47
  *
- * Copyright (c) 2018-2024 Cosmin Truta
+ * Copyright (c) 2018-2025 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -43,7 +43,7 @@
  *   libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger
  *   libpng versions 0.97, January 1998, through 1.6.35, July 2018:
  *     Glenn Randers-Pehrson
- *   libpng versions 1.6.36, December 2018, through 1.6.43, February 2024:
+ *   libpng versions 1.6.36, December 2018, through 1.6.47, February 2025:
  *     Cosmin Truta
  *   See also "Contributing Authors", below.
  */
@@ -55,8 +55,8 @@
  * PNG Reference Library License version 2
  * ---------------------------------------
  *
- *  * Copyright (c) 1995-2024 The PNG Reference Library Authors.
- *  * Copyright (c) 2018-2024 Cosmin Truta.
+ *  * Copyright (c) 1995-2025 The PNG Reference Library Authors.
+ *  * Copyright (c) 2018-2025 Cosmin Truta.
  *  * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
  *  * Copyright (c) 1996-1997 Andreas Dilger.
  *  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -267,7 +267,7 @@
  *    ...
  *    1.5.30                  15    10530  15.so.15.30[.0]
  *    ...
- *    1.6.43                  16    10643  16.so.16.43[.0]
+ *    1.6.47                  16    10647  16.so.16.47[.0]
  *
  *    Henceforth the source version will match the shared-library major and
  *    minor numbers; the shared-library major version number will be used for
@@ -303,7 +303,7 @@
  */
 
 /* Version information for png.h - this should match the version in png.c */
-#define PNG_LIBPNG_VER_STRING "1.6.43"
+#define PNG_LIBPNG_VER_STRING "1.6.47"
 #define PNG_HEADER_VERSION_STRING " libpng version " PNG_LIBPNG_VER_STRING "\n"
 
 /* The versions of shared library builds should stay in sync, going forward */
@@ -314,18 +314,18 @@
 /* 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 43
+#define PNG_LIBPNG_VER_RELEASE 47
 
 /* This should be zero for a public release, or non-zero for a
  * development version.
  */
-#define PNG_LIBPNG_VER_BUILD  0
+#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_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 */
@@ -345,7 +345,7 @@
  * From version 1.0.1 it is:
  * XXYYZZ, where XX=major, YY=minor, ZZ=release
  */
-#define PNG_LIBPNG_VER 10643 /* 1.6.43 */
+#define PNG_LIBPNG_VER 10647 /* 1.6.47 */
 
 /* Library configuration: these options cannot be changed after
  * the library has been built.
@@ -455,7 +455,7 @@ extern "C" {
 /* 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_43;
+typedef char* png_libpng_version_1_6_47;
 
 /* Basic control structions.  Read libpng-manual.txt or libpng.3 for more info.
  *
@@ -773,6 +773,21 @@ typedef png_unknown_chunk * * png_unknown_chunkpp;
 #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 */
+#define PNG_INFO_cICP 0x20000U /* PNGv3: 1.6.45 */
+#define PNG_INFO_cLLI 0x40000U /* PNGv3: 1.6.45 */
+#define PNG_INFO_mDCV 0x80000U /* PNGv3: 1.6.45 */
+/* APNG: these chunks are stored as unknown, these flags are never set
+ * however they are provided as a convenience for implementors of APNG and
+ * avoids any merge conflicts.
+ *
+ * Private chunks: these chunk names violate the chunk name recommendations
+ * because the chunk definitions have no signature and because the private
+ * chunks with these names have been reserved.  Private definitions should
+ * avoid them.
+ */
+#define PNG_INFO_acTL 0x100000U /* PNGv3: 1.6.45: unknown */
+#define PNG_INFO_fcTL 0x200000U /* PNGv3: 1.6.45: unknown */
+#define PNG_INFO_fdAT 0x400000U /* PNGv3: 1.6.45: unknown */
 
 /* This is used for the transformation routines, as some of them
  * change these values for the row.  It also should enable using
@@ -852,7 +867,7 @@ typedef PNG_CALLBACK(int, *png_user_chunk_ptr, (png_structp,
  * 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);
+PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), (jmp_buf, int), typedef);
 #endif
 
 /* Transform masks for the high-level interface */
@@ -2002,6 +2017,46 @@ PNG_FIXED_EXPORT(233, void, png_set_cHRM_XYZ_fixed, (png_const_structrp png_ptr,
     png_fixed_point int_blue_Z))
 #endif
 
+#ifdef PNG_cICP_SUPPORTED
+PNG_EXPORT(250, png_uint_32, png_get_cICP, (png_const_structrp png_ptr,
+    png_const_inforp info_ptr, png_bytep colour_primaries,
+    png_bytep transfer_function, png_bytep matrix_coefficients,
+    png_bytep video_full_range_flag));
+#endif
+
+#ifdef PNG_cICP_SUPPORTED
+PNG_EXPORT(251, void, png_set_cICP, (png_const_structrp png_ptr,
+    png_inforp info_ptr, png_byte colour_primaries,
+    png_byte transfer_function, png_byte matrix_coefficients,
+    png_byte video_full_range_flag));
+#endif
+
+#ifdef PNG_cLLI_SUPPORTED
+PNG_FP_EXPORT(252, png_uint_32, png_get_cLLI, (png_const_structrp png_ptr,
+         png_const_inforp info_ptr, double *maximum_content_light_level,
+         double *maximum_frame_average_light_level))
+PNG_FIXED_EXPORT(253, png_uint_32, png_get_cLLI_fixed,
+    (png_const_structrp png_ptr, png_const_inforp info_ptr,
+    /* The values below are in cd/m2 (nits) and are scaled by 10,000; not
+     * 100,000 as in the case of png_fixed_point.
+     */
+    png_uint_32p maximum_content_light_level_scaled_by_10000,
+    png_uint_32p maximum_frame_average_light_level_scaled_by_10000))
+#endif
+
+#ifdef PNG_cLLI_SUPPORTED
+PNG_FP_EXPORT(254, void, png_set_cLLI, (png_const_structrp png_ptr,
+         png_inforp info_ptr, double maximum_content_light_level,
+         double maximum_frame_average_light_level))
+PNG_FIXED_EXPORT(255, void, png_set_cLLI_fixed, (png_const_structrp png_ptr,
+    png_inforp info_ptr,
+    /* The values below are in cd/m2 (nits) and are scaled by 10,000; not
+     * 100,000 as in the case of png_fixed_point.
+     */
+    png_uint_32 maximum_content_light_level_scaled_by_10000,
+    png_uint_32 maximum_frame_average_light_level_scaled_by_10000))
+#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));
@@ -2046,6 +2101,60 @@ PNG_EXPORT(144, void, png_set_IHDR, (png_const_structrp png_ptr,
     int color_type, int interlace_method, int compression_method,
     int filter_method));
 
+#ifdef PNG_mDCV_SUPPORTED
+PNG_FP_EXPORT(256, png_uint_32, png_get_mDCV, (png_const_structrp png_ptr,
+    png_const_inforp info_ptr,
+    /* The chromaticities of the mastering display.  As cHRM, but independent of
+     * the encoding endpoints in cHRM, or cICP, or iCCP.  These values will
+     * always be in the range 0 to 1.3107.
+     */
+    double *white_x, double *white_y, double *red_x, double *red_y,
+    double *green_x, double *green_y, double *blue_x, double *blue_y,
+    /* Mastering display luminance in cd/m2 (nits). */
+    double *mastering_display_maximum_luminance,
+    double *mastering_display_minimum_luminance))
+
+PNG_FIXED_EXPORT(257, png_uint_32, png_get_mDCV_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,
+    /* Mastering display luminance in cd/m2 (nits) multiplied (scaled) by
+     * 10,000.
+     */
+    png_uint_32p mastering_display_maximum_luminance_scaled_by_10000,
+    png_uint_32p mastering_display_minimum_luminance_scaled_by_10000))
+#endif
+
+#ifdef PNG_mDCV_SUPPORTED
+PNG_FP_EXPORT(258, void, png_set_mDCV, (png_const_structrp png_ptr,
+    png_inforp info_ptr,
+    /* The chromaticities of the mastering display.  As cHRM, but independent of
+     * the encoding endpoints in cHRM, or cICP, or iCCP.
+     */
+    double white_x, double white_y, double red_x, double red_y, double green_x,
+    double green_y, double blue_x, double blue_y,
+    /* Mastering display luminance in cd/m2 (nits). */
+    double mastering_display_maximum_luminance,
+    double mastering_display_minimum_luminance))
+
+PNG_FIXED_EXPORT(259, void, png_set_mDCV_fixed, (png_const_structrp png_ptr,
+    png_inforp info_ptr,
+    /* The admissible range of these values is not the full range of a PNG
+     * fixed point value.  Negative values cannot be encoded and the maximum
+     * value is about 1.3 */
+    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,
+    /* These are PNG unsigned 4 byte values: 31-bit unsigned values.  The MSB
+     * must be zero.
+     */
+    png_uint_32 mastering_display_maximum_luminance_scaled_by_10000,
+    png_uint_32 mastering_display_minimum_luminance_scaled_by_10000))
+#endif
+
 #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,
@@ -3266,7 +3375,7 @@ PNG_EXPORT(244, int, png_set_option, (png_structrp png_ptr, int option,
  * one to use is one more than this.)
  */
 #ifdef PNG_EXPORT_LAST_ORDINAL
-  PNG_EXPORT_LAST_ORDINAL(249);
+  PNG_EXPORT_LAST_ORDINAL(259);
 #endif
 
 #ifdef __cplusplus
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngconf.h b/src/java.desktop/share/native/libsplashscreen/libpng/pngconf.h
index b3b441b1122..70bca6fa1c9 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngconf.h
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngconf.h
@@ -29,9 +29,9 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * libpng version 1.6.43
+ * libpng version 1.6.47
  *
- * Copyright (c) 2018-2024 Cosmin Truta
+ * Copyright (c) 2018-2025 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -116,7 +116,7 @@
 
 /* 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.
+ * prototypes.  [Deprecated.]
  */
 #ifndef PNGARG
 #  define PNGARG(arglist) arglist
@@ -326,7 +326,7 @@
 
 #ifndef PNG_EXPORTA
 #  define PNG_EXPORTA(ordinal, type, name, args, attributes) \
-      PNG_FUNCTION(PNG_EXPORT_TYPE(type), (PNGAPI name), PNGARG(args), \
+      PNG_FUNCTION(PNG_EXPORT_TYPE(type), (PNGAPI name), args, \
       PNG_LINKAGE_API attributes)
 #endif
 
@@ -344,7 +344,7 @@
 #endif
 
 #ifndef PNG_CALLBACK
-#  define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) PNGARG(args)
+#  define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) args
 #endif
 
 /* Support for compiler specific function attributes.  These are used
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngerror.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngerror.c
index ea8dd172197..ea0103331d3 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngerror.c
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngerror.c
@@ -48,13 +48,14 @@
 
 #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
 
-static PNG_FUNCTION(void, png_default_error,PNGARG((png_const_structrp png_ptr,
-    png_const_charp error_message)),PNG_NORETURN);
+static PNG_FUNCTION(void /* PRIVATE */,
+png_default_error,(png_const_structrp png_ptr, png_const_charp error_message),
+    PNG_NORETURN);
 
 #ifdef PNG_WARNINGS_SUPPORTED
 static void /* PRIVATE */
-png_default_warning PNGARG((png_const_structrp png_ptr,
-    png_const_charp warning_message));
+png_default_warning(png_const_structrp png_ptr,
+    png_const_charp warning_message);
 #endif /* WARNINGS */
 
 /* This function is called whenever there is a fatal error.  This function
@@ -963,23 +964,37 @@ png_safe_warning(png_structp png_nonconst_ptr, png_const_charp warning_message)
 int /* PRIVATE */
 png_safe_execute(png_imagep image, int (*function)(png_voidp), png_voidp arg)
 {
-   png_voidp saved_error_buf = image->opaque->error_buf;
+   const png_voidp saved_error_buf = image->opaque->error_buf;
    jmp_buf safe_jmpbuf;
-   int result;
 
    /* Safely execute function(arg), with png_error returning back here. */
    if (setjmp(safe_jmpbuf) == 0)
    {
+      int result;
+
       image->opaque->error_buf = safe_jmpbuf;
       result = function(arg);
       image->opaque->error_buf = saved_error_buf;
-      return result;
+
+      if (result)
+         return 1; /* success */
    }
 
-   /* On png_error, return via longjmp, pop the jmpbuf, and free the image. */
+   /* The function failed either because of a caught png_error and a regular
+    * return of false above or because of an uncaught png_error from the
+    * function itself.  Ensure that the error_buf is always set back to the
+    * value saved above:
+    */
    image->opaque->error_buf = saved_error_buf;
-   png_image_free(image);
-   return 0;
+
+   /* On the final false return, when about to return control to the caller, the
+    * image is freed (png_image_free does this check but it is duplicated here
+    * for clarity:
+    */
+   if (saved_error_buf == NULL)
+      png_image_free(image);
+
+   return 0; /* failure */
 }
 #endif /* SIMPLIFIED READ || SIMPLIFIED_WRITE */
 #endif /* READ || WRITE */
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngget.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngget.c
index 41e0a5abc3a..d67adbae247 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngget.c
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngget.c
@@ -409,7 +409,13 @@ png_fixed_inches_from_microns(png_const_structrp png_ptr, png_int_32 microns)
     * Notice that this can overflow - a warning is output and 0 is
     * returned.
     */
-   return png_muldiv_warn(png_ptr, microns, 500, 127);
+   png_fixed_point result;
+
+   if (png_muldiv(&result, microns, 500, 127) != 0)
+      return result;
+
+   png_warning(png_ptr, "fixed point overflow ignored");
+   return 0;
 }
 
 png_fixed_point PNGAPI
@@ -419,7 +425,7 @@ png_get_x_offset_inches_fixed(png_const_structrp png_ptr,
    return png_fixed_inches_from_microns(png_ptr,
        png_get_x_offset_microns(png_ptr, info_ptr));
 }
-#endif
+#endif /* FIXED_POINT */
 
 #ifdef PNG_FIXED_POINT_SUPPORTED
 png_fixed_point PNGAPI
@@ -547,44 +553,31 @@ png_get_bKGD(png_const_structrp png_ptr, png_inforp info_ptr,
 #  ifdef PNG_FLOATING_POINT_SUPPORTED
 png_uint_32 PNGAPI
 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)
+    double *whitex, double *whitey, double *redx, double *redy,
+    double *greenx, double *greeny, double *bluex, double *bluey)
 {
    png_debug1(1, "in %s retrieval function", "cHRM");
 
-   /* Quiet API change: this code used to only return the end points if a cHRM
-    * chunk was present, but the end points can also come from iCCP or sRGB
-    * chunks, so in 1.6.0 the png_get_ APIs return the end points regardless and
-    * the png_set_ APIs merely check that set end points are mutually
-    * consistent.
-    */
+   /* PNGv3: this just returns the values store from the cHRM, if any. */
    if (png_ptr != NULL && info_ptr != NULL &&
-      (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
+       (info_ptr->valid & PNG_INFO_cHRM) != 0)
    {
-      if (white_x != NULL)
-         *white_x = png_float(png_ptr,
-             info_ptr->colorspace.end_points_xy.whitex, "cHRM white X");
-      if (white_y != NULL)
-         *white_y = png_float(png_ptr,
-             info_ptr->colorspace.end_points_xy.whitey, "cHRM white Y");
-      if (red_x != NULL)
-         *red_x = png_float(png_ptr, info_ptr->colorspace.end_points_xy.redx,
-             "cHRM red X");
-      if (red_y != NULL)
-         *red_y = png_float(png_ptr, info_ptr->colorspace.end_points_xy.redy,
-             "cHRM red Y");
-      if (green_x != NULL)
-         *green_x = png_float(png_ptr,
-             info_ptr->colorspace.end_points_xy.greenx, "cHRM green X");
-      if (green_y != NULL)
-         *green_y = png_float(png_ptr,
-             info_ptr->colorspace.end_points_xy.greeny, "cHRM green Y");
-      if (blue_x != NULL)
-         *blue_x = png_float(png_ptr, info_ptr->colorspace.end_points_xy.bluex,
-             "cHRM blue X");
-      if (blue_y != NULL)
-         *blue_y = png_float(png_ptr, info_ptr->colorspace.end_points_xy.bluey,
-             "cHRM blue Y");
+      if (whitex != NULL)
+         *whitex = png_float(png_ptr, info_ptr->cHRM.whitex, "cHRM wx");
+      if (whitey != NULL)
+         *whitey = png_float(png_ptr, info_ptr->cHRM.whitey, "cHRM wy");
+      if (redx   != NULL)
+         *redx   = png_float(png_ptr, info_ptr->cHRM.redx,   "cHRM rx");
+      if (redy   != NULL)
+         *redy   = png_float(png_ptr, info_ptr->cHRM.redy,   "cHRM ry");
+      if (greenx != NULL)
+         *greenx = png_float(png_ptr, info_ptr->cHRM.greenx, "cHRM gx");
+      if (greeny != NULL)
+         *greeny = png_float(png_ptr, info_ptr->cHRM.greeny, "cHRM gy");
+      if (bluex  != NULL)
+         *bluex  = png_float(png_ptr, info_ptr->cHRM.bluex,  "cHRM bx");
+      if (bluey  != NULL)
+         *bluey  = png_float(png_ptr, info_ptr->cHRM.bluey,  "cHRM by");
       return PNG_INFO_cHRM;
    }
 
@@ -597,38 +590,31 @@ png_get_cHRM_XYZ(png_const_structrp png_ptr, png_const_inforp info_ptr,
     double *green_Y, double *green_Z, double *blue_X, double *blue_Y,
     double *blue_Z)
 {
+   png_XYZ XYZ;
    png_debug1(1, "in %s retrieval function", "cHRM_XYZ(float)");
 
    if (png_ptr != NULL && info_ptr != NULL &&
-       (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
+       (info_ptr->valid & PNG_INFO_cHRM) != 0 &&
+       png_XYZ_from_xy(&XYZ, &info_ptr->cHRM) == 0)
    {
       if (red_X != NULL)
-         *red_X = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_X,
-             "cHRM red X");
+         *red_X = png_float(png_ptr, XYZ.red_X, "cHRM red X");
       if (red_Y != NULL)
-         *red_Y = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_Y,
-             "cHRM red Y");
+         *red_Y = png_float(png_ptr, XYZ.red_Y, "cHRM red Y");
       if (red_Z != NULL)
-         *red_Z = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_Z,
-             "cHRM red Z");
+         *red_Z = png_float(png_ptr, XYZ.red_Z, "cHRM red Z");
       if (green_X != NULL)
-         *green_X = png_float(png_ptr,
-             info_ptr->colorspace.end_points_XYZ.green_X, "cHRM green X");
+         *green_X = png_float(png_ptr, XYZ.green_X, "cHRM green X");
       if (green_Y != NULL)
-         *green_Y = png_float(png_ptr,
-             info_ptr->colorspace.end_points_XYZ.green_Y, "cHRM green Y");
+         *green_Y = png_float(png_ptr, XYZ.green_Y, "cHRM green Y");
       if (green_Z != NULL)
-         *green_Z = png_float(png_ptr,
-             info_ptr->colorspace.end_points_XYZ.green_Z, "cHRM green Z");
+         *green_Z = png_float(png_ptr, XYZ.green_Z, "cHRM green Z");
       if (blue_X != NULL)
-         *blue_X = png_float(png_ptr,
-             info_ptr->colorspace.end_points_XYZ.blue_X, "cHRM blue X");
+         *blue_X = png_float(png_ptr, XYZ.blue_X, "cHRM blue X");
       if (blue_Y != NULL)
-         *blue_Y = png_float(png_ptr,
-             info_ptr->colorspace.end_points_XYZ.blue_Y, "cHRM blue Y");
+         *blue_Y = png_float(png_ptr, XYZ.blue_Y, "cHRM blue Y");
       if (blue_Z != NULL)
-         *blue_Z = png_float(png_ptr,
-             info_ptr->colorspace.end_points_XYZ.blue_Z, "cHRM blue Z");
+         *blue_Z = png_float(png_ptr, XYZ.blue_Z, "cHRM blue Z");
       return PNG_INFO_cHRM;
    }
 
@@ -645,29 +631,22 @@ png_get_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
     png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y,
     png_fixed_point *int_blue_Z)
 {
+   png_XYZ XYZ;
    png_debug1(1, "in %s retrieval function", "cHRM_XYZ");
 
    if (png_ptr != NULL && info_ptr != NULL &&
-      (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
+       (info_ptr->valid & PNG_INFO_cHRM) != 0U &&
+       png_XYZ_from_xy(&XYZ, &info_ptr->cHRM) == 0)
    {
-      if (int_red_X != NULL)
-         *int_red_X = info_ptr->colorspace.end_points_XYZ.red_X;
-      if (int_red_Y != NULL)
-         *int_red_Y = info_ptr->colorspace.end_points_XYZ.red_Y;
-      if (int_red_Z != NULL)
-         *int_red_Z = info_ptr->colorspace.end_points_XYZ.red_Z;
-      if (int_green_X != NULL)
-         *int_green_X = info_ptr->colorspace.end_points_XYZ.green_X;
-      if (int_green_Y != NULL)
-         *int_green_Y = info_ptr->colorspace.end_points_XYZ.green_Y;
-      if (int_green_Z != NULL)
-         *int_green_Z = info_ptr->colorspace.end_points_XYZ.green_Z;
-      if (int_blue_X != NULL)
-         *int_blue_X = info_ptr->colorspace.end_points_XYZ.blue_X;
-      if (int_blue_Y != NULL)
-         *int_blue_Y = info_ptr->colorspace.end_points_XYZ.blue_Y;
-      if (int_blue_Z != NULL)
-         *int_blue_Z = info_ptr->colorspace.end_points_XYZ.blue_Z;
+      if (int_red_X != NULL) *int_red_X = XYZ.red_X;
+      if (int_red_Y != NULL) *int_red_Y = XYZ.red_Y;
+      if (int_red_Z != NULL) *int_red_Z = XYZ.red_Z;
+      if (int_green_X != NULL) *int_green_X = XYZ.green_X;
+      if (int_green_Y != NULL) *int_green_Y = XYZ.green_Y;
+      if (int_green_Z != NULL) *int_green_Z = XYZ.green_Z;
+      if (int_blue_X != NULL) *int_blue_X = XYZ.blue_X;
+      if (int_blue_Y != NULL) *int_blue_Y = XYZ.blue_Y;
+      if (int_blue_Z != NULL) *int_blue_Z = XYZ.blue_Z;
       return PNG_INFO_cHRM;
    }
 
@@ -676,31 +655,24 @@ png_get_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
 
 png_uint_32 PNGAPI
 png_get_cHRM_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
-    png_fixed_point *white_x, png_fixed_point *white_y, png_fixed_point *red_x,
-    png_fixed_point *red_y, png_fixed_point *green_x, png_fixed_point *green_y,
-    png_fixed_point *blue_x, png_fixed_point *blue_y)
+    png_fixed_point *whitex, png_fixed_point *whitey, png_fixed_point *redx,
+    png_fixed_point *redy, png_fixed_point *greenx, png_fixed_point *greeny,
+    png_fixed_point *bluex, png_fixed_point *bluey)
 {
    png_debug1(1, "in %s retrieval function", "cHRM");
 
+   /* PNGv3: this just returns the values store from the cHRM, if any. */
    if (png_ptr != NULL && info_ptr != NULL &&
-      (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
+       (info_ptr->valid & PNG_INFO_cHRM) != 0)
    {
-      if (white_x != NULL)
-         *white_x = info_ptr->colorspace.end_points_xy.whitex;
-      if (white_y != NULL)
-         *white_y = info_ptr->colorspace.end_points_xy.whitey;
-      if (red_x != NULL)
-         *red_x = info_ptr->colorspace.end_points_xy.redx;
-      if (red_y != NULL)
-         *red_y = info_ptr->colorspace.end_points_xy.redy;
-      if (green_x != NULL)
-         *green_x = info_ptr->colorspace.end_points_xy.greenx;
-      if (green_y != NULL)
-         *green_y = info_ptr->colorspace.end_points_xy.greeny;
-      if (blue_x != NULL)
-         *blue_x = info_ptr->colorspace.end_points_xy.bluex;
-      if (blue_y != NULL)
-         *blue_y = info_ptr->colorspace.end_points_xy.bluey;
+      if (whitex != NULL) *whitex = info_ptr->cHRM.whitex;
+      if (whitey != NULL) *whitey = info_ptr->cHRM.whitey;
+      if (redx   != NULL) *redx   = info_ptr->cHRM.redx;
+      if (redy   != NULL) *redy   = info_ptr->cHRM.redy;
+      if (greenx != NULL) *greenx = info_ptr->cHRM.greenx;
+      if (greeny != NULL) *greeny = info_ptr->cHRM.greeny;
+      if (bluex  != NULL) *bluex  = info_ptr->cHRM.bluex;
+      if (bluey  != NULL) *bluey  = info_ptr->cHRM.bluey;
       return PNG_INFO_cHRM;
    }
 
@@ -717,11 +689,11 @@ png_get_gAMA_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
 {
    png_debug1(1, "in %s retrieval function", "gAMA");
 
+   /* PNGv3 compatibility: only report gAMA if it is really present. */
    if (png_ptr != NULL && info_ptr != NULL &&
-       (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 &&
-       file_gamma != NULL)
+       (info_ptr->valid & PNG_INFO_gAMA) != 0)
    {
-      *file_gamma = info_ptr->colorspace.gamma;
+      if (file_gamma != NULL) *file_gamma = info_ptr->gamma;
       return PNG_INFO_gAMA;
    }
 
@@ -736,12 +708,13 @@ png_get_gAMA(png_const_structrp png_ptr, png_const_inforp info_ptr,
 {
    png_debug1(1, "in %s retrieval function", "gAMA(float)");
 
+   /* PNGv3 compatibility: only report gAMA if it is really present. */
    if (png_ptr != NULL && info_ptr != NULL &&
-      (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 &&
-      file_gamma != NULL)
+       (info_ptr->valid & PNG_INFO_gAMA) != 0)
    {
-      *file_gamma = png_float(png_ptr, info_ptr->colorspace.gamma,
-          "png_get_gAMA");
+      if (file_gamma != NULL)
+         *file_gamma = png_float(png_ptr, info_ptr->gamma, "gAMA");
+
       return PNG_INFO_gAMA;
    }
 
@@ -758,9 +731,10 @@ png_get_sRGB(png_const_structrp png_ptr, png_const_inforp info_ptr,
    png_debug1(1, "in %s retrieval function", "sRGB");
 
    if (png_ptr != NULL && info_ptr != NULL &&
-      (info_ptr->valid & PNG_INFO_sRGB) != 0 && file_srgb_intent != NULL)
+      (info_ptr->valid & PNG_INFO_sRGB) != 0)
    {
-      *file_srgb_intent = info_ptr->colorspace.rendering_intent;
+      if (file_srgb_intent != NULL)
+         *file_srgb_intent = info_ptr->rendering_intent;
       return PNG_INFO_sRGB;
    }
 
@@ -813,6 +787,136 @@ png_get_sPLT(png_const_structrp png_ptr, png_inforp info_ptr,
 }
 #endif
 
+#ifdef PNG_cICP_SUPPORTED
+png_uint_32 PNGAPI
+png_get_cICP(png_const_structrp png_ptr,
+             png_const_inforp info_ptr, png_bytep colour_primaries,
+             png_bytep transfer_function, png_bytep matrix_coefficients,
+             png_bytep video_full_range_flag)
+{
+    png_debug1(1, "in %s retrieval function", "cICP");
+
+    if (png_ptr != NULL && info_ptr != NULL &&
+        (info_ptr->valid & PNG_INFO_cICP) != 0 &&
+        colour_primaries != NULL && transfer_function != NULL &&
+        matrix_coefficients != NULL && video_full_range_flag != NULL)
+    {
+        *colour_primaries = info_ptr->cicp_colour_primaries;
+        *transfer_function = info_ptr->cicp_transfer_function;
+        *matrix_coefficients = info_ptr->cicp_matrix_coefficients;
+        *video_full_range_flag = info_ptr->cicp_video_full_range_flag;
+        return (PNG_INFO_cICP);
+    }
+
+    return 0;
+}
+#endif
+
+#ifdef PNG_cLLI_SUPPORTED
+#  ifdef PNG_FIXED_POINT_SUPPORTED
+png_uint_32 PNGAPI
+png_get_cLLI_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
+    png_uint_32p maxCLL,
+    png_uint_32p maxFALL)
+{
+   png_debug1(1, "in %s retrieval function", "cLLI");
+
+   if (png_ptr != NULL && info_ptr != NULL &&
+       (info_ptr->valid & PNG_INFO_cLLI) != 0)
+   {
+      if (maxCLL != NULL) *maxCLL = info_ptr->maxCLL;
+      if (maxFALL != NULL) *maxFALL = info_ptr->maxFALL;
+      return PNG_INFO_cLLI;
+   }
+
+   return 0;
+}
+#  endif
+
+#  ifdef PNG_FLOATING_POINT_SUPPORTED
+png_uint_32 PNGAPI
+png_get_cLLI(png_const_structrp png_ptr, png_const_inforp info_ptr,
+      double *maxCLL, double *maxFALL)
+{
+   png_debug1(1, "in %s retrieval function", "cLLI(float)");
+
+   if (png_ptr != NULL && info_ptr != NULL &&
+       (info_ptr->valid & PNG_INFO_cLLI) != 0)
+   {
+      if (maxCLL != NULL) *maxCLL = info_ptr->maxCLL * .0001;
+      if (maxFALL != NULL) *maxFALL = info_ptr->maxFALL * .0001;
+      return PNG_INFO_cLLI;
+   }
+
+   return 0;
+}
+#  endif
+#endif /* cLLI */
+
+#ifdef PNG_mDCV_SUPPORTED
+#  ifdef PNG_FIXED_POINT_SUPPORTED
+png_uint_32 PNGAPI
+png_get_mDCV_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
+    png_fixed_point *white_x, png_fixed_point *white_y,
+    png_fixed_point *red_x, png_fixed_point *red_y,
+    png_fixed_point *green_x, png_fixed_point *green_y,
+    png_fixed_point *blue_x, png_fixed_point *blue_y,
+    png_uint_32p mastering_maxDL, png_uint_32p mastering_minDL)
+{
+   png_debug1(1, "in %s retrieval function", "mDCV");
+
+   if (png_ptr != NULL && info_ptr != NULL &&
+       (info_ptr->valid & PNG_INFO_mDCV) != 0)
+   {
+      if (white_x != NULL) *white_x = info_ptr->mastering_white_x * 2;
+      if (white_y != NULL) *white_y = info_ptr->mastering_white_y * 2;
+      if (red_x != NULL) *red_x = info_ptr->mastering_red_x * 2;
+      if (red_y != NULL) *red_y = info_ptr->mastering_red_y * 2;
+      if (green_x != NULL) *green_x = info_ptr->mastering_green_x * 2;
+      if (green_y != NULL) *green_y = info_ptr->mastering_green_y * 2;
+      if (blue_x != NULL) *blue_x = info_ptr->mastering_blue_x * 2;
+      if (blue_y != NULL) *blue_y = info_ptr->mastering_blue_y * 2;
+      if (mastering_maxDL != NULL) *mastering_maxDL = info_ptr->mastering_maxDL;
+      if (mastering_minDL != NULL) *mastering_minDL = info_ptr->mastering_minDL;
+      return PNG_INFO_mDCV;
+   }
+
+   return 0;
+}
+#  endif
+
+#  ifdef PNG_FLOATING_POINT_SUPPORTED
+png_uint_32 PNGAPI
+png_get_mDCV(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,
+    double *mastering_maxDL, double *mastering_minDL)
+{
+   png_debug1(1, "in %s retrieval function", "mDCV(float)");
+
+   if (png_ptr != NULL && info_ptr != NULL &&
+       (info_ptr->valid & PNG_INFO_mDCV) != 0)
+   {
+      if (white_x != NULL) *white_x = info_ptr->mastering_white_x * .00002;
+      if (white_y != NULL) *white_y = info_ptr->mastering_white_y * .00002;
+      if (red_x != NULL) *red_x = info_ptr->mastering_red_x * .00002;
+      if (red_y != NULL) *red_y = info_ptr->mastering_red_y * .00002;
+      if (green_x != NULL) *green_x = info_ptr->mastering_green_x * .00002;
+      if (green_y != NULL) *green_y = info_ptr->mastering_green_y * .00002;
+      if (blue_x != NULL) *blue_x = info_ptr->mastering_blue_x * .00002;
+      if (blue_y != NULL) *blue_y = info_ptr->mastering_blue_y * .00002;
+      if (mastering_maxDL != NULL)
+         *mastering_maxDL = info_ptr->mastering_maxDL * .0001;
+      if (mastering_minDL != NULL)
+         *mastering_minDL = info_ptr->mastering_minDL * .0001;
+      return PNG_INFO_mDCV;
+   }
+
+   return 0;
+}
+#  endif /* FLOATING_POINT */
+#endif /* mDCV */
+
 #ifdef PNG_eXIf_SUPPORTED
 png_uint_32 PNGAPI
 png_get_eXIf(png_const_structrp png_ptr, png_inforp info_ptr,
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pnginfo.h b/src/java.desktop/share/native/libsplashscreen/libpng/pnginfo.h
index d241eaebffb..bc6ed3d09c9 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pnginfo.h
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pnginfo.h
@@ -115,18 +115,12 @@ struct png_info_def
     * and initialize the appropriate fields below.
     */
 
-#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED)
-   /* png_colorspace only contains 'flags' if neither GAMMA or COLORSPACE are
-    * defined.  When COLORSPACE is switched on all the colorspace-defining
-    * chunks should be enabled, when GAMMA is switched on all the gamma-defining
-    * chunks should be enabled.  If this is not done it becomes possible to read
-    * inconsistent PNG files and assign a probably incorrect interpretation to
-    * the information.  (In other words, by carefully choosing which chunks to
-    * recognize the system configuration can select an interpretation for PNG
-    * files containing ambiguous data and this will result in inconsistent
-    * behavior between different libpng builds!)
-    */
-   png_colorspace colorspace;
+#ifdef PNG_cICP_SUPPORTED
+   /* cICP chunk data */
+   png_byte cicp_colour_primaries;
+   png_byte cicp_transfer_function;
+   png_byte cicp_matrix_coefficients;
+   png_byte cicp_video_full_range_flag;
 #endif
 
 #ifdef PNG_iCCP_SUPPORTED
@@ -136,6 +130,24 @@ struct png_info_def
    png_uint_32 iccp_proflen;  /* ICC profile data length */
 #endif
 
+#ifdef PNG_cLLI_SUPPORTED
+   png_uint_32 maxCLL;  /* cd/m2 (nits) * 10,000 */
+   png_uint_32 maxFALL;
+#endif
+
+#ifdef PNG_mDCV_SUPPORTED
+   png_uint_16 mastering_red_x;  /* CIE (xy) x * 50,000 */
+   png_uint_16 mastering_red_y;
+   png_uint_16 mastering_green_x;
+   png_uint_16 mastering_green_y;
+   png_uint_16 mastering_blue_x;
+   png_uint_16 mastering_blue_y;
+   png_uint_16 mastering_white_x;
+   png_uint_16 mastering_white_y;
+   png_uint_32 mastering_maxDL; /* cd/m2 (nits) * 10,000 */
+   png_uint_32 mastering_minDL;
+#endif
+
 #ifdef PNG_TEXT_SUPPORTED
    /* The tEXt, and zTXt chunks contain human-readable textual data in
     * uncompressed, compressed, and optionally compressed forms, respectively.
@@ -214,11 +226,8 @@ defined(PNG_READ_BACKGROUND_SUPPORTED)
 #endif
 
 #ifdef PNG_eXIf_SUPPORTED
-   int num_exif;  /* Added at libpng-1.6.31 */
+   png_uint_32 num_exif;  /* Added at libpng-1.6.31 */
    png_bytep exif;
-# ifdef PNG_READ_eXIf_SUPPORTED
-   png_bytep eXIf_buf;  /* Added at libpng-1.6.32 */
-# endif
 #endif
 
 #ifdef PNG_hIST_SUPPORTED
@@ -291,5 +300,16 @@ defined(PNG_READ_BACKGROUND_SUPPORTED)
    png_bytepp row_pointers;        /* the image bits */
 #endif
 
+#ifdef PNG_cHRM_SUPPORTED
+   png_xy cHRM;
+#endif
+
+#ifdef PNG_gAMA_SUPPORTED
+   png_fixed_point gamma;
+#endif
+
+#ifdef PNG_sRGB_SUPPORTED
+   int rendering_intent;
+#endif
 };
 #endif /* PNGINFO_H */
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pnglibconf.h b/src/java.desktop/share/native/libsplashscreen/libpng/pnglibconf.h
index e78933bacf2..2150e046f25 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pnglibconf.h
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pnglibconf.h
@@ -31,9 +31,9 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  */
-/* libpng version 1.6.43 */
+/* libpng version 1.6.47 */
 
-/* Copyright (c) 2018-2023 Cosmin Truta */
+/* Copyright (c) 2018-2025 Cosmin Truta */
 /* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson */
 
 /* This code is released under the libpng license. */
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngmem.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngmem.c
index d5ad0735f37..ba9eb4df402 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngmem.c
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngmem.c
@@ -101,30 +101,29 @@ png_malloc_base,(png_const_structrp png_ptr, png_alloc_size_t size),
     * to implement a user memory handler.  This checks to be sure it isn't
     * called with big numbers.
     */
-#ifndef PNG_USER_MEM_SUPPORTED
-   PNG_UNUSED(png_ptr)
-#endif
+#  ifdef PNG_MAX_MALLOC_64K
+      /* This is support for legacy systems which had segmented addressing
+       * limiting the maximum allocation size to 65536.  It takes precedence
+       * over PNG_SIZE_MAX which is set to 65535 on true 16-bit systems.
+       *
+       * TODO: libpng-1.8: finally remove both cases.
+       */
+      if (size > 65536U) return NULL;
+#  endif
 
-   /* Some compilers complain that this is always true.  However, it
-    * can be false when integer overflow happens.
+   /* This is checked too because the system malloc call below takes a (size_t).
     */
-   if (size > 0 && size <= PNG_SIZE_MAX
-#     ifdef PNG_MAX_MALLOC_64K
-         && size <= 65536U
-#     endif
-      )
-   {
-#ifdef PNG_USER_MEM_SUPPORTED
+   if (size > PNG_SIZE_MAX) return NULL;
+
+#  ifdef PNG_USER_MEM_SUPPORTED
       if (png_ptr != NULL && png_ptr->malloc_fn != NULL)
          return png_ptr->malloc_fn(png_constcast(png_structrp,png_ptr), size);
+#  else
+      PNG_UNUSED(png_ptr)
+#  endif
 
-      else
-#endif
-         return malloc((size_t)size); /* checked for truncation above */
-   }
-
-   else
-      return NULL;
+   /* Use the system malloc */
+   return malloc((size_t)/*SAFE*/size); /* checked for truncation above */
 }
 
 #if defined(PNG_TEXT_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) ||\
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngpread.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngpread.c
index 816631cae18..86d0c7aaa64 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngpread.c
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngpread.c
@@ -60,6 +60,21 @@ if (png_ptr->push_length + 4 > png_ptr->buffer_size) \
 if (png_ptr->buffer_size < N) \
    { png_push_save_buffer(png_ptr); return; }
 
+#ifdef PNG_READ_INTERLACING_SUPPORTED
+/* Arrays to facilitate interlacing - use pass (0 - 6) as index. */
+
+/* Start of interlace block */
+static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
+/* Offset to next interlace block */
+static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+/* Start of interlace block in the y direction */
+static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
+/* Offset to next interlace block in the y direction */
+static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
+
+/* TODO: Move these arrays to a common utility module to avoid duplication. */
+#endif
+
 void PNGAPI
 png_process_data(png_structrp png_ptr, png_inforp info_ptr,
     png_bytep buffer, size_t buffer_size)
@@ -207,17 +222,8 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
     */
    if ((png_ptr->mode & PNG_HAVE_CHUNK_HEADER) == 0)
    {
-      png_byte chunk_length[4];
-      png_byte chunk_tag[4];
-
       PNG_PUSH_SAVE_BUFFER_IF_LT(8)
-      png_push_fill_buffer(png_ptr, chunk_length, 4);
-      png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
-      png_reset_crc(png_ptr);
-      png_crc_read(png_ptr, chunk_tag, 4);
-      png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag);
-      png_check_chunk_name(png_ptr, png_ptr->chunk_name);
-      png_check_chunk_length(png_ptr, png_ptr->push_length);
+      png_ptr->push_length = png_read_chunk_header(png_ptr);
       png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
    }
 
@@ -258,13 +264,13 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
          png_error(png_ptr, "Invalid IHDR length");
 
       PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length);
+      png_handle_chunk(png_ptr, info_ptr, png_ptr->push_length);
    }
 
    else if (chunk_name == png_IEND)
    {
       PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length);
+      png_handle_chunk(png_ptr, info_ptr, png_ptr->push_length);
 
       png_ptr->process_mode = PNG_READ_DONE_MODE;
       png_push_have_end(png_ptr, info_ptr);
@@ -281,12 +287,6 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
    }
 #endif
 
-   else if (chunk_name == png_PLTE)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length);
-   }
-
    else if (chunk_name == png_IDAT)
    {
       png_ptr->idat_size = png_ptr->push_length;
@@ -299,155 +299,10 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
       return;
    }
 
-#ifdef PNG_READ_gAMA_SUPPORTED
-   else if (png_ptr->chunk_name == png_gAMA)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length);
-   }
-
-#endif
-#ifdef PNG_READ_sBIT_SUPPORTED
-   else if (png_ptr->chunk_name == png_sBIT)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length);
-   }
-
-#endif
-#ifdef PNG_READ_cHRM_SUPPORTED
-   else if (png_ptr->chunk_name == png_cHRM)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length);
-   }
-
-#endif
-#ifdef PNG_READ_eXIf_SUPPORTED
-   else if (png_ptr->chunk_name == png_eXIf)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_eXIf(png_ptr, info_ptr, png_ptr->push_length);
-   }
-
-#endif
-#ifdef PNG_READ_sRGB_SUPPORTED
-   else if (chunk_name == png_sRGB)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length);
-   }
-
-#endif
-#ifdef PNG_READ_iCCP_SUPPORTED
-   else if (png_ptr->chunk_name == png_iCCP)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length);
-   }
-
-#endif
-#ifdef PNG_READ_sPLT_SUPPORTED
-   else if (chunk_name == png_sPLT)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length);
-   }
-
-#endif
-#ifdef PNG_READ_tRNS_SUPPORTED
-   else if (chunk_name == png_tRNS)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length);
-   }
-
-#endif
-#ifdef PNG_READ_bKGD_SUPPORTED
-   else if (chunk_name == png_bKGD)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length);
-   }
-
-#endif
-#ifdef PNG_READ_hIST_SUPPORTED
-   else if (chunk_name == png_hIST)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length);
-   }
-
-#endif
-#ifdef PNG_READ_pHYs_SUPPORTED
-   else if (chunk_name == png_pHYs)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length);
-   }
-
-#endif
-#ifdef PNG_READ_oFFs_SUPPORTED
-   else if (chunk_name == png_oFFs)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length);
-   }
-#endif
-
-#ifdef PNG_READ_pCAL_SUPPORTED
-   else if (chunk_name == png_pCAL)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length);
-   }
-
-#endif
-#ifdef PNG_READ_sCAL_SUPPORTED
-   else if (chunk_name == png_sCAL)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length);
-   }
-
-#endif
-#ifdef PNG_READ_tIME_SUPPORTED
-   else if (chunk_name == png_tIME)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length);
-   }
-
-#endif
-#ifdef PNG_READ_tEXt_SUPPORTED
-   else if (chunk_name == png_tEXt)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length);
-   }
-
-#endif
-#ifdef PNG_READ_zTXt_SUPPORTED
-   else if (chunk_name == png_zTXt)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length);
-   }
-
-#endif
-#ifdef PNG_READ_iTXt_SUPPORTED
-   else if (chunk_name == png_iTXt)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
-   }
-#endif
-
    else
    {
       PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length,
-          PNG_HANDLE_CHUNK_AS_DEFAULT);
+      png_handle_chunk(png_ptr, info_ptr, png_ptr->push_length);
    }
 
    png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
@@ -1004,27 +859,6 @@ png_push_process_row(png_structrp png_ptr)
 void /* PRIVATE */
 png_read_push_finish_row(png_structrp png_ptr)
 {
-#ifdef PNG_READ_INTERLACING_SUPPORTED
-   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
-
-   /* Start of interlace block */
-   static const png_byte png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
-
-   /* Offset to next interlace block */
-   static const png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
-
-   /* Start of interlace block in the y direction */
-   static const png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
-
-   /* Offset to next interlace block in the y direction */
-   static const png_byte png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
-
-   /* Height of interlace block.  This is not currently used - if you need
-    * it, uncomment it here and in png.h
-   static const png_byte png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
-   */
-#endif
-
    png_ptr->row_number++;
    if (png_ptr->row_number < png_ptr->num_rows)
       return;
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngpriv.h b/src/java.desktop/share/native/libsplashscreen/libpng/pngpriv.h
index 18424542b00..25bac4b9e69 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngpriv.h
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngpriv.h
@@ -168,47 +168,6 @@
     * callbacks to do this.
     */
 #  define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_neon
-
-   /* By default the 'intrinsics' code in arm/filter_neon_intrinsics.c is used
-    * if possible - if __ARM_NEON__ is set and the compiler version is not known
-    * to be broken.  This is controlled by PNG_ARM_NEON_IMPLEMENTATION which can
-    * be:
-    *
-    *    1  The intrinsics code (the default with __ARM_NEON__)
-    *    2  The hand coded assembler (the default without __ARM_NEON__)
-    *
-    * It is possible to set PNG_ARM_NEON_IMPLEMENTATION in CPPFLAGS, however
-    * this is *NOT* supported and may cease to work even after a minor revision
-    * to libpng.  It *is* valid to do this for testing purposes, e.g. speed
-    * testing or a new compiler, but the results should be communicated to the
-    * libpng implementation list for incorporation in the next minor release.
-    */
-#  ifndef PNG_ARM_NEON_IMPLEMENTATION
-#     if defined(__ARM_NEON__) || defined(__ARM_NEON)
-#        if defined(__clang__)
-            /* At present it is unknown by the libpng developers which versions
-             * of clang support the intrinsics, however some or perhaps all
-             * versions do not work with the assembler so this may be
-             * irrelevant, so just use the default (do nothing here.)
-             */
-#        elif defined(__GNUC__)
-            /* GCC 4.5.4 NEON support is known to be broken.  4.6.3 is known to
-             * work, so if this *is* GCC, or G++, look for a version >4.5
-             */
-#           if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)
-#              define PNG_ARM_NEON_IMPLEMENTATION 2
-#           endif /* no GNUC support */
-#        endif /* __GNUC__ */
-#     else /* !defined __ARM_NEON__ */
-         /* The 'intrinsics' code simply won't compile without this -mfpu=neon:
-          */
-#        if !defined(__aarch64__) && !defined(_M_ARM64)
-            /* The assembler code currently does not work on ARM64 */
-#          define PNG_ARM_NEON_IMPLEMENTATION 2
-#        endif /* __aarch64__ */
-#     endif /* __ARM_NEON__ */
-#  endif /* !PNG_ARM_NEON_IMPLEMENTATION */
-
 #  ifndef PNG_ARM_NEON_IMPLEMENTATION
       /* Use the intrinsics code by default. */
 #     define PNG_ARM_NEON_IMPLEMENTATION 1
@@ -741,7 +700,7 @@
 #define PNG_FLAG_CRC_ANCILLARY_NOWARN     0x0200U
 #define PNG_FLAG_CRC_CRITICAL_USE         0x0400U
 #define PNG_FLAG_CRC_CRITICAL_IGNORE      0x0800U
-#define PNG_FLAG_ASSUME_sRGB              0x1000U /* Added to libpng-1.5.4 */
+/*      PNG_FLAG_ASSUME_sRGB unused       0x1000U  * Added to libpng-1.5.4 */
 #define PNG_FLAG_OPTIMIZE_ALPHA           0x2000U /* Added to libpng-1.5.4 */
 #define PNG_FLAG_DETECT_UNINITIALIZED     0x4000U /* Added to libpng-1.5.4 */
 /* #define PNG_FLAG_KEEP_UNKNOWN_CHUNKS      0x8000U */
@@ -852,6 +811,8 @@
 #ifdef PNG_FIXED_POINT_MACRO_SUPPORTED
 #define png_fixed(png_ptr, fp, s) ((fp) <= 21474 && (fp) >= -21474 ?\
     ((png_fixed_point)(100000 * (fp))) : (png_fixed_error(png_ptr, s),0))
+#define png_fixed_ITU(png_ptr, fp, s) ((fp) <= 214748 && (fp) >= 0 ?\
+    ((png_uint_32)(10000 * (fp))) : (png_fixed_error(png_ptr, s),0))
 #endif
 /* else the corresponding function is defined below, inside the scope of the
  * cplusplus test.
@@ -870,11 +831,31 @@
  *
  * PNG_32b correctly produces a value shifted by up to 24 bits, even on
  * architectures where (int) is only 16 bits.
+ *
+ * 1.6.47: PNG_32b was made into a preprocessor evaluable macro by replacing the
+ * static_cast with a promoting binary operation using a guaranteed 32-bit
+ * (minimum) unsigned value.
  */
-#define PNG_32b(b,s) ((png_uint_32)(b) << (s))
+#define PNG_32b(b,s) (((0xFFFFFFFFU)&(b)) << (s))
 #define PNG_U32(b1,b2,b3,b4) \
    (PNG_32b(b1,24) | PNG_32b(b2,16) | PNG_32b(b3,8) | PNG_32b(b4,0))
 
+/* Chunk name validation.  When using these macros all the arguments should be
+ * constants, otherwise code bloat may well occur.  The macros are provided
+ * primarily for use in #if checks.
+ *
+ * PNG_32to8 produces a byte value with the right shift; used to extract the
+ * byte value from a chunk name.
+ */
+#define PNG_32to8(cn,s) (((cn) >> (s)) & 0xffU)
+#define PNG_CN_VALID_UPPER(b) ((b) >= 65 && (b) <= 90) /* upper-case ASCII */
+#define PNG_CN_VALID_ASCII(b) PNG_CN_VALID_UPPER((b) & ~32U)
+#define PNG_CHUNK_NAME_VALID(cn) (\
+   PNG_CN_VALID_ASCII(PNG_32to8(cn,24)) && /* critical, !ancillary */\
+   PNG_CN_VALID_ASCII(PNG_32to8(cn,16)) && /* public, !privately defined */\
+   PNG_CN_VALID_UPPER(PNG_32to8(cn, 8)) && /* VALID, !reserved */\
+   PNG_CN_VALID_ASCII(PNG_32to8(cn, 0))   /* data-dependent, !copy ok */)
+
 /* Constants for known chunk types.
  *
  * MAINTAINERS: If you need to add a chunk, define the name here.
@@ -902,9 +883,14 @@
 #define png_IEND PNG_U32( 73,  69,  78,  68)
 #define png_IHDR PNG_U32( 73,  72,  68,  82)
 #define png_PLTE PNG_U32( 80,  76,  84,  69)
+#define png_acTL PNG_U32( 97,  99,  84,  76) /* PNGv3: APNG */
 #define png_bKGD PNG_U32( 98,  75,  71,  68)
 #define png_cHRM PNG_U32( 99,  72,  82,  77)
+#define png_cICP PNG_U32( 99,  73,  67,  80) /* PNGv3 */
+#define png_cLLI PNG_U32( 99,  76,  76,  73) /* PNGv3 */
 #define png_eXIf PNG_U32(101,  88,  73, 102) /* registered July 2017 */
+#define png_fcTL PNG_U32(102,  99,  84,  76) /* PNGv3: APNG */
+#define png_fdAT PNG_U32(102, 100,  65,  84) /* PNGv3: APNG */
 #define png_fRAc PNG_U32(102,  82,  65,  99) /* registered, not defined */
 #define png_gAMA PNG_U32(103,  65,  77,  65)
 #define png_gIFg PNG_U32(103,  73,  70, 103)
@@ -913,6 +899,7 @@
 #define png_hIST PNG_U32(104,  73,  83,  84)
 #define png_iCCP PNG_U32(105,  67,  67,  80)
 #define png_iTXt PNG_U32(105,  84,  88, 116)
+#define png_mDCV PNG_U32(109,  68,  67,  86) /* PNGv3 */
 #define png_oFFs PNG_U32(111,  70,  70, 115)
 #define png_pCAL PNG_U32(112,  67,  65,  76)
 #define png_pHYs PNG_U32(112,  72,  89, 115)
@@ -953,11 +940,74 @@
 #define PNG_CHUNK_RESERVED(c)     (1 & ((c) >> 13))
 #define PNG_CHUNK_SAFE_TO_COPY(c) (1 & ((c) >>  5))
 
+/* Known chunks.  All supported chunks must be listed here.  The macro PNG_CHUNK
+ * contains the four character ASCII name by which the chunk is identified.  The
+ * macro is implemented as required to build tables or switch statements which
+ * require entries for every known chunk.  The macro also contains an index
+ * value which should be in order (this is checked in png.c).
+ *
+ * Notice that "known" does not require "SUPPORTED"; tables should be built in
+ * such a way that chunks unsupported in a build require no more than the table
+ * entry (which should be small.)  In particular function pointers for
+ * unsupported chunks should be NULL.
+ *
+ * At present these index values are not exported (not part of the public API)
+ * so can be changed at will.  For convenience the names are in lexical sort
+ * order but with the critical chunks at the start in the order of occurence in
+ * a PNG.
+ *
+ * PNG_INFO_ values do not exist for every one of these chunk handles; for
+ * example PNG_INFO_{IDAT,IEND,tEXt,iTXt,zTXt} and possibly other chunks in the
+ * future.
+ */
+#define PNG_KNOWN_CHUNKS\
+   PNG_CHUNK(IHDR,  0)\
+   PNG_CHUNK(PLTE,  1)\
+   PNG_CHUNK(IDAT,  2)\
+   PNG_CHUNK(IEND,  3)\
+   PNG_CHUNK(acTL,  4)\
+   PNG_CHUNK(bKGD,  5)\
+   PNG_CHUNK(cHRM,  6)\
+   PNG_CHUNK(cICP,  7)\
+   PNG_CHUNK(cLLI,  8)\
+   PNG_CHUNK(eXIf,  9)\
+   PNG_CHUNK(fcTL, 10)\
+   PNG_CHUNK(fdAT, 11)\
+   PNG_CHUNK(gAMA, 12)\
+   PNG_CHUNK(hIST, 13)\
+   PNG_CHUNK(iCCP, 14)\
+   PNG_CHUNK(iTXt, 15)\
+   PNG_CHUNK(mDCV, 16)\
+   PNG_CHUNK(oFFs, 17)\
+   PNG_CHUNK(pCAL, 18)\
+   PNG_CHUNK(pHYs, 19)\
+   PNG_CHUNK(sBIT, 20)\
+   PNG_CHUNK(sCAL, 21)\
+   PNG_CHUNK(sPLT, 22)\
+   PNG_CHUNK(sRGB, 23)\
+   PNG_CHUNK(tEXt, 24)\
+   PNG_CHUNK(tIME, 25)\
+   PNG_CHUNK(tRNS, 26)\
+   PNG_CHUNK(zTXt, 27)
+
 /* Gamma values (new at libpng-1.5.4): */
 #define PNG_GAMMA_MAC_OLD 151724  /* Assume '1.8' is really 2.2/1.45! */
 #define PNG_GAMMA_MAC_INVERSE 65909
 #define PNG_GAMMA_sRGB_INVERSE 45455
 
+/* gamma sanity check.  libpng cannot implement gamma transforms outside a
+ * certain limit because of its use of 16-bit fixed point intermediate values.
+ * Gamma values that are too large or too small will zap the 16-bit values all
+ * to 0 or 65535 resulting in an obvious 'bad' image.
+ *
+ * In libpng 1.6.0 the limits were changed from 0.07..3 to 0.01..100 to
+ * accommodate the optimal 16-bit gamma of 36 and its reciprocal.
+ *
+ * These are png_fixed_point integral values:
+ */
+#define PNG_LIB_GAMMA_MIN 1000
+#define PNG_LIB_GAMMA_MAX 10000000
+
 /* Almost everything below is C specific; the #defines above can be used in
  * non-C code (so long as it is C-preprocessed) the rest of this stuff cannot.
  */
@@ -1021,7 +1071,6 @@ extern "C" {
  *
  * All of these functions must be declared with PNG_INTERNAL_FUNCTION.
  */
-
 /* Zlib support */
 #define PNG_UNEXPECTED_ZLIB_RETURN (-7)
 PNG_INTERNAL_FUNCTION(void, png_zstream_error,(png_structrp png_ptr, int ret),
@@ -1040,6 +1089,7 @@ PNG_INTERNAL_FUNCTION(void,png_free_buffer_list,(png_structrp png_ptr,
    !defined(PNG_FIXED_POINT_MACRO_SUPPORTED) && \
    (defined(PNG_gAMA_SUPPORTED) || defined(PNG_cHRM_SUPPORTED) || \
    defined(PNG_sCAL_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) || \
+   defined(PNG_mDCV_SUPPORTED) || \
    defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)) || \
    (defined(PNG_sCAL_SUPPORTED) && \
    defined(PNG_FLOATING_ARITHMETIC_SUPPORTED))
@@ -1047,12 +1097,38 @@ PNG_INTERNAL_FUNCTION(png_fixed_point,png_fixed,(png_const_structrp png_ptr,
    double fp, png_const_charp text),PNG_EMPTY);
 #endif
 
+#if defined(PNG_FLOATING_POINT_SUPPORTED) && \
+   !defined(PNG_FIXED_POINT_MACRO_SUPPORTED) && \
+   (defined(PNG_cLLI_SUPPORTED) || defined(PNG_mDCV_SUPPORTED))
+PNG_INTERNAL_FUNCTION(png_uint_32,png_fixed_ITU,(png_const_structrp png_ptr,
+   double fp, png_const_charp text),PNG_EMPTY);
+#endif
+
 /* Check the user version string for compatibility, returns false if the version
  * numbers aren't compatible.
  */
 PNG_INTERNAL_FUNCTION(int,png_user_version_check,(png_structrp png_ptr,
    png_const_charp user_png_ver),PNG_EMPTY);
 
+#ifdef PNG_READ_SUPPORTED /* should only be used on read */
+/* Security: read limits on the largest allocations while reading a PNG.  This
+ * avoids very large allocations caused by PNG files with damaged or altered
+ * chunk 'length' fields.
+ */
+#ifdef PNG_SET_USER_LIMITS_SUPPORTED /* run-time limit */
+#  define png_chunk_max(png_ptr) ((png_ptr)->user_chunk_malloc_max)
+
+#elif PNG_USER_CHUNK_MALLOC_MAX > 0 /* compile-time limit */
+#  define png_chunk_max(png_ptr) ((void)png_ptr, PNG_USER_CHUNK_MALLOC_MAX)
+
+#elif (defined PNG_MAX_MALLOC_64K)  /* legacy system limit */
+#  define png_chunk_max(png_ptr) ((void)png_ptr, 65536U)
+
+#else                               /* modern system limit SIZE_MAX (C99) */
+#  define png_chunk_max(png_ptr) ((void)png_ptr, PNG_SIZE_MAX)
+#endif
+#endif /* READ */
+
 /* Internal base allocator - no messages, NULL on failure to allocate.  This
  * does, however, call the application provided allocator and that could call
  * png_error (although that would be a bug in the application implementation.)
@@ -1152,9 +1228,6 @@ PNG_INTERNAL_FUNCTION(void,png_crc_read,(png_structrp png_ptr, png_bytep buf,
 PNG_INTERNAL_FUNCTION(int,png_crc_finish,(png_structrp png_ptr,
    png_uint_32 skip),PNG_EMPTY);
 
-/* Read the CRC from the file and compare it to the libpng calculated CRC */
-PNG_INTERNAL_FUNCTION(int,png_crc_error,(png_structrp png_ptr),PNG_EMPTY);
-
 /* Calculate the CRC over a section of data.  Note that we are only
  * passing a maximum of 64K on systems that have this as a memory limit,
  * since this is the maximum buffer size we can specify.
@@ -1200,6 +1273,26 @@ PNG_INTERNAL_FUNCTION(void,png_write_cHRM_fixed,(png_structrp png_ptr,
    /* The xy value must have been previously validated */
 #endif
 
+#ifdef PNG_WRITE_cICP_SUPPORTED
+PNG_INTERNAL_FUNCTION(void,png_write_cICP,(png_structrp png_ptr,
+    png_byte colour_primaries, png_byte transfer_function,
+    png_byte matrix_coefficients, png_byte video_full_range_flag), PNG_EMPTY);
+#endif
+
+#ifdef PNG_WRITE_cLLI_SUPPORTED
+PNG_INTERNAL_FUNCTION(void,png_write_cLLI_fixed,(png_structrp png_ptr,
+   png_uint_32 maxCLL, png_uint_32 maxFALL), PNG_EMPTY);
+#endif
+
+#ifdef PNG_WRITE_mDCV_SUPPORTED
+PNG_INTERNAL_FUNCTION(void,png_write_mDCV_fixed,(png_structrp png_ptr,
+   png_uint_16 red_x, png_uint_16 red_y,
+   png_uint_16 green_x, png_uint_16 green_y,
+   png_uint_16 blue_x, png_uint_16 blue_y,
+   png_uint_16 white_x, png_uint_16 white_y,
+   png_uint_32 maxDL, png_uint_32 minDL), PNG_EMPTY);
+#endif
+
 #ifdef PNG_WRITE_sRGB_SUPPORTED
 PNG_INTERNAL_FUNCTION(void,png_write_sRGB,(png_structrp png_ptr,
     int intent),PNG_EMPTY);
@@ -1212,10 +1305,10 @@ PNG_INTERNAL_FUNCTION(void,png_write_eXIf,(png_structrp png_ptr,
 
 #ifdef PNG_WRITE_iCCP_SUPPORTED
 PNG_INTERNAL_FUNCTION(void,png_write_iCCP,(png_structrp png_ptr,
-   png_const_charp name, png_const_bytep profile), PNG_EMPTY);
-   /* The profile must have been previously validated for correctness, the
-    * length comes from the first four bytes.  Only the base, deflate,
-    * compression is supported.
+   png_const_charp name, png_const_bytep profile, png_uint_32 proflen),
+   PNG_EMPTY);
+   /* Writes a previously 'set' profile.  The profile argument is **not**
+    * compressed.
     */
 #endif
 
@@ -1524,119 +1617,36 @@ PNG_INTERNAL_FUNCTION(void,png_do_bgr,(png_row_infop row_info,
 /* The following decodes the appropriate chunks, and does error correction,
  * then calls the appropriate callback for the chunk if it is valid.
  */
-
-/* Decode the IHDR chunk */
-PNG_INTERNAL_FUNCTION(void,png_handle_IHDR,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_handle_PLTE,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_handle_IEND,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-
-#ifdef PNG_READ_bKGD_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_bKGD,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_cHRM_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_cHRM,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_eXIf_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_eXIf,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_gAMA_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_gAMA,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_hIST_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_hIST,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_iCCP_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_iCCP,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-#endif /* READ_iCCP */
-
-#ifdef PNG_READ_iTXt_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_iTXt,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_oFFs_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_oFFs,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_pCAL_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_pCAL,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_pHYs_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_pHYs,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_sBIT_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_sBIT,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_sCAL_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_sCAL,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_sPLT_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_sPLT,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-#endif /* READ_sPLT */
-
-#ifdef PNG_READ_sRGB_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_sRGB,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_tEXt_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_tEXt,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_tIME_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_tIME,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_tRNS_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_tRNS,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_zTXt_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_zTXt,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-#endif
-
-PNG_INTERNAL_FUNCTION(void,png_check_chunk_name,(png_const_structrp png_ptr,
-    png_uint_32 chunk_name),PNG_EMPTY);
-
-PNG_INTERNAL_FUNCTION(void,png_check_chunk_length,(png_const_structrp png_ptr,
-    png_uint_32 chunk_length),PNG_EMPTY);
-
-PNG_INTERNAL_FUNCTION(void,png_handle_unknown,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length, int keep),PNG_EMPTY);
+typedef enum
+{
+   /* Result of a call to png_handle_chunk made to handle the current chunk
+    * png_struct::chunk_name on read.  Always informational, either the stream
+    * is read for the next chunk or the routine will call png_error.
+    *
+    * NOTE: order is important internally.  handled_saved and above are regarded
+    * as handling the chunk.
+    */
+   handled_error = 0,  /* bad crc or known and bad format or too long */
+   handled_discarded,  /* not saved in the unknown chunk list */
+   handled_saved,      /* saved in the unknown chunk list */
+   handled_ok          /* known, supported and handled without error */
+} png_handle_result_code;
+
+PNG_INTERNAL_FUNCTION(png_handle_result_code,png_handle_unknown,
+    (png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length, int keep),
+    PNG_EMPTY);
    /* This is the function that gets called for unknown chunks.  The 'keep'
     * argument is either non-zero for a known chunk that has been set to be
     * handled as unknown or zero for an unknown chunk.  By default the function
     * just skips the chunk or errors out if it is critical.
     */
 
+PNG_INTERNAL_FUNCTION(png_handle_result_code,png_handle_chunk,
+    (png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+   /* This handles the current chunk png_ptr->chunk_name with unread
+    * data[length] and returns one of the above result codes.
+    */
+
 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) ||\
     defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED)
 PNG_INTERNAL_FUNCTION(int,png_chunk_unknown_handling,
@@ -1676,8 +1686,6 @@ PNG_INTERNAL_FUNCTION(void,png_process_IDAT_data,(png_structrp png_ptr,
     png_bytep buffer, size_t buffer_length),PNG_EMPTY);
 PNG_INTERNAL_FUNCTION(void,png_push_process_row,(png_structrp png_ptr),
     PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_push_handle_unknown,(png_structrp png_ptr,
-   png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
 PNG_INTERNAL_FUNCTION(void,png_push_have_info,(png_structrp png_ptr,
    png_inforp info_ptr),PNG_EMPTY);
 PNG_INTERNAL_FUNCTION(void,png_push_have_end,(png_structrp png_ptr,
@@ -1690,109 +1698,28 @@ PNG_INTERNAL_FUNCTION(void,png_process_some_data,(png_structrp png_ptr,
     png_inforp info_ptr),PNG_EMPTY);
 PNG_INTERNAL_FUNCTION(void,png_read_push_finish_row,(png_structrp png_ptr),
     PNG_EMPTY);
-#  ifdef PNG_READ_tEXt_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_push_handle_tEXt,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_push_read_tEXt,(png_structrp png_ptr,
-    png_inforp info_ptr),PNG_EMPTY);
-#  endif
-#  ifdef PNG_READ_zTXt_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_push_handle_zTXt,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_push_read_zTXt,(png_structrp png_ptr,
-    png_inforp info_ptr),PNG_EMPTY);
-#  endif
-#  ifdef PNG_READ_iTXt_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_push_handle_iTXt,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_push_read_iTXt,(png_structrp png_ptr,
-    png_inforp info_ptr),PNG_EMPTY);
-#  endif
-
 #endif /* PROGRESSIVE_READ */
 
-/* Added at libpng version 1.6.0 */
-#ifdef PNG_GAMMA_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_colorspace_set_gamma,(png_const_structrp png_ptr,
-    png_colorspacerp colorspace, png_fixed_point gAMA), PNG_EMPTY);
-   /* Set the colorspace gamma with a value provided by the application or by
-    * the gAMA chunk on read.  The value will override anything set by an ICC
-    * profile.
-    */
-
-PNG_INTERNAL_FUNCTION(void,png_colorspace_sync_info,(png_const_structrp png_ptr,
-    png_inforp info_ptr), PNG_EMPTY);
-   /* Synchronize the info 'valid' flags with the colorspace */
-
-PNG_INTERNAL_FUNCTION(void,png_colorspace_sync,(png_const_structrp png_ptr,
-    png_inforp info_ptr), PNG_EMPTY);
-   /* Copy the png_struct colorspace to the info_struct and call the above to
-    * synchronize the flags.  Checks for NULL info_ptr and does nothing.
-    */
-#endif
-
-/* Added at libpng version 1.4.0 */
-#ifdef PNG_COLORSPACE_SUPPORTED
-/* These internal functions are for maintaining the colorspace structure within
- * a png_info or png_struct (or, indeed, both).
- */
-PNG_INTERNAL_FUNCTION(int,png_colorspace_set_chromaticities,
-   (png_const_structrp png_ptr, png_colorspacerp colorspace, const png_xy *xy,
-    int preferred), PNG_EMPTY);
-
-PNG_INTERNAL_FUNCTION(int,png_colorspace_set_endpoints,
-   (png_const_structrp png_ptr, png_colorspacerp colorspace, const png_XYZ *XYZ,
-    int preferred), PNG_EMPTY);
-
-#ifdef PNG_sRGB_SUPPORTED
-PNG_INTERNAL_FUNCTION(int,png_colorspace_set_sRGB,(png_const_structrp png_ptr,
-   png_colorspacerp colorspace, int intent), PNG_EMPTY);
-   /* This does set the colorspace gAMA and cHRM values too, but doesn't set the
-    * flags to write them, if it returns false there was a problem and an error
-    * message has already been output (but the colorspace may still need to be
-    * synced to record the invalid flag).
-    */
-#endif /* sRGB */
-
 #ifdef PNG_iCCP_SUPPORTED
-PNG_INTERNAL_FUNCTION(int,png_colorspace_set_ICC,(png_const_structrp png_ptr,
-   png_colorspacerp colorspace, png_const_charp name,
-   png_uint_32 profile_length, png_const_bytep profile, int color_type),
-   PNG_EMPTY);
-   /* The 'name' is used for information only */
-
 /* Routines for checking parts of an ICC profile. */
 #ifdef PNG_READ_iCCP_SUPPORTED
 PNG_INTERNAL_FUNCTION(int,png_icc_check_length,(png_const_structrp png_ptr,
-   png_colorspacerp colorspace, png_const_charp name,
-   png_uint_32 profile_length), PNG_EMPTY);
+   png_const_charp name, png_uint_32 profile_length), PNG_EMPTY);
 #endif /* READ_iCCP */
 PNG_INTERNAL_FUNCTION(int,png_icc_check_header,(png_const_structrp png_ptr,
-   png_colorspacerp colorspace, png_const_charp name,
-   png_uint_32 profile_length,
+   png_const_charp name, png_uint_32 profile_length,
    png_const_bytep profile /* first 132 bytes only */, int color_type),
    PNG_EMPTY);
 PNG_INTERNAL_FUNCTION(int,png_icc_check_tag_table,(png_const_structrp png_ptr,
-   png_colorspacerp colorspace, png_const_charp name,
-   png_uint_32 profile_length,
+   png_const_charp name, png_uint_32 profile_length,
    png_const_bytep profile /* header plus whole tag table */), PNG_EMPTY);
-#ifdef PNG_sRGB_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_icc_set_sRGB,(
-   png_const_structrp png_ptr, png_colorspacerp colorspace,
-   png_const_bytep profile, uLong adler), PNG_EMPTY);
-   /* 'adler' is the Adler32 checksum of the uncompressed profile data. It may
-    * be zero to indicate that it is not available.  It is used, if provided,
-    * as a fast check on the profile when checking to see if it is sRGB.
-    */
-#endif
 #endif /* iCCP */
 
 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_colorspace_set_rgb_coefficients,
-   (png_structrp png_ptr), PNG_EMPTY);
-   /* Set the rgb_to_gray coefficients from the colorspace Y values */
+PNG_INTERNAL_FUNCTION(void,png_set_rgb_coefficients, (png_structrp png_ptr),
+   PNG_EMPTY);
+   /* Set the rgb_to_gray coefficients from the cHRM Y values (if unset) */
 #endif /* READ_RGB_TO_GRAY */
-#endif /* COLORSPACE */
 
 /* Added at libpng version 1.4.0 */
 PNG_INTERNAL_FUNCTION(void,png_check_IHDR,(png_const_structrp png_ptr,
@@ -2054,8 +1981,10 @@ PNG_INTERNAL_FUNCTION(int,png_check_fp_string,(png_const_charp string,
    size_t size),PNG_EMPTY);
 #endif /* pCAL || sCAL */
 
-#if defined(PNG_GAMMA_SUPPORTED) ||\
-    defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG_READ_pHYs_SUPPORTED)
+#if defined(PNG_READ_GAMMA_SUPPORTED) ||\
+    defined(PNG_COLORSPACE_SUPPORTED) ||\
+    defined(PNG_INCH_CONVERSIONS_SUPPORTED) ||\
+    defined(PNG_READ_pHYs_SUPPORTED)
 /* Added at libpng version 1.5.0 */
 /* This is a utility to provide a*times/div (rounded) and indicate
  * if there is an overflow.  The result is a boolean - false (0)
@@ -2064,22 +1993,14 @@ PNG_INTERNAL_FUNCTION(int,png_check_fp_string,(png_const_charp string,
  */
 PNG_INTERNAL_FUNCTION(int,png_muldiv,(png_fixed_point_p res, png_fixed_point a,
    png_int_32 multiplied_by, png_int_32 divided_by),PNG_EMPTY);
-#endif
-
-#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED)
-/* Same deal, but issue a warning on overflow and return 0. */
-PNG_INTERNAL_FUNCTION(png_fixed_point,png_muldiv_warn,
-   (png_const_structrp png_ptr, png_fixed_point a, png_int_32 multiplied_by,
-   png_int_32 divided_by),PNG_EMPTY);
-#endif
 
-#ifdef PNG_GAMMA_SUPPORTED
 /* Calculate a reciprocal - used for gamma values.  This returns
  * 0 if the argument is 0 in order to maintain an undefined value;
  * there are no warnings.
  */
 PNG_INTERNAL_FUNCTION(png_fixed_point,png_reciprocal,(png_fixed_point a),
    PNG_EMPTY);
+#endif
 
 #ifdef PNG_READ_GAMMA_SUPPORTED
 /* The same but gives a reciprocal of the product of two fixed point
@@ -2088,14 +2009,22 @@ PNG_INTERNAL_FUNCTION(png_fixed_point,png_reciprocal,(png_fixed_point a),
  */
 PNG_INTERNAL_FUNCTION(png_fixed_point,png_reciprocal2,(png_fixed_point a,
    png_fixed_point b),PNG_EMPTY);
-#endif
 
 /* Return true if the gamma value is significantly different from 1.0 */
 PNG_INTERNAL_FUNCTION(int,png_gamma_significant,(png_fixed_point gamma_value),
    PNG_EMPTY);
-#endif
 
-#ifdef PNG_READ_GAMMA_SUPPORTED
+/* PNGv3: 'resolve' the file gamma according to the new PNGv3 rules for colour
+ * space information.
+ *
+ * NOTE: this uses precisely those chunks that libpng supports.  For example it
+ * doesn't use iCCP and it can only use cICP for known and manageable
+ * transforms.  For this reason a gamma specified by png_set_gamma always takes
+ * precedence.
+ */
+PNG_INTERNAL_FUNCTION(png_fixed_point,png_resolve_file_gamma,
+   (png_const_structrp png_ptr),PNG_EMPTY);
+
 /* Internal fixed point gamma correction.  These APIs are called as
  * required to convert single values - they don't need to be fast,
  * they are not used when processing image pixel values.
@@ -2113,6 +2042,22 @@ PNG_INTERNAL_FUNCTION(void,png_destroy_gamma_table,(png_structrp png_ptr),
    PNG_EMPTY);
 PNG_INTERNAL_FUNCTION(void,png_build_gamma_table,(png_structrp png_ptr,
    int bit_depth),PNG_EMPTY);
+#endif /* READ_GAMMA */
+
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+/* Set the RGB coefficients if not already set by png_set_rgb_to_gray */
+PNG_INTERNAL_FUNCTION(void,png_set_rgb_coefficients,(png_structrp png_ptr),
+   PNG_EMPTY);
+#endif
+
+#if defined(PNG_cHRM_SUPPORTED) || defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+PNG_INTERNAL_FUNCTION(int,png_XYZ_from_xy,(png_XYZ *XYZ, const png_xy *xy),
+   PNG_EMPTY);
+#endif /* cHRM || READ_RGB_TO_GRAY */
+
+#ifdef PNG_COLORSPACE_SUPPORTED
+PNG_INTERNAL_FUNCTION(int,png_xy_from_XYZ,(png_xy *xy, const png_XYZ *XYZ),
+   PNG_EMPTY);
 #endif
 
 /* SIMPLIFIED READ/WRITE SUPPORT */
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngread.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngread.c
index e9e94477545..8a6381e1b3e 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngread.c
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngread.c
@@ -29,7 +29,7 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * Copyright (c) 2018-2024 Cosmin Truta
+ * Copyright (c) 2018-2025 Cosmin Truta
  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -160,14 +160,11 @@ png_read_info(png_structrp png_ptr, png_inforp info_ptr)
          png_ptr->mode |= PNG_AFTER_IDAT;
       }
 
-      /* This should be a binary subdivision search or a hash for
-       * matching the chunk name rather than a linear search.
-       */
       if (chunk_name == png_IHDR)
-         png_handle_IHDR(png_ptr, info_ptr, length);
+         png_handle_chunk(png_ptr, info_ptr, length);
 
       else if (chunk_name == png_IEND)
-         png_handle_IEND(png_ptr, info_ptr, length);
+         png_handle_chunk(png_ptr, info_ptr, length);
 
 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
       else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0)
@@ -184,8 +181,6 @@ png_read_info(png_structrp png_ptr, png_inforp info_ptr)
          }
       }
 #endif
-      else if (chunk_name == png_PLTE)
-         png_handle_PLTE(png_ptr, info_ptr, length);
 
       else if (chunk_name == png_IDAT)
       {
@@ -193,99 +188,8 @@ png_read_info(png_structrp png_ptr, png_inforp info_ptr)
          break;
       }
 
-#ifdef PNG_READ_bKGD_SUPPORTED
-      else if (chunk_name == png_bKGD)
-         png_handle_bKGD(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_cHRM_SUPPORTED
-      else if (chunk_name == png_cHRM)
-         png_handle_cHRM(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_eXIf_SUPPORTED
-      else if (chunk_name == png_eXIf)
-         png_handle_eXIf(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_gAMA_SUPPORTED
-      else if (chunk_name == png_gAMA)
-         png_handle_gAMA(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_hIST_SUPPORTED
-      else if (chunk_name == png_hIST)
-         png_handle_hIST(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_oFFs_SUPPORTED
-      else if (chunk_name == png_oFFs)
-         png_handle_oFFs(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_pCAL_SUPPORTED
-      else if (chunk_name == png_pCAL)
-         png_handle_pCAL(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_sCAL_SUPPORTED
-      else if (chunk_name == png_sCAL)
-         png_handle_sCAL(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_pHYs_SUPPORTED
-      else if (chunk_name == png_pHYs)
-         png_handle_pHYs(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_sBIT_SUPPORTED
-      else if (chunk_name == png_sBIT)
-         png_handle_sBIT(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_sRGB_SUPPORTED
-      else if (chunk_name == png_sRGB)
-         png_handle_sRGB(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_iCCP_SUPPORTED
-      else if (chunk_name == png_iCCP)
-         png_handle_iCCP(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_sPLT_SUPPORTED
-      else if (chunk_name == png_sPLT)
-         png_handle_sPLT(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_tEXt_SUPPORTED
-      else if (chunk_name == png_tEXt)
-         png_handle_tEXt(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_tIME_SUPPORTED
-      else if (chunk_name == png_tIME)
-         png_handle_tIME(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_tRNS_SUPPORTED
-      else if (chunk_name == png_tRNS)
-         png_handle_tRNS(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_zTXt_SUPPORTED
-      else if (chunk_name == png_zTXt)
-         png_handle_zTXt(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_iTXt_SUPPORTED
-      else if (chunk_name == png_iTXt)
-         png_handle_iTXt(png_ptr, info_ptr, length);
-#endif
-
       else
-         png_handle_unknown(png_ptr, info_ptr, length,
-             PNG_HANDLE_CHUNK_AS_DEFAULT);
+         png_handle_chunk(png_ptr, info_ptr, length);
    }
 }
 #endif /* SEQUENTIAL_READ */
@@ -830,10 +734,10 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr)
          png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
 
       if (chunk_name == png_IEND)
-         png_handle_IEND(png_ptr, info_ptr, length);
+         png_handle_chunk(png_ptr, info_ptr, length);
 
       else if (chunk_name == png_IHDR)
-         png_handle_IHDR(png_ptr, info_ptr, length);
+         png_handle_chunk(png_ptr, info_ptr, length);
 
       else if (info_ptr == NULL)
          png_crc_finish(png_ptr, length);
@@ -867,102 +771,9 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr)
 
          png_crc_finish(png_ptr, length);
       }
-      else if (chunk_name == png_PLTE)
-         png_handle_PLTE(png_ptr, info_ptr, length);
-
-#ifdef PNG_READ_bKGD_SUPPORTED
-      else if (chunk_name == png_bKGD)
-         png_handle_bKGD(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_cHRM_SUPPORTED
-      else if (chunk_name == png_cHRM)
-         png_handle_cHRM(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_eXIf_SUPPORTED
-      else if (chunk_name == png_eXIf)
-         png_handle_eXIf(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_gAMA_SUPPORTED
-      else if (chunk_name == png_gAMA)
-         png_handle_gAMA(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_hIST_SUPPORTED
-      else if (chunk_name == png_hIST)
-         png_handle_hIST(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_oFFs_SUPPORTED
-      else if (chunk_name == png_oFFs)
-         png_handle_oFFs(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_pCAL_SUPPORTED
-      else if (chunk_name == png_pCAL)
-         png_handle_pCAL(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_sCAL_SUPPORTED
-      else if (chunk_name == png_sCAL)
-         png_handle_sCAL(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_pHYs_SUPPORTED
-      else if (chunk_name == png_pHYs)
-         png_handle_pHYs(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_sBIT_SUPPORTED
-      else if (chunk_name == png_sBIT)
-         png_handle_sBIT(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_sRGB_SUPPORTED
-      else if (chunk_name == png_sRGB)
-         png_handle_sRGB(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_iCCP_SUPPORTED
-      else if (chunk_name == png_iCCP)
-         png_handle_iCCP(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_sPLT_SUPPORTED
-      else if (chunk_name == png_sPLT)
-         png_handle_sPLT(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_tEXt_SUPPORTED
-      else if (chunk_name == png_tEXt)
-         png_handle_tEXt(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_tIME_SUPPORTED
-      else if (chunk_name == png_tIME)
-         png_handle_tIME(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_tRNS_SUPPORTED
-      else if (chunk_name == png_tRNS)
-         png_handle_tRNS(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_zTXt_SUPPORTED
-      else if (chunk_name == png_zTXt)
-         png_handle_zTXt(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_iTXt_SUPPORTED
-      else if (chunk_name == png_iTXt)
-         png_handle_iTXt(png_ptr, info_ptr, length);
-#endif
 
       else
-         png_handle_unknown(png_ptr, info_ptr, length,
-             PNG_HANDLE_CHUNK_AS_DEFAULT);
+         png_handle_chunk(png_ptr, info_ptr, length);
    } while ((png_ptr->mode & PNG_HAVE_IEND) == 0);
 }
 #endif /* SEQUENTIAL_READ */
@@ -1413,6 +1224,31 @@ png_image_format(png_structrp png_ptr)
    return format;
 }
 
+static int
+chromaticities_match_sRGB(const png_xy *xy)
+{
+#  define sRGB_TOLERANCE 1000
+   static const png_xy sRGB_xy = /* From ITU-R BT.709-3 */
+   {
+      /* color      x       y */
+      /* red   */ 64000, 33000,
+      /* green */ 30000, 60000,
+      /* blue  */ 15000,  6000,
+      /* white */ 31270, 32900
+   };
+
+   if (PNG_OUT_OF_RANGE(xy->whitex, sRGB_xy.whitex,sRGB_TOLERANCE) ||
+       PNG_OUT_OF_RANGE(xy->whitey, sRGB_xy.whitey,sRGB_TOLERANCE) ||
+       PNG_OUT_OF_RANGE(xy->redx,   sRGB_xy.redx,  sRGB_TOLERANCE) ||
+       PNG_OUT_OF_RANGE(xy->redy,   sRGB_xy.redy,  sRGB_TOLERANCE) ||
+       PNG_OUT_OF_RANGE(xy->greenx, sRGB_xy.greenx,sRGB_TOLERANCE) ||
+       PNG_OUT_OF_RANGE(xy->greeny, sRGB_xy.greeny,sRGB_TOLERANCE) ||
+       PNG_OUT_OF_RANGE(xy->bluex,  sRGB_xy.bluex, sRGB_TOLERANCE) ||
+       PNG_OUT_OF_RANGE(xy->bluey,  sRGB_xy.bluey, sRGB_TOLERANCE))
+      return 0;
+   return 1;
+}
+
 /* Is the given gamma significantly different from sRGB?  The test is the same
  * one used in pngrtran.c when deciding whether to do gamma correction.  The
  * arithmetic optimizes the division by using the fact that the inverse of the
@@ -1421,22 +1257,44 @@ png_image_format(png_structrp png_ptr)
 static int
 png_gamma_not_sRGB(png_fixed_point g)
 {
-   if (g < PNG_FP_1)
-   {
-      /* An uninitialized gamma is assumed to be sRGB for the simplified API. */
-      if (g == 0)
-         return 0;
-
-      return png_gamma_significant((g * 11 + 2)/5 /* i.e. *2.2, rounded */);
-   }
+   /* 1.6.47: use the same sanity checks as used in pngrtran.c */
+   if (g < PNG_LIB_GAMMA_MIN || g > PNG_LIB_GAMMA_MAX)
+      return 0; /* Includes the uninitialized value 0 */
 
-   return 1;
+   return png_gamma_significant((g * 11 + 2)/5 /* i.e. *2.2, rounded */);
 }
 
 /* Do the main body of a 'png_image_begin_read' function; read the PNG file
  * header and fill in all the information.  This is executed in a safe context,
  * unlike the init routine above.
  */
+static int
+png_image_is_not_sRGB(png_const_structrp png_ptr)
+{
+   /* Does the colorspace **not** match sRGB?  The flag is only set if the
+    * answer can be determined reliably.
+    *
+    * png_struct::chromaticities always exists since the simplified API
+    * requires rgb-to-gray.  The mDCV, cICP and cHRM chunks may all set it to
+    * a non-sRGB value, so it needs to be checked but **only** if one of
+    * those chunks occured in the file.
+    */
+   /* Highest priority: check to be safe. */
+   if (png_has_chunk(png_ptr, cICP) || png_has_chunk(png_ptr, mDCV))
+      return !chromaticities_match_sRGB(&png_ptr->chromaticities);
+
+   /* If the image is marked as sRGB then it is... */
+   if (png_has_chunk(png_ptr, sRGB))
+      return 0;
+
+   /* Last stop: cHRM, must check: */
+   if (png_has_chunk(png_ptr, cHRM))
+      return !chromaticities_match_sRGB(&png_ptr->chromaticities);
+
+   /* Else default to sRGB */
+   return 0;
+}
+
 static int
 png_image_read_header(png_voidp argument)
 {
@@ -1458,17 +1316,13 @@ png_image_read_header(png_voidp argument)
 
       image->format = format;
 
-#ifdef PNG_COLORSPACE_SUPPORTED
-      /* Does the colorspace match sRGB?  If there is no color endpoint
-       * (colorant) information assume yes, otherwise require the
-       * 'ENDPOINTS_MATCHP_sRGB' colorspace flag to have been set.  If the
-       * colorspace has been determined to be invalid ignore it.
+      /* Greyscale images don't (typically) have colour space information and
+       * using it is pretty much impossible, so use sRGB for grayscale (it
+       * doesn't matter r==g==b so the transform is irrelevant.)
        */
-      if ((format & PNG_FORMAT_FLAG_COLOR) != 0 && ((png_ptr->colorspace.flags
-         & (PNG_COLORSPACE_HAVE_ENDPOINTS|PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB|
-            PNG_COLORSPACE_INVALID)) == PNG_COLORSPACE_HAVE_ENDPOINTS))
+      if ((format & PNG_FORMAT_FLAG_COLOR) != 0 &&
+          png_image_is_not_sRGB(png_ptr))
          image->flags |= PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB;
-#endif
    }
 
    /* We need the maximum number of entries regardless of the format the
@@ -1656,21 +1510,18 @@ png_image_skip_unused_chunks(png_structrp png_ptr)
     * potential vulnerability to security problems in the unused chunks.
     *
     * At present the iCCP chunk data isn't used, so iCCP chunk can be ignored
-    * too.  This allows the simplified API to be compiled without iCCP support,
-    * however if the support is there the chunk is still checked to detect
-    * errors (which are unfortunately quite common.)
+    * too.  This allows the simplified API to be compiled without iCCP support.
     */
    {
          static const png_byte chunks_to_process[] = {
             98,  75,  71,  68, '\0',  /* bKGD */
             99,  72,  82,  77, '\0',  /* cHRM */
+            99,  73,  67,  80, '\0',  /* cICP */
            103,  65,  77,  65, '\0',  /* gAMA */
-#        ifdef PNG_READ_iCCP_SUPPORTED
-           105,  67,  67,  80, '\0',  /* iCCP */
-#        endif
+           109,  68,  67,  86, '\0',  /* mDCV */
            115,  66,  73,  84, '\0',  /* sBIT */
            115,  82,  71,  66, '\0',  /* sRGB */
-           };
+         };
 
        /* Ignore unknown chunks and all other chunks except for the
         * IHDR, PLTE, tRNS, IDAT, and IEND chunks.
@@ -1699,7 +1550,15 @@ png_image_skip_unused_chunks(png_structrp png_ptr)
 static void
 set_file_encoding(png_image_read_control *display)
 {
-   png_fixed_point g = display->image->opaque->png_ptr->colorspace.gamma;
+   png_structrp png_ptr = display->image->opaque->png_ptr;
+   png_fixed_point g = png_resolve_file_gamma(png_ptr);
+
+   /* PNGv3: the result may be 0 however the 'default_gamma' should have been
+    * set before this is called so zero is an error:
+    */
+   if (g == 0)
+      png_error(png_ptr, "internal: default gamma not set");
+
    if (png_gamma_significant(g) != 0)
    {
       if (png_gamma_not_sRGB(g) != 0)
@@ -2187,24 +2046,18 @@ png_image_read_colormap(png_voidp argument)
    /* Default the input file gamma if required - this is necessary because
     * libpng assumes that if no gamma information is present the data is in the
     * output format, but the simplified API deduces the gamma from the input
-    * format.
+    * format.  The 'default' gamma value is also set by png_set_alpha_mode, but
+    * this is happening before any such call, so:
+    *
+    * TODO: should be an internal API and all this code should be copied into a
+    * single common gamma+colorspace file.
     */
-   if ((png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) == 0)
-   {
-      /* Do this directly, not using the png_colorspace functions, to ensure
-       * that it happens even if the colorspace is invalid (though probably if
-       * it is the setting will be ignored)  Note that the same thing can be
-       * achieved at the application interface with png_set_gAMA.
-       */
-      if (png_ptr->bit_depth == 16 &&
-         (image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0)
-         png_ptr->colorspace.gamma = PNG_GAMMA_LINEAR;
-
-      else
-         png_ptr->colorspace.gamma = PNG_GAMMA_sRGB_INVERSE;
+   if (png_ptr->bit_depth == 16 &&
+      (image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0)
+      png_ptr->default_gamma = PNG_GAMMA_LINEAR;
 
-      png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
-   }
+   else
+      png_ptr->default_gamma = PNG_GAMMA_sRGB_INVERSE;
 
    /* Decide what to do based on the PNG color type of the input data.  The
     * utility function png_create_colormap_entry deals with most aspects of the
@@ -2582,6 +2435,8 @@ png_image_read_colormap(png_voidp argument)
 
             else
             {
+               const png_fixed_point gamma = png_resolve_file_gamma(png_ptr);
+
                /* Either the input or the output has no alpha channel, so there
                 * will be no non-opaque pixels in the color-map; it will just be
                 * grayscale.
@@ -2596,10 +2451,13 @@ png_image_read_colormap(png_voidp argument)
                 * this case and doing it in the palette; this will result in
                 * duplicate palette entries, but that's better than the
                 * alternative of double gamma correction.
+                *
+                * NOTE: PNGv3: check the resolved result of all the potentially
+                * different colour space chunks.
                 */
                if ((png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
                   png_ptr->num_trans > 0) &&
-                  png_gamma_not_sRGB(png_ptr->colorspace.gamma) != 0)
+                  png_gamma_not_sRGB(gamma) != 0)
                {
                   cmap_entries = (unsigned int)make_gray_file_colormap(display);
                   data_encoding = P_FILE;
@@ -2631,8 +2489,8 @@ png_image_read_colormap(png_voidp argument)
                      if (output_encoding == P_sRGB)
                         gray = png_sRGB_table[gray]; /* now P_LINEAR */
 
-                     gray = PNG_DIV257(png_gamma_16bit_correct(gray,
-                         png_ptr->colorspace.gamma)); /* now P_FILE */
+                     gray = PNG_DIV257(png_gamma_16bit_correct(gray, gamma));
+                        /* now P_FILE */
 
                      /* And make sure the corresponding palette entry contains
                       * exactly the required sRGB value.
@@ -3763,6 +3621,12 @@ png_image_read_direct(png_voidp argument)
       /* Set the gamma appropriately, linear for 16-bit input, sRGB otherwise.
        */
       {
+         /* This is safe but should no longer be necessary as
+          * png_ptr->default_gamma should have been set after the
+          * info-before-IDAT was read in png_image_read_header.
+          *
+          * TODO: 1.8: remove this and see what happens.
+          */
          png_fixed_point input_gamma_default;
 
          if ((base_format & PNG_FORMAT_FLAG_LINEAR) != 0 &&
@@ -3818,8 +3682,9 @@ png_image_read_direct(png_voidp argument)
           * yet; it's set below.  png_struct::gamma, however, is set to the
           * final value.
           */
-         if (png_muldiv(>est, output_gamma, png_ptr->colorspace.gamma,
-             PNG_FP_1) != 0 && png_gamma_significant(gtest) == 0)
+         if (png_muldiv(>est, output_gamma,
+                  png_resolve_file_gamma(png_ptr), PNG_FP_1) != 0 &&
+             png_gamma_significant(gtest) == 0)
             do_local_background = 0;
 
          else if (mode == PNG_ALPHA_STANDARD)
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngrtran.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngrtran.c
index a393de4b79d..4f31f8f07bc 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngrtran.c
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngrtran.c
@@ -247,9 +247,59 @@ png_set_strip_alpha(png_structrp png_ptr)
 #endif
 
 #if defined(PNG_READ_ALPHA_MODE_SUPPORTED) || defined(PNG_READ_GAMMA_SUPPORTED)
+/* PNGv3 conformance: this private API exists to resolve the now mandatory error
+ * resolution when multiple conflicting sources of gamma or colour space
+ * information are available.
+ *
+ * Terminology (assuming power law, "gamma", encodings):
+ *    "screen" gamma: a power law imposed by the output device when digital
+ *    samples are converted to visible light output.  The EOTF - volage to
+ *    luminance on output.
+ *
+ *    "file" gamma: a power law used to encode luminance levels from the input
+ *    data (the scene or the mastering display system) into digital voltages.
+ *    The OETF - luminance to voltage on input.
+ *
+ *    gamma "correction": a power law matching the **inverse** of the overall
+ *    transfer function from input luminance levels to output levels.  The
+ *    **inverse** of the OOTF; the correction "corrects" for the OOTF by aiming
+ *    to make the overall OOTF (including the correction) linear.
+ *
+ * It is important to understand this terminology because the defined terms are
+ * scattered throughout the libpng code and it is very easy to end up with the
+ * inverse of the power law required.
+ *
+ * Variable and struct::member names:
+ *    file_gamma        OETF  how the PNG data was encoded
+ *
+ *    screen_gamma      EOTF  how the screen will decode digital levels
+ *
+ *    -- not used --    OOTF  the net effect OETF x EOTF
+ *    gamma_correction        the inverse of OOTF to make the result linear
+ *
+ * All versions of libpng require a call to "png_set_gamma" to establish the
+ * "screen" gamma, the power law representing the EOTF.  png_set_gamma may also
+ * set or default the "file" gamma; the OETF.  gamma_correction is calculated
+ * internally.
+ *
+ * The earliest libpng versions required file_gamma to be supplied to set_gamma.
+ * Later versions started allowing png_set_gamma and, later, png_set_alpha_mode,
+ * to cause defaulting from the file data.
+ *
+ * PNGv3 mandated a particular form for this defaulting, one that is compatible
+ * with what libpng did except that if libpng detected inconsistencies it marked
+ * all the chunks as "invalid".  PNGv3 effectively invalidates this prior code.
+ *
+ * Behaviour implemented below:
+ *    translate_gamma_flags(gamma, is_screen)
+ *       The libpng-1.6 API for the gamma parameters to libpng APIs
+ *       (png_set_gamma and png_set_alpha_mode at present).  This allows the
+ *       'gamma' value to be passed as a png_fixed_point number or as one of a
+ *       set of integral values for specific "well known" examples of transfer
+ *       functions.  This is compatible with PNGv3.
+ */
 static png_fixed_point
-translate_gamma_flags(png_structrp png_ptr, png_fixed_point output_gamma,
-    int is_screen)
+translate_gamma_flags(png_fixed_point output_gamma, int is_screen)
 {
    /* Check for flag values.  The main reason for having the old Mac value as a
     * flag is that it is pretty near impossible to work out what the correct
@@ -259,14 +309,6 @@ translate_gamma_flags(png_structrp png_ptr, png_fixed_point output_gamma,
    if (output_gamma == PNG_DEFAULT_sRGB ||
       output_gamma == PNG_FP_1 / PNG_DEFAULT_sRGB)
    {
-      /* If there is no sRGB support this just sets the gamma to the standard
-       * sRGB value.  (This is a side effect of using this function!)
-       */
-#     ifdef PNG_READ_sRGB_SUPPORTED
-         png_ptr->flags |= PNG_FLAG_ASSUME_sRGB;
-#     else
-         PNG_UNUSED(png_ptr)
-#     endif
       if (is_screen != 0)
          output_gamma = PNG_GAMMA_sRGB;
       else
@@ -308,6 +350,33 @@ convert_gamma_value(png_structrp png_ptr, double output_gamma)
    return (png_fixed_point)output_gamma;
 }
 #  endif
+
+static int
+unsupported_gamma(png_structrp png_ptr, png_fixed_point gamma, int warn)
+{
+   /* Validate a gamma value to ensure it is in a reasonable range.  The value
+    * is expected to be 1 or greater, but this range test allows for some
+    * viewing correction values.  The intent is to weed out the API users
+    * who might use the inverse of the gamma value accidentally!
+    *
+    * 1.6.47: apply the test in png_set_gamma as well but only warn and return
+    * false if it fires.
+    *
+    * TODO: 1.8: make this an app_error in png_set_gamma as well.
+    */
+   if (gamma < PNG_LIB_GAMMA_MIN || gamma > PNG_LIB_GAMMA_MAX)
+   {
+#     define msg "gamma out of supported range"
+      if (warn)
+         png_app_warning(png_ptr, msg);
+      else
+         png_app_error(png_ptr, msg);
+      return 1;
+#     undef msg
+   }
+
+   return 0;
+}
 #endif /* READ_ALPHA_MODE || READ_GAMMA */
 
 #ifdef PNG_READ_ALPHA_MODE_SUPPORTED
@@ -315,31 +384,29 @@ void PNGFAPI
 png_set_alpha_mode_fixed(png_structrp png_ptr, int mode,
     png_fixed_point output_gamma)
 {
-   int compose = 0;
    png_fixed_point file_gamma;
+   int compose = 0;
 
    png_debug(1, "in png_set_alpha_mode_fixed");
 
    if (png_rtran_ok(png_ptr, 0) == 0)
       return;
 
-   output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/);
-
-   /* Validate the value to ensure it is in a reasonable range.  The value
-    * is expected to be 1 or greater, but this range test allows for some
-    * viewing correction values.  The intent is to weed out the API users
-    * who might use the inverse of the gamma value accidentally!
-    *
-    * In libpng 1.6.0, we changed from 0.07..3 to 0.01..100, to accommodate
-    * the optimal 16-bit gamma of 36 and its reciprocal.
-    */
-   if (output_gamma < 1000 || output_gamma > 10000000)
-      png_error(png_ptr, "output gamma out of expected range");
+   output_gamma = translate_gamma_flags(output_gamma, 1/*screen*/);
+   if (unsupported_gamma(png_ptr, output_gamma, 0/*error*/))
+      return;
 
    /* The default file gamma is the inverse of the output gamma; the output
-    * gamma may be changed below so get the file value first:
+    * gamma may be changed below so get the file value first.  The default_gamma
+    * is set here and from the simplified API (which uses a different algorithm)
+    * so don't overwrite a set value:
     */
-   file_gamma = png_reciprocal(output_gamma);
+   file_gamma = png_ptr->default_gamma;
+   if (file_gamma == 0)
+   {
+      file_gamma = png_reciprocal(output_gamma);
+      png_ptr->default_gamma = file_gamma;
+   }
 
    /* There are really 8 possibilities here, composed of any combination
     * of:
@@ -390,17 +457,7 @@ png_set_alpha_mode_fixed(png_structrp png_ptr, int mode,
          png_error(png_ptr, "invalid alpha mode");
    }
 
-   /* Only set the default gamma if the file gamma has not been set (this has
-    * the side effect that the gamma in a second call to png_set_alpha_mode will
-    * be ignored.)
-    */
-   if (png_ptr->colorspace.gamma == 0)
-   {
-      png_ptr->colorspace.gamma = file_gamma;
-      png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
-   }
-
-   /* But always set the output gamma: */
+   /* Set the screen gamma values: */
    png_ptr->screen_gamma = output_gamma;
 
    /* Finally, if pre-multiplying, set the background fields to achieve the
@@ -410,7 +467,7 @@ png_set_alpha_mode_fixed(png_structrp png_ptr, int mode,
    {
       /* And obtain alpha pre-multiplication by composing on black: */
       memset(&png_ptr->background, 0, (sizeof png_ptr->background));
-      png_ptr->background_gamma = png_ptr->colorspace.gamma; /* just in case */
+      png_ptr->background_gamma = file_gamma; /* just in case */
       png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_FILE;
       png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND;
 
@@ -848,8 +905,8 @@ png_set_gamma_fixed(png_structrp png_ptr, png_fixed_point scrn_gamma,
       return;
 
    /* New in libpng-1.5.4 - reserve particular negative values as flags. */
-   scrn_gamma = translate_gamma_flags(png_ptr, scrn_gamma, 1/*screen*/);
-   file_gamma = translate_gamma_flags(png_ptr, file_gamma, 0/*file*/);
+   scrn_gamma = translate_gamma_flags(scrn_gamma, 1/*screen*/);
+   file_gamma = translate_gamma_flags(file_gamma, 0/*file*/);
 
    /* Checking the gamma values for being >0 was added in 1.5.4 along with the
     * premultiplied alpha support; this actually hides an undocumented feature
@@ -863,17 +920,19 @@ png_set_gamma_fixed(png_structrp png_ptr, png_fixed_point scrn_gamma,
     * libpng-1.6.0.
     */
    if (file_gamma <= 0)
-      png_error(png_ptr, "invalid file gamma in png_set_gamma");
-
+      png_app_error(png_ptr, "invalid file gamma in png_set_gamma");
    if (scrn_gamma <= 0)
-      png_error(png_ptr, "invalid screen gamma in png_set_gamma");
+      png_app_error(png_ptr, "invalid screen gamma in png_set_gamma");
 
-   /* Set the gamma values unconditionally - this overrides the value in the PNG
-    * file if a gAMA chunk was present.  png_set_alpha_mode provides a
-    * different, easier, way to default the file gamma.
+   if (unsupported_gamma(png_ptr, file_gamma, 1/*warn*/) ||
+       unsupported_gamma(png_ptr, scrn_gamma, 1/*warn*/))
+      return;
+
+   /* 1.6.47: png_struct::file_gamma and png_struct::screen_gamma are now only
+    * written by this API.  This removes dependencies on the order of API calls
+    * and allows the complex gamma checks to be delayed until needed.
     */
-   png_ptr->colorspace.gamma = file_gamma;
-   png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
+   png_ptr->file_gamma = file_gamma;
    png_ptr->screen_gamma = scrn_gamma;
 }
 
@@ -1051,26 +1110,9 @@ png_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action,
          png_ptr->rgb_to_gray_coefficients_set = 1;
       }
 
-      else
-      {
-         if (red >= 0 && green >= 0)
-            png_app_warning(png_ptr,
-                "ignoring out of range rgb_to_gray coefficients");
-
-         /* Use the defaults, from the cHRM chunk if set, else the historical
-          * values which are close to the sRGB/HDTV/ITU-Rec 709 values.  See
-          * png_do_rgb_to_gray for more discussion of the values.  In this case
-          * the coefficients are not marked as 'set' and are not overwritten if
-          * something has already provided a default.
-          */
-         if (png_ptr->rgb_to_gray_red_coeff == 0 &&
-             png_ptr->rgb_to_gray_green_coeff == 0)
-         {
-            png_ptr->rgb_to_gray_red_coeff   = 6968;
-            png_ptr->rgb_to_gray_green_coeff = 23434;
-            /* png_ptr->rgb_to_gray_blue_coeff  = 2366; */
-         }
-      }
+      else if (red >= 0 && green >= 0)
+         png_app_warning(png_ptr,
+               "ignoring out of range rgb_to_gray coefficients");
    }
 }
 
@@ -1311,6 +1353,80 @@ png_init_rgb_transformations(png_structrp png_ptr)
 #endif /* READ_EXPAND && READ_BACKGROUND */
 }
 
+#ifdef PNG_READ_GAMMA_SUPPORTED
+png_fixed_point /* PRIVATE */
+png_resolve_file_gamma(png_const_structrp png_ptr)
+{
+   png_fixed_point file_gamma;
+
+   /* The file gamma is determined by these precedence rules, in this order
+    * (i.e. use the first value found):
+    *
+    *    png_set_gamma; png_struct::file_gammma if not zero, then:
+    *    png_struct::chunk_gamma if not 0 (determined the PNGv3 rules), then:
+    *    png_set_gamma; 1/png_struct::screen_gamma if not zero
+    *
+    *    0 (i.e. do no gamma handling)
+    */
+   file_gamma = png_ptr->file_gamma;
+   if (file_gamma != 0)
+      return file_gamma;
+
+   file_gamma = png_ptr->chunk_gamma;
+   if (file_gamma != 0)
+      return file_gamma;
+
+   file_gamma = png_ptr->default_gamma;
+   if (file_gamma != 0)
+      return file_gamma;
+
+   /* If png_reciprocal oveflows it returns 0 which indicates to the caller that
+    * there is no usable file gamma.  (The checks added to png_set_gamma and
+    * png_set_alpha_mode should prevent a screen_gamma which would overflow.)
+    */
+   if (png_ptr->screen_gamma != 0)
+      file_gamma = png_reciprocal(png_ptr->screen_gamma);
+
+   return file_gamma;
+}
+
+static int
+png_init_gamma_values(png_structrp png_ptr)
+{
+   /* The following temporary indicates if overall gamma correction is
+    * required.
+    */
+   int gamma_correction = 0;
+   png_fixed_point file_gamma, screen_gamma;
+
+   /* Resolve the file_gamma.  See above: if png_ptr::screen_gamma is set
+    * file_gamma will always be set here:
+    */
+   file_gamma = png_resolve_file_gamma(png_ptr);
+   screen_gamma = png_ptr->screen_gamma;
+
+   if (file_gamma > 0) /* file has been set */
+   {
+      if (screen_gamma > 0) /* screen set too */
+         gamma_correction = png_gamma_threshold(file_gamma, screen_gamma);
+
+      else
+         /* Assume the output matches the input; a long time default behavior
+          * of libpng, although the standard has nothing to say about this.
+          */
+         screen_gamma = png_reciprocal(file_gamma);
+   }
+
+   else /* both unset, prevent corrections: */
+      file_gamma = screen_gamma = PNG_FP_1;
+
+   png_ptr->file_gamma = file_gamma;
+   png_ptr->screen_gamma = screen_gamma;
+   return gamma_correction;
+
+}
+#endif /* READ_GAMMA */
+
 void /* PRIVATE */
 png_init_read_transformations(png_structrp png_ptr)
 {
@@ -1330,59 +1446,22 @@ png_init_read_transformations(png_structrp png_ptr)
     * the test needs to be performed later - here.  In addition prior to 1.5.4
     * the tests were repeated for the PALETTE color type here - this is no
     * longer necessary (and doesn't seem to have been necessary before.)
+    *
+    * PNGv3: the new mandatory precedence/priority rules for colour space chunks
+    * are handled here (by calling the above function).
+    *
+    * Turn the gamma transformation on or off as appropriate.  Notice that
+    * PNG_GAMMA just refers to the file->screen correction.  Alpha composition
+    * may independently cause gamma correction because it needs linear data
+    * (e.g. if the file has a gAMA chunk but the screen gamma hasn't been
+    * specified.)  In any case this flag may get turned off in the code
+    * immediately below if the transform can be handled outside the row loop.
     */
-   {
-      /* The following temporary indicates if overall gamma correction is
-       * required.
-       */
-      int gamma_correction = 0;
+   if (png_init_gamma_values(png_ptr) != 0)
+      png_ptr->transformations |= PNG_GAMMA;
 
-      if (png_ptr->colorspace.gamma != 0) /* has been set */
-      {
-         if (png_ptr->screen_gamma != 0) /* screen set too */
-            gamma_correction = png_gamma_threshold(png_ptr->colorspace.gamma,
-                png_ptr->screen_gamma);
-
-         else
-            /* Assume the output matches the input; a long time default behavior
-             * of libpng, although the standard has nothing to say about this.
-             */
-            png_ptr->screen_gamma = png_reciprocal(png_ptr->colorspace.gamma);
-      }
-
-      else if (png_ptr->screen_gamma != 0)
-         /* The converse - assume the file matches the screen, note that this
-          * perhaps undesirable default can (from 1.5.4) be changed by calling
-          * png_set_alpha_mode (even if the alpha handling mode isn't required
-          * or isn't changed from the default.)
-          */
-         png_ptr->colorspace.gamma = png_reciprocal(png_ptr->screen_gamma);
-
-      else /* neither are set */
-         /* Just in case the following prevents any processing - file and screen
-          * are both assumed to be linear and there is no way to introduce a
-          * third gamma value other than png_set_background with 'UNIQUE', and,
-          * prior to 1.5.4
-          */
-         png_ptr->screen_gamma = png_ptr->colorspace.gamma = PNG_FP_1;
-
-      /* We have a gamma value now. */
-      png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
-
-      /* Now turn the gamma transformation on or off as appropriate.  Notice
-       * that PNG_GAMMA just refers to the file->screen correction.  Alpha
-       * composition may independently cause gamma correction because it needs
-       * linear data (e.g. if the file has a gAMA chunk but the screen gamma
-       * hasn't been specified.)  In any case this flag may get turned off in
-       * the code immediately below if the transform can be handled outside the
-       * row loop.
-       */
-      if (gamma_correction != 0)
-         png_ptr->transformations |= PNG_GAMMA;
-
-      else
-         png_ptr->transformations &= ~PNG_GAMMA;
-   }
+   else
+      png_ptr->transformations &= ~PNG_GAMMA;
 #endif
 
    /* Certain transformations have the effect of preventing other
@@ -1454,7 +1533,7 @@ png_init_read_transformations(png_structrp png_ptr)
     * appropriately.
     */
    if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
-      png_colorspace_set_rgb_coefficients(png_ptr);
+      png_set_rgb_coefficients(png_ptr);
 #endif
 
 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
@@ -1597,10 +1676,10 @@ png_init_read_transformations(png_structrp png_ptr)
     */
    if ((png_ptr->transformations & PNG_GAMMA) != 0 ||
        ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0 &&
-        (png_gamma_significant(png_ptr->colorspace.gamma) != 0 ||
+        (png_gamma_significant(png_ptr->file_gamma) != 0 ||
          png_gamma_significant(png_ptr->screen_gamma) != 0)) ||
         ((png_ptr->transformations & PNG_COMPOSE) != 0 &&
-         (png_gamma_significant(png_ptr->colorspace.gamma) != 0 ||
+         (png_gamma_significant(png_ptr->file_gamma) != 0 ||
           png_gamma_significant(png_ptr->screen_gamma) != 0
 #  ifdef PNG_READ_BACKGROUND_SUPPORTED
          || (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE &&
@@ -1656,8 +1735,8 @@ png_init_read_transformations(png_structrp png_ptr)
                      break;
 
                   case PNG_BACKGROUND_GAMMA_FILE:
-                     g = png_reciprocal(png_ptr->colorspace.gamma);
-                     gs = png_reciprocal2(png_ptr->colorspace.gamma,
+                     g = png_reciprocal(png_ptr->file_gamma);
+                     gs = png_reciprocal2(png_ptr->file_gamma,
                          png_ptr->screen_gamma);
                      break;
 
@@ -1765,8 +1844,8 @@ png_init_read_transformations(png_structrp png_ptr)
                   break;
 
                case PNG_BACKGROUND_GAMMA_FILE:
-                  g = png_reciprocal(png_ptr->colorspace.gamma);
-                  gs = png_reciprocal2(png_ptr->colorspace.gamma,
+                  g = png_reciprocal(png_ptr->file_gamma);
+                  gs = png_reciprocal2(png_ptr->file_gamma,
                       png_ptr->screen_gamma);
                   break;
 
@@ -2016,11 +2095,11 @@ png_read_transform_info(png_structrp png_ptr, png_inforp info_ptr)
     * been called before this from png_read_update_info->png_read_start_row
     * sometimes does the gamma transform and cancels the flag.
     *
-    * TODO: this looks wrong; the info_ptr should end up with a gamma equal to
-    * the screen_gamma value.  The following probably results in weirdness if
-    * the info_ptr is used by the app after the rows have been read.
+    * TODO: this is confusing.  It only changes the result of png_get_gAMA and,
+    * yes, it does return the value that the transformed data effectively has
+    * but does any app really understand this?
     */
-   info_ptr->colorspace.gamma = png_ptr->colorspace.gamma;
+   info_ptr->gamma = png_ptr->file_gamma;
 #endif
 
    if (info_ptr->bit_depth == 16)
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngrutil.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngrutil.c
index 5280140d12b..6cf466d182a 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngrutil.c
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngrutil.c
@@ -46,6 +46,26 @@
 
 #ifdef PNG_READ_SUPPORTED
 
+/* The minimum 'zlib' stream is assumed to be just the 2 byte header, 5 bytes
+ * minimum 'deflate' stream, and the 4 byte checksum.
+ */
+#define LZ77Min  (2U+5U+4U)
+
+#ifdef PNG_READ_INTERLACING_SUPPORTED
+/* Arrays to facilitate interlacing - use pass (0 - 6) as index. */
+
+/* Start of interlace block */
+static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
+/* Offset to next interlace block */
+static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+/* Start of interlace block in the y direction */
+static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
+/* Offset to next interlace block in the y direction */
+static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
+
+/* TODO: Move these arrays to a common utility module to avoid duplication. */
+#endif
+
 png_uint_32 PNGAPI
 png_get_uint_31(png_const_structrp png_ptr, png_const_bytep buf)
 {
@@ -57,30 +77,6 @@ png_get_uint_31(png_const_structrp png_ptr, png_const_bytep buf)
    return uval;
 }
 
-#if defined(PNG_READ_gAMA_SUPPORTED) || defined(PNG_READ_cHRM_SUPPORTED)
-/* The following is a variation on the above for use with the fixed
- * point values used for gAMA and cHRM.  Instead of png_error it
- * issues a warning and returns (-1) - an invalid value because both
- * gAMA and cHRM use *unsigned* integers for fixed point values.
- */
-#define PNG_FIXED_ERROR (-1)
-
-static png_fixed_point /* PRIVATE */
-png_get_fixed_point(png_structrp png_ptr, png_const_bytep buf)
-{
-   png_uint_32 uval = png_get_uint_32(buf);
-
-   if (uval <= PNG_UINT_31_MAX)
-      return (png_fixed_point)uval; /* known to be in range */
-
-   /* The caller can turn off the warning by passing NULL. */
-   if (png_ptr != NULL)
-      png_warning(png_ptr, "PNG fixed point integer out of range");
-
-   return PNG_FIXED_ERROR;
-}
-#endif
-
 #ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED
 /* NOTE: the read macros will obscure these definitions, so that if
  * PNG_USE_READ_MACROS is set the library will not use them internally,
@@ -177,6 +173,38 @@ png_read_sig(png_structrp png_ptr, png_inforp info_ptr)
       png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE;
 }
 
+/* This function is called to verify that a chunk name is valid.
+ * Do this using the bit-whacking approach from contrib/tools/pngfix.c
+ *
+ * Copied from libpng 1.7.
+ */
+static int
+check_chunk_name(png_uint_32 name)
+{
+   png_uint_32 t;
+
+   /* Remove bit 5 from all but the reserved byte; this means
+    * every 8-bit unit must be in the range 65-90 to be valid.
+    * So bit 5 must be zero, bit 6 must be set and bit 7 zero.
+    */
+   name &= ~PNG_U32(32,32,0,32);
+   t = (name & ~0x1f1f1f1fU) ^ 0x40404040U;
+
+   /* Subtract 65 for each 8-bit quantity, this must not
+    * overflow and each byte must then be in the range 0-25.
+    */
+   name -= PNG_U32(65,65,65,65);
+   t |= name;
+
+   /* Subtract 26, handling the overflow which should set the
+    * top three bits of each byte.
+    */
+   name -= PNG_U32(25,25,25,26);
+   t |= ~name;
+
+   return (t & 0xe0e0e0e0U) == 0U;
+}
+
 /* Read the chunk header (length + type name).
  * Put the type name into png_ptr->chunk_name, and return the length.
  */
@@ -184,33 +212,36 @@ png_uint_32 /* PRIVATE */
 png_read_chunk_header(png_structrp png_ptr)
 {
    png_byte buf[8];
-   png_uint_32 length;
+   png_uint_32 chunk_name, length;
 
 #ifdef PNG_IO_STATE_SUPPORTED
    png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_HDR;
 #endif
 
-   /* Read the length and the chunk name.
-    * This must be performed in a single I/O call.
+   /* Read the length and the chunk name.  png_struct::chunk_name is immediately
+    * updated even if they are detectably wrong.  This aids error message
+    * handling by allowing png_chunk_error to be used.
     */
    png_read_data(png_ptr, buf, 8);
    length = png_get_uint_31(png_ptr, buf);
+   png_ptr->chunk_name = chunk_name = PNG_CHUNK_FROM_STRING(buf+4);
 
-   /* Put the chunk name into png_ptr->chunk_name. */
-   png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(buf+4);
+   /* Reset the crc and run it over the chunk name. */
+   png_reset_crc(png_ptr);
+   png_calculate_crc(png_ptr, buf + 4, 4);
 
    png_debug2(0, "Reading chunk typeid = 0x%lx, length = %lu",
        (unsigned long)png_ptr->chunk_name, (unsigned long)length);
 
-   /* Reset the crc and run it over the chunk name. */
-   png_reset_crc(png_ptr);
-   png_calculate_crc(png_ptr, buf + 4, 4);
+   /* Sanity check the length (first by <= 0x80) and the chunk name.  An error
+    * here indicates a broken stream and libpng has no recovery from this.
+    */
+   if (buf[0] >= 0x80U)
+      png_chunk_error(png_ptr, "bad header (invalid length)");
 
    /* Check to see if chunk name is valid. */
-   png_check_chunk_name(png_ptr, png_ptr->chunk_name);
-
-   /* Check for too-large chunk length */
-   png_check_chunk_length(png_ptr, length);
+   if (!check_chunk_name(chunk_name))
+      png_chunk_error(png_ptr, "bad header (invalid type)");
 
 #ifdef PNG_IO_STATE_SUPPORTED
    png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_DATA;
@@ -230,13 +261,85 @@ png_crc_read(png_structrp png_ptr, png_bytep buf, png_uint_32 length)
    png_calculate_crc(png_ptr, buf, length);
 }
 
+/* Compare the CRC stored in the PNG file with that calculated by libpng from
+ * the data it has read thus far.
+ */
+static int
+png_crc_error(png_structrp png_ptr, int handle_as_ancillary)
+{
+   png_byte crc_bytes[4];
+   png_uint_32 crc;
+   int need_crc = 1;
+
+   /* There are four flags two for ancillary and two for critical chunks.  The
+    * default setting of these flags is all zero.
+    *
+    * PNG_FLAG_CRC_ANCILLARY_USE
+    * PNG_FLAG_CRC_ANCILLARY_NOWARN
+    *  USE+NOWARN: no CRC calculation (implemented here), else;
+    *  NOWARN:     png_chunk_error on error (implemented in png_crc_finish)
+    *  else:       png_chunk_warning on error (implemented in png_crc_finish)
+    *              This is the default.
+    *
+    *    I.e. NOWARN without USE produces png_chunk_error.  The default setting
+    *    where neither are set does the same thing.
+    *
+    * PNG_FLAG_CRC_CRITICAL_USE
+    * PNG_FLAG_CRC_CRITICAL_IGNORE
+    *  IGNORE: no CRC calculation (implemented here), else;
+    *  USE:    png_chunk_warning on error (implemented in png_crc_finish)
+    *  else:   png_chunk_error on error (implemented in png_crc_finish)
+    *          This is the default.
+    *
+    * This arose because of original mis-implementation and has persisted for
+    * compatibility reasons.
+    *
+    * TODO: the flag names are internal so maybe this can be changed to
+    * something comprehensible.
+    */
+   if (handle_as_ancillary || PNG_CHUNK_ANCILLARY(png_ptr->chunk_name) != 0)
+   {
+      if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
+          (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
+         need_crc = 0;
+   }
+
+   else /* critical */
+   {
+      if ((png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) != 0)
+         need_crc = 0;
+   }
+
+#ifdef PNG_IO_STATE_SUPPORTED
+   png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_CRC;
+#endif
+
+   /* The chunk CRC must be serialized in a single I/O call. */
+   png_read_data(png_ptr, crc_bytes, 4);
+
+   if (need_crc != 0)
+   {
+      crc = png_get_uint_32(crc_bytes);
+      return crc != png_ptr->crc;
+   }
+
+   else
+      return 0;
+}
+
 /* Optionally skip data and then check the CRC.  Depending on whether we
  * are reading an ancillary or critical chunk, and how the program has set
  * things up, we may calculate the CRC on the data and print a message.
  * Returns '1' if there was a CRC error, '0' otherwise.
+ *
+ * There is one public version which is used in most places and another which
+ * takes the value for the 'critical' flag to check.  This allows PLTE and IEND
+ * handling code to ignore the CRC error and removes some confusing code
+ * duplication.
  */
-int /* PRIVATE */
-png_crc_finish(png_structrp png_ptr, png_uint_32 skip)
+static int
+png_crc_finish_critical(png_structrp png_ptr, png_uint_32 skip,
+      int handle_as_ancillary)
 {
    /* The size of the local buffer for inflate is a good guess as to a
     * reasonable size to use for buffering reads from the application.
@@ -254,14 +357,24 @@ png_crc_finish(png_structrp png_ptr, png_uint_32 skip)
       png_crc_read(png_ptr, tmpbuf, len);
    }
 
-   if (png_crc_error(png_ptr) != 0)
+   /* If 'handle_as_ancillary' has been requested and this is a critical chunk
+    * but PNG_FLAG_CRC_CRITICAL_IGNORE was set then png_read_crc did not, in
+    * fact, calculate the CRC so the ANCILLARY settings should not be used
+    * instead.
+    */
+   if (handle_as_ancillary &&
+       (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) != 0)
+      handle_as_ancillary = 0;
+
+   /* TODO: this might be more comprehensible if png_crc_error was inlined here.
+    */
+   if (png_crc_error(png_ptr, handle_as_ancillary) != 0)
    {
-      if (PNG_CHUNK_ANCILLARY(png_ptr->chunk_name) != 0 ?
+      /* See above for the explanation of how the flags work. */
+      if (handle_as_ancillary || PNG_CHUNK_ANCILLARY(png_ptr->chunk_name) != 0 ?
           (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) == 0 :
           (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE) != 0)
-      {
          png_chunk_warning(png_ptr, "CRC error");
-      }
 
       else
          png_chunk_error(png_ptr, "CRC error");
@@ -272,61 +385,29 @@ png_crc_finish(png_structrp png_ptr, png_uint_32 skip)
    return 0;
 }
 
-/* Compare the CRC stored in the PNG file with that calculated by libpng from
- * the data it has read thus far.
- */
 int /* PRIVATE */
-png_crc_error(png_structrp png_ptr)
+png_crc_finish(png_structrp png_ptr, png_uint_32 skip)
 {
-   png_byte crc_bytes[4];
-   png_uint_32 crc;
-   int need_crc = 1;
-
-   if (PNG_CHUNK_ANCILLARY(png_ptr->chunk_name) != 0)
-   {
-      if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
-          (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
-         need_crc = 0;
-   }
-
-   else /* critical */
-   {
-      if ((png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) != 0)
-         need_crc = 0;
-   }
-
-#ifdef PNG_IO_STATE_SUPPORTED
-   png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_CRC;
-#endif
-
-   /* The chunk CRC must be serialized in a single I/O call. */
-   png_read_data(png_ptr, crc_bytes, 4);
-
-   if (need_crc != 0)
-   {
-      crc = png_get_uint_32(crc_bytes);
-      return crc != png_ptr->crc;
-   }
-
-   else
-      return 0;
+   return png_crc_finish_critical(png_ptr, skip, 0/*critical handling*/);
 }
 
 #if defined(PNG_READ_iCCP_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) ||\
     defined(PNG_READ_pCAL_SUPPORTED) || defined(PNG_READ_sCAL_SUPPORTED) ||\
     defined(PNG_READ_sPLT_SUPPORTED) || defined(PNG_READ_tEXt_SUPPORTED) ||\
-    defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_SEQUENTIAL_READ_SUPPORTED)
+    defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_eXIf_SUPPORTED) ||\
+    defined(PNG_SEQUENTIAL_READ_SUPPORTED)
 /* Manage the read buffer; this simply reallocates the buffer if it is not small
  * enough (or if it is not allocated).  The routine returns a pointer to the
  * buffer; if an error occurs and 'warn' is set the routine returns NULL, else
- * it will call png_error (via png_malloc) on failure.  (warn == 2 means
- * 'silent').
+ * it will call png_error on failure.
  */
 static png_bytep
-png_read_buffer(png_structrp png_ptr, png_alloc_size_t new_size, int warn)
+png_read_buffer(png_structrp png_ptr, png_alloc_size_t new_size)
 {
    png_bytep buffer = png_ptr->read_buffer;
 
+   if (new_size > png_chunk_max(png_ptr)) return NULL;
+
    if (buffer != NULL && new_size > png_ptr->read_buffer_size)
    {
       png_ptr->read_buffer = NULL;
@@ -341,24 +422,17 @@ png_read_buffer(png_structrp png_ptr, png_alloc_size_t new_size, int warn)
 
       if (buffer != NULL)
       {
-         memset(buffer, 0, new_size); /* just in case */
+#        ifndef PNG_NO_MEMZERO /* for detecting UIM bugs **only** */
+            memset(buffer, 0, new_size); /* just in case */
+#        endif
          png_ptr->read_buffer = buffer;
          png_ptr->read_buffer_size = new_size;
       }
-
-      else if (warn < 2) /* else silent */
-      {
-         if (warn != 0)
-             png_chunk_warning(png_ptr, "insufficient memory to read chunk");
-
-         else
-             png_chunk_error(png_ptr, "insufficient memory to read chunk");
-      }
    }
 
    return buffer;
 }
-#endif /* READ_iCCP|iTXt|pCAL|sCAL|sPLT|tEXt|zTXt|SEQUENTIAL_READ */
+#endif /* READ_iCCP|iTXt|pCAL|sCAL|sPLT|tEXt|zTXt|eXIf|SEQUENTIAL_READ */
 
 /* png_inflate_claim: claim the zstream for some nefarious purpose that involves
  * decompression.  Returns Z_OK on success, else a zlib error code.  It checks
@@ -645,16 +719,7 @@ png_decompress_chunk(png_structrp png_ptr,
     * maybe a '\0' terminator too.  We have to assume that 'prefix_size' is
     * limited only by the maximum chunk size.
     */
-   png_alloc_size_t limit = PNG_SIZE_MAX;
-
-# ifdef PNG_SET_USER_LIMITS_SUPPORTED
-   if (png_ptr->user_chunk_malloc_max > 0 &&
-       png_ptr->user_chunk_malloc_max < limit)
-      limit = png_ptr->user_chunk_malloc_max;
-# elif PNG_USER_CHUNK_MALLOC_MAX > 0
-   if (PNG_USER_CHUNK_MALLOC_MAX < limit)
-      limit = PNG_USER_CHUNK_MALLOC_MAX;
-# endif
+   png_alloc_size_t limit = png_chunk_max(png_ptr);
 
    if (limit >= prefix_size + (terminate != 0))
    {
@@ -859,9 +924,9 @@ png_inflate_read(png_structrp png_ptr, png_bytep read_buffer, uInt read_size,
 }
 #endif /* READ_iCCP */
 
+/* CHUNK HANDLING */
 /* Read and check the IDHR chunk */
-
-void /* PRIVATE */
+static png_handle_result_code
 png_handle_IHDR(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 {
    png_byte buf[13];
@@ -871,12 +936,7 @@ png_handle_IHDR(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 
    png_debug(1, "in png_handle_IHDR");
 
-   if ((png_ptr->mode & PNG_HAVE_IHDR) != 0)
-      png_chunk_error(png_ptr, "out of place");
-
-   /* Check the length */
-   if (length != 13)
-      png_chunk_error(png_ptr, "invalid");
+   /* Length and position are checked by the caller. */
 
    png_ptr->mode |= PNG_HAVE_IHDR;
 
@@ -930,257 +990,196 @@ png_handle_IHDR(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
    png_debug1(3, "bit_depth = %d", png_ptr->bit_depth);
    png_debug1(3, "channels = %d", png_ptr->channels);
    png_debug1(3, "rowbytes = %lu", (unsigned long)png_ptr->rowbytes);
+
+   /* Rely on png_set_IHDR to completely validate the data and call png_error if
+    * it's wrong.
+    */
    png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
        color_type, interlace_type, compression_type, filter_type);
+
+   return handled_ok;
+   PNG_UNUSED(length)
 }
 
 /* Read and check the palette */
-void /* PRIVATE */
+/* TODO: there are several obvious errors in this code when handling
+ * out-of-place chunks and there is much over-complexity caused by trying to
+ * patch up the problems.
+ */
+static png_handle_result_code
 png_handle_PLTE(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 {
-   png_color palette[PNG_MAX_PALETTE_LENGTH];
-   int max_palette_length, num, i;
-#ifdef PNG_POINTER_INDEXING_SUPPORTED
-   png_colorp pal_ptr;
-#endif
+   png_const_charp errmsg = NULL;
 
    png_debug(1, "in png_handle_PLTE");
 
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
-
-   /* Moved to before the 'after IDAT' check below because otherwise duplicate
-    * PLTE chunks are potentially ignored (the spec says there shall not be more
-    * than one PLTE, the error is not treated as benign, so this check trumps
-    * the requirement that PLTE appears before IDAT.)
+   /* 1.6.47: consistency.  This used to be especially treated as a critical
+    * error even in an image which is not colour mapped, there isn't a good
+    * justification for treating some errors here one way and others another so
+    * everything uses the same logic.
     */
-   else if ((png_ptr->mode & PNG_HAVE_PLTE) != 0)
-      png_chunk_error(png_ptr, "duplicate");
+   if ((png_ptr->mode & PNG_HAVE_PLTE) != 0)
+      errmsg = "duplicate";
 
    else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
-   {
-      /* This is benign because the non-benign error happened before, when an
-       * IDAT was encountered in a color-mapped image with no PLTE.
-       */
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "out of place");
-      return;
-   }
+      errmsg = "out of place";
 
-   png_ptr->mode |= PNG_HAVE_PLTE;
+   else if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
+      errmsg = "ignored in grayscale PNG";
 
-   if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "ignored in grayscale PNG");
-      return;
-   }
+   else if (length > 3*PNG_MAX_PALETTE_LENGTH || (length % 3) != 0)
+      errmsg = "invalid";
 
-#ifndef PNG_READ_OPT_PLTE_SUPPORTED
-   if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
-   {
-      png_crc_finish(png_ptr, length);
-      return;
-   }
-#endif
+   /* This drops PLTE in favour of tRNS or bKGD because both of those chunks
+    * can have an effect on the rendering of the image whereas PLTE only matters
+    * in the case of an 8-bit display with a decoder which controls the palette.
+    *
+    * The alternative here is to ignore the error and store the palette anyway;
+    * destroying the tRNS will definately cause problems.
+    *
+    * NOTE: the case of PNG_COLOR_TYPE_PALETTE need not be considered because
+    * the png_handle_ routines for the three 'after PLTE' chunks tRNS, bKGD and
+    * hIST all check for a preceding PLTE in these cases.
+    */
+   else if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE &&
+            (png_has_chunk(png_ptr, tRNS) || png_has_chunk(png_ptr, bKGD)))
+      errmsg = "out of place";
 
-   if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
+   else
    {
-      png_crc_finish(png_ptr, length);
-
-      if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
-         png_chunk_benign_error(png_ptr, "invalid");
-
-      else
-         png_chunk_error(png_ptr, "invalid");
+      /* If the palette has 256 or fewer entries but is too large for the bit
+       * depth we don't issue an error to preserve the behavior of previous
+       * libpng versions. We silently truncate the unused extra palette entries
+       * here.
+       */
+      const unsigned max_palette_length =
+         (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ?
+            1U << png_ptr->bit_depth : PNG_MAX_PALETTE_LENGTH;
 
-      return;
-   }
+      /* The cast is safe because 'length' is less than
+       * 3*PNG_MAX_PALETTE_LENGTH
+       */
+      const unsigned num = (length > 3U*max_palette_length) ?
+         max_palette_length : (unsigned)length / 3U;
 
-   /* The cast is safe because 'length' is less than 3*PNG_MAX_PALETTE_LENGTH */
-   num = (int)length / 3;
+      unsigned i, j;
+      png_byte buf[3*PNG_MAX_PALETTE_LENGTH];
+      png_color palette[PNG_MAX_PALETTE_LENGTH];
 
-   /* If the palette has 256 or fewer entries but is too large for the bit
-    * depth, we don't issue an error, to preserve the behavior of previous
-    * libpng versions. We silently truncate the unused extra palette entries
-    * here.
-    */
-   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
-      max_palette_length = (1 << png_ptr->bit_depth);
-   else
-      max_palette_length = PNG_MAX_PALETTE_LENGTH;
+      /* Read the chunk into the buffer then read to the end of the chunk. */
+      png_crc_read(png_ptr, buf, num*3U);
+      png_crc_finish_critical(png_ptr, length - 3U*num,
+            /* Handle as ancillary if PLTE is optional: */
+            png_ptr->color_type != PNG_COLOR_TYPE_PALETTE);
 
-   if (num > max_palette_length)
-      num = max_palette_length;
+      for (i = 0U, j = 0U; i < num; i++)
+      {
+         palette[i].red = buf[j++];
+         palette[i].green = buf[j++];
+         palette[i].blue = buf[j++];
+      }
 
-#ifdef PNG_POINTER_INDEXING_SUPPORTED
-   for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
-   {
-      png_byte buf[3];
+      /* A valid PLTE chunk has been read */
+      png_ptr->mode |= PNG_HAVE_PLTE;
 
-      png_crc_read(png_ptr, buf, 3);
-      pal_ptr->red = buf[0];
-      pal_ptr->green = buf[1];
-      pal_ptr->blue = buf[2];
+      /* TODO: png_set_PLTE has the side effect of setting png_ptr->palette to
+       * its own copy of the palette.  This has the side effect that when
+       * png_start_row is called (this happens after any call to
+       * png_read_update_info) the info_ptr palette gets changed.  This is
+       * extremely unexpected and confusing.
+       *
+       * REVIEW: there have been consistent bugs in the past about gamma and
+       * similar transforms to colour mapped images being useless because the
+       * modified palette cannot be accessed because of the above.
+       *
+       * CONSIDER: Fix this by not sharing the palette in this way.  But does
+       * this completely fix the problem?
+       */
+      png_set_PLTE(png_ptr, info_ptr, palette, num);
+      return handled_ok;
    }
-#else
-   for (i = 0; i < num; i++)
-   {
-      png_byte buf[3];
 
-      png_crc_read(png_ptr, buf, 3);
-      /* Don't depend upon png_color being any order */
-      palette[i].red = buf[0];
-      palette[i].green = buf[1];
-      palette[i].blue = buf[2];
-   }
-#endif
-
-   /* If we actually need the PLTE chunk (ie for a paletted image), we do
-    * whatever the normal CRC configuration tells us.  However, if we
-    * have an RGB image, the PLTE can be considered ancillary, so
-    * we will act as though it is.
-    */
-#ifndef PNG_READ_OPT_PLTE_SUPPORTED
+   /* Here on error: errmsg is non NULL. */
    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
-#endif
    {
-      png_crc_finish(png_ptr, (png_uint_32) (length - (unsigned int)num * 3));
+      png_crc_finish(png_ptr, length);
+      png_chunk_error(png_ptr, errmsg);
    }
 
-#ifndef PNG_READ_OPT_PLTE_SUPPORTED
-   else if (png_crc_error(png_ptr) != 0)  /* Only if we have a CRC error */
+   else /* not critical to this image */
    {
-      /* If we don't want to use the data from an ancillary chunk,
-       * we have two options: an error abort, or a warning and we
-       * ignore the data in this chunk (which should be OK, since
-       * it's considered ancillary for a RGB or RGBA image).
-       *
-       * IMPLEMENTATION NOTE: this is only here because png_crc_finish uses the
-       * chunk type to determine whether to check the ancillary or the critical
-       * flags.
-       */
-      if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE) == 0)
-      {
-         if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) != 0)
-            return;
-
-         else
-            png_chunk_error(png_ptr, "CRC error");
-      }
-
-      /* Otherwise, we (optionally) emit a warning and use the chunk. */
-      else if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) == 0)
-         png_chunk_warning(png_ptr, "CRC error");
+      png_crc_finish_critical(png_ptr, length, 1/*handle as ancillary*/);
+      png_chunk_benign_error(png_ptr, errmsg);
    }
-#endif
 
-   /* TODO: png_set_PLTE has the side effect of setting png_ptr->palette to its
-    * own copy of the palette.  This has the side effect that when png_start_row
-    * is called (this happens after any call to png_read_update_info) the
-    * info_ptr palette gets changed.  This is extremely unexpected and
-    * confusing.
-    *
-    * Fix this by not sharing the palette in this way.
+   /* Because PNG_UNUSED(errmsg) does not work if all the uses are compiled out
+    * (this does happen).
     */
-   png_set_PLTE(png_ptr, info_ptr, palette, num);
-
-   /* The three chunks, bKGD, hIST and tRNS *must* appear after PLTE and before
-    * IDAT.  Prior to 1.6.0 this was not checked; instead the code merely
-    * checked the apparent validity of a tRNS chunk inserted before PLTE on a
-    * palette PNG.  1.6.0 attempts to rigorously follow the standard and
-    * therefore does a benign error if the erroneous condition is detected *and*
-    * cancels the tRNS if the benign error returns.  The alternative is to
-    * amend the standard since it would be rather hypocritical of the standards
-    * maintainers to ignore it.
-    */
-#ifdef PNG_READ_tRNS_SUPPORTED
-   if (png_ptr->num_trans > 0 ||
-       (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS) != 0))
-   {
-      /* Cancel this because otherwise it would be used if the transforms
-       * require it.  Don't cancel the 'valid' flag because this would prevent
-       * detection of duplicate chunks.
-       */
-      png_ptr->num_trans = 0;
-
-      if (info_ptr != NULL)
-         info_ptr->num_trans = 0;
-
-      png_chunk_benign_error(png_ptr, "tRNS must be after");
-   }
-#endif
-
-#ifdef PNG_READ_hIST_SUPPORTED
-   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST) != 0)
-      png_chunk_benign_error(png_ptr, "hIST must be after");
-#endif
-
-#ifdef PNG_READ_bKGD_SUPPORTED
-   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) != 0)
-      png_chunk_benign_error(png_ptr, "bKGD must be after");
-#endif
+   return errmsg != NULL ? handled_error : handled_error;
 }
 
-void /* PRIVATE */
+/* On read the IDAT chunk is always handled specially, even if marked for
+ * unknown handling (this is allowed), so:
+ */
+#define png_handle_IDAT NULL
+
+static png_handle_result_code
 png_handle_IEND(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 {
    png_debug(1, "in png_handle_IEND");
 
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0 ||
-       (png_ptr->mode & PNG_HAVE_IDAT) == 0)
-      png_chunk_error(png_ptr, "out of place");
-
    png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
 
-   png_crc_finish(png_ptr, length);
-
    if (length != 0)
       png_chunk_benign_error(png_ptr, "invalid");
 
+   png_crc_finish_critical(png_ptr, length, 1/*handle as ancillary*/);
+
+   return handled_ok;
    PNG_UNUSED(info_ptr)
 }
 
 #ifdef PNG_READ_gAMA_SUPPORTED
-void /* PRIVATE */
+static png_handle_result_code
 png_handle_gAMA(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 {
-   png_fixed_point igamma;
+   png_uint_32 ugamma;
    png_byte buf[4];
 
    png_debug(1, "in png_handle_gAMA");
 
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
+   png_crc_read(png_ptr, buf, 4);
 
-   else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "out of place");
-      return;
-   }
+   if (png_crc_finish(png_ptr, 0) != 0)
+      return handled_error;
+
+   ugamma = png_get_uint_32(buf);
 
-   if (length != 4)
+   if (ugamma > PNG_UINT_31_MAX)
    {
-      png_crc_finish(png_ptr, length);
       png_chunk_benign_error(png_ptr, "invalid");
-      return;
+      return handled_error;
    }
 
-   png_crc_read(png_ptr, buf, 4);
-
-   if (png_crc_finish(png_ptr, 0) != 0)
-      return;
+   png_set_gAMA_fixed(png_ptr, info_ptr, (png_fixed_point)/*SAFE*/ugamma);
 
-   igamma = png_get_fixed_point(NULL, buf);
+#ifdef PNG_READ_GAMMA_SUPPORTED
+      /* PNGv3: chunk precedence for gamma is cICP, [iCCP], sRGB, gAMA.  gAMA is
+       * at the end of the chain so simply check for an unset value.
+       */
+      if (png_ptr->chunk_gamma == 0)
+         png_ptr->chunk_gamma = (png_fixed_point)/*SAFE*/ugamma;
+#endif /*READ_GAMMA*/
 
-   png_colorspace_set_gamma(png_ptr, &png_ptr->colorspace, igamma);
-   png_colorspace_sync(png_ptr, info_ptr);
+   return handled_ok;
+   PNG_UNUSED(length)
 }
+#else
+#  define png_handle_gAMA NULL
 #endif
 
 #ifdef PNG_READ_sBIT_SUPPORTED
-void /* PRIVATE */
+static png_handle_result_code /* PRIVATE */
 png_handle_sBIT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 {
    unsigned int truelen, i;
@@ -1189,23 +1188,6 @@ png_handle_sBIT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 
    png_debug(1, "in png_handle_sBIT");
 
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
-
-   else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "out of place");
-      return;
-   }
-
-   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "duplicate");
-      return;
-   }
-
    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
    {
       truelen = 3;
@@ -1218,25 +1200,25 @@ png_handle_sBIT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
       sample_depth = png_ptr->bit_depth;
    }
 
-   if (length != truelen || length > 4)
+   if (length != truelen)
    {
-      png_chunk_benign_error(png_ptr, "invalid");
       png_crc_finish(png_ptr, length);
-      return;
+      png_chunk_benign_error(png_ptr, "bad length");
+      return handled_error;
    }
 
    buf[0] = buf[1] = buf[2] = buf[3] = sample_depth;
    png_crc_read(png_ptr, buf, truelen);
 
    if (png_crc_finish(png_ptr, 0) != 0)
-      return;
+      return handled_error;
 
    for (i=0; i sample_depth)
       {
          png_chunk_benign_error(png_ptr, "invalid");
-         return;
+         return handled_error;
       }
    }
 
@@ -1248,7 +1230,7 @@ png_handle_sBIT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
       png_ptr->sig_bit.alpha = buf[3];
    }
 
-   else
+   else /* grayscale */
    {
       png_ptr->sig_bit.gray = buf[0];
       png_ptr->sig_bit.red = buf[0];
@@ -1258,133 +1240,132 @@ png_handle_sBIT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
    }
 
    png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
+   return handled_ok;
 }
+#else
+#  define png_handle_sBIT NULL
 #endif
 
 #ifdef PNG_READ_cHRM_SUPPORTED
-void /* PRIVATE */
-png_handle_cHRM(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+static png_int_32
+png_get_int_32_checked(png_const_bytep buf, int *error)
 {
-   png_byte buf[32];
-   png_xy xy;
+   png_uint_32 uval = png_get_uint_32(buf);
+   if ((uval & 0x80000000) == 0) /* non-negative */
+      return (png_int_32)uval;
 
-   png_debug(1, "in png_handle_cHRM");
+   uval = (uval ^ 0xffffffff) + 1;  /* 2's complement: -x = ~x+1 */
+   if ((uval & 0x80000000) == 0) /* no overflow */
+      return -(png_int_32)uval;
 
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
+   /* This version of png_get_int_32 has a way of returning the error to the
+    * caller, so:
+    */
+   *error = 1;
+   return 0; /* Safe */
+}
 
-   else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "out of place");
-      return;
-   }
+static png_handle_result_code /* PRIVATE */
+png_handle_cHRM(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+{
+   int error = 0;
+   png_xy xy;
+   png_byte buf[32];
 
-   if (length != 32)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "invalid");
-      return;
-   }
+   png_debug(1, "in png_handle_cHRM");
 
    png_crc_read(png_ptr, buf, 32);
 
    if (png_crc_finish(png_ptr, 0) != 0)
-      return;
+      return handled_error;
+
+   xy.whitex = png_get_int_32_checked(buf +  0, &error);
+   xy.whitey = png_get_int_32_checked(buf +  4, &error);
+   xy.redx   = png_get_int_32_checked(buf +  8, &error);
+   xy.redy   = png_get_int_32_checked(buf + 12, &error);
+   xy.greenx = png_get_int_32_checked(buf + 16, &error);
+   xy.greeny = png_get_int_32_checked(buf + 20, &error);
+   xy.bluex  = png_get_int_32_checked(buf + 24, &error);
+   xy.bluey  = png_get_int_32_checked(buf + 28, &error);
 
-   xy.whitex = png_get_fixed_point(NULL, buf);
-   xy.whitey = png_get_fixed_point(NULL, buf + 4);
-   xy.redx   = png_get_fixed_point(NULL, buf + 8);
-   xy.redy   = png_get_fixed_point(NULL, buf + 12);
-   xy.greenx = png_get_fixed_point(NULL, buf + 16);
-   xy.greeny = png_get_fixed_point(NULL, buf + 20);
-   xy.bluex  = png_get_fixed_point(NULL, buf + 24);
-   xy.bluey  = png_get_fixed_point(NULL, buf + 28);
-
-   if (xy.whitex == PNG_FIXED_ERROR ||
-       xy.whitey == PNG_FIXED_ERROR ||
-       xy.redx   == PNG_FIXED_ERROR ||
-       xy.redy   == PNG_FIXED_ERROR ||
-       xy.greenx == PNG_FIXED_ERROR ||
-       xy.greeny == PNG_FIXED_ERROR ||
-       xy.bluex  == PNG_FIXED_ERROR ||
-       xy.bluey  == PNG_FIXED_ERROR)
+   if (error)
    {
-      png_chunk_benign_error(png_ptr, "invalid values");
-      return;
+      png_chunk_benign_error(png_ptr, "invalid");
+      return handled_error;
    }
 
-   /* If a colorspace error has already been output skip this chunk */
-   if ((png_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) != 0)
-      return;
+   /* png_set_cHRM may complain about some of the values but this doesn't matter
+    * because it was a cHRM and it did have vaguely (if, perhaps, ridiculous)
+    * values.  Ridiculousity will be checked if the values are used later.
+    */
+   png_set_cHRM_fixed(png_ptr, info_ptr, xy.whitex, xy.whitey, xy.redx, xy.redy,
+         xy.greenx, xy.greeny, xy.bluex, xy.bluey);
 
-   if ((png_ptr->colorspace.flags & PNG_COLORSPACE_FROM_cHRM) != 0)
-   {
-      png_ptr->colorspace.flags |= PNG_COLORSPACE_INVALID;
-      png_colorspace_sync(png_ptr, info_ptr);
-      png_chunk_benign_error(png_ptr, "duplicate");
-      return;
-   }
+   /* We only use 'chromaticities' for RGB to gray */
+#  ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+      /* There is no need to check sRGB here, cICP is NYI and iCCP is not
+       * supported so just check mDCV.
+       */
+      if (!png_has_chunk(png_ptr, mDCV))
+      {
+         png_ptr->chromaticities = xy;
+      }
+#  endif /* READ_RGB_TO_GRAY */
 
-   png_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM;
-   (void)png_colorspace_set_chromaticities(png_ptr, &png_ptr->colorspace, &xy,
-       1/*prefer cHRM values*/);
-   png_colorspace_sync(png_ptr, info_ptr);
+   return handled_ok;
+   PNG_UNUSED(length)
 }
+#else
+#  define png_handle_cHRM NULL
 #endif
 
 #ifdef PNG_READ_sRGB_SUPPORTED
-void /* PRIVATE */
+static png_handle_result_code /* PRIVATE */
 png_handle_sRGB(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 {
    png_byte intent;
 
    png_debug(1, "in png_handle_sRGB");
 
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
-
-   else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "out of place");
-      return;
-   }
-
-   if (length != 1)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "invalid");
-      return;
-   }
-
    png_crc_read(png_ptr, &intent, 1);
 
    if (png_crc_finish(png_ptr, 0) != 0)
-      return;
+      return handled_error;
 
-   /* If a colorspace error has already been output skip this chunk */
-   if ((png_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) != 0)
-      return;
-
-   /* Only one sRGB or iCCP chunk is allowed, use the HAVE_INTENT flag to detect
-    * this.
+   /* This checks the range of the "rendering intent" because it is specified in
+    * the PNG spec itself; the "reserved" values will result in the chunk not
+    * being accepted, just as they do with the various "reserved" values in
+    * IHDR.
     */
-   if ((png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_INTENT) != 0)
+   if (intent > 3/*PNGv3 spec*/)
    {
-      png_ptr->colorspace.flags |= PNG_COLORSPACE_INVALID;
-      png_colorspace_sync(png_ptr, info_ptr);
-      png_chunk_benign_error(png_ptr, "too many profiles");
-      return;
+      png_chunk_benign_error(png_ptr, "invalid");
+      return handled_error;
    }
 
-   (void)png_colorspace_set_sRGB(png_ptr, &png_ptr->colorspace, intent);
-   png_colorspace_sync(png_ptr, info_ptr);
+   png_set_sRGB(png_ptr, info_ptr, intent);
+   /* NOTE: png_struct::chromaticities is not set here because the RGB to gray
+    * coefficients are known without a need for the chromaticities.
+    */
+
+#ifdef PNG_READ_GAMMA_SUPPORTED
+      /* PNGv3: chunk precedence for gamma is cICP, [iCCP], sRGB, gAMA.  iCCP is
+       * not supported by libpng so the only requirement is to check for cICP
+       * setting the gamma (this is NYI, but this check is safe.)
+       */
+      if (!png_has_chunk(png_ptr, cICP) || png_ptr->chunk_gamma == 0)
+         png_ptr->chunk_gamma = PNG_GAMMA_sRGB_INVERSE;
+#endif /*READ_GAMMA*/
+
+   return handled_ok;
+   PNG_UNUSED(length)
 }
+#else
+#  define png_handle_sRGB NULL
 #endif /* READ_sRGB */
 
 #ifdef PNG_READ_iCCP_SUPPORTED
-void /* PRIVATE */
+static png_handle_result_code /* PRIVATE */
 png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 /* Note: this does not properly handle profiles that are > 64K under DOS */
 {
@@ -1393,44 +1374,10 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 
    png_debug(1, "in png_handle_iCCP");
 
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
-
-   else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "out of place");
-      return;
-   }
-
-   /* Consistent with all the above colorspace handling an obviously *invalid*
-    * chunk is just ignored, so does not invalidate the color space.  An
-    * alternative is to set the 'invalid' flags at the start of this routine
-    * and only clear them in they were not set before and all the tests pass.
+   /* PNGv3: allow PNG files with both sRGB and iCCP because the PNG spec only
+    * ever said that there "should" be only one, not "shall" and the PNGv3
+    * colour chunk precedence rules give a handling for this case anyway.
     */
-
-   /* The keyword must be at least one character and there is a
-    * terminator (0) byte and the compression method byte, and the
-    * 'zlib' datastream is at least 11 bytes.
-    */
-   if (length < 14)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "too short");
-      return;
-   }
-
-   /* If a colorspace error has already been output skip this chunk */
-   if ((png_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      return;
-   }
-
-   /* Only one sRGB or iCCP chunk is allowed, use the HAVE_INTENT flag to detect
-    * this.
-    */
-   if ((png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_INTENT) == 0)
    {
       uInt read_length, keyword_length;
       char keyword[81];
@@ -1440,19 +1387,16 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
        */
       read_length = 81; /* maximum */
       if (read_length > length)
-         read_length = (uInt)length;
+         read_length = (uInt)/*SAFE*/length;
 
       png_crc_read(png_ptr, (png_bytep)keyword, read_length);
       length -= read_length;
 
-      /* The minimum 'zlib' stream is assumed to be just the 2 byte header,
-       * 5 bytes minimum 'deflate' stream, and the 4 byte checksum.
-       */
-      if (length < 11)
+      if (length < LZ77Min)
       {
          png_crc_finish(png_ptr, length);
          png_chunk_benign_error(png_ptr, "too short");
-         return;
+         return handled_error;
       }
 
       keyword_length = 0;
@@ -1489,15 +1433,14 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
                    */
                   png_uint_32 profile_length = png_get_uint_32(profile_header);
 
-                  if (png_icc_check_length(png_ptr, &png_ptr->colorspace,
-                      keyword, profile_length) != 0)
+                  if (png_icc_check_length(png_ptr, keyword, profile_length) !=
+                      0)
                   {
                      /* The length is apparently ok, so we can check the 132
                       * byte header.
                       */
-                     if (png_icc_check_header(png_ptr, &png_ptr->colorspace,
-                         keyword, profile_length, profile_header,
-                         png_ptr->color_type) != 0)
+                     if (png_icc_check_header(png_ptr, keyword, profile_length,
+                              profile_header, png_ptr->color_type) != 0)
                      {
                         /* Now read the tag table; a variable size buffer is
                          * needed at this point, allocate one for the whole
@@ -1507,7 +1450,7 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
                         png_uint_32 tag_count =
                            png_get_uint_32(profile_header + 128);
                         png_bytep profile = png_read_buffer(png_ptr,
-                            profile_length, 2/*silent*/);
+                              profile_length);
 
                         if (profile != NULL)
                         {
@@ -1526,8 +1469,7 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
                            if (size == 0)
                            {
                               if (png_icc_check_tag_table(png_ptr,
-                                  &png_ptr->colorspace, keyword, profile_length,
-                                  profile) != 0)
+                                       keyword, profile_length, profile) != 0)
                               {
                                  /* The profile has been validated for basic
                                   * security issues, so read the whole thing in.
@@ -1559,13 +1501,6 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
                                     png_crc_finish(png_ptr, length);
                                     finished = 1;
 
-# if defined(PNG_sRGB_SUPPORTED) && PNG_sRGB_PROFILE_CHECKS >= 0
-                                    /* Check for a match against sRGB */
-                                    png_icc_set_sRGB(png_ptr,
-                                        &png_ptr->colorspace, profile,
-                                        png_ptr->zstream.adler);
-# endif
-
                                     /* Steal the profile for info_ptr. */
                                     if (info_ptr != NULL)
                                     {
@@ -1588,11 +1523,7 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
                                        }
 
                                        else
-                                       {
-                                          png_ptr->colorspace.flags |=
-                                             PNG_COLORSPACE_INVALID;
                                           errmsg = "out of memory";
-                                       }
                                     }
 
                                     /* else the profile remains in the read
@@ -1600,13 +1531,10 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
                                      * chunks.
                                      */
 
-                                    if (info_ptr != NULL)
-                                       png_colorspace_sync(png_ptr, info_ptr);
-
                                     if (errmsg == NULL)
                                     {
                                        png_ptr->zowner = 0;
-                                       return;
+                                       return handled_ok;
                                     }
                                  }
                                  if (errmsg == NULL)
@@ -1647,22 +1575,21 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
          errmsg = "bad keyword";
    }
 
-   else
-      errmsg = "too many profiles";
-
    /* Failure: the reason is in 'errmsg' */
    if (finished == 0)
       png_crc_finish(png_ptr, length);
 
-   png_ptr->colorspace.flags |= PNG_COLORSPACE_INVALID;
-   png_colorspace_sync(png_ptr, info_ptr);
    if (errmsg != NULL) /* else already output */
       png_chunk_benign_error(png_ptr, errmsg);
+
+   return handled_error;
 }
+#else
+#  define png_handle_iCCP NULL
 #endif /* READ_iCCP */
 
 #ifdef PNG_READ_sPLT_SUPPORTED
-void /* PRIVATE */
+static png_handle_result_code /* PRIVATE */
 png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 /* Note: this does not properly handle chunks that are > 64K under DOS */
 {
@@ -1683,43 +1610,24 @@ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
       if (png_ptr->user_chunk_cache_max == 1)
       {
          png_crc_finish(png_ptr, length);
-         return;
+         return handled_error;
       }
 
       if (--png_ptr->user_chunk_cache_max == 1)
       {
          png_warning(png_ptr, "No space in chunk cache for sPLT");
          png_crc_finish(png_ptr, length);
-         return;
+         return handled_error;
       }
    }
 #endif
 
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
-
-   else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "out of place");
-      return;
-   }
-
-#ifdef PNG_MAX_MALLOC_64K
-   if (length > 65535U)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "too large to fit in memory");
-      return;
-   }
-#endif
-
-   buffer = png_read_buffer(png_ptr, length+1, 2/*silent*/);
+   buffer = png_read_buffer(png_ptr, length+1);
    if (buffer == NULL)
    {
       png_crc_finish(png_ptr, length);
       png_chunk_benign_error(png_ptr, "out of memory");
-      return;
+      return handled_error;
    }
 
 
@@ -1730,7 +1638,7 @@ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
    png_crc_read(png_ptr, buffer, length);
 
    if (png_crc_finish(png_ptr, skip) != 0)
-      return;
+      return handled_error;
 
    buffer[length] = 0;
 
@@ -1743,7 +1651,7 @@ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
    if (length < 2U || entry_start > buffer + (length - 2U))
    {
       png_warning(png_ptr, "malformed sPLT chunk");
-      return;
+      return handled_error;
    }
 
    new_palette.depth = *entry_start++;
@@ -1757,7 +1665,7 @@ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
    if ((data_length % (unsigned int)entry_size) != 0)
    {
       png_warning(png_ptr, "sPLT chunk has bad length");
-      return;
+      return handled_error;
    }
 
    dl = (png_uint_32)(data_length / (unsigned int)entry_size);
@@ -1766,7 +1674,7 @@ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
    if (dl > max_dl)
    {
       png_warning(png_ptr, "sPLT chunk too long");
-      return;
+      return handled_error;
    }
 
    new_palette.nentries = (png_int_32)(data_length / (unsigned int)entry_size);
@@ -1777,10 +1685,9 @@ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
    if (new_palette.entries == NULL)
    {
       png_warning(png_ptr, "sPLT chunk requires too much memory");
-      return;
+      return handled_error;
    }
 
-#ifdef PNG_POINTER_INDEXING_SUPPORTED
    for (i = 0; i < new_palette.nentries; i++)
    {
       pp = new_palette.entries + i;
@@ -1803,31 +1710,6 @@ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 
       pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
    }
-#else
-   pp = new_palette.entries;
-
-   for (i = 0; i < new_palette.nentries; i++)
-   {
-
-      if (new_palette.depth == 8)
-      {
-         pp[i].red   = *entry_start++;
-         pp[i].green = *entry_start++;
-         pp[i].blue  = *entry_start++;
-         pp[i].alpha = *entry_start++;
-      }
-
-      else
-      {
-         pp[i].red   = png_get_uint_16(entry_start); entry_start += 2;
-         pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
-         pp[i].blue  = png_get_uint_16(entry_start); entry_start += 2;
-         pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
-      }
-
-      pp[i].frequency = png_get_uint_16(entry_start); entry_start += 2;
-   }
-#endif
 
    /* Discard all chunk data except the name and stash that */
    new_palette.name = (png_charp)buffer;
@@ -1835,34 +1717,20 @@ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
    png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
 
    png_free(png_ptr, new_palette.entries);
+   return handled_ok;
 }
+#else
+#  define png_handle_sPLT NULL
 #endif /* READ_sPLT */
 
 #ifdef PNG_READ_tRNS_SUPPORTED
-void /* PRIVATE */
+static png_handle_result_code /* PRIVATE */
 png_handle_tRNS(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 {
    png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
 
    png_debug(1, "in png_handle_tRNS");
 
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
-
-   else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "out of place");
-      return;
-   }
-
-   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "duplicate");
-      return;
-   }
-
    if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
    {
       png_byte buf[2];
@@ -1871,7 +1739,7 @@ png_handle_tRNS(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
       {
          png_crc_finish(png_ptr, length);
          png_chunk_benign_error(png_ptr, "invalid");
-         return;
+         return handled_error;
       }
 
       png_crc_read(png_ptr, buf, 2);
@@ -1887,7 +1755,7 @@ png_handle_tRNS(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
       {
          png_crc_finish(png_ptr, length);
          png_chunk_benign_error(png_ptr, "invalid");
-         return;
+         return handled_error;
       }
 
       png_crc_read(png_ptr, buf, length);
@@ -1901,10 +1769,9 @@ png_handle_tRNS(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
    {
       if ((png_ptr->mode & PNG_HAVE_PLTE) == 0)
       {
-         /* TODO: is this actually an error in the ISO spec? */
          png_crc_finish(png_ptr, length);
          png_chunk_benign_error(png_ptr, "out of place");
-         return;
+         return handled_error;
       }
 
       if (length > (unsigned int) png_ptr->num_palette ||
@@ -1913,7 +1780,7 @@ png_handle_tRNS(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
       {
          png_crc_finish(png_ptr, length);
          png_chunk_benign_error(png_ptr, "invalid");
-         return;
+         return handled_error;
       }
 
       png_crc_read(png_ptr, readbuf, length);
@@ -1924,13 +1791,13 @@ png_handle_tRNS(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
    {
       png_crc_finish(png_ptr, length);
       png_chunk_benign_error(png_ptr, "invalid with alpha channel");
-      return;
+      return handled_error;
    }
 
    if (png_crc_finish(png_ptr, 0) != 0)
    {
       png_ptr->num_trans = 0;
-      return;
+      return handled_error;
    }
 
    /* TODO: this is a horrible side effect in the palette case because the
@@ -1939,11 +1806,14 @@ png_handle_tRNS(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
     */
    png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
        &(png_ptr->trans_color));
+   return handled_ok;
 }
+#else
+#  define png_handle_tRNS NULL
 #endif
 
 #ifdef PNG_READ_bKGD_SUPPORTED
-void /* PRIVATE */
+static png_handle_result_code /* PRIVATE */
 png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 {
    unsigned int truelen;
@@ -1952,27 +1822,17 @@ png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 
    png_debug(1, "in png_handle_bKGD");
 
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
-
-   else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0 ||
-       (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
-       (png_ptr->mode & PNG_HAVE_PLTE) == 0))
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "out of place");
-      return;
-   }
-
-   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) != 0)
+   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
    {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "duplicate");
-      return;
-   }
+      if ((png_ptr->mode & PNG_HAVE_PLTE) == 0)
+      {
+         png_crc_finish(png_ptr, length);
+         png_chunk_benign_error(png_ptr, "out of place");
+         return handled_error;
+      }
 
-   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
       truelen = 1;
+   }
 
    else if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
       truelen = 6;
@@ -1984,13 +1844,13 @@ png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
    {
       png_crc_finish(png_ptr, length);
       png_chunk_benign_error(png_ptr, "invalid");
-      return;
+      return handled_error;
    }
 
    png_crc_read(png_ptr, buf, truelen);
 
    if (png_crc_finish(png_ptr, 0) != 0)
-      return;
+      return handled_error;
 
    /* We convert the index value into RGB components so that we can allow
     * arbitrary RGB values for background when we have transparency, and
@@ -2006,7 +1866,7 @@ png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
          if (buf[0] >= info_ptr->num_palette)
          {
             png_chunk_benign_error(png_ptr, "invalid index");
-            return;
+            return handled_error;
          }
 
          background.red = (png_uint_16)png_ptr->palette[buf[0]].red;
@@ -2027,7 +1887,7 @@ png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
          if (buf[0] != 0 || buf[1] >= (unsigned int)(1 << png_ptr->bit_depth))
          {
             png_chunk_benign_error(png_ptr, "invalid gray level");
-            return;
+            return handled_error;
          }
       }
 
@@ -2045,7 +1905,7 @@ png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
          if (buf[0] != 0 || buf[2] != 0 || buf[4] != 0)
          {
             png_chunk_benign_error(png_ptr, "invalid color");
-            return;
+            return handled_error;
          }
       }
 
@@ -2057,75 +1917,174 @@ png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
    }
 
    png_set_bKGD(png_ptr, info_ptr, &background);
+   return handled_ok;
 }
+#else
+#  define png_handle_bKGD NULL
 #endif
 
-#ifdef PNG_READ_eXIf_SUPPORTED
-void /* PRIVATE */
-png_handle_eXIf(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+#ifdef PNG_READ_cICP_SUPPORTED
+static png_handle_result_code /* PRIVATE */
+png_handle_cICP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 {
-   unsigned int i;
+   png_byte buf[4];
 
-   png_debug(1, "in png_handle_eXIf");
+   png_debug(1, "in png_handle_cICP");
 
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
+   png_crc_read(png_ptr, buf, 4);
 
-   if (length < 2)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "too short");
-      return;
-   }
+   if (png_crc_finish(png_ptr, 0) != 0)
+      return handled_error;
 
-   else if (info_ptr == NULL || (info_ptr->valid & PNG_INFO_eXIf) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "duplicate");
-      return;
-   }
+   png_set_cICP(png_ptr, info_ptr, buf[0], buf[1],  buf[2], buf[3]);
 
-   info_ptr->free_me |= PNG_FREE_EXIF;
+   /* We only use 'chromaticities' for RGB to gray */
+#  ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+      if (!png_has_chunk(png_ptr, mDCV))
+      {
+         /* TODO: png_ptr->chromaticities = chromaticities; */
+      }
+#  endif /* READ_RGB_TO_GRAY */
 
-   info_ptr->eXIf_buf = png_voidcast(png_bytep,
-             png_malloc_warn(png_ptr, length));
+#ifdef PNG_READ_GAMMA_SUPPORTED
+      /* PNGv3: chunk precedence for gamma is cICP, [iCCP], sRGB, gAMA.  cICP is
+       * at the head so simply set the gamma if it can be determined.  If not
+       * chunk_gamma remains unchanged; sRGB and gAMA handling check it for
+       * being zero.
+       */
+      /* TODO: set png_struct::chunk_gamma when possible */
+#endif /*READ_GAMMA*/
+
+   return handled_ok;
+   PNG_UNUSED(length)
+}
+#else
+#  define png_handle_cICP NULL
+#endif
+
+#ifdef PNG_READ_cLLI_SUPPORTED
+static png_handle_result_code /* PRIVATE */
+png_handle_cLLI(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+{
+   png_byte buf[8];
 
-   if (info_ptr->eXIf_buf == NULL)
+   png_debug(1, "in png_handle_cLLI");
+
+   png_crc_read(png_ptr, buf, 8);
+
+   if (png_crc_finish(png_ptr, 0) != 0)
+      return handled_error;
+
+   /* The error checking happens here, this puts it in just one place: */
+   png_set_cLLI_fixed(png_ptr, info_ptr, png_get_uint_32(buf),
+         png_get_uint_32(buf+4));
+   return handled_ok;
+   PNG_UNUSED(length)
+}
+#else
+#  define png_handle_cLLI NULL
+#endif
+
+#ifdef PNG_READ_mDCV_SUPPORTED
+static png_handle_result_code /* PRIVATE */
+png_handle_mDCV(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+{
+   png_xy chromaticities;
+   png_byte buf[24];
+
+   png_debug(1, "in png_handle_mDCV");
+
+   png_crc_read(png_ptr, buf, 24);
+
+   if (png_crc_finish(png_ptr, 0) != 0)
+      return handled_error;
+
+   /* The error checking happens here, this puts it in just one place.  The
+    * odd /50000 scaling factor makes it more difficult but the (x.y) values are
+    * only two bytes so a <<1 is safe.
+    *
+    * WARNING: the PNG specification defines the cHRM chunk to **start** with
+    * the white point (x,y).  The W3C PNG v3 specification puts the white point
+    * **after* R,G,B.  The x,y values in mDCV are also scaled by 50,000 and
+    * stored in just two bytes, whereas those in cHRM are scaled by 100,000 and
+    * stored in four bytes.  This is very, very confusing.  These APIs remove
+    * the confusion by copying the existing, well established, API.
+    */
+   chromaticities.redx   = png_get_uint_16(buf+ 0U) << 1; /* red x */
+   chromaticities.redy   = png_get_uint_16(buf+ 2U) << 1; /* red y */
+   chromaticities.greenx = png_get_uint_16(buf+ 4U) << 1; /* green x */
+   chromaticities.greeny = png_get_uint_16(buf+ 6U) << 1; /* green y */
+   chromaticities.bluex  = png_get_uint_16(buf+ 8U) << 1; /* blue x */
+   chromaticities.bluey  = png_get_uint_16(buf+10U) << 1; /* blue y */
+   chromaticities.whitex = png_get_uint_16(buf+12U) << 1; /* white x */
+   chromaticities.whitey = png_get_uint_16(buf+14U) << 1; /* white y */
+
+   png_set_mDCV_fixed(png_ptr, info_ptr,
+         chromaticities.whitex, chromaticities.whitey,
+         chromaticities.redx, chromaticities.redy,
+         chromaticities.greenx, chromaticities.greeny,
+         chromaticities.bluex, chromaticities.bluey,
+         png_get_uint_32(buf+16U), /* peak luminance */
+         png_get_uint_32(buf+20U));/* minimum perceivable luminance */
+
+   /* We only use 'chromaticities' for RGB to gray */
+#  ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+      png_ptr->chromaticities = chromaticities;
+#  endif /* READ_RGB_TO_GRAY */
+
+   return handled_ok;
+   PNG_UNUSED(length)
+}
+#else
+#  define png_handle_mDCV NULL
+#endif
+
+#ifdef PNG_READ_eXIf_SUPPORTED
+static png_handle_result_code /* PRIVATE */
+png_handle_eXIf(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+{
+   png_bytep buffer = NULL;
+
+   png_debug(1, "in png_handle_eXIf");
+
+   buffer = png_read_buffer(png_ptr, length);
+
+   if (buffer == NULL)
    {
       png_crc_finish(png_ptr, length);
       png_chunk_benign_error(png_ptr, "out of memory");
-      return;
+      return handled_error;
    }
 
-   for (i = 0; i < length; i++)
+   png_crc_read(png_ptr, buffer, length);
+
+   if (png_crc_finish(png_ptr, 0) != 0)
+      return handled_error;
+
+   /* PNGv3: the code used to check the byte order mark at the start for MM or
+    * II, however PNGv3 states that the the first 4 bytes should be checked.
+    * The caller ensures that there are four bytes available.
+    */
    {
-      png_byte buf[1];
-      png_crc_read(png_ptr, buf, 1);
-      info_ptr->eXIf_buf[i] = buf[0];
-      if (i == 1)
+      png_uint_32 header = png_get_uint_32(buffer);
+
+      /* These numbers are copied from the PNGv3 spec: */
+      if (header != 0x49492A00 && header != 0x4D4D002A)
       {
-         if ((buf[0] != 'M' && buf[0] != 'I') ||
-             (info_ptr->eXIf_buf[0] != buf[0]))
-         {
-            png_crc_finish(png_ptr, length - 2);
-            png_chunk_benign_error(png_ptr, "incorrect byte-order specifier");
-            png_free(png_ptr, info_ptr->eXIf_buf);
-            info_ptr->eXIf_buf = NULL;
-            return;
-         }
+         png_chunk_benign_error(png_ptr, "invalid");
+         return handled_error;
       }
    }
 
-   if (png_crc_finish(png_ptr, 0) == 0)
-      png_set_eXIf_1(png_ptr, info_ptr, length, info_ptr->eXIf_buf);
-
-   png_free(png_ptr, info_ptr->eXIf_buf);
-   info_ptr->eXIf_buf = NULL;
+   png_set_eXIf_1(png_ptr, info_ptr, length, buffer);
+   return handled_ok;
 }
+#else
+#  define png_handle_eXIf NULL
 #endif
 
 #ifdef PNG_READ_hIST_SUPPORTED
-void /* PRIVATE */
+static png_handle_result_code /* PRIVATE */
 png_handle_hIST(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 {
    unsigned int num, i;
@@ -2133,25 +2092,13 @@ png_handle_hIST(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 
    png_debug(1, "in png_handle_hIST");
 
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
-
-   else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0 ||
-       (png_ptr->mode & PNG_HAVE_PLTE) == 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "out of place");
-      return;
-   }
-
-   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "duplicate");
-      return;
-   }
-
-   num = length / 2 ;
+   /* This cast is safe because the chunk definition limits the length to a
+    * maximum of 1024 bytes.
+    *
+    * TODO: maybe use png_uint_32 anyway, not unsigned int, to reduce the
+    * casts.
+    */
+   num = (unsigned int)length / 2 ;
 
    if (length != num * 2 ||
        num != (unsigned int)png_ptr->num_palette ||
@@ -2159,7 +2106,7 @@ png_handle_hIST(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
    {
       png_crc_finish(png_ptr, length);
       png_chunk_benign_error(png_ptr, "invalid");
-      return;
+      return handled_error;
    }
 
    for (i = 0; i < num; i++)
@@ -2171,14 +2118,17 @@ png_handle_hIST(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
    }
 
    if (png_crc_finish(png_ptr, 0) != 0)
-      return;
+      return handled_error;
 
    png_set_hIST(png_ptr, info_ptr, readbuf);
+   return handled_ok;
 }
+#else
+#  define png_handle_hIST NULL
 #endif
 
 #ifdef PNG_READ_pHYs_SUPPORTED
-void /* PRIVATE */
+static png_handle_result_code /* PRIVATE */
 png_handle_pHYs(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 {
    png_byte buf[9];
@@ -2187,44 +2137,24 @@ png_handle_pHYs(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 
    png_debug(1, "in png_handle_pHYs");
 
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
-
-   else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "out of place");
-      return;
-   }
-
-   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "duplicate");
-      return;
-   }
-
-   if (length != 9)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "invalid");
-      return;
-   }
-
    png_crc_read(png_ptr, buf, 9);
 
    if (png_crc_finish(png_ptr, 0) != 0)
-      return;
+      return handled_error;
 
    res_x = png_get_uint_32(buf);
    res_y = png_get_uint_32(buf + 4);
    unit_type = buf[8];
    png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
+   return handled_ok;
+   PNG_UNUSED(length)
 }
+#else
+#  define png_handle_pHYs NULL
 #endif
 
 #ifdef PNG_READ_oFFs_SUPPORTED
-void /* PRIVATE */
+static png_handle_result_code /* PRIVATE */
 png_handle_oFFs(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 {
    png_byte buf[9];
@@ -2233,45 +2163,25 @@ png_handle_oFFs(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 
    png_debug(1, "in png_handle_oFFs");
 
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
-
-   else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "out of place");
-      return;
-   }
-
-   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "duplicate");
-      return;
-   }
-
-   if (length != 9)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "invalid");
-      return;
-   }
-
    png_crc_read(png_ptr, buf, 9);
 
    if (png_crc_finish(png_ptr, 0) != 0)
-      return;
+      return handled_error;
 
    offset_x = png_get_int_32(buf);
    offset_y = png_get_int_32(buf + 4);
    unit_type = buf[8];
    png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
+   return handled_ok;
+   PNG_UNUSED(length)
 }
+#else
+#  define png_handle_oFFs NULL
 #endif
 
 #ifdef PNG_READ_pCAL_SUPPORTED
 /* Read the pCAL chunk (described in the PNG Extensions document) */
-void /* PRIVATE */
+static png_handle_result_code /* PRIVATE */
 png_handle_pCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 {
    png_int_32 X0, X1;
@@ -2281,40 +2191,22 @@ png_handle_pCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
    int i;
 
    png_debug(1, "in png_handle_pCAL");
-
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
-
-   else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "out of place");
-      return;
-   }
-
-   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "duplicate");
-      return;
-   }
-
    png_debug1(2, "Allocating and reading pCAL chunk data (%u bytes)",
        length + 1);
 
-   buffer = png_read_buffer(png_ptr, length+1, 2/*silent*/);
+   buffer = png_read_buffer(png_ptr, length+1);
 
    if (buffer == NULL)
    {
       png_crc_finish(png_ptr, length);
       png_chunk_benign_error(png_ptr, "out of memory");
-      return;
+      return handled_error;
    }
 
    png_crc_read(png_ptr, buffer, length);
 
    if (png_crc_finish(png_ptr, 0) != 0)
-      return;
+      return handled_error;
 
    buffer[length] = 0; /* Null terminate the last string */
 
@@ -2330,7 +2222,7 @@ png_handle_pCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
    if (endptr - buf <= 12)
    {
       png_chunk_benign_error(png_ptr, "invalid");
-      return;
+      return handled_error;
    }
 
    png_debug(3, "Reading pCAL X0, X1, type, nparams, and units");
@@ -2350,7 +2242,7 @@ png_handle_pCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
        (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
    {
       png_chunk_benign_error(png_ptr, "invalid parameter count");
-      return;
+      return handled_error;
    }
 
    else if (type >= PNG_EQUATION_LAST)
@@ -2369,7 +2261,7 @@ png_handle_pCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
    if (params == NULL)
    {
       png_chunk_benign_error(png_ptr, "out of memory");
-      return;
+      return handled_error;
    }
 
    /* Get pointers to the start of each parameter string. */
@@ -2387,20 +2279,29 @@ png_handle_pCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
       {
          png_free(png_ptr, params);
          png_chunk_benign_error(png_ptr, "invalid data");
-         return;
+         return handled_error;
       }
    }
 
    png_set_pCAL(png_ptr, info_ptr, (png_charp)buffer, X0, X1, type, nparams,
        (png_charp)units, params);
 
+   /* TODO: BUG: png_set_pCAL calls png_chunk_report which, in this case, calls
+    * png_benign_error and that can error out.
+    *
+    * png_read_buffer needs to be allocated with space for both nparams and the
+    * parameter strings.  Not hard to do.
+    */
    png_free(png_ptr, params);
+   return handled_ok;
 }
+#else
+#  define png_handle_pCAL NULL
 #endif
 
 #ifdef PNG_READ_sCAL_SUPPORTED
 /* Read the sCAL chunk */
-void /* PRIVATE */
+static png_handle_result_code /* PRIVATE */
 png_handle_sCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 {
    png_bytep buffer;
@@ -2408,55 +2309,29 @@ png_handle_sCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
    int state;
 
    png_debug(1, "in png_handle_sCAL");
-
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
-
-   else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "out of place");
-      return;
-   }
-
-   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "duplicate");
-      return;
-   }
-
-   /* Need unit type, width, \0, height: minimum 4 bytes */
-   else if (length < 4)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "invalid");
-      return;
-   }
-
    png_debug1(2, "Allocating and reading sCAL chunk data (%u bytes)",
        length + 1);
 
-   buffer = png_read_buffer(png_ptr, length+1, 2/*silent*/);
+   buffer = png_read_buffer(png_ptr, length+1);
 
    if (buffer == NULL)
    {
-      png_chunk_benign_error(png_ptr, "out of memory");
       png_crc_finish(png_ptr, length);
-      return;
+      png_chunk_benign_error(png_ptr, "out of memory");
+      return handled_error;
    }
 
    png_crc_read(png_ptr, buffer, length);
    buffer[length] = 0; /* Null terminate the last string */
 
    if (png_crc_finish(png_ptr, 0) != 0)
-      return;
+      return handled_error;
 
    /* Validate the unit. */
    if (buffer[0] != 1 && buffer[0] != 2)
    {
       png_chunk_benign_error(png_ptr, "invalid unit");
-      return;
+      return handled_error;
    }
 
    /* Validate the ASCII numbers, need two ASCII numbers separated by
@@ -2485,15 +2360,22 @@ png_handle_sCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
          png_chunk_benign_error(png_ptr, "non-positive height");
 
       else
+      {
          /* This is the (only) success case. */
          png_set_sCAL_s(png_ptr, info_ptr, buffer[0],
              (png_charp)buffer+1, (png_charp)buffer+heighti);
+         return handled_ok;
+      }
    }
+
+   return handled_error;
 }
+#else
+#  define png_handle_sCAL NULL
 #endif
 
 #ifdef PNG_READ_tIME_SUPPORTED
-void /* PRIVATE */
+static png_handle_result_code /* PRIVATE */
 png_handle_tIME(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 {
    png_byte buf[7];
@@ -2501,30 +2383,17 @@ png_handle_tIME(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 
    png_debug(1, "in png_handle_tIME");
 
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
-
-   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "duplicate");
-      return;
-   }
-
+   /* TODO: what is this doing here?  It should be happened in pngread.c and
+    * pngpread.c, although it could be moved to png_handle_chunk below and
+    * thereby avoid some code duplication.
+    */
    if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
       png_ptr->mode |= PNG_AFTER_IDAT;
 
-   if (length != 7)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "invalid");
-      return;
-   }
-
    png_crc_read(png_ptr, buf, 7);
 
    if (png_crc_finish(png_ptr, 0) != 0)
-      return;
+      return handled_error;
 
    mod_time.second = buf[6];
    mod_time.minute = buf[5];
@@ -2534,12 +2403,16 @@ png_handle_tIME(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
    mod_time.year = png_get_uint_16(buf);
 
    png_set_tIME(png_ptr, info_ptr, &mod_time);
+   return handled_ok;
+   PNG_UNUSED(length)
 }
+#else
+#  define png_handle_tIME NULL
 #endif
 
 #ifdef PNG_READ_tEXt_SUPPORTED
 /* Note: this does not properly handle chunks that are > 64K under DOS */
-void /* PRIVATE */
+static png_handle_result_code /* PRIVATE */
 png_handle_tEXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 {
    png_text  text_info;
@@ -2556,45 +2429,35 @@ png_handle_tEXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
       if (png_ptr->user_chunk_cache_max == 1)
       {
          png_crc_finish(png_ptr, length);
-         return;
+         return handled_error;
       }
 
       if (--png_ptr->user_chunk_cache_max == 1)
       {
          png_crc_finish(png_ptr, length);
          png_chunk_benign_error(png_ptr, "no space in chunk cache");
-         return;
+         return handled_error;
       }
    }
 #endif
 
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
-
+   /* TODO: this doesn't work and shouldn't be necessary. */
    if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
       png_ptr->mode |= PNG_AFTER_IDAT;
 
-#ifdef PNG_MAX_MALLOC_64K
-   if (length > 65535U)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "too large to fit in memory");
-      return;
-   }
-#endif
-
-   buffer = png_read_buffer(png_ptr, length+1, 1/*warn*/);
+   buffer = png_read_buffer(png_ptr, length+1);
 
    if (buffer == NULL)
    {
+      png_crc_finish(png_ptr, length);
       png_chunk_benign_error(png_ptr, "out of memory");
-      return;
+      return handled_error;
    }
 
    png_crc_read(png_ptr, buffer, length);
 
    if (png_crc_finish(png_ptr, skip) != 0)
-      return;
+      return handled_error;
 
    key = (png_charp)buffer;
    key[length] = 0;
@@ -2613,14 +2476,19 @@ png_handle_tEXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
    text_info.text = text;
    text_info.text_length = strlen(text);
 
-   if (png_set_text_2(png_ptr, info_ptr, &text_info, 1) != 0)
-      png_warning(png_ptr, "Insufficient memory to process text chunk");
+   if (png_set_text_2(png_ptr, info_ptr, &text_info, 1) == 0)
+      return handled_ok;
+
+   png_chunk_benign_error(png_ptr, "out of memory");
+   return handled_error;
 }
+#else
+#  define png_handle_tEXt NULL
 #endif
 
 #ifdef PNG_READ_zTXt_SUPPORTED
 /* Note: this does not correctly handle chunks that are > 64K under DOS */
-void /* PRIVATE */
+static png_handle_result_code /* PRIVATE */
 png_handle_zTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 {
    png_const_charp errmsg = NULL;
@@ -2635,40 +2503,39 @@ png_handle_zTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
       if (png_ptr->user_chunk_cache_max == 1)
       {
          png_crc_finish(png_ptr, length);
-         return;
+         return handled_error;
       }
 
       if (--png_ptr->user_chunk_cache_max == 1)
       {
          png_crc_finish(png_ptr, length);
          png_chunk_benign_error(png_ptr, "no space in chunk cache");
-         return;
+         return handled_error;
       }
    }
 #endif
 
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
-
+   /* TODO: should not be necessary. */
    if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
       png_ptr->mode |= PNG_AFTER_IDAT;
 
    /* Note, "length" is sufficient here; we won't be adding
-    * a null terminator later.
+    * a null terminator later.  The limit check in png_handle_chunk should be
+    * sufficient.
     */
-   buffer = png_read_buffer(png_ptr, length, 2/*silent*/);
+   buffer = png_read_buffer(png_ptr, length);
 
    if (buffer == NULL)
    {
       png_crc_finish(png_ptr, length);
       png_chunk_benign_error(png_ptr, "out of memory");
-      return;
+      return handled_error;
    }
 
    png_crc_read(png_ptr, buffer, length);
 
    if (png_crc_finish(png_ptr, 0) != 0)
-      return;
+      return handled_error;
 
    /* TODO: also check that the keyword contents match the spec! */
    for (keyword_length = 0;
@@ -2721,8 +2588,10 @@ png_handle_zTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
             text.lang = NULL;
             text.lang_key = NULL;
 
-            if (png_set_text_2(png_ptr, info_ptr, &text, 1) != 0)
-               errmsg = "insufficient memory";
+            if (png_set_text_2(png_ptr, info_ptr, &text, 1) == 0)
+               return handled_ok;
+
+            errmsg = "out of memory";
          }
       }
 
@@ -2730,14 +2599,16 @@ png_handle_zTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
          errmsg = png_ptr->zstream.msg;
    }
 
-   if (errmsg != NULL)
-      png_chunk_benign_error(png_ptr, errmsg);
+   png_chunk_benign_error(png_ptr, errmsg);
+   return handled_error;
 }
+#else
+#  define png_handle_zTXt NULL
 #endif
 
 #ifdef PNG_READ_iTXt_SUPPORTED
 /* Note: this does not correctly handle chunks that are > 64K under DOS */
-void /* PRIVATE */
+static png_handle_result_code /* PRIVATE */
 png_handle_iTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 {
    png_const_charp errmsg = NULL;
@@ -2752,37 +2623,35 @@ png_handle_iTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
       if (png_ptr->user_chunk_cache_max == 1)
       {
          png_crc_finish(png_ptr, length);
-         return;
+         return handled_error;
       }
 
       if (--png_ptr->user_chunk_cache_max == 1)
       {
          png_crc_finish(png_ptr, length);
          png_chunk_benign_error(png_ptr, "no space in chunk cache");
-         return;
+         return handled_error;
       }
    }
 #endif
 
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
-
+   /* TODO: should not be necessary. */
    if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
       png_ptr->mode |= PNG_AFTER_IDAT;
 
-   buffer = png_read_buffer(png_ptr, length+1, 1/*warn*/);
+   buffer = png_read_buffer(png_ptr, length+1);
 
    if (buffer == NULL)
    {
       png_crc_finish(png_ptr, length);
       png_chunk_benign_error(png_ptr, "out of memory");
-      return;
+      return handled_error;
    }
 
    png_crc_read(png_ptr, buffer, length);
 
    if (png_crc_finish(png_ptr, 0) != 0)
-      return;
+      return handled_error;
 
    /* First the keyword. */
    for (prefix_length=0;
@@ -2872,8 +2741,10 @@ png_handle_iTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
          text.text_length = 0;
          text.itxt_length = uncompressed_length;
 
-         if (png_set_text_2(png_ptr, info_ptr, &text, 1) != 0)
-            errmsg = "insufficient memory";
+         if (png_set_text_2(png_ptr, info_ptr, &text, 1) == 0)
+            return handled_ok;
+
+         errmsg = "out of memory";
       }
    }
 
@@ -2882,7 +2753,10 @@ png_handle_iTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 
    if (errmsg != NULL)
       png_chunk_benign_error(png_ptr, errmsg);
+   return handled_error;
 }
+#else
+#  define png_handle_iTXt NULL
 #endif
 
 #ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
@@ -2890,7 +2764,7 @@ png_handle_iTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 static int
 png_cache_unknown_chunk(png_structrp png_ptr, png_uint_32 length)
 {
-   png_alloc_size_t limit = PNG_SIZE_MAX;
+   const png_alloc_size_t limit = png_chunk_max(png_ptr);
 
    if (png_ptr->unknown_chunk.data != NULL)
    {
@@ -2898,16 +2772,6 @@ png_cache_unknown_chunk(png_structrp png_ptr, png_uint_32 length)
       png_ptr->unknown_chunk.data = NULL;
    }
 
-#  ifdef PNG_SET_USER_LIMITS_SUPPORTED
-   if (png_ptr->user_chunk_malloc_max > 0 &&
-       png_ptr->user_chunk_malloc_max < limit)
-      limit = png_ptr->user_chunk_malloc_max;
-
-#  elif PNG_USER_CHUNK_MALLOC_MAX > 0
-   if (PNG_USER_CHUNK_MALLOC_MAX < limit)
-      limit = PNG_USER_CHUNK_MALLOC_MAX;
-#  endif
-
    if (length <= limit)
    {
       PNG_CSTRING_FROM_CHUNK(png_ptr->unknown_chunk.name, png_ptr->chunk_name);
@@ -2946,11 +2810,11 @@ png_cache_unknown_chunk(png_structrp png_ptr, png_uint_32 length)
 #endif /* READ_UNKNOWN_CHUNKS */
 
 /* Handle an unknown, or known but disabled, chunk */
-void /* PRIVATE */
+png_handle_result_code /*PRIVATE*/
 png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr,
     png_uint_32 length, int keep)
 {
-   int handled = 0; /* the chunk was handled */
+   png_handle_result_code handled = handled_discarded; /* the default */
 
    png_debug(1, "in png_handle_unknown");
 
@@ -2997,7 +2861,7 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr,
           *           error at this point unless it is to be saved.
           * positive: The chunk was handled, libpng will ignore/discard it.
           */
-         if (ret < 0)
+         if (ret < 0) /* handled_error */
             png_chunk_error(png_ptr, "error in user chunk");
 
          else if (ret == 0)
@@ -3031,7 +2895,7 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr,
 
          else /* chunk was handled */
          {
-            handled = 1;
+            handled = handled_ok;
             /* Critical chunks can be safely discarded at this point. */
             keep = PNG_HANDLE_CHUNK_NEVER;
          }
@@ -3116,7 +2980,7 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr,
              */
             png_set_unknown_chunks(png_ptr, info_ptr,
                 &png_ptr->unknown_chunk, 1);
-            handled = 1;
+            handled = handled_saved;
 #  ifdef PNG_USER_LIMITS_SUPPORTED
             break;
       }
@@ -3142,79 +3006,267 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr,
 #endif /* !READ_UNKNOWN_CHUNKS */
 
    /* Check for unhandled critical chunks */
-   if (handled == 0 && PNG_CHUNK_CRITICAL(png_ptr->chunk_name))
+   if (handled < handled_saved && PNG_CHUNK_CRITICAL(png_ptr->chunk_name))
       png_chunk_error(png_ptr, "unhandled critical chunk");
+
+   return handled;
 }
 
-/* This function is called to verify that a chunk name is valid.
- * This function can't have the "critical chunk check" incorporated
- * into it, since in the future we will need to be able to call user
- * functions to handle unknown critical chunks after we check that
- * the chunk name itself is valid.
+/* APNG handling: the minimal implementation of APNG handling in libpng 1.6
+ * requires that those significant applications which already handle APNG not
+ * get hosed.  To do this ensure the code here will have to ensure than APNG
+ * data by default (at least in 1.6) gets stored in the unknown chunk list.
+ * Maybe this can be relaxed in a few years but at present it's just the only
+ * safe way.
+ *
+ * ATM just cause unknown handling for all three chunks:
  */
+#define png_handle_acTL NULL
+#define png_handle_fcTL NULL
+#define png_handle_fdAT NULL
 
-/* Bit hacking: the test for an invalid byte in the 4 byte chunk name is:
+/*
+ * 1.6.47: This is the new table driven interface to all the chunk handling.
  *
- * ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
+ * The table describes the PNG standard rules for **reading** known chunks -
+ * every chunk which has an entry in PNG_KNOWN_CHUNKS.  The table contains an
+ * entry for each PNG_INDEX_cHNK describing the rules.
+ *
+ * In this initial version the only information in the entry is the
+ * png_handle_cHNK function for the chunk in question.  When chunk support is
+ * compiled out the entry will be NULL.
  */
-
-void /* PRIVATE */
-png_check_chunk_name(png_const_structrp png_ptr, png_uint_32 chunk_name)
+static const struct
 {
-   int i;
-   png_uint_32 cn=chunk_name;
-
-   png_debug(1, "in png_check_chunk_name");
+   png_handle_result_code (*handler)(
+         png_structrp, png_inforp, png_uint_32 length);
+      /* A chunk-specific 'handler', NULL if the chunk is not supported in this
+       * build.
+       */
 
-   for (i=1; i<=4; ++i)
+   /* Crushing these values helps on modern 32-bit architectures because the
+    * pointer and the following bit fields both end up requiring 32 bits.
+    * Typically this will halve the table size.  On 64-bit architectures the
+    * table entries will typically be 8 bytes.
+    */
+   png_uint_32 max_length :12; /* Length min, max in bytes */
+   png_uint_32 min_length :8;
+      /* Length errors on critical chunks have special handling to preserve the
+       * existing behaviour in libpng 1.6.  Anciallary chunks are checked below
+       * and produce a 'benign' error.
+       */
+   png_uint_32 pos_before :4; /* PNG_HAVE_ values chunk must precede */
+   png_uint_32 pos_after  :4; /* PNG_HAVE_ values chunk must follow */
+      /* NOTE: PLTE, tRNS and bKGD require special handling which depends on
+       * the colour type of the base image.
+       */
+   png_uint_32 multiple   :1; /* Multiple occurences permitted */
+      /* This is enabled for PLTE because PLTE may, in practice, be optional */
+}
+read_chunks[PNG_INDEX_unknown] =
+{
+   /* Definitions as above but done indirectly by #define so that
+    * PNG_KNOWN_CHUNKS can be used safely to build the table in order.
+    *
+    * Each CDcHNK definition lists the values for the parameters **after**
+    * the first, 'handler', function.  'handler' is NULL when the chunk has no
+    * compiled in support.
+    */
+#  define NoCheck 0x801U      /* Do not check the maximum length */
+#  define Limit   0x802U      /* Limit to png_chunk_max bytes */
+#  define LKMin   3U+LZ77Min  /* Minimum length of keyword+LZ77 */
+
+#define hIHDR PNG_HAVE_IHDR
+#define hPLTE PNG_HAVE_PLTE
+#define hIDAT PNG_HAVE_IDAT
+   /* For the two chunks, tRNS and bKGD which can occur in PNGs without a PLTE
+    * but must occur after the PLTE use this and put the check in the handler
+    * routine for colour mapped images were PLTE is required.  Also put a check
+    * in PLTE for other image types to drop the PLTE if tRNS or bKGD have been
+    * seen.
+    */
+#define hCOL  (PNG_HAVE_PLTE|PNG_HAVE_IDAT)
+   /* Used for the decoding chunks which must be before PLTE. */
+#define aIDAT PNG_AFTER_IDAT
+
+   /* Chunks from W3C PNG v3: */
+   /*       cHNK  max_len,   min, before, after, multiple */
+#  define CDIHDR      13U,   13U,  hIHDR,     0,        0
+#  define CDPLTE  NoCheck,    0U,      0, hIHDR,        1
+      /* PLTE errors are only critical for colour-map images, consequently the
+       * hander does all the checks.
+       */
+#  define CDIDAT  NoCheck,    0U,  aIDAT, hIHDR,        1
+#  define CDIEND  NoCheck,    0U,      0, aIDAT,        0
+      /* Historically data was allowed in IEND */
+#  define CDtRNS     256U,    0U,  hIDAT, hIHDR,        0
+#  define CDcHRM      32U,   32U,   hCOL, hIHDR,        0
+#  define CDgAMA       4U,    4U,   hCOL, hIHDR,        0
+#  define CDiCCP  NoCheck, LKMin,   hCOL, hIHDR,        0
+#  define CDsBIT       4U,    1U,   hCOL, hIHDR,        0
+#  define CDsRGB       1U,    1U,   hCOL, hIHDR,        0
+#  define CDcICP       4U,    4U,   hCOL, hIHDR,        0
+#  define CDmDCV      24U,   24U,   hCOL, hIHDR,        0
+#  define CDeXIf    Limit,    4U,      0, hIHDR,        0
+#  define CDcLLI       8U,    8U,   hCOL, hIHDR,        0
+#  define CDtEXt  NoCheck,    2U,      0, hIHDR,        1
+      /* Allocates 'length+1'; checked in the handler */
+#  define CDzTXt    Limit, LKMin,      0, hIHDR,        1
+#  define CDiTXt  NoCheck,    6U,      0, hIHDR,        1
+      /* Allocates 'length+1'; checked in the handler */
+#  define CDbKGD       6U,    1U,  hIDAT, hIHDR,        0
+#  define CDhIST    1024U,    0U,  hPLTE, hIHDR,        0
+#  define CDpHYs       9U,    9U,  hIDAT, hIHDR,        0
+#  define CDsPLT  NoCheck,    3U,  hIDAT, hIHDR,        1
+      /* Allocates 'length+1'; checked in the handler */
+#  define CDtIME       7U,    7U,      0, hIHDR,        0
+#  define CDacTL       8U,    8U,  hIDAT, hIHDR,        0
+#  define CDfcTL      25U,   26U,      0, hIHDR,        1
+#  define CDfdAT    Limit,    4U,  hIDAT, hIHDR,        1
+   /* Supported chunks from PNG extensions 1.5.0, NYI so limit */
+#  define CDoFFs       9U,    9U,  hIDAT, hIHDR,        0
+#  define CDpCAL  NoCheck,   14U,  hIDAT, hIHDR,        0
+      /* Allocates 'length+1'; checked in the handler */
+#  define CDsCAL    Limit,    4U,  hIDAT, hIHDR,        0
+      /* Allocates 'length+1'; checked in the handler */
+
+#  define PNG_CHUNK(cHNK, index) { png_handle_ ## cHNK, CD ## cHNK },
+   PNG_KNOWN_CHUNKS
+#  undef PNG_CHUNK
+};
+
+
+static png_index
+png_chunk_index_from_name(png_uint_32 chunk_name)
+{
+   /* For chunk png_cHNK return PNG_INDEX_cHNK.  Return PNG_INDEX_unknown if
+    * chunk_name is not known.  Notice that in a particular build "known" does
+    * not necessarily mean "supported", although the inverse applies.
+    */
+   switch (chunk_name)
    {
-      int c = cn & 0xff;
+#     define PNG_CHUNK(cHNK, index)\
+         case png_ ## cHNK: return PNG_INDEX_ ## cHNK; /* == index */
+
+      PNG_KNOWN_CHUNKS
 
-      if (c < 65 || c > 122 || (c > 90 && c < 97))
-         png_chunk_error(png_ptr, "invalid chunk type");
+#     undef PNG_CHUNK
 
-      cn >>= 8;
+      default: return PNG_INDEX_unknown;
    }
 }
 
-void /* PRIVATE */
-png_check_chunk_length(png_const_structrp png_ptr, png_uint_32 length)
+png_handle_result_code /*PRIVATE*/
+png_handle_chunk(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 {
-   png_alloc_size_t limit = PNG_UINT_31_MAX;
-
-# ifdef PNG_SET_USER_LIMITS_SUPPORTED
-   if (png_ptr->user_chunk_malloc_max > 0 &&
-       png_ptr->user_chunk_malloc_max < limit)
-      limit = png_ptr->user_chunk_malloc_max;
-# elif PNG_USER_CHUNK_MALLOC_MAX > 0
-   if (PNG_USER_CHUNK_MALLOC_MAX < limit)
-      limit = PNG_USER_CHUNK_MALLOC_MAX;
-# endif
-   if (png_ptr->chunk_name == png_IDAT)
+   /* CSE: these things don't change, these autos are just to save typing and
+    * make the code more clear.
+    */
+   const png_uint_32 chunk_name = png_ptr->chunk_name;
+   const png_index chunk_index = png_chunk_index_from_name(chunk_name);
+
+   png_handle_result_code handled = handled_error;
+   png_const_charp errmsg = NULL;
+
+   /* Is this a known chunk?  If not there are no checks performed here;
+    * png_handle_unknown does the correct checks.  This means that the values
+    * for known but unsupported chunks in the above table are not used here
+    * however the chunks_seen fields in png_struct are still set.
+    */
+   if (chunk_index == PNG_INDEX_unknown ||
+       read_chunks[chunk_index].handler == NULL)
    {
-      png_alloc_size_t idat_limit = PNG_UINT_31_MAX;
-      size_t row_factor =
-         (size_t)png_ptr->width
-         * (size_t)png_ptr->channels
-         * (png_ptr->bit_depth > 8? 2: 1)
-         + 1
-         + (png_ptr->interlaced? 6: 0);
-      if (png_ptr->height > PNG_UINT_32_MAX/row_factor)
-         idat_limit = PNG_UINT_31_MAX;
-      else
-         idat_limit = png_ptr->height * row_factor;
-      row_factor = row_factor > 32566? 32566 : row_factor;
-      idat_limit += 6 + 5*(idat_limit/row_factor+1); /* zlib+deflate overhead */
-      idat_limit=idat_limit < PNG_UINT_31_MAX? idat_limit : PNG_UINT_31_MAX;
-      limit = limit < idat_limit? idat_limit : limit;
+      handled = png_handle_unknown(
+            png_ptr, info_ptr, length, PNG_HANDLE_CHUNK_AS_DEFAULT);
+   }
+
+   /* First check the position.   The first check is historical; the stream must
+    * start with IHDR and anything else causes libpng to give up immediately.
+    */
+   else if (chunk_index != PNG_INDEX_IHDR &&
+            (png_ptr->mode & PNG_HAVE_IHDR) == 0)
+      png_chunk_error(png_ptr, "missing IHDR"); /* NORETURN */
+
+   /* Before all the pos_before chunks, after all the pos_after chunks. */
+   else if (((png_ptr->mode & read_chunks[chunk_index].pos_before) != 0) ||
+            ((png_ptr->mode & read_chunks[chunk_index].pos_after) !=
+             read_chunks[chunk_index].pos_after))
+   {
+      errmsg = "out of place";
+   }
+
+   /* Now check for duplicates: duplicated critical chunks also produce a
+    * full error.
+    */
+   else if (read_chunks[chunk_index].multiple == 0 &&
+            png_file_has_chunk(png_ptr, chunk_index))
+   {
+      errmsg = "duplicate";
+   }
+
+   else if (length < read_chunks[chunk_index].min_length)
+      errmsg = "too short";
+   else
+   {
+      /* NOTE: apart from IHDR the critical chunks (PLTE, IDAT and IEND) are set
+       * up above not to do any length checks.
+       *
+       * The png_chunk_max check ensures that the variable length chunks are
+       * always checked at this point for being within the system allocation
+       * limits.
+       */
+      unsigned max_length = read_chunks[chunk_index].max_length;
+
+      switch (max_length)
+      {
+         case Limit:
+            /* png_read_chunk_header has already png_error'ed chunks with a
+             * length exceeding the 31-bit PNG limit, so just check the memory
+             * limit:
+             */
+            if (length <= png_chunk_max(png_ptr))
+               goto MeetsLimit;
+
+            errmsg = "length exceeds libpng limit";
+            break;
+
+         default:
+            if (length <= max_length)
+               goto MeetsLimit;
+
+            errmsg = "too long";
+            break;
+
+         case NoCheck:
+         MeetsLimit:
+            handled = read_chunks[chunk_index].handler(
+                  png_ptr, info_ptr, length);
+            break;
+      }
+   }
+
+   /* If there was an error or the chunk was simply skipped it is not counted as
+    * 'seen'.
+    */
+   if (errmsg != NULL)
+   {
+      if (PNG_CHUNK_CRITICAL(chunk_name)) /* stop immediately */
+         png_chunk_error(png_ptr, errmsg);
+      else /* ancillary chunk */
+      {
+         /* The chunk data is skipped: */
+         png_crc_finish(png_ptr, length);
+         png_chunk_benign_error(png_ptr, errmsg);
+      }
    }
 
-   if (length > limit)
+   else if (handled >= handled_saved)
    {
-      png_debug2(0," length = %lu, limit = %lu",
-         (unsigned long)length,(unsigned long)limit);
-      png_benign_error(png_ptr, "chunk data is too large");
+      if (chunk_index != PNG_INDEX_unknown)
+         png_file_add_chunk(png_ptr, chunk_index);
    }
+
+   return handled;
 }
 
 /* Combines the row recently read in with the existing pixels in the row.  This
@@ -3712,10 +3764,6 @@ void /* PRIVATE */
 png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
     png_uint_32 transformations /* Because these may affect the byte layout */)
 {
-   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
-   /* Offset to next interlace block */
-   static const unsigned int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
-
    png_debug(1, "in png_do_read_interlace");
    if (row != NULL && row_info != NULL)
    {
@@ -4208,6 +4256,9 @@ png_read_IDAT_data(png_structrp png_ptr, png_bytep output,
 
          avail_in = png_ptr->IDAT_read_size;
 
+         if (avail_in > png_chunk_max(png_ptr))
+            avail_in = (uInt)/*SAFE*/png_chunk_max(png_ptr);
+
          if (avail_in > png_ptr->idat_size)
             avail_in = (uInt)png_ptr->idat_size;
 
@@ -4215,8 +4266,13 @@ png_read_IDAT_data(png_structrp png_ptr, png_bytep output,
           * to minimize memory usage by causing lots of re-allocs, but
           * realistically doing IDAT_read_size re-allocs is not likely to be a
           * big problem.
+          *
+          * An error here corresponds to the system being out of memory.
           */
-         buffer = png_read_buffer(png_ptr, avail_in, 0/*error*/);
+         buffer = png_read_buffer(png_ptr, avail_in);
+
+         if (buffer == NULL)
+            png_chunk_error(png_ptr, "out of memory");
 
          png_crc_read(png_ptr, buffer, avail_in);
          png_ptr->idat_size -= avail_in;
@@ -4353,20 +4409,6 @@ png_read_finish_IDAT(png_structrp png_ptr)
 void /* PRIVATE */
 png_read_finish_row(png_structrp png_ptr)
 {
-   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
-
-   /* Start of interlace block */
-   static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
-
-   /* Offset to next interlace block */
-   static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
-
-   /* Start of interlace block in the y direction */
-   static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
-
-   /* Offset to next interlace block in the y direction */
-   static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
-
    png_debug(1, "in png_read_finish_row");
    png_ptr->row_number++;
    if (png_ptr->row_number < png_ptr->num_rows)
@@ -4418,20 +4460,6 @@ png_read_finish_row(png_structrp png_ptr)
 void /* PRIVATE */
 png_read_start_row(png_structrp png_ptr)
 {
-   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
-
-   /* Start of interlace block */
-   static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
-
-   /* Offset to next interlace block */
-   static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
-
-   /* Start of interlace block in the y direction */
-   static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
-
-   /* Offset to next interlace block in the y direction */
-   static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
-
    unsigned int max_pixel_depth;
    size_t row_bytes;
 
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngset.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngset.c
index f53ab6fa1d1..1bfd292bd46 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngset.c
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngset.c
@@ -29,7 +29,7 @@
  * However, the following notice accompanied the original version of this
  * file and, per its terms, should not be removed:
  *
- * Copyright (c) 2018-2024 Cosmin Truta
+ * Copyright (c) 2018-2025 Cosmin Truta
  * Copyright (c) 1998-2018 Glenn Randers-Pehrson
  * Copyright (c) 1996-1997 Andreas Dilger
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -70,27 +70,21 @@ png_set_cHRM_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
     png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y,
     png_fixed_point blue_x, png_fixed_point blue_y)
 {
-   png_xy xy;
-
    png_debug1(1, "in %s storage function", "cHRM fixed");
 
    if (png_ptr == NULL || info_ptr == NULL)
       return;
 
-   xy.redx = red_x;
-   xy.redy = red_y;
-   xy.greenx = green_x;
-   xy.greeny = green_y;
-   xy.bluex = blue_x;
-   xy.bluey = blue_y;
-   xy.whitex = white_x;
-   xy.whitey = white_y;
-
-   if (png_colorspace_set_chromaticities(png_ptr, &info_ptr->colorspace, &xy,
-       2/* override with app values*/) != 0)
-      info_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM;
+   info_ptr->cHRM.redx = red_x;
+   info_ptr->cHRM.redy = red_y;
+   info_ptr->cHRM.greenx = green_x;
+   info_ptr->cHRM.greeny = green_y;
+   info_ptr->cHRM.bluex = blue_x;
+   info_ptr->cHRM.bluey = blue_y;
+   info_ptr->cHRM.whitex = white_x;
+   info_ptr->cHRM.whitey = white_y;
 
-   png_colorspace_sync_info(png_ptr, info_ptr);
+   info_ptr->valid |= PNG_INFO_cHRM;
 }
 
 void PNGFAPI
@@ -102,6 +96,7 @@ png_set_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
     png_fixed_point int_blue_Z)
 {
    png_XYZ XYZ;
+   png_xy xy;
 
    png_debug1(1, "in %s storage function", "cHRM XYZ fixed");
 
@@ -118,11 +113,14 @@ png_set_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
    XYZ.blue_Y = int_blue_Y;
    XYZ.blue_Z = int_blue_Z;
 
-   if (png_colorspace_set_endpoints(png_ptr, &info_ptr->colorspace,
-       &XYZ, 2) != 0)
-      info_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM;
+   if (png_xy_from_XYZ(&xy, &XYZ) == 0)
+   {
+      info_ptr->cHRM = xy;
+      info_ptr->valid |= PNG_INFO_cHRM;
+   }
 
-   png_colorspace_sync_info(png_ptr, info_ptr);
+   else
+      png_app_error(png_ptr, "invalid cHRM XYZ");
 }
 
 #  ifdef PNG_FLOATING_POINT_SUPPORTED
@@ -162,6 +160,192 @@ png_set_cHRM_XYZ(png_const_structrp png_ptr, png_inforp info_ptr, double red_X,
 
 #endif /* cHRM */
 
+#ifdef PNG_cICP_SUPPORTED
+void PNGAPI
+png_set_cICP(png_const_structrp png_ptr, png_inforp info_ptr,
+             png_byte colour_primaries, png_byte transfer_function,
+             png_byte matrix_coefficients, png_byte video_full_range_flag)
+{
+   png_debug1(1, "in %s storage function", "cICP");
+
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+   info_ptr->cicp_colour_primaries = colour_primaries;
+   info_ptr->cicp_transfer_function = transfer_function;
+   info_ptr->cicp_matrix_coefficients = matrix_coefficients;
+   info_ptr->cicp_video_full_range_flag = video_full_range_flag;
+
+   if (info_ptr->cicp_matrix_coefficients != 0)
+   {
+      png_warning(png_ptr, "Invalid cICP matrix coefficients");
+      return;
+   }
+
+   info_ptr->valid |= PNG_INFO_cICP;
+}
+#endif /* cICP */
+
+#ifdef PNG_cLLI_SUPPORTED
+void PNGFAPI
+png_set_cLLI_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
+    /* The values below are in cd/m2 (nits) and are scaled by 10,000; not
+     * 100,000 as in the case of png_fixed_point.
+     */
+    png_uint_32 maxCLL, png_uint_32 maxFALL)
+{
+   png_debug1(1, "in %s storage function", "cLLI");
+
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+   /* Check the light level range: */
+   if (maxCLL > 0x7FFFFFFFU || maxFALL > 0x7FFFFFFFU)
+   {
+      /* The limit is 200kcd/m2; somewhat bright but not inconceivable because
+       * human vision is said to run up to 100Mcd/m2.  The sun is about 2Gcd/m2.
+       *
+       * The reference sRGB monitor is 80cd/m2 and the limit of PQ encoding is
+       * 2kcd/m2.
+       */
+      png_chunk_report(png_ptr, "cLLI light level exceeds PNG limit",
+            PNG_CHUNK_WRITE_ERROR);
+      return;
+   }
+
+   info_ptr->maxCLL = maxCLL;
+   info_ptr->maxFALL = maxFALL;
+   info_ptr->valid |= PNG_INFO_cLLI;
+}
+
+#  ifdef PNG_FLOATING_POINT_SUPPORTED
+void PNGAPI
+png_set_cLLI(png_const_structrp png_ptr, png_inforp info_ptr,
+   double maxCLL, double maxFALL)
+{
+   png_set_cLLI_fixed(png_ptr, info_ptr,
+       png_fixed_ITU(png_ptr, maxCLL, "png_set_cLLI(maxCLL)"),
+       png_fixed_ITU(png_ptr, maxFALL, "png_set_cLLI(maxFALL)"));
+}
+#  endif /* FLOATING_POINT */
+#endif /* cLLI */
+
+#ifdef PNG_mDCV_SUPPORTED
+static png_uint_16
+png_ITU_fixed_16(int *error, png_fixed_point v)
+{
+   /* Return a safe uint16_t value scaled according to the ITU H273 rules for
+    * 16-bit display chromaticities.  Functions like the corresponding
+    * png_fixed() internal function with regard to errors: it's an error on
+    * write, a chunk_benign_error on read: See the definition of
+    * png_chunk_report in pngpriv.h.
+    */
+   v /= 2; /* rounds to 0 in C: avoids insignificant arithmetic errors */
+   if (v > 65535 || v < 0)
+   {
+      *error = 1;
+      return 0;
+   }
+
+   return (png_uint_16)/*SAFE*/v;
+}
+
+void PNGAPI
+png_set_mDCV_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
+    png_fixed_point white_x, png_fixed_point white_y,
+    png_fixed_point red_x, png_fixed_point red_y,
+    png_fixed_point green_x, png_fixed_point green_y,
+    png_fixed_point blue_x, png_fixed_point blue_y,
+    png_uint_32 maxDL,
+    png_uint_32 minDL)
+{
+   png_uint_16 rx, ry, gx, gy, bx, by, wx, wy;
+   int error;
+
+   png_debug1(1, "in %s storage function", "mDCV");
+
+   if (png_ptr == NULL || info_ptr == NULL)
+      return;
+
+   /* Check the input values to ensure they are in the expected range: */
+   error = 0;
+   rx = png_ITU_fixed_16(&error, red_x);
+   ry = png_ITU_fixed_16(&error, red_y);
+   gx = png_ITU_fixed_16(&error, green_x);
+   gy = png_ITU_fixed_16(&error, green_y);
+   bx = png_ITU_fixed_16(&error, blue_x);
+   by = png_ITU_fixed_16(&error, blue_y);
+   wx = png_ITU_fixed_16(&error, white_x);
+   wy = png_ITU_fixed_16(&error, white_y);
+
+   if (error)
+   {
+      png_chunk_report(png_ptr,
+         "mDCV chromaticities outside representable range",
+         PNG_CHUNK_WRITE_ERROR);
+      return;
+   }
+
+   /* Check the light level range: */
+   if (maxDL > 0x7FFFFFFFU || minDL > 0x7FFFFFFFU)
+   {
+      /* The limit is 200kcd/m2; somewhat bright but not inconceivable because
+       * human vision is said to run up to 100Mcd/m2.  The sun is about 2Gcd/m2.
+       *
+       * The reference sRGB monitor is 80cd/m2 and the limit of PQ encoding is
+       * 2kcd/m2.
+       */
+      png_chunk_report(png_ptr, "mDCV display light level exceeds PNG limit",
+            PNG_CHUNK_WRITE_ERROR);
+      return;
+   }
+
+   /* All values are safe, the settings are accepted.
+    *
+    * IMPLEMENTATION NOTE: in practice the values can be checked and assigned
+    * but the result is confusing if a writing app calls png_set_mDCV more than
+    * once, the second time with an invalid value.  This approach is more
+    * obviously correct at the cost of typing and a very slight machine
+    * overhead.
+    */
+   info_ptr->mastering_red_x = rx;
+   info_ptr->mastering_red_y = ry;
+   info_ptr->mastering_green_x = gx;
+   info_ptr->mastering_green_y = gy;
+   info_ptr->mastering_blue_x = bx;
+   info_ptr->mastering_blue_y = by;
+   info_ptr->mastering_white_x = wx;
+   info_ptr->mastering_white_y = wy;
+   info_ptr->mastering_maxDL = maxDL;
+   info_ptr->mastering_minDL = minDL;
+   info_ptr->valid |= PNG_INFO_mDCV;
+}
+
+#  ifdef PNG_FLOATING_POINT_SUPPORTED
+void PNGAPI
+png_set_mDCV(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,
+    double maxDL, double minDL)
+{
+   png_set_mDCV_fixed(png_ptr, info_ptr,
+      /* The ITU approach is to scale by 50,000, not 100,000 so just divide
+       * the input values by 2 and use png_fixed:
+       */
+      png_fixed(png_ptr, white_x / 2, "png_set_mDCV(white(x))"),
+      png_fixed(png_ptr, white_y / 2, "png_set_mDCV(white(y))"),
+      png_fixed(png_ptr, red_x / 2, "png_set_mDCV(red(x))"),
+      png_fixed(png_ptr, red_y / 2, "png_set_mDCV(red(y))"),
+      png_fixed(png_ptr, green_x / 2, "png_set_mDCV(green(x))"),
+      png_fixed(png_ptr, green_y / 2, "png_set_mDCV(green(y))"),
+      png_fixed(png_ptr, blue_x / 2, "png_set_mDCV(blue(x))"),
+      png_fixed(png_ptr, blue_y / 2, "png_set_mDCV(blue(y))"),
+      png_fixed_ITU(png_ptr, maxDL, "png_set_mDCV(maxDL)"),
+      png_fixed_ITU(png_ptr, minDL, "png_set_mDCV(minDL)"));
+}
+#  endif /* FLOATING_POINT */
+#endif /* mDCV */
+
 #ifdef PNG_eXIf_SUPPORTED
 void PNGAPI
 png_set_eXIf(png_const_structrp png_ptr, png_inforp info_ptr,
@@ -213,8 +397,8 @@ png_set_gAMA_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
    if (png_ptr == NULL || info_ptr == NULL)
       return;
 
-   png_colorspace_set_gamma(png_ptr, &info_ptr->colorspace, file_gamma);
-   png_colorspace_sync_info(png_ptr, info_ptr);
+   info_ptr->gamma = file_gamma;
+   info_ptr->valid |= PNG_INFO_gAMA;
 }
 
 #  ifdef PNG_FLOATING_POINT_SUPPORTED
@@ -673,8 +857,8 @@ png_set_sRGB(png_const_structrp png_ptr, png_inforp info_ptr, int srgb_intent)
    if (png_ptr == NULL || info_ptr == NULL)
       return;
 
-   (void)png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace, srgb_intent);
-   png_colorspace_sync_info(png_ptr, info_ptr);
+   info_ptr->rendering_intent = srgb_intent;
+   info_ptr->valid |= PNG_INFO_sRGB;
 }
 
 void PNGAPI
@@ -686,15 +870,20 @@ png_set_sRGB_gAMA_and_cHRM(png_const_structrp png_ptr, png_inforp info_ptr,
    if (png_ptr == NULL || info_ptr == NULL)
       return;
 
-   if (png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace,
-       srgb_intent) != 0)
-   {
-      /* This causes the gAMA and cHRM to be written too */
-      info_ptr->colorspace.flags |=
-         PNG_COLORSPACE_FROM_gAMA|PNG_COLORSPACE_FROM_cHRM;
-   }
+   png_set_sRGB(png_ptr, info_ptr, srgb_intent);
+
+#  ifdef PNG_gAMA_SUPPORTED
+      png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_sRGB_INVERSE);
+#  endif /* gAMA */
 
-   png_colorspace_sync_info(png_ptr, info_ptr);
+#  ifdef PNG_cHRM_SUPPORTED
+      png_set_cHRM_fixed(png_ptr, info_ptr,
+         /* color      x       y */
+         /* white */ 31270, 32900,
+         /* red   */ 64000, 33000,
+         /* green */ 30000, 60000,
+         /* blue  */ 15000,  6000);
+#  endif /* cHRM */
 }
 #endif /* sRGB */
 
@@ -717,27 +906,6 @@ png_set_iCCP(png_const_structrp png_ptr, png_inforp info_ptr,
    if (compression_type != PNG_COMPRESSION_TYPE_BASE)
       png_app_error(png_ptr, "Invalid iCCP compression method");
 
-   /* Set the colorspace first because this validates the profile; do not
-    * override previously set app cHRM or gAMA here (because likely as not the
-    * application knows better than libpng what the correct values are.)  Pass
-    * the info_ptr color_type field to png_colorspace_set_ICC because in the
-    * write case it has not yet been stored in png_ptr.
-    */
-   {
-      int result = png_colorspace_set_ICC(png_ptr, &info_ptr->colorspace, name,
-          proflen, profile, info_ptr->color_type);
-
-      png_colorspace_sync_info(png_ptr, info_ptr);
-
-      /* Don't do any of the copying if the profile was bad, or inconsistent. */
-      if (result == 0)
-         return;
-
-      /* But do write the gAMA and cHRM chunks from the profile. */
-      info_ptr->colorspace.flags |=
-         PNG_COLORSPACE_FROM_gAMA|PNG_COLORSPACE_FROM_cHRM;
-   }
-
    length = strlen(name)+1;
    new_iccp_name = png_voidcast(png_charp, png_malloc_warn(png_ptr, length));
 
@@ -1423,11 +1591,14 @@ png_set_keep_unknown_chunks(png_structrp png_ptr, int keep,
       static const png_byte chunks_to_ignore[] = {
          98,  75,  71,  68, '\0',  /* bKGD */
          99,  72,  82,  77, '\0',  /* cHRM */
+         99,  73,  67,  80, '\0',  /* cICP */
+         99,  76,  76,  73, '\0',  /* cLLI */
         101,  88,  73, 102, '\0',  /* eXIf */
         103,  65,  77,  65, '\0',  /* gAMA */
         104,  73,  83,  84, '\0',  /* hIST */
         105,  67,  67,  80, '\0',  /* iCCP */
         105,  84,  88, 116, '\0',  /* iTXt */
+        109,  68,  67,  86, '\0',  /* mDCV */
         111,  70,  70, 115, '\0',  /* oFFs */
         112,  67,  65,  76, '\0',  /* pCAL */
         112,  72,  89, 115, '\0',  /* pHYs */
@@ -1689,8 +1860,24 @@ png_set_chunk_malloc_max(png_structrp png_ptr,
 {
    png_debug(1, "in png_set_chunk_malloc_max");
 
+   /* pngstruct::user_chunk_malloc_max is initialized to a non-zero value in
+    * png.c.  This API supports '0' for unlimited, make sure the correct
+    * (unlimited) value is set here to avoid a need to check for 0 everywhere
+    * the parameter is used.
+    */
    if (png_ptr != NULL)
-      png_ptr->user_chunk_malloc_max = user_chunk_malloc_max;
+   {
+      if (user_chunk_malloc_max == 0U) /* unlimited */
+      {
+#        ifdef PNG_MAX_MALLOC_64K
+            png_ptr->user_chunk_malloc_max = 65536U;
+#        else
+            png_ptr->user_chunk_malloc_max = PNG_SIZE_MAX;
+#        endif
+      }
+      else
+         png_ptr->user_chunk_malloc_max = user_chunk_malloc_max;
+   }
 }
 #endif /* ?SET_USER_LIMITS */
 
diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngstruct.h b/src/java.desktop/share/native/libsplashscreen/libpng/pngstruct.h
index f153bdec602..d6c446564d1 100644
--- a/src/java.desktop/share/native/libsplashscreen/libpng/pngstruct.h
+++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngstruct.h
@@ -98,13 +98,7 @@ typedef struct png_compression_buffer
 
 /* Colorspace support; structures used in png_struct, png_info and in internal
  * functions to hold and communicate information about the color space.
- *
- * PNG_COLORSPACE_SUPPORTED is only required if the application will perform
- * colorspace corrections, otherwise all the colorspace information can be
- * skipped and the size of libpng can be reduced (significantly) by compiling
- * out the colorspace support.
  */
-#ifdef PNG_COLORSPACE_SUPPORTED
 /* The chromaticities of the red, green and blue colorants and the chromaticity
  * of the corresponding white point (i.e. of rgb(1.0,1.0,1.0)).
  */
@@ -125,48 +119,36 @@ typedef struct png_XYZ
    png_fixed_point green_X, green_Y, green_Z;
    png_fixed_point blue_X, blue_Y, blue_Z;
 } png_XYZ;
-#endif /* COLORSPACE */
 
-#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED)
-/* A colorspace is all the above plus, potentially, profile information;
- * however at present libpng does not use the profile internally so it is only
- * stored in the png_info struct (if iCCP is supported.)  The rendering intent
- * is retained here and is checked.
- *
- * The file gamma encoding information is also stored here and gamma correction
- * is done by libpng, whereas color correction must currently be done by the
- * application.
+/* Chunk index values as an enum, PNG_INDEX_unknown is also a count of the
+ * number of chunks.
  */
-typedef struct png_colorspace
+#define PNG_CHUNK(cHNK, i) PNG_INDEX_ ## cHNK = (i),
+typedef enum
 {
-#ifdef PNG_GAMMA_SUPPORTED
-   png_fixed_point gamma;        /* File gamma */
-#endif
+   PNG_KNOWN_CHUNKS
+   PNG_INDEX_unknown
+} png_index;
+#undef PNG_CHUNK
 
-#ifdef PNG_COLORSPACE_SUPPORTED
-   png_xy      end_points_xy;    /* End points as chromaticities */
-   png_XYZ     end_points_XYZ;   /* End points as CIE XYZ colorant values */
-   png_uint_16 rendering_intent; /* Rendering intent of a profile */
-#endif
-
-   /* Flags are always defined to simplify the code. */
-   png_uint_16 flags;            /* As defined below */
-} png_colorspace, * PNG_RESTRICT png_colorspacerp;
+/* Chunk flag values.  These are (png_uint_32 values) with exactly one bit set
+ * and can be combined into a flag set with bitwise 'or'.
+ *
+ * TODO: C23: convert these macros to C23 inlines (which are static).
+ */
+#define png_chunk_flag_from_index(i) (0x80000000U >> (31 - (i)))
+   /* The flag coresponding to the given png_index enum value.  This is defined
+    * for png_unknown as well (until it reaches the value 32) but this should
+    * not be relied on.
+    */
 
-typedef const png_colorspace * PNG_RESTRICT png_const_colorspacerp;
+#define png_file_has_chunk(png_ptr, i)\
+   (((png_ptr)->chunks & png_chunk_flag_from_index(i)) != 0)
+   /* The chunk has been recorded in png_struct */
 
-/* General flags for the 'flags' field */
-#define PNG_COLORSPACE_HAVE_GAMMA           0x0001
-#define PNG_COLORSPACE_HAVE_ENDPOINTS       0x0002
-#define PNG_COLORSPACE_HAVE_INTENT          0x0004
-#define PNG_COLORSPACE_FROM_gAMA            0x0008
-#define PNG_COLORSPACE_FROM_cHRM            0x0010
-#define PNG_COLORSPACE_FROM_sRGB            0x0020
-#define PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB 0x0040
-#define PNG_COLORSPACE_MATCHES_sRGB         0x0080 /* exact match on profile */
-#define PNG_COLORSPACE_INVALID              0x8000
-#define PNG_COLORSPACE_CANCEL(flags)        (0xffff ^ (flags))
-#endif /* COLORSPACE || GAMMA */
+#define png_file_add_chunk(pnt_ptr, i)\
+   ((void)((png_ptr)->chunks |= png_chunk_flag_from_index(i)))
+   /* Record the chunk in the png_struct */
 
 struct png_struct_def
 {
@@ -238,6 +220,11 @@ struct png_struct_def
    int zlib_set_strategy;
 #endif
 
+   png_uint_32 chunks; /* PNG_CF_ for every chunk read or (NYI) written */
+#  define png_has_chunk(png_ptr, cHNK)\
+      png_file_has_chunk(png_ptr, PNG_INDEX_ ## cHNK)
+      /* Convenience accessor - use this to check for a known chunk by name */
+
    png_uint_32 width;         /* width of image in pixels */
    png_uint_32 height;        /* height of image in pixels */
    png_uint_32 num_rows;      /* number of rows in current pass */
@@ -314,9 +301,16 @@ struct png_struct_def
    png_uint_32 flush_rows;    /* number of rows written since last flush */
 #endif
 
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+   png_xy          chromaticities; /* From mDVC, cICP, [iCCP], sRGB or cHRM */
+#endif
+
 #ifdef PNG_READ_GAMMA_SUPPORTED
    int gamma_shift;      /* number of "insignificant" bits in 16-bit gamma */
-   png_fixed_point screen_gamma; /* screen gamma value (display_exponent) */
+   png_fixed_point screen_gamma; /* screen gamma value (display exponent) */
+   png_fixed_point file_gamma;   /* file gamma value (encoding exponent) */
+   png_fixed_point chunk_gamma;  /* from cICP, iCCP, sRGB or gAMA */
+   png_fixed_point default_gamma;/* from png_set_alpha_mode */
 
    png_bytep gamma_table;     /* gamma table for 8-bit depth files */
    png_uint_16pp gamma_16_table; /* gamma table for 16-bit depth files */
@@ -328,7 +322,7 @@ struct png_struct_def
    png_uint_16pp gamma_16_from_1; /* converts from 1.0 to screen */
    png_uint_16pp gamma_16_to_1; /* converts from file to 1.0 */
 #endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
-#endif
+#endif /* READ_GAMMA */
 
 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED)
    png_color_8 sig_bit;       /* significant bits in each available channel */
@@ -378,8 +372,8 @@ struct png_struct_def
 /* To do: remove this from libpng-1.7 */
 #ifdef PNG_TIME_RFC1123_SUPPORTED
    char time_buffer[29]; /* String to hold RFC 1123 time text */
-#endif
-#endif
+#endif /* TIME_RFC1123 */
+#endif /* LIBPNG_VER < 10700 */
 
 /* New members added in libpng-1.0.6 */
 
@@ -389,8 +383,8 @@ struct png_struct_def
    png_voidp user_chunk_ptr;
 #ifdef PNG_READ_USER_CHUNKS_SUPPORTED
    png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */
-#endif
-#endif
+#endif /* READ_USER_CHUNKS */
+#endif /* USER_CHUNKS */
 
 #ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
    int          unknown_default; /* As PNG_HANDLE_* */
@@ -497,11 +491,5 @@ struct png_struct_def
 /* New member added in libpng-1.5.7 */
    void (*read_filter[PNG_FILTER_VALUE_LAST-1])(png_row_infop row_info,
       png_bytep row, png_const_bytep prev_row);
-
-#ifdef PNG_READ_SUPPORTED
-#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED)
-   png_colorspace   colorspace;
-#endif
-#endif
 };
 #endif /* PNGSTRUCT_H */
diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Button.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Button.cpp
index 1a7a89fdef4..714becbca20 100644
--- a/src/java.desktop/windows/native/libawt/windows/awt_Button.cpp
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Button.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -242,7 +242,7 @@ AwtButton::OwnerDrawItem(UINT /*ctrlId*/, DRAWITEMSTRUCT& drawInfo)
         RECT focusRect;
         VERIFY(::CopyRect(&focusRect, &rect));
         VERIFY(::InflateRect(&focusRect,-inf,-inf));
-        if(::DrawFocusRect(hDC, &focusRect) == 0)
+        if (!::IsRectEmpty(&focusRect) && (::DrawFocusRect(hDC, &focusRect) == 0))
             VERIFY(::GetLastError() == 0);
     }
 
diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Checkbox.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Checkbox.cpp
index d77ebb74a3e..f50ddbb5d57 100644
--- a/src/java.desktop/windows/native/libawt/windows/awt_Checkbox.cpp
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Checkbox.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -290,13 +290,13 @@ AwtCheckbox::OwnerDrawItem(UINT /*ctrlId*/, DRAWITEMSTRUCT& drawInfo)
     if ((drawInfo.itemState & ODS_FOCUS) &&
         ((drawInfo.itemAction & ODA_FOCUS)||
          (drawInfo.itemAction &ODA_DRAWENTIRE))) {
-        if(::DrawFocusRect(hDC, &focusRect) == 0)
+        if (!::IsRectEmpty(&focusRect) && (::DrawFocusRect(hDC, &focusRect) == 0))
             VERIFY(::GetLastError() == 0);
     }
     /*  erase focus rect */
     else if (!(drawInfo.itemState & ODS_FOCUS) &&
              (drawInfo.itemAction & ODA_FOCUS)) {
-        if(::DrawFocusRect(hDC, &focusRect) == 0)
+        if (!::IsRectEmpty(&focusRect) && (::DrawFocusRect(hDC, &focusRect) == 0))
             VERIFY(::GetLastError() == 0);
     }
 
diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp
index cefccdec758..47b9b9adb35 100644
--- a/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -4499,7 +4499,7 @@ void AwtComponent::DrawListItem(JNIEnv *env, DRAWITEMSTRUCT &drawInfo)
     if ((drawInfo.itemState & ODS_FOCUS)  &&
         (drawInfo.itemAction & (ODA_FOCUS | ODA_DRAWENTIRE))) {
       if (!unfocusableChoice){
-          if(::DrawFocusRect(hDC, &rect) == 0)
+          if (!::IsRectEmpty(&rect) && (::DrawFocusRect(hDC, &rect) == 0))
               VERIFY(::GetLastError() == 0);
       }
     }
diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java b/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java
index 4f9d3cf56f0..d114d314bf3 100644
--- a/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -41,12 +41,15 @@
 import java.net.http.HttpClient;
 import java.net.http.HttpHeaders;
 import java.net.http.HttpRequest;
+import java.util.function.BiPredicate;
+
 import jdk.internal.net.http.common.HttpHeadersBuilder;
 import jdk.internal.net.http.common.Utils;
 import jdk.internal.net.http.websocket.OpeningHandshake;
 import jdk.internal.net.http.websocket.WebSocketRequest;
 
 import static jdk.internal.net.http.common.Utils.ALLOWED_HEADERS;
+import static jdk.internal.net.http.common.Utils.copyProxy;
 
 public class HttpRequestImpl extends HttpRequest implements WebSocketRequest {
 
@@ -125,15 +128,7 @@ public HttpRequestImpl(HttpRequest request, ProxySelector ps) {
             this.systemHeadersBuilder.setHeader("User-Agent", USER_AGENT);
         }
         this.uri = requestURI;
-        if (isWebSocket) {
-            // WebSocket determines and sets the proxy itself
-            this.proxy = ((HttpRequestImpl) request).proxy;
-        } else {
-            if (ps != null)
-                this.proxy = retrieveProxy(ps, uri);
-            else
-                this.proxy = null;
-        }
+        this.proxy = retrieveProxy(request, ps, uri);
         this.expectContinue = request.expectContinue();
         this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https");
         this.requestPublisher = request.bodyPublisher().orElse(null);
@@ -152,13 +147,18 @@ private static void checkTimeout(Duration duration) {
     /** Returns a new instance suitable for redirection. */
     public static HttpRequestImpl newInstanceForRedirection(URI uri,
                                                             String method,
-                                                            HttpRequestImpl other) {
-        return new HttpRequestImpl(uri, method, other);
+                                                            HttpRequestImpl other,
+                                                            boolean mayHaveBody) {
+        if (uri.getScheme().equalsIgnoreCase(other.uri.getScheme()) &&
+                uri.getRawAuthority().equals(other.uri.getRawAuthority())) {
+            return new HttpRequestImpl(uri, method, other, mayHaveBody, Optional.empty());
+        }
+        return new HttpRequestImpl(uri, method, other, mayHaveBody, Optional.of(Utils.ALLOWED_REDIRECT_HEADERS));
     }
 
     /** Returns a new instance suitable for authentication. */
     public static HttpRequestImpl newInstanceForAuthentication(HttpRequestImpl other) {
-        HttpRequestImpl request = new HttpRequestImpl(other.uri(), other.method(), other);
+        HttpRequestImpl request = new HttpRequestImpl(other.uri(), other.method(), other, true);
         if (request.isWebSocket()) {
             Utils.setWebSocketUpgradeHeaders(request);
         }
@@ -171,10 +171,21 @@ public static HttpRequestImpl newInstanceForAuthentication(HttpRequestImpl other
      */
     private HttpRequestImpl(URI uri,
                             String method,
-                            HttpRequestImpl other) {
+                            HttpRequestImpl other,
+                            boolean mayHaveBody) {
+        this(uri, method, other, mayHaveBody, Optional.empty());
+    }
+
+    private HttpRequestImpl(URI uri,
+                            String method,
+                            HttpRequestImpl other,
+                            boolean mayHaveBody,
+                            Optional> redirectHeadersFilter) {
         assert method == null || Utils.isValidName(method);
-        this.method = method == null? "GET" : method;
-        this.userHeaders = other.userHeaders;
+        this.method = method == null ? "GET" : method;
+        HttpHeaders userHeaders = redirectHeadersFilter.isPresent() ?
+                HttpHeaders.of(other.userHeaders.map(), redirectHeadersFilter.get()) : other.userHeaders;
+        this.userHeaders = userHeaders;
         this.isWebSocket = other.isWebSocket;
         this.systemHeadersBuilder = new HttpHeadersBuilder();
         if (!userHeaders.firstValue("User-Agent").isPresent()) {
@@ -184,13 +195,21 @@ private HttpRequestImpl(URI uri,
         this.proxy = other.proxy;
         this.expectContinue = other.expectContinue;
         this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https");
-        this.requestPublisher = other.requestPublisher;  // may be null
+        this.requestPublisher = mayHaveBody ? publisher(other) : null; // may be null
         this.acc = other.acc;
         this.timeout = other.timeout;
         this.version = other.version();
         this.authority = null;
     }
 
+    private BodyPublisher publisher(HttpRequestImpl other) {
+        BodyPublisher res = other.requestPublisher;
+        if (!Objects.equals(method, other.method)) {
+            res = null;
+        }
+        return res;
+    }
+
     /* used for creating CONNECT requests  */
     HttpRequestImpl(String method, InetSocketAddress authority, HttpHeaders headers) {
         // TODO: isWebSocket flag is not specified, but the assumption is that
@@ -281,16 +300,30 @@ void setH2Upgrade(Exchange exchange) {
     @Override
     public boolean expectContinue() { return expectContinue; }
 
-    /** Retrieves the proxy, from the given ProxySelector, if there is one. */
-    private static Proxy retrieveProxy(ProxySelector ps, URI uri) {
-        Proxy proxy = null;
-        List pl = ps.select(uri);
-        if (!pl.isEmpty()) {
-            Proxy p = pl.get(0);
-            if (p.type() == Proxy.Type.HTTP)
-                proxy = p;
+    /** Retrieves a copy of the proxy either from the given {@link HttpRequest} or {@link ProxySelector}, if there is one. */
+    private static Proxy retrieveProxy(HttpRequest request, ProxySelector ps, URI uri) {
+
+        // WebSocket determines and sets the proxy itself
+        if (request instanceof HttpRequestImpl) {
+            HttpRequestImpl requestImpl = (HttpRequestImpl)request;
+            if (requestImpl.isWebSocket) {
+                return requestImpl.proxy;
+            }
+        }
+
+        // Try to find a matching one from the `ProxySelector`
+        if (ps != null) {
+            List pl = ps.select(uri);
+            if (!pl.isEmpty()) {
+                Proxy p = pl.get(0);
+                if (p.type() == Proxy.Type.HTTP) {
+                    return copyProxy(p);
+                }
+            }
         }
-        return proxy;
+
+        return null;
+
     }
 
     InetSocketAddress proxy() {
@@ -306,7 +339,7 @@ InetSocketAddress proxy() {
     @Override
     public void setProxy(Proxy proxy) {
         assert isWebSocket;
-        this.proxy = proxy;
+        this.proxy = copyProxy(proxy);
     }
 
     @Override
diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/RedirectFilter.java b/src/java.net.http/share/classes/jdk/internal/net/http/RedirectFilter.java
index 3161132f313..79e2a2fbfc3 100644
--- a/src/java.net.http/share/classes/jdk/internal/net/http/RedirectFilter.java
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/RedirectFilter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -89,6 +89,31 @@ private static String redirectedMethod(int statusCode, String orig) {
         }
     }
 
+    private static boolean isRedirecting(int statusCode) {
+        // < 300: not a redirect codes
+        if (statusCode < 300) return false;
+        // 309-399 Unassigned => don't follow
+        // > 399: not a redirect code
+        if (statusCode > 308) return false;
+        switch (statusCode) {
+            // 300: MultipleChoice => don't follow
+            case 300:
+                return false;
+            // 304: Not Modified => don't follow
+            case 304:
+                return false;
+            // 305: Proxy Redirect => don't follow.
+            case 305:
+                return false;
+            // 306: Unused => don't follow
+            case 306:
+                return false;
+            // 301, 302, 303, 307, 308: OK to follow.
+            default:
+                return true;
+        }
+    }
+
     /**
      * Checks to see if a new request is needed and returns it.
      * Null means response is ok to return to user.
@@ -102,13 +127,13 @@ private HttpRequestImpl handleResponse(Response r) {
         if (rcode == HTTP_NOT_MODIFIED)
             return null;
 
-        if (rcode >= 300 && rcode <= 399) {
+        if (isRedirecting(rcode)) {
             URI redir = getRedirectedURI(r.headers());
             String newMethod = redirectedMethod(rcode, method);
             Log.logTrace("response code: {0}, redirected URI: {1}", rcode, redir);
             if (canRedirect(redir) && ++exchange.numberOfRedirects < max_redirects) {
                 Log.logTrace("redirect to: {0} with method: {1}", redir, newMethod);
-                return HttpRequestImpl.newInstanceForRedirection(redir, newMethod, request);
+                return HttpRequestImpl.newInstanceForRedirection(redir, newMethod, request, rcode != 303);
             } else {
                 Log.logTrace("not redirecting");
                 return null;
diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java b/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java
index 984e6214b3c..15a9cf4035f 100644
--- a/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,6 +42,7 @@
 import java.lang.System.Logger.Level;
 import java.net.ConnectException;
 import java.net.InetSocketAddress;
+import java.net.Proxy;
 import java.net.URI;
 import java.net.URLPermission;
 import java.net.http.HttpClient;
@@ -151,6 +152,18 @@ private static Set getDisallowedHeaders() {
     public static final BiPredicate
             ALLOWED_HEADERS = (header, unused) -> !DISALLOWED_HEADERS_SET.contains(header);
 
+    private static final Set DISALLOWED_REDIRECT_HEADERS_SET = getDisallowedRedirectHeaders();
+
+    private static Set getDisallowedRedirectHeaders() {
+        Set headers = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
+        headers.addAll(Set.of("Authorization", "Cookie", "Origin", "Referer", "Host"));
+
+        return Collections.unmodifiableSet(headers);
+    }
+
+    public static final BiPredicate
+            ALLOWED_REDIRECT_HEADERS = (header, unused) -> !DISALLOWED_REDIRECT_HEADERS_SET.contains(header);
+
     public static final BiPredicate VALIDATE_USER_HEADER =
             (name, value) -> {
                 assert name != null : "null header name";
@@ -267,6 +280,17 @@ public static boolean proxyHasDisabledSchemes(boolean tunnel) {
                       : ! PROXY_AUTH_DISABLED_SCHEMES.isEmpty();
     }
 
+    /**
+     * Creates a new {@link Proxy} instance for the given proxy iff it is
+     * neither null, {@link Proxy#NO_PROXY Proxy.NO_PROXY}, nor already a
+     * {@code Proxy} instance.
+     */
+    public static Proxy copyProxy(Proxy proxy) {
+        return proxy == null || proxy.getClass() == Proxy.class
+                ? proxy
+                : new Proxy(proxy.type(), proxy.address());
+    }
+
     // WebSocket connection Upgrade headers
     private static final String HEADER_CONNECTION = "Connection";
     private static final String HEADER_UPGRADE    = "Upgrade";
diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/websocket/OpeningHandshake.java b/src/java.net.http/share/classes/jdk/internal/net/http/websocket/OpeningHandshake.java
index c0c3ab6e871..dad094688f1 100644
--- a/src/java.net.http/share/classes/jdk/internal/net/http/websocket/OpeningHandshake.java
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/websocket/OpeningHandshake.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -66,6 +66,7 @@
 import java.util.stream.Stream;
 
 import static java.lang.String.format;
+import static jdk.internal.net.http.common.Utils.copyProxy;
 import static jdk.internal.net.http.common.Utils.isValidName;
 import static jdk.internal.net.http.common.Utils.permissionForProxy;
 import static jdk.internal.net.http.common.Utils.stringOf;
@@ -373,7 +374,7 @@ private static Proxy proxyFor(Optional selector, URI uri) {
         if (proxy.type() != Proxy.Type.HTTP) {
             return null;
         }
-        return proxy;
+        return copyProxy(proxy);
     }
 
     /**
diff --git a/src/jdk.accessibility/windows/classes/com/sun/java/accessibility/internal/AccessBridge.java b/src/jdk.accessibility/windows/classes/com/sun/java/accessibility/internal/AccessBridge.java
index c75795f180f..e0175ea446c 100644
--- a/src/jdk.accessibility/windows/classes/com/sun/java/accessibility/internal/AccessBridge.java
+++ b/src/jdk.accessibility/windows/classes/com/sun/java/accessibility/internal/AccessBridge.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -3838,6 +3838,8 @@ private int controlCode(KeyStroke keyStroke) {
             return 0;
         int code = keyStroke.getKeyCode();
         switch (code) {
+            case KeyEvent.VK_TAB:
+            case KeyEvent.VK_SPACE:
             case KeyEvent.VK_BACK_SPACE:
             case KeyEvent.VK_DELETE:
             case KeyEvent.VK_DOWN:
@@ -3880,15 +3882,10 @@ private char getKeyChar(KeyStroke keyStroke) {
             debugString("[INFO]:   Shortcut is control character: " + Integer.toHexString(keyCode));
             return (char)keyCode;
         }
-        String keyText = KeyEvent.getKeyText(keyStroke.getKeyCode());
-        debugString("[INFO]:   Shortcut is: " + keyText);
-        if (keyText != null || keyText.length() > 0) {
-            CharSequence seq = keyText.subSequence(0, 1);
-            if (seq != null || seq.length() > 0) {
-                return seq.charAt(0);
-            }
-        }
-        return 0;
+
+        keyCode = keyStroke.getKeyCode();
+        debugString("[INFO]:   Shortcut is: " + Integer.toHexString(keyCode));
+        return (char)keyCode;
     }
 
     /*
diff --git a/src/jdk.accessibility/windows/native/include/bridge/AccessBridgePackages.h b/src/jdk.accessibility/windows/native/include/bridge/AccessBridgePackages.h
index 27c31be09a8..232cab4b21b 100644
--- a/src/jdk.accessibility/windows/native/include/bridge/AccessBridgePackages.h
+++ b/src/jdk.accessibility/windows/native/include/bridge/AccessBridgePackages.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1108,6 +1108,8 @@ typedef long ABHWND64;
 #define ACCESSIBLE_CONTROLCODE_KEYSTROKE        512  // Control code key pressed, character contains control code.
 
 // The supported control code keys are:
+#define ACCESSIBLE_VK_TAB           9
+#define ACCESSIBLE_VK_SPACE         32
 #define ACCESSIBLE_VK_BACK_SPACE    8
 #define ACCESSIBLE_VK_DELETE        127
 #define ACCESSIBLE_VK_DOWN          40
diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java
index 83b633358ac..6fdd46f6429 100644
--- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java
+++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -126,6 +126,9 @@ private static void debug(Object o) {
     // whether to print debug info during startup
     private boolean showInfo = false;
 
+    // whether to allow legacy mechanisms
+    private boolean allowLegacy = false;
+
     // template manager, initialized from parsed attributes
     private TemplateManager templateManager;
 
@@ -256,6 +259,10 @@ boolean getShowInfo() {
         return (SunPKCS11.debug != null) || showInfo;
     }
 
+    boolean getAllowLegacy() {
+        return allowLegacy;
+    }
+
     TemplateManager getTemplateManager() {
         if (templateManager == null) {
             templateManager = new TemplateManager();
@@ -449,6 +456,8 @@ private void parse() throws IOException {
                 destroyTokenAfterLogout = parseBooleanEntry(word);
             } else if (word.equals("showInfo")) {
                 showInfo = parseBooleanEntry(word);
+            } else if (word.equals("allowLegacy")) {
+                allowLegacy = parseBooleanEntry(word);
             } else if (word.equals("keyStoreCompatibilityMode")) {
                 keyStoreCompatibilityMode = parseBooleanEntry(word);
             } else if (word.equals("explicitCancel")) {
diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11ECKeyFactory.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11ECKeyFactory.java
index f19014cb0f0..0f3a8af3cb8 100644
--- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11ECKeyFactory.java
+++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11ECKeyFactory.java
@@ -294,7 +294,13 @@  T implGetPublicKeySpec(P11Key key, Class keySpec,
             try {
                 token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);
                 ECParameterSpec params = decodeParameters(attributes[1].getByteArray());
-                ECPoint point = decodePoint(attributes[0].getByteArray(), params.getCurve());
+                ECPoint point;
+
+                if (!token.config.getUseEcX963Encoding()) {
+                    point = decodePoint(new DerValue(attributes[0].getByteArray()).getOctetString(), params.getCurve());
+                } else {
+                    point = decodePoint(attributes[0].getByteArray(), params.getCurve());
+                }
                 return keySpec.cast(new ECPublicKeySpec(point, params));
             } catch (IOException e) {
                 throw new InvalidKeySpecException("Could not parse key", e);
diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java
index ffbd671246a..fdbd8cdac34 100644
--- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java
+++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java
@@ -956,25 +956,6 @@ public Object run() {
         }
     }
 
-    private static boolean isLegacy(CK_MECHANISM_INFO mechInfo)
-            throws PKCS11Exception {
-        // assume full support if no mech info available
-        // For vendor-specific mechanisms, often no mech info is provided
-        boolean partialSupport = false;
-
-        if (mechInfo != null) {
-            if ((mechInfo.flags & CKF_DECRYPT) != 0) {
-                // non-legacy cipher mechs should support encryption
-                partialSupport |= ((mechInfo.flags & CKF_ENCRYPT) == 0);
-            }
-            if ((mechInfo.flags & CKF_VERIFY) != 0) {
-                // non-legacy signature mechs should support signing
-                partialSupport |= ((mechInfo.flags & CKF_SIGN) == 0);
-            }
-        }
-        return partialSupport;
-    }
-
     // test if a token is present and initialize this provider for it if so.
     // does nothing if no token is found
     // called from constructor and by poller
@@ -1025,12 +1006,6 @@ private void initToken(CK_SLOT_INFO slotInfo) throws PKCS11Exception {
                 }
                 continue;
             }
-            if (isLegacy(mechInfo)) {
-                if (showInfo) {
-                    System.out.println("DISABLED due to legacy");
-                }
-                continue;
-            }
 
             // we do not know of mechs with the upper 32 bits set
             if (longMech >>> 32 != 0) {
@@ -1045,9 +1020,25 @@ private void initToken(CK_SLOT_INFO slotInfo) throws PKCS11Exception {
             if (ds == null) {
                 continue;
             }
+            boolean allowLegacy = config.getAllowLegacy();
             for (Descriptor d : ds) {
                 Integer oldMech = supportedAlgs.get(d);
                 if (oldMech == null) {
+
+                    // assume full support if no mech info available
+                    if (!allowLegacy && mechInfo != null) {
+                        if ((d.type == CIP &&
+                                (mechInfo.flags & CKF_ENCRYPT) == 0) ||
+                                (d.type == SIG &&
+                                (mechInfo.flags & CKF_SIGN) == 0)) {
+                            if (showInfo) {
+                                System.out.println("DISABLED " +  d.type +
+                                        " " + d.algorithm +
+                                        " due to partial support");
+                            }
+                            continue;
+                        }
+                    }
                     supportedAlgs.put(d, integerMech);
                     continue;
                 }
diff --git a/src/jdk.crypto.cryptoki/share/legal/pkcs11cryptotoken.md b/src/jdk.crypto.cryptoki/share/legal/pkcs11cryptotoken.md
index 08d1e3c713d..7877f54fe6e 100644
--- a/src/jdk.crypto.cryptoki/share/legal/pkcs11cryptotoken.md
+++ b/src/jdk.crypto.cryptoki/share/legal/pkcs11cryptotoken.md
@@ -1,16 +1,16 @@
-## OASIS PKCS #11 Cryptographic Token Interface v3.0
+## OASIS PKCS #11 Cryptographic Token Interface v3.1
 
 ### OASIS PKCS #11 Cryptographic Token Interface License
 
 
-Copyright © OASIS Open 2020. All Rights Reserved.
+Copyright © OASIS Open 2023. All Rights Reserved.
 
-    All capitalized terms in the following text have the meanings
+All capitalized terms in the following text have the meanings
 assigned to them in the OASIS Intellectual Property Rights Policy (the
 "OASIS IPR Policy"). The full Policy may be found at the OASIS website:
-[http://www.oasis-open.org/policies-guidelines/ipr]
+[https://www.oasis-open.org/policies-guidelines/ipr/].
 
-    This document and translations of it may be copied and furnished to
+This document and translations of it may be copied and furnished to
 others, and derivative works that comment on or otherwise explain it or
 assist in its implementation may be prepared, copied, published, and
 distributed, in whole or in part, without restriction of any kind,
@@ -23,10 +23,10 @@ Committee (in which case the rules applicable to copyrights, as set
 forth in the OASIS IPR Policy, must be followed) or as required to
 translate it into languages other than English.
 
-    The limited permissions granted above are perpetual and will not be
+The limited permissions granted above are perpetual and will not be
 revoked by OASIS or its successors or assigns.
 
-    This document and the information contained herein is provided on an
+This document and the information contained herein is provided on an
 "AS IS" basis and OASIS DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
 INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
 INFORMATION HEREIN WILL NOT INFRINGE ANY OWNERSHIP RIGHTS OR ANY IMPLIED
@@ -35,7 +35,11 @@ AND ITS MEMBERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR
 CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THIS DOCUMENT OR ANY
 PART THEREOF.
 
-    [OASIS requests that any OASIS Party or any other party that
+As stated in the OASIS IPR Policy, the following three paragraphs in
+brackets apply to OASIS Standards Final Deliverable documents (Committee
+Specifications, OASIS Standards, or Approved Errata).
+
+[OASIS requests that any OASIS Party or any other party that
 believes it has patent claims that would necessarily be infringed by
 implementations of this OASIS Standards Final Deliverable, to notify
 OASIS TC Administrator and provide an indication of its willingness to
@@ -43,7 +47,7 @@ grant patent licenses to such patent claims in a manner consistent with
 the IPR Mode of the OASIS Technical Committee that produced this
 deliverable.]
 
-    [OASIS invites any party to contact the OASIS TC Administrator if it
+[OASIS invites any party to contact the OASIS TC Administrator if it
 is aware of a claim of ownership of any patent claims that would
 necessarily be infringed by implementations of this OASIS Standards
 Final Deliverable by a patent holder that is not willing to provide a
@@ -52,7 +56,7 @@ of the OASIS Technical Committee that produced this OASIS Standards
 Final Deliverable. OASIS may include such claims on its website, but
 disclaims any obligation to do so.]
 
-    [OASIS takes no position regarding the validity or scope of any
+[OASIS takes no position regarding the validity or scope of any
 intellectual property or other rights that might be claimed to pertain
 to the implementation or use of the technology described in this OASIS
 Standards Final Deliverable or the extent to which any license under
diff --git a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11.h b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11.h
index 5b050def520..5933da0e3b7 100644
--- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11.h
+++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11.h
@@ -1,8 +1,11 @@
-/* Copyright (c) OASIS Open 2016-2019. All Rights Reserved.
- * Distributed under the terms of the OASIS IPR Policy,
- * [http://www.oasis-open.org/policies-guidelines/ipr], AS-IS, WITHOUT ANY
- * IMPLIED OR EXPRESS WARRANTY; there is no warranty of MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE or NONINFRINGEMENT of the rights of others.
+/*
+ * PKCS #11 Specification Version 3.1
+ * OASIS Standard
+ * 23 July 2023
+ * Copyright (c) OASIS Open 2023. All Rights Reserved.
+ * Source: https://docs.oasis-open.org/pkcs11/pkcs11-spec/v3.1/os/include/pkcs11-v3.1/
+ * Latest stage of narrative specification: https://docs.oasis-open.org/pkcs11/pkcs11-spec/v3.1/pkcs11-spec-v3.1.html
+ * TC IPR Statement: https://www.oasis-open.org/committees/pkcs11/ipr.php
  */
 
 #ifndef _PKCS11_H_
@@ -47,7 +50,7 @@ extern "C" {
  *
  * typedef CK_BYTE CK_PTR CK_BYTE_PTR;
  *
- * If you're using windows, it might be defined by:
+ * If you're using Windows, it might be defined by:
  *
  * #define CK_PTR *
  *
@@ -65,7 +68,7 @@ extern "C" {
  *   CK_VOID_PTR pReserved
  * );
  *
- * If you're using Windows to declare a function in a Win32 cryptoki .dll,
+ * If you're using Windows to declare a function in a Win32 Cryptoki .dll,
  * it might be defined by:
  *
  * #define CK_DECLARE_FUNCTION(returnType, name) \
@@ -241,4 +244,3 @@ struct CK_FUNCTION_LIST {
 
 #endif /* _PKCS11_H_ */
 
-
diff --git a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11f.h b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11f.h
index 0553c1dc73c..80c43400d05 100644
--- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11f.h
+++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11f.h
@@ -1,12 +1,11 @@
-/* Copyright (c) OASIS Open 2016, 2019. All Rights Reserved./
- * /Distributed under the terms of the OASIS IPR Policy,
- * [http://www.oasis-open.org/policies-guidelines/ipr], AS-IS, WITHOUT ANY
- * IMPLIED OR EXPRESS WARRANTY; there is no warranty of MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE or NONINFRINGEMENT of the rights of others.
- */
-
-/* Latest version of the specification:
- * http://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/pkcs11-base-v2.40.html
+/*
+ * PKCS #11 Specification Version 3.1
+ * OASIS Standard
+ * 23 July 2023
+ * Copyright (c) OASIS Open 2023. All Rights Reserved.
+ * Source: https://docs.oasis-open.org/pkcs11/pkcs11-spec/v3.1/os/include/pkcs11-v3.1/
+ * Latest stage of narrative specification: https://docs.oasis-open.org/pkcs11/pkcs11-spec/v3.1/pkcs11-spec-v3.1.html
+ * TC IPR Statement: https://www.oasis-open.org/committees/pkcs11/ipr.php
  */
 
 /* This header file contains pretty much everything about all the
diff --git a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11t.h b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11t.h
index ab6ef326e8b..79d7cf7d7da 100644
--- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11t.h
+++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/pkcs11t.h
@@ -1,12 +1,11 @@
-/* Copyright (c) OASIS Open 2016, 2019. All Rights Reserved./
- * /Distributed under the terms of the OASIS IPR Policy,
- * [http://www.oasis-open.org/policies-guidelines/ipr], AS-IS, WITHOUT ANY
- * IMPLIED OR EXPRESS WARRANTY; there is no warranty of MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE or NONINFRINGEMENT of the rights of others.
- */
-
-/* Latest version of the specification:
- * http://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/pkcs11-base-v2.40.html
+/*
+ * PKCS #11 Specification Version 3.1
+ * OASIS Standard
+ * 23 July 2023
+ * Copyright (c) OASIS Open 2023. All Rights Reserved.
+ * Source: https://docs.oasis-open.org/pkcs11/pkcs11-spec/v3.1/os/include/pkcs11-v3.1/
+ * Latest stage of narrative specification: https://docs.oasis-open.org/pkcs11/pkcs11-spec/v3.1/pkcs11-spec-v3.1.html
+ * TC IPR Statement: https://www.oasis-open.org/committees/pkcs11/ipr.php
  */
 
 /* See top of pkcs11.h for information about the macros that
@@ -18,7 +17,7 @@
 #define _PKCS11T_H_ 1
 
 #define CRYPTOKI_VERSION_MAJOR          3
-#define CRYPTOKI_VERSION_MINOR          0
+#define CRYPTOKI_VERSION_MINOR          1
 #define CRYPTOKI_VERSION_AMENDMENT      0
 
 #define CK_TRUE         1
@@ -329,8 +328,11 @@ typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR;
 #define CKP_EXTENDED_PROVIDER         0x00000002UL
 #define CKP_AUTHENTICATION_TOKEN      0x00000003UL
 #define CKP_PUBLIC_CERTIFICATES_TOKEN 0x00000004UL
+#define CKP_COMPLETE_PROVIDER         0x00000005UL
+#define CKP_HKDF_TLS_TOKEN            0x00000006UL
 #define CKP_VENDOR_DEFINED            0x80000000UL
 
+
 /* CK_HW_FEATURE_TYPE is a value that identifies the hardware feature type
  * of an object with CK_OBJECT_CLASS equal to CKO_HW_FEATURE.
  */
@@ -409,9 +411,11 @@ typedef CK_ULONG          CK_KEY_TYPE;
 #define CKK_EC_EDWARDS          0x00000040UL
 #define CKK_EC_MONTGOMERY       0x00000041UL
 #define CKK_HKDF                0x00000042UL
+
 #define CKK_SHA512_224_HMAC     0x00000043UL
 #define CKK_SHA512_256_HMAC     0x00000044UL
 #define CKK_SHA512_T_HMAC       0x00000045UL
+#define CKK_HSS                 0x00000046UL
 
 #define CKK_VENDOR_DEFINED      0x80000000UL
 
@@ -481,9 +485,9 @@ typedef CK_ULONG          CK_ATTRIBUTE_TYPE;
 #define CKA_CERTIFICATE_CATEGORY        0x00000087UL
 #define CKA_JAVA_MIDP_SECURITY_DOMAIN   0x00000088UL
 #define CKA_URL                         0x00000089UL
-#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY  0x0000008AUL
-#define CKA_HASH_OF_ISSUER_PUBLIC_KEY   0x0000008BUL
-#define CKA_NAME_HASH_ALGORITHM         0x0000008CUL
+#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY  0x0000008aUL
+#define CKA_HASH_OF_ISSUER_PUBLIC_KEY   0x0000008bUL
+#define CKA_NAME_HASH_ALGORITHM         0x0000008cUL
 #define CKA_CHECK_VALUE                 0x00000090UL
 
 #define CKA_KEY_TYPE           0x00000100UL
@@ -496,9 +500,9 @@ typedef CK_ULONG          CK_ATTRIBUTE_TYPE;
 #define CKA_UNWRAP             0x00000107UL
 #define CKA_SIGN               0x00000108UL
 #define CKA_SIGN_RECOVER       0x00000109UL
-#define CKA_VERIFY             0x0000010AUL
-#define CKA_VERIFY_RECOVER     0x0000010BUL
-#define CKA_DERIVE             0x0000010CUL
+#define CKA_VERIFY             0x0000010aUL
+#define CKA_VERIFY_RECOVER     0x0000010bUL
+#define CKA_DERIVE             0x0000010cUL
 #define CKA_START_DATE         0x00000110UL
 #define CKA_END_DATE           0x00000111UL
 #define CKA_MODULUS            0x00000120UL
@@ -555,12 +559,12 @@ typedef CK_ULONG          CK_ATTRIBUTE_TYPE;
 #define CKA_OTP_TIME_REQUIREMENT      0x00000225UL
 #define CKA_OTP_COUNTER_REQUIREMENT   0x00000226UL
 #define CKA_OTP_PIN_REQUIREMENT       0x00000227UL
-#define CKA_OTP_COUNTER               0x0000022EUL
-#define CKA_OTP_TIME                  0x0000022FUL
-#define CKA_OTP_USER_IDENTIFIER       0x0000022AUL
-#define CKA_OTP_SERVICE_IDENTIFIER    0x0000022BUL
-#define CKA_OTP_SERVICE_LOGO          0x0000022CUL
-#define CKA_OTP_SERVICE_LOGO_TYPE     0x0000022DUL
+#define CKA_OTP_COUNTER               0x0000022eUL
+#define CKA_OTP_TIME                  0x0000022fUL
+#define CKA_OTP_USER_IDENTIFIER       0x0000022aUL
+#define CKA_OTP_SERVICE_IDENTIFIER    0x0000022bUL
+#define CKA_OTP_SERVICE_LOGO          0x0000022cUL
+#define CKA_OTP_SERVICE_LOGO_TYPE     0x0000022dUL
 
 #define CKA_GOSTR3410_PARAMS            0x00000250UL
 #define CKA_GOSTR3411_PARAMS            0x00000251UL
@@ -586,6 +590,7 @@ typedef CK_ULONG          CK_ATTRIBUTE_TYPE;
 #define CKA_SUPPORTED_CMS_ATTRIBUTES    0x00000503UL
 #define CKA_ALLOWED_MECHANISMS          (CKF_ARRAY_ATTRIBUTE|0x00000600UL)
 #define CKA_PROFILE_ID                  0x00000601UL
+
 #define CKA_X2RATCHET_BAG               0x00000602UL
 #define CKA_X2RATCHET_BAGSIZE           0x00000603UL
 #define CKA_X2RATCHET_BOBS1STMSG        0x00000604UL
@@ -603,6 +608,13 @@ typedef CK_ULONG          CK_ATTRIBUTE_TYPE;
 #define CKA_X2RATCHET_NS                0x00000610UL
 #define CKA_X2RATCHET_PNS               0x00000611UL
 #define CKA_X2RATCHET_RK                0x00000612UL
+/* HSS */
+#define CKA_HSS_LEVELS                  0x00000617UL
+#define CKA_HSS_LMS_TYPE                0x00000618UL
+#define CKA_HSS_LMOTS_TYPE              0x00000619UL
+#define CKA_HSS_LMS_TYPES               0x0000061aUL
+#define CKA_HSS_LMOTS_TYPES             0x0000061bUL
+#define CKA_HSS_KEYS_REMAINING          0x0000061cUL
 
 #define CKA_VENDOR_DEFINED              0x80000000UL
 
@@ -644,11 +656,11 @@ typedef CK_ULONG          CK_MECHANISM_TYPE;
 #define CKM_RIPEMD160_RSA_PKCS         0x00000008UL
 #define CKM_RSA_PKCS_OAEP              0x00000009UL
 
-#define CKM_RSA_X9_31_KEY_PAIR_GEN     0x0000000AUL
-#define CKM_RSA_X9_31                  0x0000000BUL
-#define CKM_SHA1_RSA_X9_31             0x0000000CUL
-#define CKM_RSA_PKCS_PSS               0x0000000DUL
-#define CKM_SHA1_RSA_PKCS_PSS          0x0000000EUL
+#define CKM_RSA_X9_31_KEY_PAIR_GEN     0x0000000aUL
+#define CKM_RSA_X9_31                  0x0000000bUL
+#define CKM_SHA1_RSA_X9_31             0x0000000cUL
+#define CKM_RSA_PKCS_PSS               0x0000000dUL
+#define CKM_SHA1_RSA_PKCS_PSS          0x0000000eUL
 
 #define CKM_DSA_KEY_PAIR_GEN           0x00000010UL
 #define CKM_DSA                        0x00000011UL
@@ -659,8 +671,8 @@ typedef CK_ULONG          CK_MECHANISM_TYPE;
 #define CKM_DSA_SHA512                 0x00000016UL
 #define CKM_DSA_SHA3_224               0x00000018UL
 #define CKM_DSA_SHA3_256               0x00000019UL
-#define CKM_DSA_SHA3_384               0x0000001AUL
-#define CKM_DSA_SHA3_512               0x0000001BUL
+#define CKM_DSA_SHA3_384               0x0000001aUL
+#define CKM_DSA_SHA3_512               0x0000001bUL
 
 #define CKM_DH_PKCS_KEY_PAIR_GEN       0x00000020UL
 #define CKM_DH_PKCS_DERIVE             0x00000021UL
@@ -682,12 +694,12 @@ typedef CK_ULONG          CK_MECHANISM_TYPE;
 
 #define CKM_SHA512_224                 0x00000048UL
 #define CKM_SHA512_224_HMAC            0x00000049UL
-#define CKM_SHA512_224_HMAC_GENERAL    0x0000004AUL
-#define CKM_SHA512_224_KEY_DERIVATION  0x0000004BUL
-#define CKM_SHA512_256                 0x0000004CUL
-#define CKM_SHA512_256_HMAC            0x0000004DUL
-#define CKM_SHA512_256_HMAC_GENERAL    0x0000004EUL
-#define CKM_SHA512_256_KEY_DERIVATION  0x0000004FUL
+#define CKM_SHA512_224_HMAC_GENERAL    0x0000004aUL
+#define CKM_SHA512_224_KEY_DERIVATION  0x0000004bUL
+#define CKM_SHA512_256                 0x0000004cUL
+#define CKM_SHA512_256_HMAC            0x0000004dUL
+#define CKM_SHA512_256_HMAC_GENERAL    0x0000004eUL
+#define CKM_SHA512_256_KEY_DERIVATION  0x0000004fUL
 
 #define CKM_SHA512_T                   0x00000050UL
 #define CKM_SHA512_T_HMAC              0x00000051UL
@@ -781,25 +793,25 @@ typedef CK_ULONG          CK_MECHANISM_TYPE;
 #define CKM_SECURID                    0x00000282UL
 #define CKM_HOTP_KEY_GEN               0x00000290UL
 #define CKM_HOTP                       0x00000291UL
-#define CKM_ACTI                       0x000002A0UL
-#define CKM_ACTI_KEY_GEN               0x000002A1UL
-
-#define CKM_SHA3_256                   0x000002B0UL
-#define CKM_SHA3_256_HMAC              0x000002B1UL
-#define CKM_SHA3_256_HMAC_GENERAL      0x000002B2UL
-#define CKM_SHA3_256_KEY_GEN           0x000002B3UL
-#define CKM_SHA3_224                   0x000002B5UL
-#define CKM_SHA3_224_HMAC              0x000002B6UL
-#define CKM_SHA3_224_HMAC_GENERAL      0x000002B7UL
-#define CKM_SHA3_224_KEY_GEN           0x000002B8UL
-#define CKM_SHA3_384                   0x000002C0UL
-#define CKM_SHA3_384_HMAC              0x000002C1UL
-#define CKM_SHA3_384_HMAC_GENERAL      0x000002C2UL
-#define CKM_SHA3_384_KEY_GEN           0x000002C3UL
-#define CKM_SHA3_512                   0x000002D0UL
-#define CKM_SHA3_512_HMAC              0x000002D1UL
-#define CKM_SHA3_512_HMAC_GENERAL      0x000002D2UL
-#define CKM_SHA3_512_KEY_GEN           0x000002D3UL
+#define CKM_ACTI                       0x000002a0UL
+#define CKM_ACTI_KEY_GEN               0x000002a1UL
+
+#define CKM_SHA3_256                   0x000002b0UL
+#define CKM_SHA3_256_HMAC              0x000002b1UL
+#define CKM_SHA3_256_HMAC_GENERAL      0x000002b2UL
+#define CKM_SHA3_256_KEY_GEN           0x000002b3UL
+#define CKM_SHA3_224                   0x000002b5UL
+#define CKM_SHA3_224_HMAC              0x000002b6UL
+#define CKM_SHA3_224_HMAC_GENERAL      0x000002b7UL
+#define CKM_SHA3_224_KEY_GEN           0x000002b8UL
+#define CKM_SHA3_384                   0x000002c0UL
+#define CKM_SHA3_384_HMAC              0x000002c1UL
+#define CKM_SHA3_384_HMAC_GENERAL      0x000002c2UL
+#define CKM_SHA3_384_KEY_GEN           0x000002c3UL
+#define CKM_SHA3_512                   0x000002d0UL
+#define CKM_SHA3_512_HMAC              0x000002d1UL
+#define CKM_SHA3_512_HMAC_GENERAL      0x000002d2UL
+#define CKM_SHA3_512_KEY_GEN           0x000002d3UL
 
 
 #define CKM_CAST_KEY_GEN               0x00000300UL
@@ -870,9 +882,9 @@ typedef CK_ULONG          CK_MECHANISM_TYPE;
 #define CKM_SHA3_256_KEY_DERIVATION    0x00000397UL
 #define CKM_SHA3_224_KEY_DERIVATION    0x00000398UL
 #define CKM_SHA3_384_KEY_DERIVATION    0x00000399UL
-#define CKM_SHA3_512_KEY_DERIVATION    0x0000039AUL
-#define CKM_SHAKE_128_KEY_DERIVATION   0x0000039BUL
-#define CKM_SHAKE_256_KEY_DERIVATION   0x0000039CUL
+#define CKM_SHA3_512_KEY_DERIVATION    0x0000039aUL
+#define CKM_SHAKE_128_KEY_DERIVATION   0x0000039bUL
+#define CKM_SHAKE_256_KEY_DERIVATION   0x0000039cUL
 #define CKM_SHA3_256_KEY_DERIVE  CKM_SHA3_256_KEY_DERIVATION
 #define CKM_SHA3_224_KEY_DERIVE  CKM_SHA3_224_KEY_DERIVATION
 #define CKM_SHA3_384_KEY_DERIVE  CKM_SHA3_384_KEY_DERIVATION
@@ -880,40 +892,42 @@ typedef CK_ULONG          CK_MECHANISM_TYPE;
 #define CKM_SHAKE_128_KEY_DERIVE CKM_SHAKE_128_KEY_DERIVATION
 #define CKM_SHAKE_256_KEY_DERIVE CKM_SHAKE_256_KEY_DERIVATION
 
-#define CKM_PBE_MD2_DES_CBC            0x000003A0UL
-#define CKM_PBE_MD5_DES_CBC            0x000003A1UL
-#define CKM_PBE_MD5_CAST_CBC           0x000003A2UL
-#define CKM_PBE_MD5_CAST3_CBC          0x000003A3UL
-#define CKM_PBE_MD5_CAST5_CBC          0x000003A4UL /* Deprecated */
-#define CKM_PBE_MD5_CAST128_CBC        0x000003A4UL
-#define CKM_PBE_SHA1_CAST5_CBC         0x000003A5UL /* Deprecated */
-#define CKM_PBE_SHA1_CAST128_CBC       0x000003A5UL
-#define CKM_PBE_SHA1_RC4_128           0x000003A6UL
-#define CKM_PBE_SHA1_RC4_40            0x000003A7UL
-#define CKM_PBE_SHA1_DES3_EDE_CBC      0x000003A8UL
-#define CKM_PBE_SHA1_DES2_EDE_CBC      0x000003A9UL
-#define CKM_PBE_SHA1_RC2_128_CBC       0x000003AAUL
-#define CKM_PBE_SHA1_RC2_40_CBC        0x000003ABUL
-
-#define CKM_PKCS5_PBKD2                0x000003B0UL
-
-#define CKM_PBA_SHA1_WITH_SHA1_HMAC    0x000003C0UL
-
-#define CKM_WTLS_PRE_MASTER_KEY_GEN         0x000003D0UL
-#define CKM_WTLS_MASTER_KEY_DERIVE          0x000003D1UL
-#define CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC   0x000003D2UL
-#define CKM_WTLS_PRF                        0x000003D3UL
-#define CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE  0x000003D4UL
-#define CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE  0x000003D5UL
-
-#define CKM_TLS12_MAC                       0x000003D8UL
-#define CKM_TLS12_KDF                       0x000003D9UL
-#define CKM_TLS12_MASTER_KEY_DERIVE         0x000003E0UL
-#define CKM_TLS12_KEY_AND_MAC_DERIVE        0x000003E1UL
-#define CKM_TLS12_MASTER_KEY_DERIVE_DH      0x000003E2UL
-#define CKM_TLS12_KEY_SAFE_DERIVE           0x000003E3UL
-#define CKM_TLS_MAC                         0x000003E4UL
-#define CKM_TLS_KDF                         0x000003E5UL
+#define CKM_PBE_MD2_DES_CBC            0x000003a0UL
+#define CKM_PBE_MD5_DES_CBC            0x000003a1UL
+#define CKM_PBE_MD5_CAST_CBC           0x000003a2UL
+#define CKM_PBE_MD5_CAST3_CBC          0x000003a3UL
+#define CKM_PBE_MD5_CAST5_CBC          0x000003a4UL /* Deprecated */
+#define CKM_PBE_MD5_CAST128_CBC        0x000003a4UL
+#define CKM_PBE_SHA1_CAST5_CBC         0x000003a5UL /* Deprecated */
+#define CKM_PBE_SHA1_CAST128_CBC       0x000003a5UL
+#define CKM_PBE_SHA1_RC4_128           0x000003a6UL
+#define CKM_PBE_SHA1_RC4_40            0x000003a7UL
+#define CKM_PBE_SHA1_DES3_EDE_CBC      0x000003a8UL
+#define CKM_PBE_SHA1_DES2_EDE_CBC      0x000003a9UL
+#define CKM_PBE_SHA1_RC2_128_CBC       0x000003aaUL
+#define CKM_PBE_SHA1_RC2_40_CBC        0x000003abUL
+
+#define CKM_PKCS5_PBKD2                0x000003b0UL
+
+#define CKM_PBA_SHA1_WITH_SHA1_HMAC    0x000003c0UL
+
+#define CKM_WTLS_PRE_MASTER_KEY_GEN         0x000003d0UL
+#define CKM_WTLS_MASTER_KEY_DERIVE          0x000003d1UL
+#define CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC   0x000003d2UL
+#define CKM_WTLS_PRF                        0x000003d3UL
+#define CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE  0x000003d4UL
+#define CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE  0x000003d5UL
+
+#define CKM_TLS10_MAC_SERVER                0x000003d6UL
+#define CKM_TLS10_MAC_CLIENT                0x000003d7UL
+#define CKM_TLS12_MAC                       0x000003d8UL
+#define CKM_TLS12_KDF                       0x000003d9UL
+#define CKM_TLS12_MASTER_KEY_DERIVE         0x000003e0UL
+#define CKM_TLS12_KEY_AND_MAC_DERIVE        0x000003e1UL
+#define CKM_TLS12_MASTER_KEY_DERIVE_DH      0x000003e2UL
+#define CKM_TLS12_KEY_SAFE_DERIVE           0x000003e3UL
+#define CKM_TLS_MAC                         0x000003e4UL
+#define CKM_TLS_KDF                         0x000003e5UL
 
 #define CKM_KEY_WRAP_LYNKS             0x00000400UL
 #define CKM_KEY_WRAP_SET_OAEP          0x00000401UL
@@ -983,7 +997,7 @@ typedef CK_ULONG          CK_MECHANISM_TYPE;
 #define CKM_ECDSA_SHA256               0x00001044UL
 #define CKM_ECDSA_SHA384               0x00001045UL
 #define CKM_ECDSA_SHA512               0x00001046UL
-#define CKM_EC_KEY_PAIR_GEN_W_EXTRA_BITS 0x0000140BUL
+#define CKM_EC_KEY_PAIR_GEN_W_EXTRA_BITS 0x0000140bUL
 
 #define CKM_ECDH1_DERIVE               0x00001050UL
 #define CKM_ECDH1_COFACTOR_DERIVE      0x00001051UL
@@ -1012,12 +1026,12 @@ typedef CK_ULONG          CK_MECHANISM_TYPE;
 #define CKM_AES_GCM                    0x00001087UL
 #define CKM_AES_CCM                    0x00001088UL
 #define CKM_AES_CTS                    0x00001089UL
-#define CKM_AES_CMAC                   0x0000108AUL
-#define CKM_AES_CMAC_GENERAL           0x0000108BUL
+#define CKM_AES_CMAC                   0x0000108aUL
+#define CKM_AES_CMAC_GENERAL           0x0000108bUL
 
-#define CKM_AES_XCBC_MAC               0x0000108CUL
-#define CKM_AES_XCBC_MAC_96            0x0000108DUL
-#define CKM_AES_GMAC                   0x0000108EUL
+#define CKM_AES_XCBC_MAC               0x0000108cUL
+#define CKM_AES_XCBC_MAC_96            0x0000108dUL
+#define CKM_AES_GMAC                   0x0000108eUL
 
 #define CKM_BLOWFISH_KEY_GEN           0x00001090UL
 #define CKM_BLOWFISH_CBC               0x00001091UL
@@ -1066,6 +1080,7 @@ typedef CK_ULONG          CK_MECHANISM_TYPE;
 #define CKM_AES_KEY_WRAP               0x00002109UL     /* WAS: 0x00001090 */
 #define CKM_AES_KEY_WRAP_PAD           0x0000210AUL     /* WAS: 0x00001091 */
 #define CKM_AES_KEY_WRAP_KWP           0x0000210BUL
+#define CKM_AES_KEY_WRAP_PKCS7         0x0000210CUL
 
 #define CKM_RSA_PKCS_TPM_1_1           0x00004001UL
 #define CKM_RSA_PKCS_OAEP_TPM_1_1      0x00004002UL
@@ -1125,6 +1140,14 @@ typedef CK_ULONG          CK_MECHANISM_TYPE;
 #define CKM_SP800_108_FEEDBACK_KDF     0x000003adUL
 #define CKM_SP800_108_DOUBLE_PIPELINE_KDF 0x000003aeUL
 
+#define CKM_IKE2_PRF_PLUS_DERIVE       0x0000402eUL
+#define CKM_IKE_PRF_DERIVE             0x0000402fUL
+#define CKM_IKE1_PRF_DERIVE            0x00004030UL
+#define CKM_IKE1_EXTENDED_DERIVE       0x00004031UL
+#define CKM_HSS_KEY_PAIR_GEN           0x00004032UL
+#define CKM_HSS                        0x00004033UL
+
+
 #define CKM_VENDOR_DEFINED             0x80000000UL
 
 typedef CK_MECHANISM_TYPE CK_PTR CK_MECHANISM_TYPE_PTR;
@@ -1320,6 +1343,7 @@ typedef CK_ULONG          CK_RV;
 #define CKR_FUNCTION_REJECTED                 0x00000200UL
 #define CKR_TOKEN_RESOURCE_EXCEEDED           0x00000201UL
 #define CKR_OPERATION_CANCEL_FAILED           0x00000202UL
+#define CKR_KEY_EXHAUSTED                     0x00000203UL
 
 #define CKR_VENDOR_DEFINED                    0x80000000UL
 
@@ -1436,6 +1460,7 @@ typedef CK_RSA_PKCS_MGF_TYPE CK_PTR CK_RSA_PKCS_MGF_TYPE_PTR;
 #define CKG_MGF1_SHA3_384     0x00000008UL
 #define CKG_MGF1_SHA3_512     0x00000009UL
 
+
 /* CK_RSA_PKCS_OAEP_SOURCE_TYPE  is used to indicate the source
  * of the encoding parameter when formatting a message block
  * for the PKCS #1 OAEP encryption scheme.
@@ -1701,8 +1726,7 @@ typedef struct CK_DES_CBC_ENCRYPT_DATA_PARAMS {
     CK_ULONG    length;
 } CK_DES_CBC_ENCRYPT_DATA_PARAMS;
 
-typedef CK_DES_CBC_ENCRYPT_DATA_PARAMS CK_PTR \
-        CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR;
+typedef CK_DES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR;
 
 typedef struct CK_AES_CBC_ENCRYPT_DATA_PARAMS {
     CK_BYTE     iv[16];
@@ -1710,8 +1734,7 @@ typedef struct CK_AES_CBC_ENCRYPT_DATA_PARAMS {
     CK_ULONG    length;
 } CK_AES_CBC_ENCRYPT_DATA_PARAMS;
 
-typedef CK_AES_CBC_ENCRYPT_DATA_PARAMS CK_PTR \
-        CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR;
+typedef CK_AES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR;
 
 /* CK_SKIPJACK_PRIVATE_WRAP_PARAMS provides the parameters to the
  * CKM_SKIPJACK_PRIVATE_WRAP mechanism
@@ -2051,6 +2074,7 @@ typedef CK_ULONG CK_GENERATOR_FUNCTION;
 #define CKG_GENERATE         0x00000001UL
 #define CKG_GENERATE_COUNTER 0x00000002UL
 #define CKG_GENERATE_RANDOM  0x00000003UL
+#define CKG_GENERATE_COUNTER_XOR 0x00000004UL
 
 typedef struct CK_GCM_MESSAGE_PARAMS {
     CK_BYTE_PTR           pIv;
@@ -2061,7 +2085,7 @@ typedef struct CK_GCM_MESSAGE_PARAMS {
     CK_ULONG              ulTagBits;
 } CK_GCM_MESSAGE_PARAMS;
 
-typedef CK_GCM_MESSAGE_PARAMS CK_GCM_MESSAGE_PARAMS_PTR;
+typedef CK_GCM_MESSAGE_PARAMS CK_PTR CK_GCM_MESSAGE_PARAMS_PTR;
 
 typedef struct CK_CCM_PARAMS {
     CK_ULONG    ulDataLen;
@@ -2084,7 +2108,7 @@ typedef struct CK_CCM_MESSAGE_PARAMS {
     CK_ULONG              ulMACLen;
 } CK_CCM_MESSAGE_PARAMS;
 
-typedef CK_CCM_MESSAGE_PARAMS CK_CCM_MESSAGE_PARAMS_PTR;
+typedef CK_CCM_MESSAGE_PARAMS CK_PTR CK_CCM_MESSAGE_PARAMS_PTR;
 
 /* Deprecated. Use CK_GCM_PARAMS */
 typedef struct CK_AES_GCM_PARAMS {
@@ -2339,7 +2363,6 @@ typedef struct CK_SALSA20_PARAMS {
     CK_BYTE_PTR pNonce;
     CK_ULONG    ulNonceBits;
 } CK_SALSA20_PARAMS;
-
 typedef CK_SALSA20_PARAMS CK_PTR CK_SALSA20_PARAMS_PTR;
 
 typedef struct CK_SALSA20_CHACHA20_POLY1305_PARAMS {
@@ -2423,6 +2446,7 @@ typedef struct CK_XEDDSA_PARAMS {
 } CK_XEDDSA_PARAMS;
 typedef CK_XEDDSA_PARAMS CK_PTR CK_XEDDSA_PARAMS_PTR;
 
+/* HKDF params */
 typedef struct CK_HKDF_PARAMS {
     CK_BBOOL          bExtract;
     CK_BBOOL          bExpand;
@@ -2440,5 +2464,60 @@ typedef CK_HKDF_PARAMS CK_PTR CK_HKDF_PARAMS_PTR;
 #define CKF_HKDF_SALT_DATA   0x00000002UL
 #define CKF_HKDF_SALT_KEY    0x00000004UL
 
+/* HSS */
+typedef CK_ULONG                   CK_HSS_LEVELS;
+typedef CK_ULONG                   CK_LMS_TYPE;
+typedef CK_ULONG                   CK_LMOTS_TYPE;
+
+typedef struct specifiedParams {
+    CK_HSS_LEVELS levels;
+    CK_LMS_TYPE   lm_type[8];
+    CK_LMOTS_TYPE lm_ots_type[8];
+} specifiedParams;
+
+/* IKE Params */
+typedef struct CK_IKE2_PRF_PLUS_DERIVE_PARAMS {
+    CK_MECHANISM_TYPE prfMechanism;
+    CK_BBOOL          bHasSeedKey;
+    CK_OBJECT_HANDLE  hSeedKey;
+    CK_BYTE_PTR       pSeedData;
+    CK_ULONG          ulSeedDataLen;
+} CK_IKE2_PRF_PLUS_DERIVE_PARAMS;
+typedef CK_IKE2_PRF_PLUS_DERIVE_PARAMS CK_PTR CK_IKE2_PRF_PLUS_DERIVE_PARAMS_PTR;
+
+typedef struct CK_IKE_PRF_DERIVE_PARAMS {
+    CK_MECHANISM_TYPE prfMechanism;
+    CK_BBOOL          bDataAsKey;
+    CK_BBOOL          bRekey;
+    CK_BYTE_PTR       pNi;
+    CK_ULONG          ulNiLen;
+    CK_BYTE_PTR       pNr;
+    CK_ULONG          ulNrLen;
+    CK_OBJECT_HANDLE  hNewKey;
+} CK_IKE_PRF_DERIVE_PARAMS;
+typedef CK_IKE_PRF_DERIVE_PARAMS CK_PTR CK_IKE_PRF_DERIVE_PARAMS_PTR;
+
+typedef struct CK_IKE1_PRF_DERIVE_PARAMS {
+    CK_MECHANISM_TYPE prfMechanism;
+    CK_BBOOL          bHasPrevKey;
+    CK_OBJECT_HANDLE  hKeygxy;
+    CK_OBJECT_HANDLE  hPrevKey;
+    CK_BYTE_PTR       pCKYi;
+    CK_ULONG          ulCKYiLen;
+    CK_BYTE_PTR       pCKYr;
+    CK_ULONG          ulCKYrLen;
+    CK_BYTE           keyNumber;
+} CK_IKE1_PRF_DERIVE_PARAMS;
+typedef CK_IKE1_PRF_DERIVE_PARAMS CK_PTR CK_IKE1_PRF_DERIVE_PARAMS_PTR;
+
+typedef struct CK_IKE1_EXTENDED_DERIVE_PARAMS {
+    CK_MECHANISM_TYPE prfMechanism;
+    CK_BBOOL          bHasKeygxy;
+    CK_OBJECT_HANDLE  hKeygxy;
+    CK_BYTE_PTR       pExtraData;
+    CK_ULONG          ulExtraDataLen;
+} CK_IKE1_EXTENDED_DERIVE_PARAMS;
+typedef CK_IKE1_EXTENDED_DERIVE_PARAMS CK_PTR CK_IKE1_EXTENDED_DERIVE_PARAMS_PTR;
+
 #endif /* _PKCS11T_H_ */
 
diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/BindingReader.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/BindingReader.java
index 46a45ae396d..74d3a46ecf2 100644
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/BindingReader.java
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/BindingReader.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2018, the original author or authors.
+ * Copyright (c) 2002-2018, the original author(s).
  *
  * This software is distributable under the BSD license. See the terms of the
  * BSD license in the documentation provided with this software.
@@ -66,7 +66,7 @@ public  T readBinding(KeyMap keys, KeyMap local, boolean block) {
         T o = null;
         int[] remaining = new int[1];
         boolean hasRead = false;
-        for (;;) {
+        for (; ; ) {
             if (local != null) {
                 o = local.getBound(opBuffer, remaining);
             }
@@ -78,8 +78,7 @@ public  T readBinding(KeyMap keys, KeyMap local, boolean block) {
                 if (remaining[0] >= 0) {
                     runMacro(opBuffer.substring(opBuffer.length() - remaining[0]));
                     opBuffer.setLength(opBuffer.length() - remaining[0]);
-                }
-                else {
+                } else {
                     long ambiguousTimeout = keys.getAmbiguousTimeout();
                     if (ambiguousTimeout > 0 && peekCharacter(ambiguousTimeout) != NonBlockingReader.READ_EXPIRED) {
                         o = null;
@@ -234,5 +233,4 @@ public String getCurrentBuffer() {
     public String getLastBinding() {
         return lastBinding;
     }
-
 }
diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/KeyMap.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/KeyMap.java
index 43c3a1b4fd1..a8a90ea5e0d 100644
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/KeyMap.java
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/keymap/KeyMap.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2016, the original author or authors.
+ * Copyright (c) 2002-2016, the original author(s).
  *
  * This software is distributable under the BSD license. See the terms of the
  * BSD license in the documentation provided with this software.
@@ -8,8 +8,6 @@
  */
 package jdk.internal.org.jline.keymap;
 
-import java.io.IOException;
-import java.io.StringWriter;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Comparator;
@@ -218,7 +216,6 @@ public static Collection range(String range) {
         return seqs;
     }
 
-
     public static String esc() {
         return "\033";
     }
@@ -264,7 +261,6 @@ public static String key(Terminal terminal, Capability capability) {
     // Methods
     //
 
-
     public T getUnicode() {
         return unicode;
     }
@@ -306,9 +302,7 @@ private static  void doGetBoundKeys(KeyMap keyMap, String prefix, Map) keyMap.mapping[c],
-                        prefix + (char) (c),
-                        bound);
+                doGetBoundKeys((KeyMap) keyMap.mapping[c], prefix + (char) (c), bound);
             } else if (keyMap.mapping[c] != null) {
                 bound.put(prefix + (char) (c), (T) keyMap.mapping[c]);
             }
@@ -456,5 +450,4 @@ private static  void bind(KeyMap map, CharSequence keySeq, T function, boo
             }
         }
     }
-
 }
diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Binding.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Binding.java
index 0070b55c22d..15e7a49a643 100644
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Binding.java
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Binding.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2016, the original author or authors.
+ * Copyright (c) 2002-2016, the original author(s).
  *
  * This software is distributable under the BSD license. See the terms of the
  * BSD license in the documentation provided with this software.
@@ -14,9 +14,8 @@
  * @see Macro
  * @see Reference
  * @see Widget
- * @see jdk.internal.org.jline.keymap.KeyMap
+ * @see org.jline.keymap.KeyMap
  *
  * @author Guillaume Nodet
  */
-public interface Binding {
-}
+public interface Binding {}
diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Buffer.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Buffer.java
index 9fdd6e0bd7e..8d65891d9d9 100644
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Buffer.java
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Buffer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2017, the original author or authors.
+ * Copyright (c) 2002-2017, the original author(s).
  *
  * This software is distributable under the BSD license. See the terms of the
  * BSD license in the documentation provided with this software.
@@ -84,4 +84,8 @@ public interface Buffer {
 
     void copyFrom(Buffer buffer);
 
+    /**
+     * Clear any internal buffer.
+     */
+    void zeroOut();
 }
diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Candidate.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Candidate.java
index 0e95538492d..e28e72ffb23 100644
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Candidate.java
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Candidate.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2019, the original author or authors.
+ * Copyright (c) 2002-2019, the original author(s).
  *
  * This software is distributable under the BSD license. See the terms of the
  * BSD license in the documentation provided with this software.
@@ -47,7 +47,15 @@ public Candidate(String value) {
      * @param complete the complete flag
      * @param sort the sort flag
      */
-    public Candidate(String value, String displ, String group, String descr, String suffix, String key, boolean complete, int sort) {
+    public Candidate(
+            String value,
+            String displ,
+            String group,
+            String descr,
+            String suffix,
+            String key,
+            boolean complete,
+            int sort) {
         this.value = Objects.requireNonNull(value);
         this.displ = Objects.requireNonNull(displ);
         this.group = group;
@@ -69,7 +77,8 @@ public Candidate(String value, String displ, String group, String descr, String
      * @param key the key
      * @param complete the complete flag
      */
-    public Candidate(String value, String displ, String group, String descr, String suffix, String key, boolean complete) {
+    public Candidate(
+            String value, String displ, String group, String descr, String suffix, String key, boolean complete) {
         this(value, displ, group, descr, suffix, key, complete, 0);
     }
 
@@ -159,11 +168,10 @@ public int sort() {
         return sort;
     }
 
-
     @Override
     public int compareTo(Candidate o) {
         // If both candidates have same sort, use default behavior
-        if( sort == o.sort() ) {
+        if (sort == o.sort()) {
             return value.compareTo(o.value);
         } else {
             return Integer.compare(sort, o.sort());
@@ -180,7 +188,7 @@ public boolean equals(Object o) {
 
     @Override
     public int hashCode() {
-        return Objects.hash(value);
+        return Objects.hashCode(value);
     }
 
     @Override
diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Completer.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Completer.java
index b87db7afbf0..7a5937460d8 100644
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Completer.java
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Completer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2018, the original author or authors.
+ * Copyright (c) 2002-2018, the original author(s).
  *
  * This software is distributable under the BSD license. See the terms of the
  * BSD license in the documentation provided with this software.
@@ -18,8 +18,7 @@
  * @author Guillaume Nodet
  * @since 2.3
  */
-public interface Completer
-{
+public interface Completer {
     /**
      * Populates candidates with a list of possible completions for the command line.
      *
diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/CompletingParsedLine.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/CompletingParsedLine.java
index 52a36b83896..93558001af1 100644
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/CompletingParsedLine.java
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/CompletingParsedLine.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2018, the original author or authors.
+ * Copyright (c) 2002-2018, the original author(s).
  *
  * This software is distributable under the BSD license. See the terms of the
  * BSD license in the documentation provided with this software.
@@ -10,7 +10,7 @@
 
 /**
  * An extension of {@link ParsedLine} that, being aware of the quoting and escaping rules
- * of the {@link jdk.internal.org.jline.reader.Parser} that produced it, knows if and how a completion candidate
+ * of the {@link org.jline.reader.Parser} that produced it, knows if and how a completion candidate
  * should be escaped/quoted.
  *
  * @author Eric Bottard
@@ -22,5 +22,4 @@ public interface CompletingParsedLine extends ParsedLine {
     int rawWordCursor();
 
     int rawWordLength();
-
 }
diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/CompletionMatcher.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/CompletionMatcher.java
index 58117c8f213..4a2334642ca 100644
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/CompletionMatcher.java
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/CompletionMatcher.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2020, the original author or authors.
+ * Copyright (c) 2002-2020, the original author(s).
  *
  * This software is distributable under the BSD license. See the terms of the
  * BSD license in the documentation provided with this software.
@@ -23,8 +23,13 @@ public interface CompletionMatcher {
      * @param errors number of errors accepted in matching
      * @param originalGroupName value of JLineReader variable original-group-name
      */
-    void compile(Map options, boolean prefix, CompletingParsedLine line
-            , boolean caseInsensitive, int errors, String originalGroupName);
+    void compile(
+            Map options,
+            boolean prefix,
+            CompletingParsedLine line,
+            boolean caseInsensitive,
+            int errors,
+            String originalGroupName);
 
     /**
      *
@@ -44,5 +49,4 @@ void compile(Map options, boolean prefix, Completing
      * @return a common prefix of matched candidates
      */
     String getCommonPrefix();
-
 }
diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/EOFError.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/EOFError.java
index 382db8bc49f..8a4f516174e 100644
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/EOFError.java
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/EOFError.java
@@ -1,20 +1,10 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
+ * Copyright (c) 2023, the original author(s).
  *
- *   http://www.apache.org/licenses/LICENSE-2.0
+ * This software is distributable under the BSD license. See the terms of the
+ * BSD license in the documentation provided with this software.
  *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
+ * https://opensource.org/licenses/BSD-3-Clause
  */
 package jdk.internal.org.jline.reader;
 
@@ -45,7 +35,7 @@ public String getMissing() {
         return missing;
     }
 
-    public int getOpenBrackets(){
+    public int getOpenBrackets() {
         return openBrackets;
     }
 
diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Editor.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Editor.java
index e99706ed5d5..b2fadd3bd52 100644
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Editor.java
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Editor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2019, the original author or authors.
+ * Copyright (c) 2002-2019, the original author(s).
  *
  * This software is distributable under the BSD license. See the terms of the
  * BSD license in the documentation provided with this software.
@@ -13,6 +13,8 @@
 
 public interface Editor {
     public void open(List files) throws IOException;
+
     public void run() throws IOException;
+
     public void setRestricted(boolean restricted);
 }
diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/EndOfFileException.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/EndOfFileException.java
index 9f70420d9df..1e50a7ea1ae 100644
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/EndOfFileException.java
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/EndOfFileException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2020, the original author or authors.
+ * Copyright (c) 2002-2020, the original author(s).
  *
  * This software is distributable under the BSD license. See the terms of the
  * BSD license in the documentation provided with this software.
@@ -17,8 +17,7 @@ public class EndOfFileException extends RuntimeException {
     private static final long serialVersionUID = 528485360925144689L;
     private String partialLine;
 
-    public EndOfFileException() {
-    }
+    public EndOfFileException() {}
 
     public EndOfFileException(String message) {
         super(message);
diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Expander.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Expander.java
index 0562e92ed96..614c89b3e61 100644
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Expander.java
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Expander.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2016, the original author or authors.
+ * Copyright (c) 2002-2016, the original author(s).
  *
  * This software is distributable under the BSD license. See the terms of the
  * BSD license in the documentation provided with this software.
@@ -13,5 +13,4 @@ public interface Expander {
     String expandHistory(History history, String line);
 
     String expandVar(String word);
-
 }
diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Highlighter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Highlighter.java
index 136fb20324b..dad62551ee0 100644
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Highlighter.java
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Highlighter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2021, the original author or authors.
+ * Copyright (c) 2002-2021, the original author(s).
  *
  * This software is distributable under the BSD license. See the terms of the
  * BSD license in the documentation provided with this software.
diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/History.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/History.java
index 7a669edddb5..0cb46a1ee9d 100644
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/History.java
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/History.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2018, the original author or authors.
+ * Copyright (c) 2002-2018, the original author(s).
  *
  * This software is distributable under the BSD license. See the terms of the
  * BSD license in the documentation provided with this software.
@@ -21,8 +21,7 @@
  * @author Jason Dillon
  * @since 2.3
  */
-public interface History extends Iterable
-{
+public interface History extends Iterable {
 
     /**
      * Initialize the history for the given reader.
@@ -75,7 +74,6 @@ public interface History extends Iterable
      */
     void purge() throws IOException;
 
-
     int size();
 
     default boolean isEmpty() {
@@ -110,8 +108,7 @@ default boolean isPersistable(Entry entry) {
     // Entries
     //
 
-    interface Entry
-    {
+    interface Entry {
         int index();
 
         Instant time();
@@ -132,14 +129,17 @@ default Iterator reverseIterator() {
     default Iterator reverseIterator(int index) {
         return new Iterator() {
             private final ListIterator it = iterator(index + 1);
+
             @Override
             public boolean hasNext() {
                 return it.hasPrevious();
             }
+
             @Override
             public Entry next() {
                 return it.previous();
             }
+
             @Override
             public void remove() {
                 it.remove();
diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReader.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReader.java
index 03729853ca5..bc513f5f636 100644
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReader.java
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReader.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2021, the original author or authors.
+ * Copyright (c) 2002-2023, the original author(s).
  *
  * This software is distributable under the BSD license. See the terms of the
  * BSD license in the documentation provided with this software.
@@ -21,7 +21,7 @@
 
 /** Read lines from the console, with input editing.
  *
- * 

Thread safety

+ *

Thread safety

* The LineReader implementations are not thread safe, * thus you should not attempt to use a single reader in several threads. * Any attempt to call one of the readLine call while one is @@ -31,7 +31,7 @@ * {@link #printAbove(String)} or {@link #printAbove(AttributedString)} at * any time to allow text to be printed above the current prompt. * - *

Prompt strings

+ *

Prompt strings

* It is traditional for an interactive console-based program * to print a short prompt string to signal that the user is expected * to type a command. JLine supports 3 kinds of prompt string: @@ -81,7 +81,6 @@ * * */ - public interface LineReader { /** @@ -284,6 +283,7 @@ public interface LineReader { String MAIN = "main"; String EMACS = "emacs"; String SAFE = ".safe"; + String DUMB = "dumb"; String MENU = "menu"; // @@ -301,6 +301,7 @@ public interface LineReader { * they are displayed in a list below the field to be completed */ String MENU_LIST_MAX = "menu-list-max"; + String DISABLE_HISTORY = "disable-history"; String DISABLE_COMPLETION = "disable-completion"; String EDITING_MODE = "editing-mode"; @@ -317,18 +318,23 @@ public interface LineReader { String ORIGINAL_GROUP_NAME = "ORIGINAL_GROUP_NAME"; /** Completion style for displaying groups name */ String COMPLETION_STYLE_GROUP = "COMPLETION_STYLE_GROUP"; + String COMPLETION_STYLE_LIST_GROUP = "COMPLETION_STYLE_LIST_GROUP"; /** Completion style for displaying the current selected item */ String COMPLETION_STYLE_SELECTION = "COMPLETION_STYLE_SELECTION"; + String COMPLETION_STYLE_LIST_SELECTION = "COMPLETION_STYLE_LIST_SELECTION"; /** Completion style for displaying the candidate description */ String COMPLETION_STYLE_DESCRIPTION = "COMPLETION_STYLE_DESCRIPTION"; + String COMPLETION_STYLE_LIST_DESCRIPTION = "COMPLETION_STYLE_LIST_DESCRIPTION"; /** Completion style for displaying the matching part of candidates */ String COMPLETION_STYLE_STARTING = "COMPLETION_STYLE_STARTING"; + String COMPLETION_STYLE_LIST_STARTING = "COMPLETION_STYLE_LIST_STARTING"; /** Completion style for displaying the list */ String COMPLETION_STYLE_BACKGROUND = "COMPLETION_STYLE_BACKGROUND"; + String COMPLETION_STYLE_LIST_BACKGROUND = "COMPLETION_STYLE_LIST_BACKGROUND"; /** * Set the template for prompts for secondary (continuation) lines. @@ -390,6 +396,26 @@ public interface LineReader { */ String SUGGESTIONS_MIN_BUFFER_SIZE = "suggestions-min-buffer-size"; + /** + * Max number of times a command can be repeated. + */ + String MAX_REPEAT_COUNT = "max-repeat-count"; + + /** + * Number of spaces to display a tabulation, the default is 4. + */ + String TAB_WIDTH = "tab-width"; + + /** + * Name of inputrc to read at line reader creation time. + */ + String INPUT_RC_FILE_NAME = "input-rc-file-name"; + + /** + * Prefix to automatically delegate variables to system properties + */ + String SYSTEM_PROPERTY_PREFIX = "system-property-prefix"; + Map> defaultKeyMaps(); enum Option { @@ -469,8 +495,7 @@ enum Option { EMPTY_WORD_OPTIONS(true), /** Disable the undo feature */ - DISABLE_UNDO - ; + DISABLE_UNDO; private final boolean def; @@ -611,7 +636,8 @@ enum SuggestionType { * @throws EndOfFileException if an EOF has been found (using Ctrl-D for example) * @throws java.io.IOError in case of other i/o errors */ - String readLine(String prompt, String rightPrompt, Character mask, String buffer) throws UserInterruptException, EndOfFileException; + String readLine(String prompt, String rightPrompt, Character mask, String buffer) + throws UserInterruptException, EndOfFileException; /** * Read a line from the in {@link InputStream}, and return the line @@ -631,7 +657,8 @@ enum SuggestionType { * @throws EndOfFileException if an EOF has been found (using Ctrl-D for example) * @throws java.io.IOError in case of other i/o errors */ - String readLine(String prompt, String rightPrompt, MaskingCallback maskingCallback, String buffer) throws UserInterruptException, EndOfFileException; + String readLine(String prompt, String rightPrompt, MaskingCallback maskingCallback, String buffer) + throws UserInterruptException, EndOfFileException; /** * Prints a line above the prompt and redraw everything. @@ -702,7 +729,7 @@ enum SuggestionType { void runMacro(String macro); /** - * Read a mouse event when the {@link jdk.internal.org.jline.utils.InfoCmp.Capability#key_mouse} sequence + * Read a mouse event when the {@link org.jline.utils.InfoCmp.Capability#key_mouse} sequence * has just been read on the input stream. * Compared to {@link Terminal#readMouseEvent()}, this method takes into account keys * that have been pushed back using {@link #runMacro(String)}. @@ -750,4 +777,9 @@ enum SuggestionType { void setAutosuggestion(SuggestionType type); SuggestionType getAutosuggestion(); + + /** + * Clear any internal buffers. + */ + void zeroOut(); } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReaderBuilder.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReaderBuilder.java index 14d5a0e8b1c..942bba3605d 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReaderBuilder.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/LineReaderBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2020, the original author or authors. + * Copyright (c) 2002-2020, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -38,8 +38,7 @@ public static LineReaderBuilder builder() { Expander expander; CompletionMatcher completionMatcher; - private LineReaderBuilder() { - } + private LineReaderBuilder() {} public LineReaderBuilder terminal(Terminal terminal) { this.terminal = terminal; @@ -88,8 +87,9 @@ public LineReaderBuilder parser(Parser parser) { try { if (!Boolean.getBoolean(LineReader.PROP_SUPPORT_PARSEDLINE) && !(parser.parse("", 0) instanceof CompletingParsedLine)) { - Log.warn("The Parser of class " + parser.getClass().getName() + " does not support the CompletingParsedLine interface. " + - "Completion with escaped or quoted words won't work correctly."); + Log.warn("The Parser of class " + parser.getClass().getName() + + " does not support the CompletingParsedLine interface. " + + "Completion with escaped or quoted words won't work correctly."); } } catch (Throwable t) { // Ignore @@ -153,5 +153,4 @@ public LineReader build() { } return reader; } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Macro.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Macro.java index e66efcc5f92..b00769aff52 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Macro.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Macro.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -35,7 +35,6 @@ public int hashCode() { @Override public String toString() { - return "Macro[" + - sequence + ']'; + return "Macro[" + sequence + ']'; } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/MaskingCallback.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/MaskingCallback.java index 03501aaf07c..3b624e306f2 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/MaskingCallback.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/MaskingCallback.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -31,5 +31,4 @@ public interface MaskingCallback { * @return the modified line */ String history(String line); - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/ParsedLine.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/ParsedLine.java index 683c4b48d77..3d87e6b80b2 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/ParsedLine.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/ParsedLine.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -64,5 +64,4 @@ public interface ParsedLine { * @return the cursor position within the line */ int cursor(); - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Parser.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Parser.java index 1f7df67d573..5db53818f67 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Parser.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Parser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2021, the original author or authors. + * Copyright (c) 2002-2021, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -35,7 +35,7 @@ default boolean validVariableName(String name) { default String getCommand(final String line) { String out; - Pattern patternCommand = Pattern.compile("^\\s*" + REGEX_VARIABLE + "=(" + REGEX_COMMAND + ")(\\s+|$)"); + Pattern patternCommand = Pattern.compile("^\\s*" + REGEX_VARIABLE + "=(" + REGEX_COMMAND + ")(\\s+|$)"); Matcher matcher = patternCommand.matcher(line); if (matcher.find()) { out = matcher.group(1); @@ -50,7 +50,7 @@ default String getCommand(final String line) { default String getVariable(final String line) { String out = null; - Pattern patternCommand = Pattern.compile("^\\s*(" + REGEX_VARIABLE + ")\\s*=[^=~].*"); + Pattern patternCommand = Pattern.compile("^\\s*(" + REGEX_VARIABLE + ")\\s*=[^=~].*"); Matcher matcher = patternCommand.matcher(line); if (matcher.find()) { out = matcher.group(1); diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/PrintAboveWriter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/PrintAboveWriter.java index 63c9decd194..e23988310a5 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/PrintAboveWriter.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/PrintAboveWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2021, the original author or authors. + * Copyright (c) 2002-2021, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Reference.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Reference.java index f799a3da220..2fb1aaa671b 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Reference.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Reference.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -38,7 +38,6 @@ public int hashCode() { @Override public String toString() { - return "Reference[" + - name + ']'; + return "Reference[" + name + ']'; } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/SyntaxError.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/SyntaxError.java index e46143e4c39..eaf3e1d7580 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/SyntaxError.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/SyntaxError.java @@ -1,20 +1,10 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at + * Copyright (c) 2023, the original author(s). * - * http://www.apache.org/licenses/LICENSE-2.0 + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * https://opensource.org/licenses/BSD-3-Clause */ package jdk.internal.org.jline.reader; diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/UserInterruptException.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/UserInterruptException.java index b5510cab5c9..68bec8041fa 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/UserInterruptException.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/UserInterruptException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -14,23 +14,19 @@ * interrupt character (ctrl-C). The partially entered line is * available via the {@link #getPartialLine()} method. */ -public class UserInterruptException - extends RuntimeException -{ +public class UserInterruptException extends RuntimeException { private static final long serialVersionUID = 6172232572140736750L; private final String partialLine; - public UserInterruptException(String partialLine) - { + public UserInterruptException(String partialLine) { this.partialLine = partialLine; } /** * @return the partially entered line when ctrl-C was pressed */ - public String getPartialLine() - { + public String getPartialLine() { return partialLine; } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Widget.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Widget.java index d5add7fb1a7..ae831c5eaad 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Widget.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/Widget.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -15,5 +15,4 @@ public interface Widget extends Binding { boolean apply(); - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/BufferImpl.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/BufferImpl.java index a3b2a21ac66..a68ef229f86 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/BufferImpl.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/BufferImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2017, the original author or authors. + * Copyright (c) 2002-2017, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -8,6 +8,7 @@ */ package jdk.internal.org.jline.reader.impl; +import java.util.Arrays; import java.util.Objects; import jdk.internal.org.jline.reader.Buffer; @@ -19,8 +20,7 @@ * @author Jason Dillon * @since 2.0 */ -public class BufferImpl implements Buffer -{ +public class BufferImpl implements Buffer { private int cursor = 0; private int cursorCol = -1; private int[] buffer; @@ -45,7 +45,7 @@ private BufferImpl(BufferImpl buffer) { this.g1 = buffer.g1; } - public BufferImpl copy () { + public BufferImpl copy() { return new BufferImpl(this); } @@ -106,7 +106,7 @@ private int adjust(int i) { * @param c the character to insert */ public void write(int c) { - write(new int[] { c }); + write(new int[] {c}); } /** @@ -120,7 +120,7 @@ public void write(int c, boolean overTyping) { if (overTyping) { delete(1); } - write(new int[] { c }); + write(new int[] {c}); } /** @@ -223,8 +223,7 @@ public int move(final int num) { if ((cursor + where) < 0) { where = -cursor; - } - else if ((cursor + where) > length()) { + } else if ((cursor + where) > length()) { where = length() - cursor; } @@ -369,4 +368,9 @@ private void moveGapToCursor() { g1 += l; } } + + @Override + public void zeroOut() { + Arrays.fill(buffer, 0); + } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/CompletionMatcherImpl.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/CompletionMatcherImpl.java index f829f13d51b..761ee1815c3 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/CompletionMatcherImpl.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/CompletionMatcherImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2021, the original author or authors. + * Copyright (c) 2002-2021, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -8,26 +8,25 @@ */ package jdk.internal.org.jline.reader.impl; -import jdk.internal.org.jline.reader.Candidate; -import jdk.internal.org.jline.reader.CompletingParsedLine; -import jdk.internal.org.jline.reader.CompletionMatcher; -import jdk.internal.org.jline.reader.LineReader; -import jdk.internal.org.jline.utils.AttributedString; - import java.util.*; import java.util.function.Function; import java.util.function.Predicate; import java.util.regex.Pattern; import java.util.stream.Collectors; +import jdk.internal.org.jline.reader.Candidate; +import jdk.internal.org.jline.reader.CompletingParsedLine; +import jdk.internal.org.jline.reader.CompletionMatcher; +import jdk.internal.org.jline.reader.LineReader; +import jdk.internal.org.jline.utils.AttributedString; + public class CompletionMatcherImpl implements CompletionMatcher { protected Predicate exact; protected List>, Map>>> matchers; private Map> matching; private boolean caseInsensitive; - public CompletionMatcherImpl() { - } + public CompletionMatcherImpl() {} protected void reset(boolean caseInsensitive) { this.caseInsensitive = caseInsensitive; @@ -37,8 +36,13 @@ protected void reset(boolean caseInsensitive) { } @Override - public void compile(Map options, boolean prefix, CompletingParsedLine line - , boolean caseInsensitive, int errors, String originalGroupName) { + public void compile( + Map options, + boolean prefix, + CompletingParsedLine line, + boolean caseInsensitive, + int errors, + String originalGroupName) { reset(caseInsensitive); defaultMatchers(options, prefix, line, caseInsensitive, errors, originalGroupName); } @@ -47,15 +51,18 @@ public void compile(Map options, boolean prefix, Com public List matches(List candidates) { matching = Collections.emptyMap(); Map> sortedCandidates = sort(candidates); - for (Function>, - Map>> matcher : matchers) { + for (Function>, Map>> matcher : matchers) { matching = matcher.apply(sortedCandidates); if (!matching.isEmpty()) { break; } } - return !matching.isEmpty() ? matching.entrySet().stream().flatMap(e -> e.getValue().stream()).distinct().collect(Collectors.toList()) - : new ArrayList<>(); + return !matching.isEmpty() + ? matching.entrySet().stream() + .flatMap(e -> e.getValue().stream()) + .distinct() + .collect(Collectors.toList()) + : new ArrayList<>(); } @Override @@ -63,10 +70,12 @@ public Candidate exactMatch() { if (matching == null) { throw new IllegalStateException(); } - return matching.values().stream().flatMap(Collection::stream) + return matching.values().stream() + .flatMap(Collection::stream) .filter(Candidate::complete) .filter(c -> exact.test(c.value())) - .findFirst().orElse(null); + .findFirst() + .orElse(null); } @Override @@ -84,8 +93,13 @@ public String getCommonPrefix() { /** * Default JLine matchers */ - protected void defaultMatchers(Map options, boolean prefix, CompletingParsedLine line - , boolean caseInsensitive, int errors, String originalGroupName) { + protected void defaultMatchers( + Map options, + boolean prefix, + CompletingParsedLine line, + boolean caseInsensitive, + int errors, + String originalGroupName) { // Find matchers // TODO: glob completion String wd = line.word(); @@ -94,8 +108,7 @@ protected void defaultMatchers(Map options, boolean if (prefix) { matchers = new ArrayList<>(Arrays.asList( simpleMatcher(s -> (caseInsensitive ? s.toLowerCase() : s).startsWith(wp)), - simpleMatcher(s -> (caseInsensitive ? s.toLowerCase() : s).contains(wp)) - )); + simpleMatcher(s -> (caseInsensitive ? s.toLowerCase() : s).contains(wp)))); if (LineReader.Option.COMPLETE_MATCHER_TYPO.isSet(options)) { matchers.add(typoMatcher(wp, errors, caseInsensitive, originalGroupName)); } @@ -109,14 +122,14 @@ protected void defaultMatchers(Map options, boolean Pattern p1 = Pattern.compile(Pattern.quote(wp) + ".*" + Pattern.quote(ws) + ".*"); Pattern p2 = Pattern.compile(".*" + Pattern.quote(wp) + ".*" + Pattern.quote(ws) + ".*"); matchers = new ArrayList<>(Arrays.asList( - simpleMatcher(s -> p1.matcher(caseInsensitive ? s.toLowerCase() : s).matches()), - simpleMatcher(s -> p2.matcher(caseInsensitive ? s.toLowerCase() : s).matches()) - )); + simpleMatcher(s -> p1.matcher(caseInsensitive ? s.toLowerCase() : s) + .matches()), + simpleMatcher(s -> p2.matcher(caseInsensitive ? s.toLowerCase() : s) + .matches()))); } else { matchers = new ArrayList<>(Arrays.asList( simpleMatcher(s -> (caseInsensitive ? s.toLowerCase() : s).startsWith(wdi)), - simpleMatcher(s -> (caseInsensitive ? s.toLowerCase() : s).contains(wdi)) - )); + simpleMatcher(s -> (caseInsensitive ? s.toLowerCase() : s).contains(wdi)))); } if (LineReader.Option.COMPLETE_MATCHER_CAMELCASE.isSet(options)) { matchers.add(simpleMatcher(s -> camelMatch(wd, 0, s, 0))); @@ -128,18 +141,20 @@ protected void defaultMatchers(Map options, boolean } } - protected Function>, - Map>> simpleMatcher(Predicate predicate) { + protected Function>, Map>> simpleMatcher( + Predicate predicate) { return m -> m.entrySet().stream() .filter(e -> predicate.test(e.getKey())) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); } - protected Function>, - Map>> typoMatcher(String word, int errors, boolean caseInsensitive, String originalGroupName) { + protected Function>, Map>> typoMatcher( + String word, int errors, boolean caseInsensitive, String originalGroupName) { return m -> { Map> map = m.entrySet().stream() - .filter(e -> ReaderUtils.distance(word, caseInsensitive ? e.getKey().toLowerCase() : e.getKey()) < errors) + .filter(e -> ReaderUtils.distance( + word, caseInsensitive ? e.getKey().toLowerCase() : e.getKey()) + < errors) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); if (map.size() > 1) { map.computeIfAbsent(word, w -> new ArrayList<>()) @@ -178,7 +193,8 @@ private Map> sort(List candidates) { Map> sortedCandidates = new HashMap<>(); for (Candidate candidate : candidates) { sortedCandidates - .computeIfAbsent(AttributedString.fromAnsi(candidate.value()).toString(), s -> new ArrayList<>()) + .computeIfAbsent( + AttributedString.fromAnsi(candidate.value()).toString(), s -> new ArrayList<>()) .add(candidate); } return sortedCandidates; @@ -206,5 +222,4 @@ private String getCommonStart(String str1, String str2, boolean caseInsensitive) } return new String(s1, 0, len); } - -} \ No newline at end of file +} diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultExpander.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultExpander.java index b534b96ff2f..e5e7735a384 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultExpander.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultExpander.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -32,27 +32,25 @@ public String expandHistory(History history, String line) { if (unicode > 0) { escaped = (--unicode >= 0); sb.append(c); - } - else if (escaped) { + } else if (escaped) { if (c == 'u') { unicode = 4; } else { escaped = false; } sb.append(c); - } - else if (c == '\'') { + } else if (c == '\'') { inQuote = !inQuote; sb.append(c); - } - else if (inQuote) { + } else if (inQuote) { sb.append(c); - } - else { + } else { switch (c) { case '\\': - // any '\!' should be considered an expansion escape, so skip expansion and strip the escape character - // a leading '\^' should be considered an expansion escape, so skip expansion and strip the escape character + // any '\!' should be considered an expansion escape, so skip expansion and strip the escape + // character + // a leading '\^' should be considered an expansion escape, so skip expansion and strip the + // escape character // otherwise, add the escape escaped = true; sb.append(c); @@ -91,7 +89,8 @@ else if (inQuote) { if (history.size() == 0) { throw new IllegalArgumentException("!$: event not found"); } - String previous = history.get(history.index() - 1).trim(); + String previous = + history.get(history.index() - 1).trim(); int lastSpace = previous.lastIndexOf(' '); if (lastSpace != -1) { rep = previous.substring(lastSpace + 1); @@ -128,14 +127,18 @@ else if (inQuote) { try { idx = Integer.parseInt(line.substring(i1, i)); } catch (NumberFormatException e) { - throw new IllegalArgumentException((neg ? "!-" : "!") + line.substring(i1, i) + ": event not found"); + throw new IllegalArgumentException( + (neg ? "!-" : "!") + line.substring(i1, i) + ": event not found"); } if (neg && idx > 0 && idx <= history.size()) { rep = history.get(history.index() - idx); - } else if (!neg && idx > history.index() - history.size() && idx <= history.index()) { + } else if (!neg + && idx > history.index() - history.size() + && idx <= history.index()) { rep = history.get(idx - 1); } else { - throw new IllegalArgumentException((neg ? "!-" : "!") + line.substring(i1, i) + ": event not found"); + throw new IllegalArgumentException( + (neg ? "!-" : "!") + line.substring(i1, i) + ": event not found"); } break; default: diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultHighlighter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultHighlighter.java index ac286ad734f..55d39efde27 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultHighlighter.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultHighlighter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2021, the original author or authors. + * Copyright (c) 2002-2021, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -10,9 +10,9 @@ import java.util.regex.Pattern; +import jdk.internal.org.jline.reader.Highlighter; import jdk.internal.org.jline.reader.LineReader; import jdk.internal.org.jline.reader.LineReader.RegionType; -import jdk.internal.org.jline.reader.Highlighter; import jdk.internal.org.jline.utils.AttributedString; import jdk.internal.org.jline.utils.AttributedStringBuilder; import jdk.internal.org.jline.utils.AttributedStyle; @@ -57,7 +57,8 @@ public AttributedString highlight(LineReader reader, String buffer) { while (negativeStart > 0 && reader.getBuffer().atChar(negativeStart - 1) != '\n') { negativeStart--; } - while (negativeEnd < reader.getBuffer().length() - 1 && reader.getBuffer().atChar(negativeEnd + 1) != '\n') { + while (negativeEnd < reader.getBuffer().length() - 1 + && reader.getBuffer().atChar(negativeEnd + 1) != '\n') { negativeEnd++; } } @@ -104,5 +105,4 @@ public AttributedString highlight(LineReader reader, String buffer) { } return sb.toAttributedString(); } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultParser.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultParser.java index d9b3a9948d5..26cdf6abc51 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultParser.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/DefaultParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2020, the original author or authors. + * Copyright (c) 2002-2020, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -21,18 +21,18 @@ public class DefaultParser implements Parser { public enum Bracket { - ROUND, // () - CURLY, // {} - SQUARE, // [] - ANGLE // <> + ROUND, // () + CURLY, // {} + SQUARE, // [] + ANGLE // <> } public static class BlockCommentDelims { private final String start; private final String end; + public BlockCommentDelims(String start, String end) { - if (start == null || end == null - || start.isEmpty() || end.isEmpty() || start.equals(end)) { + if (start == null || end == null || start.isEmpty() || end.isEmpty() || start.equals(end)) { throw new IllegalArgumentException("Bad block comment delimiter!"); } this.start = start; @@ -185,22 +185,22 @@ public void setEofOnUnclosedBracket(Bracket... brackets) { int i = 0; for (Bracket b : bs) { switch (b) { - case ROUND: - openingBrackets[i] = '('; - closingBrackets[i] = ')'; - break; - case CURLY: - openingBrackets[i] = '{'; - closingBrackets[i] = '}'; - break; - case SQUARE: - openingBrackets[i] = '['; - closingBrackets[i] = ']'; - break; - case ANGLE: - openingBrackets[i] = '<'; - closingBrackets[i] = '>'; - break; + case ROUND: + openingBrackets[i] = '('; + closingBrackets[i] = ')'; + break; + case CURLY: + openingBrackets[i] = '{'; + closingBrackets[i] = '}'; + break; + case SQUARE: + openingBrackets[i] = '['; + closingBrackets[i] = ']'; + break; + case ANGLE: + openingBrackets[i] = '<'; + closingBrackets[i] = '>'; + break; } i++; } @@ -229,7 +229,6 @@ public boolean validVariableName(String name) { return name != null && regexVariable != null && name.matches(regexVariable); } - @Override public String getCommand(final String line) { String out = ""; @@ -296,7 +295,7 @@ public ParsedLine parse(final String line, final int cursor, ParseContext contex if (quoteStart < 0 && isQuoteChar(line, i) && !lineCommented && !blockCommented) { // Start a quote block quoteStart = i; - if (current.length()==0) { + if (current.length() == 0) { quotedWord = true; if (context == ParseContext.SPLIT_LINE) { current.append(line.charAt(i)); @@ -324,13 +323,15 @@ public ParsedLine parse(final String line, final int cursor, ParseContext contex } } else { // Delimiter - rawWordLength = handleDelimiterAndGetRawWordLength(current, words, rawWordStart, rawWordCursor, rawWordLength, i); + rawWordLength = handleDelimiterAndGetRawWordLength( + current, words, rawWordStart, rawWordCursor, rawWordLength, i); rawWordStart = i + 1; } } else { if (quoteStart < 0 && !blockCommented && (lineCommented || isLineCommentStarted(line, i))) { lineCommented = true; - } else if (quoteStart < 0 && !lineCommented + } else if (quoteStart < 0 + && !lineCommented && (blockCommented || isCommentDelim(line, i, blockCommentStart))) { if (blockCommented) { if (blockCommentEnd != null && isCommentDelim(line, i, blockCommentEnd)) { @@ -339,12 +340,12 @@ public ParsedLine parse(final String line, final int cursor, ParseContext contex } } else { blockCommented = true; - rawWordLength = handleDelimiterAndGetRawWordLength(current, words, rawWordStart, rawWordCursor, rawWordLength, i); + rawWordLength = handleDelimiterAndGetRawWordLength( + current, words, rawWordStart, rawWordCursor, rawWordLength, i); i += blockCommentStart == null ? 0 : blockCommentStart.length() - 1; rawWordStart = i + 1; } - } else if (quoteStart < 0 && !lineCommented - && isCommentDelim(line, i, blockCommentEnd)) { + } else if (quoteStart < 0 && !lineCommented && isCommentDelim(line, i, blockCommentEnd)) { current.append(line.charAt(i)); blockCommentInRightOrder = false; } else if (!isEscapeChar(line, i)) { @@ -377,16 +378,14 @@ && isCommentDelim(line, i, blockCommentEnd)) { throw new EOFError(-1, -1, "Escaped new line", "newline"); } if (eofOnUnclosedQuote && quoteStart >= 0) { - throw new EOFError(-1, -1, "Missing closing quote", line.charAt(quoteStart) == '\'' - ? "quote" : "dquote"); + throw new EOFError( + -1, -1, "Missing closing quote", line.charAt(quoteStart) == '\'' ? "quote" : "dquote"); } if (blockCommented) { - throw new EOFError(-1, -1, "Missing closing block comment delimiter", - "add: " + blockCommentEnd); + throw new EOFError(-1, -1, "Missing closing block comment delimiter", "add: " + blockCommentEnd); } if (!blockCommentInRightOrder) { - throw new EOFError(-1, -1, "Missing opening block comment delimiter", - "missing: " + blockCommentStart); + throw new EOFError(-1, -1, "Missing opening block comment delimiter", "missing: " + blockCommentStart); } if (bracketChecker.isClosingBracketMissing() || bracketChecker.isOpeningBracketMissing()) { String message = null; @@ -398,8 +397,13 @@ && isCommentDelim(line, i, blockCommentEnd)) { message = "Missing opening bracket"; missing = "missing: " + bracketChecker.getMissingOpeningBracket(); } - throw new EOFError(-1, -1, message, missing, - bracketChecker.getOpenBrackets(), bracketChecker.getNextClosingBracket()); + throw new EOFError( + -1, + -1, + message, + missing, + bracketChecker.getOpenBrackets(), + bracketChecker.getNextClosingBracket()); } } @@ -420,7 +424,13 @@ public boolean isDelimiter(final CharSequence buffer, final int pos) { return !isQuoted(buffer, pos) && !isEscaped(buffer, pos) && isDelimiterChar(buffer, pos); } - private int handleDelimiterAndGetRawWordLength(StringBuilder current, List words, int rawWordStart, int rawWordCursor, int rawWordLength, int pos) { + private int handleDelimiterAndGetRawWordLength( + StringBuilder current, + List words, + int rawWordStart, + int rawWordCursor, + int rawWordLength, + int pos) { if (current.length() > 0) { words.add(current.toString()); current.setLength(0); // reset the arg @@ -470,7 +480,7 @@ private boolean isCommentDelim(final CharSequence buffer, final int pos, final S public boolean isLineCommentStarted(final CharSequence buffer, final int pos) { if (lineCommentDelims != null) { - for (String comment: lineCommentDelims) { + for (String comment : lineCommentDelims) { if (isCommentDelim(buffer, pos, comment)) { return true; } @@ -584,8 +594,8 @@ public void check(final CharSequence buffer, final int pos) { } else { bid = bracketId(closingBrackets, buffer, pos); if (bid >= 0) { - if (!nested.isEmpty() && bid == nested.get(nested.size()-1)) { - nested.remove(nested.size()-1); + if (!nested.isEmpty() && bid == nested.get(nested.size() - 1)) { + nested.remove(nested.size() - 1); } else { missingOpeningBracket = bid; } @@ -634,7 +644,7 @@ public String getNextClosingBracket() { } private int bracketId(final char[] brackets, final CharSequence buffer, final int pos) { - for (int i=0; i < brackets.length; i++) { + for (int i = 0; i < brackets.length; i++) { if (buffer.charAt(pos) == brackets[i]) { return i; } @@ -648,8 +658,7 @@ private int bracketId(final char[] brackets, final CharSequence buffer, final in * * @author Marc Prud'hommeaux */ - public class ArgumentList implements ParsedLine, CompletingParsedLine - { + public class ArgumentList implements ParsedLine, CompletingParsedLine { private final String line; private final List words; @@ -667,11 +676,21 @@ public class ArgumentList implements ParsedLine, CompletingParsedLine private final int rawWordLength; @Deprecated - public ArgumentList(final String line, final List words, - final int wordIndex, final int wordCursor, - final int cursor) { - this(line, words, wordIndex, wordCursor, cursor, - null, wordCursor, words.get(wordIndex).length()); + public ArgumentList( + final String line, + final List words, + final int wordIndex, + final int wordCursor, + final int cursor) { + this( + line, + words, + wordIndex, + wordCursor, + cursor, + null, + wordCursor, + words.get(wordIndex).length()); } /** @@ -685,10 +704,15 @@ public ArgumentList(final String line, final List words, * @param rawWordCursor the cursor position inside the raw word (i.e. including quotes and escape characters) * @param rawWordLength the raw word length, including quotes and escape characters */ - public ArgumentList(final String line, final List words, - final int wordIndex, final int wordCursor, - final int cursor, final String openingQuote, - final int rawWordCursor, final int rawWordLength) { + public ArgumentList( + final String line, + final List words, + final int wordIndex, + final int wordCursor, + final int cursor, + final String openingQuote, + final int rawWordCursor, + final int rawWordLength) { this.line = line; this.words = Collections.unmodifiableList(Objects.requireNonNull(words)); this.wordIndex = wordIndex; @@ -732,8 +756,8 @@ public CharSequence escape(CharSequence candidate, boolean complete) { Predicate needToBeEscaped; String quote = openingQuote; boolean middleQuotes = false; - if (openingQuote==null) { - for (int i=0; i < sb.length(); i++) { + if (openingQuote == null) { + for (int i = 0; i < sb.length(); i++) { if (isQuoteChar(sb, i)) { middleQuotes = true; break; @@ -746,7 +770,8 @@ public CharSequence escape(CharSequence candidate, boolean complete) { // Delimiters (spaces) don't need to be escaped, nor do other quotes, but everything else does. // Also, close the quote at the end if (openingQuote != null) { - needToBeEscaped = i -> isRawEscapeChar(sb.charAt(i)) || String.valueOf(sb.charAt(i)).equals(openingQuote); + needToBeEscaped = i -> isRawEscapeChar(sb.charAt(i)) + || String.valueOf(sb.charAt(i)).equals(openingQuote); } // Completion is protected by middle quotes: // Delimiters (spaces) don't need to be escaped, nor do quotes, but everything else does. @@ -756,8 +781,8 @@ else if (middleQuotes) { // No quote protection, need to escape everything: delimiter chars (spaces), quote chars // and escapes themselves else { - needToBeEscaped = i -> isDelimiterChar(sb, i) || isRawEscapeChar(sb.charAt(i)) - || isRawQuoteChar(sb.charAt(i)); + needToBeEscaped = i -> + isDelimiterChar(sb, i) || isRawEscapeChar(sb.charAt(i)) || isRawQuoteChar(sb.charAt(i)); } for (int i = 0; i < sb.length(); i++) { if (needToBeEscaped.test(i)) { @@ -792,5 +817,4 @@ public int rawWordLength() { return rawWordLength; } } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/InputRC.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/InputRC.java new file mode 100644 index 00000000000..0c3aee057a4 --- /dev/null +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/InputRC.java @@ -0,0 +1,394 @@ +/* + * Copyright (c) 2002-2023, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * https://opensource.org/licenses/BSD-3-Clause + */ +package jdk.internal.org.jline.reader.impl; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +import jdk.internal.org.jline.reader.LineReader; +import jdk.internal.org.jline.reader.Macro; +import jdk.internal.org.jline.reader.Reference; +import jdk.internal.org.jline.terminal.Terminal; +import jdk.internal.org.jline.utils.Log; + +public final class InputRC { + + public static void configure(LineReader reader, URL url) throws IOException { + try (InputStream is = url.openStream()) { + configure(reader, is); + } + } + + public static void configure(LineReader reader, InputStream is) throws IOException { + try (InputStreamReader r = new InputStreamReader(is)) { + configure(reader, r); + } + } + + public static void configure(LineReader reader, Reader r) throws IOException { + BufferedReader br; + if (r instanceof BufferedReader) { + br = (BufferedReader) r; + } else { + br = new BufferedReader(r); + } + + Terminal terminal = reader.getTerminal(); + + if (Terminal.TYPE_DUMB.equals(terminal.getType()) || Terminal.TYPE_DUMB_COLOR.equals(terminal.getType())) { + reader.getVariables().putIfAbsent(LineReader.EDITING_MODE, "dumb"); + } else { + reader.getVariables().putIfAbsent(LineReader.EDITING_MODE, "emacs"); + } + + reader.setKeyMap(LineReader.MAIN); + new InputRC(reader).parse(br); + if ("vi".equals(reader.getVariable(LineReader.EDITING_MODE))) { + reader.getKeyMaps().put(LineReader.MAIN, reader.getKeyMaps().get(LineReader.VIINS)); + } else if ("emacs".equals(reader.getVariable(LineReader.EDITING_MODE))) { + reader.getKeyMaps().put(LineReader.MAIN, reader.getKeyMaps().get(LineReader.EMACS)); + } else if ("dumb".equals(reader.getVariable(LineReader.EDITING_MODE))) { + reader.getKeyMaps().put(LineReader.MAIN, reader.getKeyMaps().get(LineReader.DUMB)); + } + } + + private final LineReader reader; + + private InputRC(LineReader reader) { + this.reader = reader; + } + + private void parse(BufferedReader br) throws IOException, IllegalArgumentException { + String line; + boolean parsing = true; + List ifsStack = new ArrayList<>(); + while ((line = br.readLine()) != null) { + try { + line = line.trim(); + if (line.length() == 0) { + continue; + } + if (line.charAt(0) == '#') { + continue; + } + int i = 0; + if (line.charAt(i) == '$') { + String cmd; + String args; + ++i; + while (i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t')) { + i++; + } + int s = i; + while (i < line.length() && (line.charAt(i) != ' ' && line.charAt(i) != '\t')) { + i++; + } + cmd = line.substring(s, i); + while (i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t')) { + i++; + } + s = i; + while (i < line.length() && (line.charAt(i) != ' ' && line.charAt(i) != '\t')) { + i++; + } + args = line.substring(s, i); + if ("if".equalsIgnoreCase(cmd)) { + ifsStack.add(parsing); + if (!parsing) { + continue; + } + if (args.startsWith("term=")) { + // TODO + } else if (args.startsWith("mode=")) { + String mode = (String) reader.getVariable(LineReader.EDITING_MODE); + parsing = args.substring("mode=".length()).equalsIgnoreCase(mode); + } else { + parsing = args.equalsIgnoreCase(reader.getAppName()); + } + } else if ("else".equalsIgnoreCase(cmd)) { + if (ifsStack.isEmpty()) { + throw new IllegalArgumentException("$else found without matching $if"); + } + boolean invert = true; + for (boolean b : ifsStack) { + if (!b) { + invert = false; + break; + } + } + if (invert) { + parsing = !parsing; + } + } else if ("endif".equalsIgnoreCase(cmd)) { + if (ifsStack.isEmpty()) { + throw new IllegalArgumentException("endif found without matching $if"); + } + parsing = ifsStack.remove(ifsStack.size() - 1); + } else if ("include".equalsIgnoreCase(cmd)) { + // TODO + } + continue; + } + if (!parsing) { + continue; + } + if (line.charAt(i++) == '"') { + boolean esc = false; + for (; ; i++) { + if (i >= line.length()) { + throw new IllegalArgumentException("Missing closing quote on line '" + line + "'"); + } + if (esc) { + esc = false; + } else if (line.charAt(i) == '\\') { + esc = true; + } else if (line.charAt(i) == '"') { + break; + } + } + } + while (i < line.length() && line.charAt(i) != ':' && line.charAt(i) != ' ' && line.charAt(i) != '\t') { + i++; + } + String keySeq = line.substring(0, i); + boolean equivalency = i + 1 < line.length() && line.charAt(i) == ':' && line.charAt(i + 1) == '='; + i++; + if (equivalency) { + i++; + } + if (keySeq.equalsIgnoreCase("set")) { + String key; + String val; + while (i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t')) { + i++; + } + int s = i; + while (i < line.length() && (line.charAt(i) != ' ' && line.charAt(i) != '\t')) { + i++; + } + key = line.substring(s, i); + while (i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t')) { + i++; + } + s = i; + while (i < line.length() && (line.charAt(i) != ' ' && line.charAt(i) != '\t')) { + i++; + } + val = line.substring(s, i); + setVar(reader, key, val); + } else { + while (i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t')) { + i++; + } + int start = i; + if (i < line.length() && (line.charAt(i) == '\'' || line.charAt(i) == '\"')) { + char delim = line.charAt(i++); + boolean esc = false; + for (; ; i++) { + if (i >= line.length()) { + break; + } + if (esc) { + esc = false; + } else if (line.charAt(i) == '\\') { + esc = true; + } else if (line.charAt(i) == delim) { + break; + } + } + } + for (; i < line.length() && line.charAt(i) != ' ' && line.charAt(i) != '\t'; i++) + ; + String val = line.substring(Math.min(start, line.length()), Math.min(i, line.length())); + if (keySeq.charAt(0) == '"') { + keySeq = translateQuoted(keySeq); + } else { + // Bind key name + String keyName = + keySeq.lastIndexOf('-') > 0 ? keySeq.substring(keySeq.lastIndexOf('-') + 1) : keySeq; + char key = getKeyFromName(keyName); + keyName = keySeq.toLowerCase(); + keySeq = ""; + if (keyName.contains("meta-") || keyName.contains("m-")) { + keySeq += "\u001b"; + } + if (keyName.contains("control-") || keyName.contains("c-") || keyName.contains("ctrl-")) { + key = (char) (Character.toUpperCase(key) & 0x1f); + } + keySeq += key; + } + if (val.length() > 0 && (val.charAt(0) == '\'' || val.charAt(0) == '\"')) { + reader.getKeys().bind(new Macro(translateQuoted(val)), keySeq); + } else { + reader.getKeys().bind(new Reference(val), keySeq); + } + } + } catch (IllegalArgumentException e) { + Log.warn("Unable to parse user configuration: ", e); + } + } + } + + private static String translateQuoted(String keySeq) { + int i; + String str = keySeq.substring(1, keySeq.length() - 1); + StringBuilder sb = new StringBuilder(); + for (i = 0; i < str.length(); i++) { + char c = str.charAt(i); + if (c == '\\') { + boolean ctrl = str.regionMatches(i, "\\C-", 0, 3) || str.regionMatches(i, "\\M-\\C-", 0, 6); + boolean meta = str.regionMatches(i, "\\M-", 0, 3) || str.regionMatches(i, "\\C-\\M-", 0, 6); + i += (meta ? 3 : 0) + (ctrl ? 3 : 0) + (!meta && !ctrl ? 1 : 0); + if (i >= str.length()) { + break; + } + c = str.charAt(i); + if (meta) { + sb.append("\u001b"); + } + if (ctrl) { + c = c == '?' ? 0x7f : (char) (Character.toUpperCase(c) & 0x1f); + } + if (!meta && !ctrl) { + switch (c) { + case 'a': + c = 0x07; + break; + case 'b': + c = '\b'; + break; + case 'd': + c = 0x7f; + break; + case 'e': + c = 0x1b; + break; + case 'f': + c = '\f'; + break; + case 'n': + c = '\n'; + break; + case 'r': + c = '\r'; + break; + case 't': + c = '\t'; + break; + case 'v': + c = 0x0b; + break; + case '\\': + c = '\\'; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + c = 0; + for (int j = 0; j < 3; j++, i++) { + if (i >= str.length()) { + break; + } + int k = Character.digit(str.charAt(i), 8); + if (k < 0) { + break; + } + c = (char) (c * 8 + k); + } + c &= 0xFF; + break; + case 'x': + i++; + c = 0; + for (int j = 0; j < 2; j++, i++) { + if (i >= str.length()) { + break; + } + int k = Character.digit(str.charAt(i), 16); + if (k < 0) { + break; + } + c = (char) (c * 16 + k); + } + c &= 0xFF; + break; + case 'u': + i++; + c = 0; + for (int j = 0; j < 4; j++, i++) { + if (i >= str.length()) { + break; + } + int k = Character.digit(str.charAt(i), 16); + if (k < 0) { + break; + } + c = (char) (c * 16 + k); + } + break; + } + } + sb.append(c); + } else { + sb.append(c); + } + } + return sb.toString(); + } + + private static char getKeyFromName(String name) { + if ("DEL".equalsIgnoreCase(name) || "Rubout".equalsIgnoreCase(name)) { + return 0x7f; + } else if ("ESC".equalsIgnoreCase(name) || "Escape".equalsIgnoreCase(name)) { + return '\033'; + } else if ("LFD".equalsIgnoreCase(name) || "NewLine".equalsIgnoreCase(name)) { + return '\n'; + } else if ("RET".equalsIgnoreCase(name) || "Return".equalsIgnoreCase(name)) { + return '\r'; + } else if ("SPC".equalsIgnoreCase(name) || "Space".equalsIgnoreCase(name)) { + return ' '; + } else if ("Tab".equalsIgnoreCase(name)) { + return '\t'; + } else { + return name.charAt(0); + } + } + + static void setVar(LineReader reader, String key, String val) { + if (LineReader.KEYMAP.equalsIgnoreCase(key)) { + reader.setKeyMap(val); + return; + } + + for (LineReader.Option option : LineReader.Option.values()) { + if (option.name().toLowerCase(Locale.ENGLISH).replace('_', '-').equals(val)) { + if ("on".equalsIgnoreCase(val)) { + reader.setOpt(option); + } else if ("off".equalsIgnoreCase(val)) { + reader.unsetOpt(option); + } + return; + } + } + + reader.setVariable(key, val); + } +} diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/KillRing.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/KillRing.java index f89ed35d04e..2510fd9e320 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/KillRing.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/KillRing.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/LineReaderImpl.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/LineReaderImpl.java index ee8a434e1a2..94ed9ae450d 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/LineReaderImpl.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/LineReaderImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2022, the original author or authors. + * Copyright (c) 2002-2023, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -18,6 +18,9 @@ import java.io.InputStream; import java.io.InterruptedIOException; import java.lang.reflect.Constructor; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.time.Instant; import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; @@ -56,6 +59,7 @@ import static jdk.internal.org.jline.keymap.KeyMap.esc; import static jdk.internal.org.jline.keymap.KeyMap.range; import static jdk.internal.org.jline.keymap.KeyMap.translate; +import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_DISABLE_ALTERNATE_CHARSET; /** * A reader for terminal applications. It supports custom tab-completion, @@ -66,23 +70,27 @@ * @author Guillaume Nodet */ @SuppressWarnings("StatementWithEmptyBody") -public class LineReaderImpl implements LineReader, Flushable -{ +public class LineReaderImpl implements LineReader, Flushable { public static final char NULL_MASK = 0; + /** + * @deprecated use {@link #DEFAULT_TAB_WIDTH} and {@link #getTabWidth()} + */ + @Deprecated public static final int TAB_WIDTH = 4; + public static final int DEFAULT_TAB_WIDTH = 4; public static final String DEFAULT_WORDCHARS = "*?_-.[]~=/&;!#$%^(){}<>"; public static final String DEFAULT_REMOVE_SUFFIX_CHARS = " \t\n;&|"; public static final String DEFAULT_COMMENT_BEGIN = "#"; public static final String DEFAULT_SEARCH_TERMINATORS = "\033\012"; public static final String DEFAULT_BELL_STYLE = ""; - public static final int DEFAULT_LIST_MAX = 100; - public static final int DEFAULT_MENU_LIST_MAX = Integer.MAX_VALUE; - public static final int DEFAULT_ERRORS = 2; - public static final long DEFAULT_BLINK_MATCHING_PAREN = 500L; - public static final long DEFAULT_AMBIGUOUS_BINDING = 1000L; + public static final int DEFAULT_LIST_MAX = 100; + public static final int DEFAULT_MENU_LIST_MAX = Integer.MAX_VALUE; + public static final int DEFAULT_ERRORS = 2; + public static final long DEFAULT_BLINK_MATCHING_PAREN = 500L; + public static final long DEFAULT_AMBIGUOUS_BINDING = 1000L; public static final String DEFAULT_SECONDARY_PROMPT_PATTERN = "%M> "; public static final String DEFAULT_OTHERS_GROUP_NAME = "others"; public static final String DEFAULT_ORIGINAL_GROUP_NAME = "original"; @@ -96,9 +104,10 @@ public class LineReaderImpl implements LineReader, Flushable public static final String DEFAULT_COMPLETION_STYLE_LIST_GROUP = "fg:black,bold"; public static final String DEFAULT_COMPLETION_STYLE_LIST_SELECTION = DEFAULT_COMPLETION_STYLE_SELECTION; public static final String DEFAULT_COMPLETION_STYLE_LIST_BACKGROUND = "bg:bright-magenta"; - public static final int DEFAULT_INDENTATION = 0; - public static final int DEFAULT_FEATURES_MAX_BUFFER_SIZE = 1000; - public static final int DEFAULT_SUGGESTIONS_MIN_BUFFER_SIZE = 1; + public static final int DEFAULT_INDENTATION = 0; + public static final int DEFAULT_FEATURES_MAX_BUFFER_SIZE = 1000; + public static final int DEFAULT_SUGGESTIONS_MIN_BUFFER_SIZE = 1; + public static final String DEFAULT_SYSTEM_PROPERTY_PREFIX = "org.jline.reader.props."; private static final int MIN_ROWS = 3; @@ -109,6 +118,7 @@ public class LineReaderImpl implements LineReader, Flushable public static final String FOCUS_IN_SEQ = "\033[I"; public static final String FOCUS_OUT_SEQ = "\033[O"; + public static final int DEFAULT_MAX_REPEAT_COUNT = 9999; /** * Possible states in which the current readline operation may be in. @@ -197,27 +207,28 @@ protected enum BellType { protected int searchIndex = -1; protected boolean doAutosuggestion; - // Reading buffers protected final BindingReader bindingReader; - /** * VI character find */ protected int findChar; + protected int findDir; protected int findTailAdd; /** * VI history string search */ private int searchDir; + private String searchString; /** * Region state */ protected int regionMark; + protected RegionType regionActive; private boolean forceChar; @@ -232,7 +243,7 @@ protected enum BellType { protected KillRing killRing = new KillRing(); - protected UndoTree undo = new UndoTree<>(this::setBuffer); + protected UndoTree undo; protected boolean isUndo; /** @@ -242,7 +253,7 @@ protected enum BellType { /* * Current internal state of the line reader */ - protected State state = State.DONE; + protected State state = State.DONE; protected final AtomicBoolean startedReading = new AtomicBoolean(); protected boolean reading; @@ -278,7 +289,10 @@ protected enum BellType { */ protected List commandsBuffer = new ArrayList<>(); - int candidateStartPosition = 0; + protected int candidateStartPosition = 0; + + protected String alternateIn; + protected String alternateOut; public LineReaderImpl(Terminal terminal) throws IOException { this(terminal, terminal.getName(), null); @@ -288,6 +302,7 @@ public LineReaderImpl(Terminal terminal, String appName) throws IOException { this(terminal, appName, null); } + @SuppressWarnings("this-escape") public LineReaderImpl(Terminal terminal, String appName, Map variables) { Objects.requireNonNull(terminal, "terminal can not be null"); this.terminal = terminal; @@ -300,11 +315,40 @@ public LineReaderImpl(Terminal terminal, String appName, Map var } else { this.variables = new HashMap<>(); } + String prefix = getString(SYSTEM_PROPERTY_PREFIX, DEFAULT_SYSTEM_PROPERTY_PREFIX); + if (prefix != null) { + Properties sysProps = System.getProperties(); + for (String s : sysProps.stringPropertyNames()) { + if (s.startsWith(prefix)) { + String key = s.substring(prefix.length()); + InputRC.setVar(this, key, sysProps.getProperty(s)); + } + } + } + this.keyMaps = defaultKeyMaps(); + if (!Boolean.getBoolean(PROP_DISABLE_ALTERNATE_CHARSET)) { + this.alternateIn = Curses.tputs(terminal.getStringCapability(Capability.enter_alt_charset_mode)); + this.alternateOut = Curses.tputs(terminal.getStringCapability(Capability.exit_alt_charset_mode)); + } + undo = new UndoTree<>(this::setBuffer); builtinWidgets = builtinWidgets(); widgets = new HashMap<>(builtinWidgets); bindingReader = new BindingReader(terminal.reader()); + + String inputRc = getString(INPUT_RC_FILE_NAME, null); + if (inputRc != null) { + Path inputRcPath = Paths.get(inputRc); + if (Files.exists(inputRcPath)) { + try (InputStream is = Files.newInputStream(inputRcPath)) { + InputRC.configure(this, is); + } catch (Exception e) { + Log.debug("Error reading inputRc config file: ", inputRc, e); + } + } + } + doDisplay(); } @@ -489,7 +533,8 @@ public String readLine(String prompt, Character mask) throws UserInterruptExcept * @param buffer A string that will be set for editing. * @return A line that is read from the terminal, can never be null. */ - public String readLine(String prompt, Character mask, String buffer) throws UserInterruptException, EndOfFileException { + public String readLine(String prompt, Character mask, String buffer) + throws UserInterruptException, EndOfFileException { return readLine(prompt, null, mask, buffer); } @@ -503,7 +548,8 @@ public String readLine(String prompt, Character mask, String buffer) throws User * @param buffer A string that will be set for editing. * @return A line that is read from the terminal, can never be null. */ - public String readLine(String prompt, String rightPrompt, Character mask, String buffer) throws UserInterruptException, EndOfFileException { + public String readLine(String prompt, String rightPrompt, Character mask, String buffer) + throws UserInterruptException, EndOfFileException { return readLine(prompt, rightPrompt, mask != null ? new SimpleMaskingCallback(mask) : null, buffer); } @@ -517,7 +563,8 @@ public String readLine(String prompt, String rightPrompt, Character mask, String * @param buffer A string that will be set for editing. * @return A line that is read from the terminal, can never be null. */ - public String readLine(String prompt, String rightPrompt, MaskingCallback maskingCallback, String buffer) throws UserInterruptException, EndOfFileException { + public String readLine(String prompt, String rightPrompt, MaskingCallback maskingCallback, String buffer) + throws UserInterruptException, EndOfFileException { // prompt may be null // maskingCallback may be null // buffer may be null @@ -618,23 +665,14 @@ public String readLine(String prompt, String rightPrompt, MaskingCallback maskin // Move into application mode if (!dumb) { terminal.puts(Capability.keypad_xmit); - if (isSet(Option.AUTO_FRESH_LINE)) - callWidget(FRESH_LINE); - if (isSet(Option.MOUSE)) - terminal.trackMouse(Terminal.MouseTracking.Normal); - if (isSet(Option.BRACKETED_PASTE)) - terminal.writer().write(BRACKETED_PASTE_ON); - } else { - // For dumb terminals, we need to make sure that CR are ignored - Attributes attr = new Attributes(originalAttributes); - attr.setInputFlag(Attributes.InputFlag.IGNCR, true); - terminal.setAttributes(attr); + if (isSet(Option.AUTO_FRESH_LINE)) callWidget(FRESH_LINE); + if (isSet(Option.MOUSE)) terminal.trackMouse(Terminal.MouseTracking.Normal); + if (isSet(Option.BRACKETED_PASTE)) terminal.writer().write(BRACKETED_PASTE_ON); } callWidget(CALLBACK_INIT); - if (!isSet(Option.DISABLE_UNDO)) - undo.newState(buf.copy()); + if (!isSet(Option.DISABLE_UNDO)) undo.newState(buf.copy()); // Draw initial prompt redrawLine(); @@ -654,7 +692,8 @@ public String readLine(String prompt, String rightPrompt, MaskingCallback maskin throw new EndOfFileException().partialLine(buf.length() > 0 ? buf.toString() : null); } Log.trace("Binding: ", o); - if (buf.length() == 0 && getLastBinding().charAt(0) == originalAttributes.getControlChar(ControlChar.VEOF)) { + if (buf.length() == 0 + && getLastBinding().charAt(0) == originalAttributes.getControlChar(ControlChar.VEOF)) { throw new EndOfFileException(); } @@ -675,12 +714,17 @@ public String readLine(String prompt, String rightPrompt, MaskingCallback maskin try { lock.lock(); // Get executable widget - Buffer copy = buf.length() <= getInt(FEATURES_MAX_BUFFER_SIZE, DEFAULT_FEATURES_MAX_BUFFER_SIZE) ? buf.copy() : null; + Buffer copy = buf.length() <= getInt(FEATURES_MAX_BUFFER_SIZE, DEFAULT_FEATURES_MAX_BUFFER_SIZE) + ? buf.copy() + : null; Widget w = getWidget(o); if (!w.apply()) { beep(); } - if (!isSet(Option.DISABLE_UNDO) && !isUndo && copy != null && buf.length() <= getInt(FEATURES_MAX_BUFFER_SIZE, DEFAULT_FEATURES_MAX_BUFFER_SIZE) + if (!isSet(Option.DISABLE_UNDO) + && !isUndo + && copy != null + && buf.length() <= getInt(FEATURES_MAX_BUFFER_SIZE, DEFAULT_FEATURES_MAX_BUFFER_SIZE) && !copy.toString().equals(buf.toString())) { undo.newState(buf.copy()); } @@ -718,13 +762,18 @@ public String readLine(String prompt, String rightPrompt, MaskingCallback maskin } else { throw e; } - } - finally { + } finally { + AtomicBoolean interrupted = new AtomicBoolean(Thread.interrupted()); try { lock.lock(); this.reading = false; + Terminal.SignalHandler tmpHandler = terminal.handle(Signal.INT, s -> interrupted.set(true)); + if (previousIntrHandler == null) { + previousIntrHandler = tmpHandler; + } + cleanup(); if (originalAttributes != null) { terminal.setAttributes(originalAttributes); @@ -741,13 +790,15 @@ public String readLine(String prompt, String rightPrompt, MaskingCallback maskin } finally { lock.unlock(); startedReading.set(false); + if (interrupted.get()) { + Thread.currentThread().interrupt(); + } } } } private boolean isTerminalDumb() { - return Terminal.TYPE_DUMB.equals(terminal.getType()) - || Terminal.TYPE_DUMB_COLOR.equals(terminal.getType()); + return Terminal.TYPE_DUMB.equals(terminal.getType()) || Terminal.TYPE_DUMB_COLOR.equals(terminal.getType()); } private void doDisplay() { @@ -757,8 +808,7 @@ private void doDisplay() { display = new Display(terminal, false); display.resize(size.getRows(), size.getColumns()); - if (isSet(Option.DELAY_LINE_WRAP)) - display.setDelayLineWrap(true); + if (isSet(Option.DELAY_LINE_WRAP)) display.setDelayLineWrap(true); } @Override @@ -965,8 +1015,10 @@ public Binding readBinding(KeyMap keys, KeyMap local) { if (!YANK_POP.equals(ref) && !YANK.equals(ref)) { killRing.resetLastYank(); } - if (!KILL_LINE.equals(ref) && !KILL_WHOLE_LINE.equals(ref) - && !BACKWARD_KILL_WORD.equals(ref) && !KILL_WORD.equals(ref)) { + if (!KILL_LINE.equals(ref) + && !KILL_WHOLE_LINE.equals(ref) + && !BACKWARD_KILL_WORD.equals(ref) + && !KILL_WORD.equals(ref)) { killRing.resetLastKill(); } } @@ -1083,7 +1135,7 @@ public void editAndAddInBuffer(File file) throws Exception { if (isSet(Option.BRACKETED_PASTE)) { terminal.writer().write(BRACKETED_PASTE_OFF); } - Constructor ctor = Class.forName("jdk.internal.org.jline.builtins.Nano").getConstructor(Terminal.class, File.class); + Constructor ctor = Class.forName("org.jline.builtins.Nano").getConstructor(Terminal.class, File.class); Editor editor = (Editor) ctor.newInstance(terminal, new File(file.getParent())); editor.setRestricted(true); editor.open(Collections.singletonList(file.getName())); @@ -1097,6 +1149,10 @@ public void editAndAddInBuffer(File file) throws Exception { } } + protected int getTabWidth() { + return getInt(LineReader.TAB_WIDTH, DEFAULT_TAB_WIDTH); + } + // // Widget implementation // @@ -1137,26 +1193,27 @@ protected String finish(String str) { } // we only add it to the history if the buffer is not empty - if (historyLine != null && historyLine.length() > 0 ) { + if (historyLine != null && historyLine.length() > 0) { history.add(Instant.now(), historyLine); } return str; } - protected void handleSignal(Signal signal) { + protected synchronized void handleSignal(Signal signal) { doAutosuggestion = false; if (signal == Signal.WINCH) { + size.copy(terminal.getBufferSize()); + display.resize(size.getRows(), size.getColumns()); Status status = Status.getStatus(terminal, false); if (status != null) { - status.hardReset(); + status.resize(size); + status.reset(); } - size.copy(terminal.getBufferSize()); - display.resize(size.getRows(), size.getColumns()); - // restores prompt but also prevents scrolling in consoleZ, see #492 - // redrawLine(); + terminal.puts(Capability.carriage_return); + terminal.puts(Capability.clr_eos); + redrawLine(); redisplay(); - } - else if (signal == Signal.CONT) { + } else if (signal == Signal.CONT) { terminal.enterRawMode(); size.copy(terminal.getBufferSize()); display.resize(size.getRows(), size.getColumns()); @@ -1200,13 +1257,11 @@ protected Widget getWidget(Object binding) { // public void setPrompt(final String prompt) { - this.prompt = (prompt == null ? AttributedString.EMPTY - : expandPromptPattern(prompt, 0, "", 0)); + this.prompt = (prompt == null ? AttributedString.EMPTY : expandPromptPattern(prompt, 0, "", 0)); } public void setRightPrompt(final String rightPrompt) { - this.rightPrompt = (rightPrompt == null ? AttributedString.EMPTY - : expandPromptPattern(rightPrompt, 0, "", 0)); + this.rightPrompt = (rightPrompt == null ? AttributedString.EMPTY : expandPromptPattern(rightPrompt, 0, "", 0)); } protected void setBuffer(Buffer buffer) { @@ -1233,7 +1288,7 @@ protected void setBuffer(final String buffer) { * @param op The incoming operation to remap * @return The remaped operation */ - protected String viDeleteChangeYankToRemap (String op) { + protected String viDeleteChangeYankToRemap(String op) { switch (op) { case SEND_BREAK: case BACKWARD_CHAR: @@ -1292,7 +1347,6 @@ protected boolean isInViCmdMode() { return VICMD.equals(keyMap); } - // // Movement // @@ -1332,7 +1386,6 @@ protected boolean viBackwardChar() { return true; } - // // Word movement // @@ -1365,9 +1418,7 @@ protected boolean viForwardWord() { buf.move(1); } } else { - while (buf.cursor() < buf.length() - && !isViAlphaNum(buf.currChar()) - && !isWhitespace(buf.currChar())) { + while (buf.cursor() < buf.length() && !isViAlphaNum(buf.currChar()) && !isWhitespace(buf.currChar())) { buf.move(1); } } @@ -1375,9 +1426,7 @@ protected boolean viForwardWord() { return true; } int nl = buf.currChar() == '\n' ? 1 : 0; - while (buf.cursor() < buf.length() - && nl < 2 - && isWhitespace(buf.currChar())) { + while (buf.cursor() < buf.length() && nl < 2 && isWhitespace(buf.currChar())) { buf.move(1); nl += buf.currChar() == '\n' ? 1 : 0; } @@ -1397,9 +1446,7 @@ protected boolean viForwardBlankWord() { return true; } int nl = buf.currChar() == '\n' ? 1 : 0; - while (buf.cursor() < buf.length() - && nl < 2 - && isWhitespace(buf.currChar())) { + while (buf.cursor() < buf.length() && nl < 2 && isWhitespace(buf.currChar())) { buf.move(1); nl += buf.currChar() == '\n' ? 1 : 0; } @@ -1451,7 +1498,9 @@ protected boolean viForwardWordEnd() { } } else { buf.move(1); - while (buf.cursor() < buf.length() && !isViAlphaNum(buf.nextChar()) && !isWhitespace(buf.nextChar())) { + while (buf.cursor() < buf.length() + && !isViAlphaNum(buf.nextChar()) + && !isWhitespace(buf.nextChar())) { buf.move(1); } } @@ -1720,9 +1769,7 @@ protected boolean capitalizeWord() { buf.move(1); } while (buf.cursor() < buf.length() && isWord(buf.currChar())) { - buf.currChar(first - ? Character.toUpperCase(buf.currChar()) - : Character.toLowerCase(buf.currChar())); + buf.currChar(first ? Character.toUpperCase(buf.currChar()) : Character.toLowerCase(buf.currChar())); buf.move(1); first = false; } @@ -1810,7 +1857,8 @@ protected boolean transposeWords() { sta1--; } end1 = sta1; - while (end1 < lend && !isDelimiter(buf.atChar(++end1))); + while (end1 < lend && !isDelimiter(buf.atChar(++end1))) + ; if (neg) { end2 = sta1 - 1; while (end2 > lstart && isDelimiter(buf.atChar(end2 - 1))) { @@ -1819,9 +1867,11 @@ protected boolean transposeWords() { if (end2 < lstart) { // No word before, use the word after sta2 = end1; - while (isDelimiter(buf.atChar(++sta2))); + while (isDelimiter(buf.atChar(++sta2))) + ; end2 = sta2; - while (end2 < lend && !isDelimiter(buf.atChar(++end2))); + while (end2 < lend && !isDelimiter(buf.atChar(++end2))) + ; } else { sta2 = end2; while (sta2 > lstart && !isDelimiter(buf.atChar(sta2 - 1))) { @@ -1830,7 +1880,8 @@ protected boolean transposeWords() { } } else { sta2 = end1; - while (sta2 < lend && isDelimiter(buf.atChar(++sta2))); + while (sta2 < lend && isDelimiter(buf.atChar(++sta2))) + ; if (sta2 == lend) { // No word after, use the word before end2 = sta1; @@ -1843,19 +1894,24 @@ protected boolean transposeWords() { } } else { end2 = sta2; - while (end2 < lend && !isDelimiter(buf.atChar(++end2))) ; + while (end2 < lend && !isDelimiter(buf.atChar(++end2))) + ; } } if (sta1 < sta2) { - String res = buf.substring(0, sta1) + buf.substring(sta2, end2) - + buf.substring(end1, sta2) + buf.substring(sta1, end1) + String res = buf.substring(0, sta1) + + buf.substring(sta2, end2) + + buf.substring(end1, sta2) + + buf.substring(sta1, end1) + buf.substring(end2); buf.clear(); buf.write(res); buf.cursor(neg ? end1 : end2); } else { - String res = buf.substring(0, sta2) + buf.substring(sta1, end1) - + buf.substring(end2, sta1) + buf.substring(sta2, end2) + String res = buf.substring(0, sta2) + + buf.substring(sta1, end1) + + buf.substring(end2, sta1) + + buf.substring(sta2, end2) + buf.substring(end1); buf.clear(); buf.write(res); @@ -1988,11 +2044,11 @@ private boolean vifindchar(boolean repeat) { while (count-- > 0) { do { buf.move(findDir); - } while (buf.cursor() > 0 && buf.cursor() < buf.length() + } while (buf.cursor() > 0 + && buf.cursor() < buf.length() && buf.currChar() != findChar && buf.currChar() != '\n'); - if (buf.cursor() <= 0 || buf.cursor() >= buf.length() - || buf.currChar() == '\n') { + if (buf.cursor() <= 0 || buf.cursor() >= buf.length() || buf.currChar() == '\n') { buf.cursor(cursor); return false; } @@ -2211,18 +2267,17 @@ protected boolean undefinedKey() { * character or if there was no matching bracket. */ protected boolean doViMatchBracket() { - int pos = buf.cursor(); + int pos = buf.cursor(); if (pos == buf.length()) { return false; } - int type = getBracketType(buf.atChar(pos)); - int move = (type < 0) ? -1 : 1; - int count = 1; + int type = getBracketType(buf.atChar(pos)); + int move = (type < 0) ? -1 : 1; + int count = 1; - if (type == 0) - return false; + if (type == 0) return false; while (count > 0) { pos += move; @@ -2235,8 +2290,7 @@ protected boolean doViMatchBracket() { int curType = getBracketType(buf.atChar(pos)); if (curType == type) { ++count; - } - else if (curType == -type) { + } else if (curType == -type) { --count; } } @@ -2245,8 +2299,7 @@ else if (curType == -type) { * Slight adjustment for delete-to, yank-to, change-to to ensure * that the matching paren is consumed */ - if (move > 0 && isInViMoveOperation()) - ++pos; + if (move > 0 && isInViMoveOperation()) ++pos; buf.cursor(pos); return true; @@ -2259,14 +2312,20 @@ else if (curType == -type) { * @return 1 is square, 2 curly, 3 parent, or zero for none. The value * will be negated if it is the closing form of the bracket. */ - protected int getBracketType (int ch) { + protected int getBracketType(int ch) { switch (ch) { - case '[': return 1; - case ']': return -1; - case '{': return 2; - case '}': return -2; - case '(': return 3; - case ')': return -3; + case '[': + return 1; + case ']': + return -1; + case '{': + return 2; + case '}': + return -2; + case '(': + return 3; + case ')': + return -3; default: return 0; } @@ -2331,7 +2390,7 @@ protected boolean sendBreak() { buf.clear(); println(); redrawLine(); -// state = State.INTERRUPT; + // state = State.INTERRUPT; return false; } return true; @@ -2378,6 +2437,10 @@ protected boolean negArgument() { protected boolean digitArgument() { String s = getLastBinding(); repeatCount = (repeatCount * 10) + s.charAt(s.length() - 1) - '0'; + int maxRepeatCount = getInt(MAX_REPEAT_COUNT, DEFAULT_MAX_REPEAT_COUNT); + if (repeatCount > maxRepeatCount) { + throw new IllegalArgumentException("digit argument should be less than " + maxRepeatCount); + } isArgDigit = true; return true; } @@ -2438,10 +2501,12 @@ protected boolean viYankTo() { protected boolean viYankWholeLine() { int s, e; int p = buf.cursor(); - while (buf.move(-1) == -1 && buf.prevChar() != '\n') ; + while (buf.move(-1) == -1 && buf.prevChar() != '\n') + ; s = buf.cursor(); for (int i = 0; i < repeatCount; i++) { - while (buf.move(1) == 1 && buf.prevChar() != '\n') ; + while (buf.move(1) == 1 && buf.prevChar() != '\n') + ; } e = buf.cursor(); yankBuffer = buf.substring(s, e); @@ -2554,15 +2619,19 @@ protected boolean historyIncrementalSearchBackward() { return doSearchHistory(true); } - static class Pair { - final U u; final V v; + static class Pair { + final U u; + final V v; + public Pair(U u, V v) { this.u = u; this.v = v; } + public U getU() { return u; } + public V getV() { return v; } @@ -2575,7 +2644,8 @@ protected boolean doSearchHistory(boolean backward) { KeyMap terminators = new KeyMap<>(); getString(SEARCH_TERMINATORS, DEFAULT_SEARCH_TERMINATORS) - .codePoints().forEach(c -> bind(terminators, ACCEPT_LINE, new String(Character.toChars(c)))); + .codePoints() + .forEach(c -> bind(terminators, ACCEPT_LINE, new String(Character.toChars(c)))); Buffer originalBuffer = buf.copy(); searchIndex = -1; @@ -2583,8 +2653,8 @@ protected boolean doSearchHistory(boolean backward) { searchBackward = backward; searchFailing = false; post = () -> new AttributedString((searchFailing ? "failing" + " " : "") - + (searchBackward ? "bck-i-search" : "fwd-i-search") - + ": " + searchTerm + "_"); + + (searchBackward ? "bck-i-search" : "fwd-i-search") + + ": " + searchTerm + "_"); redisplay(); try { @@ -2630,8 +2700,9 @@ protected boolean doSearchHistory(boolean backward) { searchFailing = false; } else { boolean caseInsensitive = isSet(Option.CASE_INSENSITIVE_SEARCH); - Pattern pat = Pattern.compile(pattern, caseInsensitive ? Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE - : Pattern.UNICODE_CASE); + Pattern pat = Pattern.compile( + pattern, + caseInsensitive ? Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE : Pattern.UNICODE_CASE); Pair pair = null; if (searchBackward) { boolean nextOnly = next; @@ -2641,7 +2712,11 @@ protected boolean doSearchHistory(boolean backward) { .orElse(null); if (pair == null) { pair = StreamSupport.stream( - Spliterators.spliteratorUnknownSize(history.reverseIterator(searchIndex < 0 ? history.last() : searchIndex - 1), Spliterator.ORDERED), false) + Spliterators.spliteratorUnknownSize( + history.reverseIterator( + searchIndex < 0 ? history.last() : searchIndex - 1), + Spliterator.ORDERED), + false) .flatMap(e -> matches(pat, e.line(), e.index()).stream()) .findFirst() .orElse(null); @@ -2654,7 +2729,11 @@ protected boolean doSearchHistory(boolean backward) { .orElse(null); if (pair == null) { pair = StreamSupport.stream( - Spliterators.spliteratorUnknownSize(history.iterator((searchIndex < 0 ? history.last() : searchIndex) + 1), Spliterator.ORDERED), false) + Spliterators.spliteratorUnknownSize( + history.iterator( + (searchIndex < 0 ? history.last() : searchIndex) + 1), + Spliterator.ORDERED), + false) .flatMap(e -> matches(pat, e.line(), e.index()).stream()) .findFirst() .orElse(null); @@ -2714,7 +2793,10 @@ private String doGetSearchPattern() { sb.append("\\E"); inQuote = false; } - sb.append("[").append(Character.toLowerCase(c)).append(Character.toUpperCase(c)).append("]"); + sb.append("[") + .append(Character.toLowerCase(c)) + .append(Character.toUpperCase(c)) + .append("]"); } else { if (!inQuote) { sb.append("\\Q"); @@ -2742,8 +2824,7 @@ private void pushBackBinding(boolean skip) { } protected boolean historySearchForward() { - if (historyBuffer == null || buf.length() == 0 - || !buf.toString().equals(history.current())) { + if (historyBuffer == null || buf.length() == 0 || !buf.toString().equals(history.current())) { historyBuffer = buf.copy(); searchBuffer = getFirstWord(); } @@ -2791,8 +2872,7 @@ private CharSequence getFirstWord() { } protected boolean historySearchBackward() { - if (historyBuffer == null || buf.length() == 0 - || !buf.toString().equals(history.current())) { + if (historyBuffer == null || buf.length() == 0 || !buf.toString().equals(history.current())) { historyBuffer = buf.copy(); searchBuffer = getFirstWord(); } @@ -2984,7 +3064,7 @@ protected boolean acceptLine() { } void indention(int nb, StringBuilder sb) { - int indent = getInt(INDENTATION, DEFAULT_INDENTATION)*nb; + int indent = getInt(INDENTATION, DEFAULT_INDENTATION) * nb; for (int i = 0; i < indent; i++) { sb.append(' '); } @@ -3017,7 +3097,6 @@ protected boolean overwriteMode() { return true; } - // // History Control // @@ -3108,13 +3187,11 @@ protected boolean downHistory() { } protected boolean viUpLineOrHistory() { - return upLine() - || upHistory() && viFirstNonBlank(); + return upLine() || upHistory() && viFirstNonBlank(); } protected boolean viDownLineOrHistory() { - return downLine() - || downHistory() && viFirstNonBlank(); + return downLine() || downHistory() && viFirstNonBlank(); } protected boolean upLine() { @@ -3175,8 +3252,7 @@ protected boolean viChangeWholeLine() { } protected boolean viChangeEol() { - return viChange(buf.cursor(), buf.length()) - && setKeyMap(VIINS); + return viChange(buf.cursor(), buf.length()) && setKeyMap(VIINS); } protected boolean viKillEol() { @@ -3199,7 +3275,8 @@ protected boolean quotedInsert() { protected boolean viJoin() { if (buf.down()) { - while (buf.move(-1) == -1 && buf.prevChar() != '\n') ; + while (buf.move(-1) == -1 && buf.prevChar() != '\n') + ; buf.backspace(); buf.write(' '); buf.move(-1); @@ -3253,14 +3330,16 @@ protected boolean viEndOfLine() { protected boolean beginningOfLine() { while (count-- > 0) { - while (buf.move(-1) == -1 && buf.prevChar() != '\n') ; + while (buf.move(-1) == -1 && buf.prevChar() != '\n') + ; } return true; } protected boolean endOfLine() { while (count-- > 0) { - while (buf.move(1) == 1 && buf.currChar() != '\n') ; + while (buf.move(1) == 1 && buf.currChar() != '\n') + ; } return true; } @@ -3384,7 +3463,7 @@ protected boolean doViDeleteOrChange(int startPos, int endPos, boolean isChange) // what is really happening is that if we are in "move-mode" then the // cursor can't be moved off the end of the line, but in "edit-mode" it // is ok, but I have no easy way of knowing which mode we are in. - if (! isChange && startPos > 0 && startPos == buf.length()) { + if (!isChange && startPos > 0 && startPos == buf.length()) { buf.move(-1); } return true; @@ -3424,14 +3503,16 @@ protected boolean viYankTo(int startPos, int endPos) { } protected boolean viOpenLineAbove() { - while (buf.move(-1) == -1 && buf.prevChar() != '\n') ; + while (buf.move(-1) == -1 && buf.prevChar() != '\n') + ; buf.write('\n'); buf.move(-1); return setKeyMap(VIINS); } protected boolean viOpenLineBelow() { - while (buf.move(1) == 1 && buf.currChar() != '\n') ; + while (buf.move(1) == 1 && buf.currChar() != '\n') + ; buf.write('\n'); return setKeyMap(VIINS); } @@ -3443,11 +3524,12 @@ protected boolean viOpenLineBelow() { */ protected boolean viPutAfter() { if (yankBuffer.indexOf('\n') >= 0) { - while (buf.move(1) == 1 && buf.currChar() != '\n'); + while (buf.move(1) == 1 && buf.currChar() != '\n') + ; buf.move(1); putString(yankBuffer); - buf.move(- yankBuffer.length()); - } else if (yankBuffer.length () != 0) { + buf.move(-yankBuffer.length()); + } else if (yankBuffer.length() != 0) { if (buf.cursor() < buf.length()) { buf.move(1); } @@ -3461,10 +3543,11 @@ protected boolean viPutAfter() { protected boolean viPutBefore() { if (yankBuffer.indexOf('\n') >= 0) { - while (buf.move(-1) == -1 && buf.prevChar() != '\n'); + while (buf.move(-1) == -1 && buf.prevChar() != '\n') + ; putString(yankBuffer); - buf.move(- yankBuffer.length()); - } else if (yankBuffer.length () != 0) { + buf.move(-yankBuffer.length()); + } else if (yankBuffer.length() != 0) { if (buf.cursor() > 0) { buf.move(-1); } @@ -3681,7 +3764,7 @@ protected Map builtinWidgets() { addBuiltinWidget(widgets, MENU_EXPAND_OR_COMPLETE, this::menuExpandOrComplete); addBuiltinWidget(widgets, NEG_ARGUMENT, this::negArgument); addBuiltinWidget(widgets, OVERWRITE_MODE, this::overwriteMode); -// addBuiltinWidget(widgets, QUIT, this::quit); + // addBuiltinWidget(widgets, QUIT, this::quit); addBuiltinWidget(widgets, QUOTED_INSERT, this::quotedInsert); addBuiltinWidget(widgets, REDISPLAY, this::redisplay); addBuiltinWidget(widgets, REDRAW_LINE, this::redrawLine); @@ -3774,6 +3857,7 @@ private Widget namedWidget(String name, Widget widget) { public String toString() { return name; } + @Override public boolean apply() { return widget.apply(); @@ -3797,14 +3881,11 @@ protected void redisplay(boolean flush) { Status status = Status.getStatus(terminal, false); if (status != null) { - if (terminal.getType().startsWith(AbstractWindowsTerminal.TYPE_WINDOWS)) { - status.resize(); - } status.redraw(); } if (size.getRows() > 0 && size.getRows() < MIN_ROWS) { - AttributedStringBuilder sb = new AttributedStringBuilder().tabs(TAB_WIDTH); + AttributedStringBuilder sb = new AttributedStringBuilder().tabs(getTabWidth()); sb.append(prompt); concat(getHighlightedBuffer(buf.toString()).columnSplitLength(Integer.MAX_VALUE), sb); @@ -3877,14 +3958,15 @@ protected void redisplay(boolean flush) { int cursorNewLinesId = -1; int cursorColPos = -1; if (size.getColumns() > 0) { - AttributedStringBuilder sb = new AttributedStringBuilder().tabs(TAB_WIDTH); + AttributedStringBuilder sb = new AttributedStringBuilder().tabs(getTabWidth()); sb.append(prompt); String buffer = buf.upToCursor(); if (maskingCallback != null) { buffer = maskingCallback.display(buffer); } sb.append(insertSecondaryPrompts(new AttributedString(buffer), secondaryPrompts, false)); - List promptLines = sb.columnSplitLength(size.getColumns(), false, display.delayLineWrap()); + List promptLines = + sb.columnSplitLength(size.getColumns(), false, display.delayLineWrap()); if (!promptLines.isEmpty()) { cursorNewLinesId = promptLines.size() - 1; cursorColPos = promptLines.get(promptLines.size() - 1).columnLength(); @@ -3904,7 +3986,7 @@ protected void redisplay(boolean flush) { int lineId = newLines.size() - displaySize + 1; int endId = displaySize; int startId = 1; - if (lineId > cursorNewLinesId) { + if (lineId > cursorNewLinesId) { lineId = cursorNewLinesId; endId = displaySize - 1; startId = 0; @@ -3949,10 +4031,9 @@ private String matchPreviousCommand(String buffer) { } History history = getHistory(); StringBuilder sb = new StringBuilder(); - for (char c: buffer.replace("\\", "\\\\").toCharArray()) { - if (c == '(' || c == ')' || c == '[' || c == ']' || c == '{' || c == '}' || c == '^' || c == '*' - || c == '$' || c == '.' || c == '?' || c == '+' || c == '|' || c == '<' || c == '>' || c == '!' - || c == '-') { + for (char c : buffer.replace("\\", "\\\\").toCharArray()) { + if (c == '(' || c == ')' || c == '[' || c == ']' || c == '{' || c == '}' || c == '^' || c == '*' || c == '$' + || c == '.' || c == '?' || c == '+' || c == '|' || c == '<' || c == '>' || c == '!' || c == '-') { sb.append('\\'); } sb.append(c); @@ -3984,7 +4065,7 @@ public AttributedString getDisplayedBufferWithPrompts(List sec AttributedString attBuf = getHighlightedBuffer(buf.toString()); AttributedString tNewBuf = insertSecondaryPrompts(attBuf, secondaryPrompts); - AttributedStringBuilder full = new AttributedStringBuilder().tabs(TAB_WIDTH); + AttributedStringBuilder full = new AttributedStringBuilder().tabs(getTabWidth()); full.append(prompt); full.append(tNewBuf); if (doAutosuggestion && !isTerminalDumb()) { @@ -4040,15 +4121,15 @@ private AttributedString getHighlightedBuffer(String buffer) { if (maskingCallback != null) { buffer = maskingCallback.display(buffer); } - if (highlighter != null && !isSet(Option.DISABLE_HIGHLIGHTER) + if (highlighter != null + && !isSet(Option.DISABLE_HIGHLIGHTER) && buffer.length() < getInt(FEATURES_MAX_BUFFER_SIZE, DEFAULT_FEATURES_MAX_BUFFER_SIZE)) { return highlighter.highlight(this, buffer); } return new AttributedString(buffer); } - private AttributedString expandPromptPattern(String pattern, int padToWidth, - String message, int line) { + private AttributedString expandPromptPattern(String pattern, int padToWidth, String message, int line) { ArrayList parts = new ArrayList<>(); boolean isHidden = false; int padPartIndex = -1; @@ -4065,7 +4146,8 @@ private AttributedString expandPromptPattern(String pattern, int padToWidth, if (ch == '%' && i < plen) { int count = 0; boolean countSeen = false; - decode: while (true) { + decode: + while (true) { ch = pattern.charAt(i++); switch (ch) { case '{': @@ -4073,7 +4155,7 @@ private AttributedString expandPromptPattern(String pattern, int padToWidth, String str = sb.toString(); AttributedString astr; if (!isHidden) { - astr = AttributedString.fromAnsi(str); + astr = fromAnsi(str); cols += astr.columnLength(); } else { astr = new AttributedString(str, AttributedStyle.HIDDEN); @@ -4096,12 +4178,10 @@ private AttributedString expandPromptPattern(String pattern, int padToWidth, sb.append(getInt(LINE_OFFSET, 0) + line); break decode; case 'M': - if (message != null) - sb.append(message); + if (message != null) sb.append(message); break decode; case 'P': - if (countSeen && count >= 0) - padToWidth = count; + if (countSeen && count >= 0) padToWidth = count; if (i < plen) { padChar = pattern.charAt(i++); // FIXME check surrogate @@ -4140,25 +4220,28 @@ private AttributedString expandPromptPattern(String pattern, int padToWidth, break decode; } } - } else - sb.append(ch); + } else sb.append(ch); } if (padToWidth > cols && padToWidth > 0) { int padCharCols = WCWidth.wcwidth(padChar); int padCount = (padToWidth - cols) / padCharCols; sb = padPartString; - while (--padCount >= 0) - sb.insert(padPos, (char) padChar); // FIXME if wide - parts.set(padPartIndex, AttributedString.fromAnsi(sb.toString())); + while (--padCount >= 0) sb.insert(padPos, (char) padChar); // FIXME if wide + parts.set(padPartIndex, fromAnsi(sb.toString())); } return AttributedString.join(null, parts); } + private AttributedString fromAnsi(String str) { + return AttributedString.fromAnsi(str, Collections.singletonList(0), alternateIn, alternateOut); + } + private AttributedString insertSecondaryPrompts(AttributedString str, List prompts) { return insertSecondaryPrompts(str, prompts, true); } - private AttributedString insertSecondaryPrompts(AttributedString strAtt, List prompts, boolean computePrompts) { + private AttributedString insertSecondaryPrompts( + AttributedString strAtt, List prompts, boolean computePrompts) { Objects.requireNonNull(prompts); List lines = strAtt.columnSplitLength(Integer.MAX_VALUE); AttributedStringBuilder sb = new AttributedStringBuilder(); @@ -4171,7 +4254,9 @@ private AttributedString insertSecondaryPrompts(AttributedString strAtt, List size.getColumns() || prompt.contains('\n')) { - width = new TerminalLine(prompt.toString(), 0, size.getColumns()).getEndLine().length(); + width = new TerminalLine(prompt.toString(), 0, size.getColumns()) + .getEndLine() + .length(); } for (int line = 0; line < lines.size() - 1; line++) { AttributedString prompt; @@ -4227,11 +4312,9 @@ private AttributedString insertSecondaryPrompts(AttributedString strAtt, List 0 - && line.charAt(line.length() - 1) == '\n'; + boolean endsWithNl = line.length() > 0 && line.charAt(line.length() - 1) == '\n'; // columnLength counts -1 for the final newline; adjust for that - int nb = size.getColumns() - width - - (line.columnLength() + (endsWithNl ? 1 : 0)); + int nb = size.getColumns() - width - (line.columnLength() + (endsWithNl ? 1 : 0)); if (nb >= 3) { AttributedStringBuilder sb = new AttributedStringBuilder(size.getColumns()); sb.append(line, 0, endsWithNl ? line.length() - 1 : line.length()); @@ -4253,8 +4336,8 @@ private AttributedString addRightPrompt(AttributedString prompt, AttributedStrin protected boolean insertTab() { return isSet(Option.INSERT_TAB) - && getLastBinding().equals("\t") - && buf.toString().matches("(^|[\\s\\S]*\n)[\r\n\t ]*"); + && getLastBinding().equals("\t") + && buf.toString().matches("(^|[\\s\\S]*\n)[\r\n\t ]*"); } protected boolean expandHistory() { @@ -4465,7 +4548,8 @@ else if (isSet(Option.RECOGNIZE_EXACT)) { if (op != null) { String chars = getString(REMOVE_SUFFIX_CHARS, DEFAULT_REMOVE_SUFFIX_CHARS); String ref = op instanceof Reference ? ((Reference) op).name() : null; - if (SELF_INSERT.equals(ref) && chars.indexOf(getLastBinding().charAt(0)) >= 0 + if (SELF_INSERT.equals(ref) + && chars.indexOf(getLastBinding().charAt(0)) >= 0 || ACCEPT_LINE.equals(ref)) { buf.backspace(completion.suffix().length()); if (getLastBinding().charAt(0) != ' ') { @@ -4533,27 +4617,35 @@ protected static CompletingParsedLine wrap(ParsedLine line) { public String word() { return line.word(); } + public int wordCursor() { return line.wordCursor(); } + public int wordIndex() { return line.wordIndex(); } + public List words() { return line.words(); } + public String line() { return line.line(); } + public int cursor() { return line.cursor(); } + public CharSequence escape(CharSequence candidate, boolean complete) { return candidate; } + public int rawWordCursor() { return wordCursor(); } + public int rawWordLength() { return word().length(); } @@ -4564,8 +4656,7 @@ public int rawWordLength() { protected Comparator getCandidateComparator(boolean caseInsensitive, String word) { String wdi = caseInsensitive ? word.toLowerCase() : word; ToIntFunction wordDistance = w -> ReaderUtils.distance(wdi, caseInsensitive ? w.toLowerCase() : w); - return Comparator - .comparing(Candidate::value, Comparator.comparingInt(wordDistance)) + return Comparator.comparing(Candidate::value, Comparator.comparingInt(wordDistance)) .thenComparing(Comparator.naturalOrder()); } @@ -4577,9 +4668,10 @@ protected String getOriginalGroupName() { return getString(ORIGINAL_GROUP_NAME, DEFAULT_ORIGINAL_GROUP_NAME); } - protected Comparator getGroupComparator() { - return Comparator.comparingInt(s -> getOthersGroupName().equals(s) ? 1 : getOriginalGroupName().equals(s) ? -1 : 0) + return Comparator.comparingInt(s -> getOthersGroupName().equals(s) + ? 1 + : getOriginalGroupName().equals(s) ? -1 : 0) .thenComparing(String::toLowerCase, Comparator.naturalOrder()); } @@ -4600,11 +4692,9 @@ private void mergeCandidates(List possible) { // the same description candidates.sort(Comparator.comparing(Candidate::value)); Candidate first = candidates.get(0); - String disp = candidates.stream() - .map(Candidate::displ) - .collect(Collectors.joining(" ")); - possible.add(new Candidate(first.value(), disp, first.group(), - first.descr(), first.suffix(), null, first.complete())); + String disp = candidates.stream().map(Candidate::displ).collect(Collectors.joining(" ")); + possible.add(new Candidate( + first.value(), disp, first.group(), first.descr(), first.suffix(), null, first.complete())); } } } @@ -4636,8 +4726,10 @@ private int visibleDisplayRows() { } private int promptLines() { - AttributedString text = insertSecondaryPrompts(AttributedStringBuilder.append(prompt, buf.toString()), new ArrayList<>()); - return text.columnSplitLength(size.getColumns(), false, display.delayLineWrap()).size(); + AttributedString text = + insertSecondaryPrompts(AttributedStringBuilder.append(prompt, buf.toString()), new ArrayList<>()); + return text.columnSplitLength(size.getColumns(), false, display.delayLineWrap()) + .size(); } private class MenuSupport implements Supplier { @@ -4651,7 +4743,8 @@ private class MenuSupport implements Supplier { int columns; String completed; - public MenuSupport(List original, String completed, BiFunction escaper) { + public MenuSupport( + List original, String completed, BiFunction escaper) { this.possible = new ArrayList<>(); this.escaper = escaper; this.selection = -1; @@ -4714,7 +4807,7 @@ private void minor(int step) { if (selection - row + axis > options) { // selection is the last row/column // so there are fewer options than other rows - axis = options%axis; + axis = options % axis; } selection = selection - row + ((axis + row + step) % axis); update(); @@ -4772,7 +4865,9 @@ private void update() { AttributedString post = pr.post; if (post.length() > 0 && post.charAt(post.length() - 1) != '\n') { post = new AttributedStringBuilder(post.length() + 1) - .append(post).append("\n").toAttributedString(); + .append(post) + .append("\n") + .toAttributedString(); } List lines = post.columnSplitLength(size.getColumns(), true, display.delayLineWrap()); List sub = new ArrayList<>(lines.subList(topLine, topLine + displayed)); @@ -4785,7 +4880,8 @@ private void update() { .append(" of ") .append(Integer.toString(lines.size())) .append("\n") - .style(AttributedStyle.DEFAULT).toAttributedString()); + .style(AttributedStyle.DEFAULT) + .toAttributedString()); computed = AttributedString.join(AttributedString.EMPTY, sub); } else { computed = pr.post; @@ -4798,10 +4894,10 @@ private void update() { public AttributedString get() { return computed; } - } - protected boolean doMenu(List original, String completed, BiFunction escaper) { + protected boolean doMenu( + List original, String completed, BiFunction escaper) { // Reorder candidates according to display order final List possible = new ArrayList<>(); boolean caseInsensitive = isSet(Option.CASE_INSENSITIVE); @@ -4854,7 +4950,7 @@ protected boolean doMenu(List original, String completed, BiFunction< if (completion.suffix() != null) { String chars = getString(REMOVE_SUFFIX_CHARS, DEFAULT_REMOVE_SUFFIX_CHARS); if (SELF_INSERT.equals(ref) - && chars.indexOf(getLastBinding().charAt(0)) >= 0 + && chars.indexOf(getLastBinding().charAt(0)) >= 0 || BACKWARD_DELETE_CHAR.equals(ref)) { buf.backspace(completion.suffix().length()); } @@ -4866,8 +4962,8 @@ && getLastBinding().charAt(0) != ' ' } if (!ACCEPT_LINE.equals(ref) && !(SELF_INSERT.equals(ref) - && completion.suffix() != null - && completion.suffix().startsWith(getLastBinding()))) { + && completion.suffix() != null + && completion.suffix().startsWith(getLastBinding()))) { pushBackBinding(true); } post = null; @@ -4888,29 +4984,40 @@ protected boolean clearChoices() { return doList(new ArrayList<>(), "", false, null, false); } - protected boolean doList(List possible - , String completed, boolean runLoop, BiFunction escaper) { + protected boolean doList( + List possible, + String completed, + boolean runLoop, + BiFunction escaper) { return doList(possible, completed, runLoop, escaper, false); } - protected boolean doList(List possible - , String completed - , boolean runLoop, BiFunction escaper, boolean forSuggestion) { + protected boolean doList( + List possible, + String completed, + boolean runLoop, + BiFunction escaper, + boolean forSuggestion) { // If we list only and if there's a big // number of items, we should ask the user // for confirmation, display the list // and redraw the line at the bottom mergeCandidates(possible); - AttributedString text = insertSecondaryPrompts(AttributedStringBuilder.append(prompt, buf.toString()), new ArrayList<>()); - int promptLines = text.columnSplitLength(size.getColumns(), false, display.delayLineWrap()).size(); + AttributedString text = + insertSecondaryPrompts(AttributedStringBuilder.append(prompt, buf.toString()), new ArrayList<>()); + int promptLines = text.columnSplitLength(size.getColumns(), false, display.delayLineWrap()) + .size(); PostResult postResult = computePost(possible, null, null, completed); int lines = postResult.lines; int listMax = getInt(LIST_MAX, DEFAULT_LIST_MAX); - if (listMax > 0 && possible.size() >= listMax - || lines >= size.getRows() - promptLines) { + int possibleSize = possible.size(); + if (possibleSize == 0 || size.getRows() == 0) { + return false; + } + if (listMax > 0 && possibleSize >= listMax || lines >= size.getRows() - promptLines) { if (!forSuggestion) { // prompt - post = () -> new AttributedString(getAppName() + ": do you wish to see all " + possible.size() + post = () -> new AttributedString(getAppName() + ": do you wish to see all " + possibleSize + " possibilities (" + lines + " lines)?"); redisplay(true); int c = readCharacter(); @@ -4930,8 +5037,7 @@ protected boolean doList(List possible String current = completed + sb.toString(); List cands; if (sb.length() > 0) { - completionMatcher.compile(options, false, new CompletingWord(current), caseInsensitive, 0 - , null); + completionMatcher.compile(options, false, new CompletingWord(current), caseInsensitive, 0, null); cands = completionMatcher.matches(possible).stream() .sorted(getCandidateComparator(caseInsensitive, current)) .collect(Collectors.toList()); @@ -4944,8 +5050,10 @@ protected boolean doList(List possible candidateStartPosition = candidateStartPosition(cands); } post = () -> { - AttributedString t = insertSecondaryPrompts(AttributedStringBuilder.append(prompt, buf.toString()), new ArrayList<>()); - int pl = t.columnSplitLength(size.getColumns(), false, display.delayLineWrap()).size(); + AttributedString t = insertSecondaryPrompts( + AttributedStringBuilder.append(prompt, buf.toString()), new ArrayList<>()); + int pl = t.columnSplitLength(size.getColumns(), false, display.delayLineWrap()) + .size(); PostResult pr = computePost(cands, null, null, current); if (pr.lines >= size.getRows() - pl) { post = null; @@ -4954,7 +5062,8 @@ protected boolean doList(List possible redisplay(false); buf.cursor(oldCursor); println(); - List ls = pr.post.columnSplitLength(size.getColumns(), false, display.delayLineWrap()); + List ls = + pr.post.columnSplitLength(size.getColumns(), false, display.delayLineWrap()); Display d = new Display(terminal, false); d.resize(size.getRows(), size.getColumns()); d.update(ls, -1); @@ -5074,25 +5183,41 @@ public PostResult(AttributedString post, int lines, int selectedLine) { } } - protected PostResult computePost(List possible, Candidate selection, List ordered, String completed) { - return computePost(possible, selection, ordered, completed, display::wcwidth, size.getColumns(), isSet(Option.AUTO_GROUP), isSet(Option.GROUP), isSet(Option.LIST_ROWS_FIRST)); - } - - protected PostResult computePost(List possible, Candidate selection, List ordered, String completed, Function wcwidth, int width, boolean autoGroup, boolean groupName, boolean rowsFirst) { + protected PostResult computePost( + List possible, Candidate selection, List ordered, String completed) { + return computePost( + possible, + selection, + ordered, + completed, + display::wcwidth, + size.getColumns(), + isSet(Option.AUTO_GROUP), + isSet(Option.GROUP), + isSet(Option.LIST_ROWS_FIRST)); + } + + protected PostResult computePost( + List possible, + Candidate selection, + List ordered, + String completed, + Function wcwidth, + int width, + boolean autoGroup, + boolean groupName, + boolean rowsFirst) { List strings = new ArrayList<>(); - boolean customOrder = possible.stream().anyMatch(c -> c.sort() != 0); if (groupName) { Comparator groupComparator = getGroupComparator(); - Map> sorted; - sorted = groupComparator != null - ? new TreeMap<>(groupComparator) - : new LinkedHashMap<>(); + Map> sorted; + sorted = groupComparator != null ? new TreeMap<>(groupComparator) : new LinkedHashMap<>(); for (Candidate cand : possible) { String group = cand.group(); - sorted.computeIfAbsent(group != null ? group : "", s -> new LinkedHashMap<>()) - .put((customOrder ? cand.sort() : cand.value()), cand); + sorted.computeIfAbsent(group != null ? group : "", s -> new ArrayList<>()) + .add(cand); } - for (Map.Entry> entry : sorted.entrySet()) { + for (Map.Entry> entry : sorted.entrySet()) { String group = entry.getKey(); if (group.isEmpty() && sorted.size() > 1) { group = getOthersGroupName(); @@ -5100,27 +5225,30 @@ protected PostResult computePost(List possible, Candidate selection, if (!group.isEmpty() && autoGroup) { strings.add(group); } - strings.add(new ArrayList<>(entry.getValue().values())); + List candidates = entry.getValue(); + Collections.sort(candidates); + strings.add(candidates); if (ordered != null) { - ordered.addAll(entry.getValue().values()); + ordered.addAll(candidates); } } } else { Set groups = new LinkedHashSet<>(); - TreeMap sorted = new TreeMap<>(); + List sorted = new ArrayList<>(); for (Candidate cand : possible) { String group = cand.group(); if (group != null) { groups.add(group); } - sorted.put((customOrder ? cand.sort() : cand.value()), cand); + sorted.add(cand); } if (autoGroup) { strings.addAll(groups); } - strings.add(new ArrayList<>(sorted.values())); + Collections.sort(sorted); + strings.add(sorted); if (ordered != null) { - ordered.addAll(sorted.values()); + ordered.addAll(sorted); } } return toColumns(strings, selection, completed, wcwidth, width, rowsFirst); @@ -5163,12 +5291,15 @@ public String getEndLine() { } private int candidateStartPosition(List cands) { - List values = cands.stream().map(c -> AttributedString.stripAnsi(c.displ())) - .filter(c -> !c.matches("\\w+") && c.length() > 1).collect(Collectors.toList()); + List values = cands.stream() + .map(c -> AttributedString.stripAnsi(c.displ())) + .filter(c -> !c.matches("\\w+") && c.length() > 1) + .collect(Collectors.toList()); Set notDelimiters = new HashSet<>(); - values.forEach(v -> v.substring(0, v.length() - 1).chars() + values.forEach(v -> v.substring(0, v.length() - 1) + .chars() .filter(c -> !Character.isDigit(c) && !Character.isAlphabetic(c)) - .forEach(c -> notDelimiters.add(Character.toString((char)c)))); + .forEach(c -> notDelimiters.add(Character.toString((char) c)))); int width = size.getColumns(); int promptLength = prompt != null ? prompt.length() : 0; if (promptLength > 0) { @@ -5179,8 +5310,7 @@ private int candidateStartPosition(List cands) { int out = tl.getStartPos(); String buffer = tl.getEndLine(); for (int i = buffer.length(); i > 0; i--) { - if (buffer.substring(0, i).matches(".*\\W") - && !notDelimiters.contains(buffer.substring(i - 1, i))) { + if (buffer.substring(0, i).matches(".*\\W") && !notDelimiters.contains(buffer.substring(i - 1, i))) { out += i; break; } @@ -5189,7 +5319,13 @@ private int candidateStartPosition(List cands) { } @SuppressWarnings("unchecked") - protected PostResult toColumns(List items, Candidate selection, String completed, Function wcwidth, int width, boolean rowsFirst) { + protected PostResult toColumns( + List items, + Candidate selection, + String completed, + Function wcwidth, + int width, + boolean rowsFirst) { int[] out = new int[2]; // TODO: support Option.LIST_PACKED // Compute column width @@ -5199,8 +5335,7 @@ protected PostResult toColumns(List items, Candidate selection, String c if (item instanceof String) { int len = wcwidth.apply((String) item); maxWidth = Math.max(maxWidth, len); - } - else if (item instanceof List) { + } else if (item instanceof List) { for (Candidate cand : (List) item) { listSize++; int len = wcwidth.apply(cand.displ()); @@ -5218,7 +5353,10 @@ else if (item instanceof List) { AttributedStringBuilder sb = new AttributedStringBuilder(); if (listSize > 0) { if (isSet(Option.AUTO_MENU_LIST) - && listSize < Math.min(getInt(MENU_LIST_MAX, DEFAULT_MENU_LIST_MAX), visibleDisplayRows() - promptLines())) { + && listSize + < Math.min( + getInt(MENU_LIST_MAX, DEFAULT_MENU_LIST_MAX), + visibleDisplayRows() - promptLines())) { maxWidth = Math.max(maxWidth, MENU_LIST_WIDTH); sb.tabs(Math.max(Math.min(candidateStartPosition, width - maxWidth - 1), 1)); width = maxWidth + 2; @@ -5251,8 +5389,16 @@ else if (item instanceof List) { } @SuppressWarnings("unchecked") - protected void toColumns(Object items, int width, int maxWidth, AttributedStringBuilder sb, Candidate selection, String completed - , boolean rowsFirst, boolean doMenuList, int[] out) { + protected void toColumns( + Object items, + int width, + int maxWidth, + AttributedStringBuilder sb, + Candidate selection, + String completed, + boolean rowsFirst, + boolean doMenuList, + int[] out) { if (maxWidth <= 0 || width <= 0) { return; } @@ -5305,18 +5451,20 @@ else if (items instanceof List) { if (idx < candidates.size()) { Candidate cand = candidates.get(idx); boolean hasRightItem = j < columns - 1 && index.applyAsInt(i, j + 1) < candidates.size(); - AttributedString left = AttributedString.fromAnsi(cand.displ()); - AttributedString right = AttributedString.fromAnsi(cand.descr()); + AttributedString left = fromAnsi(cand.displ()); + AttributedString right = fromAnsi(cand.descr()); int lw = left.columnLength(); int rw = 0; if (right != null) { - int rem = maxWidth - (lw + MARGIN_BETWEEN_DISPLAY_AND_DESC - + DESC_PREFIX.length() + DESC_SUFFIX.length()); + int rem = maxWidth + - (lw + + MARGIN_BETWEEN_DISPLAY_AND_DESC + + DESC_PREFIX.length() + + DESC_SUFFIX.length()); rw = right.columnLength(); if (rw > rem) { right = AttributedStringBuilder.append( - right.columnSubSequence(0, rem - WCWidth.wcwidth('\u2026')), - "\u2026"); + right.columnSubSequence(0, rem - WCWidth.wcwidth('\u2026')), "\u2026"); rw = right.columnLength(); } right = AttributedStringBuilder.append(DESC_PREFIX, right, DESC_SUFFIX); @@ -5325,8 +5473,9 @@ else if (items instanceof List) { if (cand == selection) { out[1] = i; asb.style(getCompletionStyleSelection(doMenuList)); - if (left.toString().regionMatches( - isSet(Option.CASE_INSENSITIVE), 0, completed, 0, completed.length())) { + if (left.toString() + .regionMatches( + isSet(Option.CASE_INSENSITIVE), 0, completed, 0, completed.length())) { asb.append(left.toString(), 0, completed.length()); asb.append(left.toString(), completed.length(), left.length()); } else { @@ -5340,8 +5489,9 @@ else if (items instanceof List) { } asb.style(AttributedStyle.DEFAULT); } else { - if (left.toString().regionMatches( - isSet(Option.CASE_INSENSITIVE), 0, completed, 0, completed.length())) { + if (left.toString() + .regionMatches( + isSet(Option.CASE_INSENSITIVE), 0, completed, 0, completed.length())) { asb.style(getCompletionStyleStarting(doMenuList)); asb.append(left, 0, completed.length()); asb.style(AttributedStyle.DEFAULT); @@ -5447,7 +5597,7 @@ protected AttributedStyle getCompletionStyle(String name, String value) { } protected AttributedStyle buildStyle(String str) { - return AttributedString.fromAnsi("\u001b[" + str + "m ").styleAt(0); + return fromAnsi("\u001b[" + str + "m ").styleAt(0); } /** @@ -5477,14 +5627,14 @@ protected boolean moveHistory(final boolean next) { } if (next && !history.next()) { return false; - } - else if (!next && !history.previous()) { + } else if (!next && !history.previous()) { return false; } - setBuffer(modifiedHistory.containsKey(history.index()) - ? modifiedHistory.get(history.index()) - : history.current()); + setBuffer( + modifiedHistory.containsKey(history.index()) + ? modifiedHistory.get(history.index()) + : history.current()); return true; } @@ -5515,7 +5665,6 @@ void println() { redrawLine(); } - // // Actions // @@ -5725,8 +5874,7 @@ public boolean yankPop() { public boolean mouse() { MouseEvent event = readMouseEvent(); - if (event.getType() == MouseEvent.Type.Released - && event.getButton() == MouseEvent.Button.Button1) { + if (event.getType() == MouseEvent.Type.Released && event.getButton() == MouseEvent.Button.Button1) { StringBuilder tsb = new StringBuilder(); Cursor cursor = terminal.getCursorPosition(c -> tsb.append((char) c)); bindingReader.runMacro(tsb.toString()); @@ -5734,15 +5882,20 @@ public boolean mouse() { List secondaryPrompts = new ArrayList<>(); getDisplayedBufferWithPrompts(secondaryPrompts); - AttributedStringBuilder sb = new AttributedStringBuilder().tabs(TAB_WIDTH); + AttributedStringBuilder sb = new AttributedStringBuilder().tabs(getTabWidth()); sb.append(prompt); sb.append(insertSecondaryPrompts(new AttributedString(buf.upToCursor()), secondaryPrompts, false)); - List promptLines = sb.columnSplitLength(size.getColumns(), false, display.delayLineWrap()); + List promptLines = + sb.columnSplitLength(size.getColumns(), false, display.delayLineWrap()); int currentLine = promptLines.size() - 1; int wantedLine = Math.max(0, Math.min(currentLine + event.getY() - cursor.getY(), secondaryPrompts.size())); - int pl0 = currentLine == 0 ? prompt.columnLength() : secondaryPrompts.get(currentLine - 1).columnLength(); - int pl1 = wantedLine == 0 ? prompt.columnLength() : secondaryPrompts.get(wantedLine - 1).columnLength(); + int pl0 = currentLine == 0 + ? prompt.columnLength() + : secondaryPrompts.get(currentLine - 1).columnLength(); + int pl1 = wantedLine == 0 + ? prompt.columnLength() + : secondaryPrompts.get(wantedLine - 1).columnLength(); int adjust = pl1 - pl0; buf.moveXY(event.getX() - cursor.getX() - adjust, event.getY() - cursor.getY()); } @@ -5814,13 +5967,11 @@ public boolean beep() { bell_preference = BellType.VISIBLE; break; case "on": - bell_preference = getBoolean(PREFER_VISIBLE_BELL, false) - ? BellType.VISIBLE : BellType.AUDIBLE; + bell_preference = getBoolean(PREFER_VISIBLE_BELL, false) ? BellType.VISIBLE : BellType.AUDIBLE; break; } if (bell_preference == BellType.VISIBLE) { - if (terminal.puts(Capability.flash_screen) - || terminal.puts(Capability.bell)) { + if (terminal.puts(Capability.flash_screen) || terminal.puts(Capability.bell)) { flush(); } } else if (bell_preference == BellType.AUDIBLE) { @@ -5869,8 +6020,7 @@ protected boolean isAlpha(int c) { protected boolean isWord(int c) { String wordchars = getString(WORDCHARS, DEFAULT_WORDCHARS); - return Character.isLetterOrDigit(c) - || (c < 128 && wordchars.indexOf((char) c) >= 0); + return Character.isLetterOrDigit(c) || (c < 128 && wordchars.indexOf((char) c) >= 0); } String getString(String name, String def) { @@ -5899,6 +6049,8 @@ public Map> defaultKeyMaps() { keyMaps.put(VIOPP, viOpp()); keyMaps.put(VISUAL, visual()); keyMaps.put(SAFE, safe()); + keyMaps.put(DUMB, dumb()); + if (getBoolean(BIND_TTY_SPECIAL_CHARS, true)) { Attributes attr = terminal.getAttributes(); bindConsoleChars(keyMaps.get(EMACS), attr); @@ -5909,240 +6061,241 @@ public Map> defaultKeyMaps() { keyMap.setUnicode(new Reference(SELF_INSERT)); keyMap.setAmbiguousTimeout(getLong(AMBIGUOUS_BINDING, DEFAULT_AMBIGUOUS_BINDING)); } - // By default, link main to emacs - keyMaps.put(MAIN, keyMaps.get(EMACS)); + // By default, link main to emacs unless the temrinal is dumb + keyMaps.put(MAIN, keyMaps.get(isTerminalDumb() ? DUMB : EMACS)); + return keyMaps; } public KeyMap emacs() { KeyMap emacs = new KeyMap<>(); bindKeys(emacs); - bind(emacs, SET_MARK_COMMAND, ctrl('@')); - bind(emacs, BEGINNING_OF_LINE, ctrl('A')); - bind(emacs, BACKWARD_CHAR, ctrl('B')); - bind(emacs, DELETE_CHAR_OR_LIST, ctrl('D')); - bind(emacs, END_OF_LINE, ctrl('E')); - bind(emacs, FORWARD_CHAR, ctrl('F')); - bind(emacs, SEND_BREAK, ctrl('G')); - bind(emacs, BACKWARD_DELETE_CHAR, ctrl('H')); - bind(emacs, EXPAND_OR_COMPLETE, ctrl('I')); - bind(emacs, ACCEPT_LINE, ctrl('J')); - bind(emacs, KILL_LINE, ctrl('K')); - bind(emacs, CLEAR_SCREEN, ctrl('L')); - bind(emacs, ACCEPT_LINE, ctrl('M')); - bind(emacs, DOWN_LINE_OR_HISTORY, ctrl('N')); - bind(emacs, ACCEPT_LINE_AND_DOWN_HISTORY, ctrl('O')); - bind(emacs, UP_LINE_OR_HISTORY, ctrl('P')); - bind(emacs, HISTORY_INCREMENTAL_SEARCH_BACKWARD, ctrl('R')); - bind(emacs, HISTORY_INCREMENTAL_SEARCH_FORWARD, ctrl('S')); - bind(emacs, TRANSPOSE_CHARS, ctrl('T')); - bind(emacs, KILL_WHOLE_LINE, ctrl('U')); - bind(emacs, QUOTED_INSERT, ctrl('V')); - bind(emacs, BACKWARD_KILL_WORD, ctrl('W')); - bind(emacs, YANK, ctrl('Y')); - bind(emacs, CHARACTER_SEARCH, ctrl(']')); - bind(emacs, UNDO, ctrl('_')); - bind(emacs, SELF_INSERT, range(" -~")); - bind(emacs, INSERT_CLOSE_PAREN, ")"); - bind(emacs, INSERT_CLOSE_SQUARE, "]"); - bind(emacs, INSERT_CLOSE_CURLY, "}"); - bind(emacs, BACKWARD_DELETE_CHAR, del()); - bind(emacs, VI_MATCH_BRACKET, translate("^X^B")); - bind(emacs, SEND_BREAK, translate("^X^G")); - bind(emacs, EDIT_AND_EXECUTE_COMMAND, translate("^X^E")); - bind(emacs, VI_FIND_NEXT_CHAR, translate("^X^F")); - bind(emacs, VI_JOIN, translate("^X^J")); - bind(emacs, KILL_BUFFER, translate("^X^K")); - bind(emacs, INFER_NEXT_HISTORY, translate("^X^N")); - bind(emacs, OVERWRITE_MODE, translate("^X^O")); - bind(emacs, REDO, translate("^X^R")); - bind(emacs, UNDO, translate("^X^U")); - bind(emacs, VI_CMD_MODE, translate("^X^V")); - bind(emacs, EXCHANGE_POINT_AND_MARK, translate("^X^X")); - bind(emacs, DO_LOWERCASE_VERSION, translate("^XA-^XZ")); - bind(emacs, WHAT_CURSOR_POSITION, translate("^X=")); - bind(emacs, KILL_LINE, translate("^X^?")); - bind(emacs, SEND_BREAK, alt(ctrl('G'))); - bind(emacs, BACKWARD_KILL_WORD, alt(ctrl('H'))); - bind(emacs, SELF_INSERT_UNMETA, alt(ctrl('M'))); - bind(emacs, COMPLETE_WORD, alt(esc())); - bind(emacs, CHARACTER_SEARCH_BACKWARD, alt(ctrl(']'))); - bind(emacs, COPY_PREV_WORD, alt(ctrl('_'))); - bind(emacs, SET_MARK_COMMAND, alt(' ')); - bind(emacs, NEG_ARGUMENT, alt('-')); - bind(emacs, DIGIT_ARGUMENT, range("\\E0-\\E9")); - bind(emacs, BEGINNING_OF_HISTORY, alt('<')); - bind(emacs, LIST_CHOICES, alt('=')); - bind(emacs, END_OF_HISTORY, alt('>')); - bind(emacs, LIST_CHOICES, alt('?')); - bind(emacs, DO_LOWERCASE_VERSION, range("^[A-^[Z")); - bind(emacs, ACCEPT_AND_HOLD, alt('a')); - bind(emacs, BACKWARD_WORD, alt('b')); - bind(emacs, CAPITALIZE_WORD, alt('c')); - bind(emacs, KILL_WORD, alt('d')); - bind(emacs, KILL_WORD, translate("^[[3;5~")); // ctrl-delete - bind(emacs, FORWARD_WORD, alt('f')); - bind(emacs, DOWN_CASE_WORD, alt('l')); - bind(emacs, HISTORY_SEARCH_FORWARD, alt('n')); - bind(emacs, HISTORY_SEARCH_BACKWARD, alt('p')); - bind(emacs, TRANSPOSE_WORDS, alt('t')); - bind(emacs, UP_CASE_WORD, alt('u')); - bind(emacs, YANK_POP, alt('y')); - bind(emacs, BACKWARD_KILL_WORD, alt(del())); + bind(emacs, SET_MARK_COMMAND, ctrl('@')); + bind(emacs, BEGINNING_OF_LINE, ctrl('A')); + bind(emacs, BACKWARD_CHAR, ctrl('B')); + bind(emacs, DELETE_CHAR_OR_LIST, ctrl('D')); + bind(emacs, END_OF_LINE, ctrl('E')); + bind(emacs, FORWARD_CHAR, ctrl('F')); + bind(emacs, SEND_BREAK, ctrl('G')); + bind(emacs, BACKWARD_DELETE_CHAR, ctrl('H')); + bind(emacs, EXPAND_OR_COMPLETE, ctrl('I')); + bind(emacs, ACCEPT_LINE, ctrl('J')); + bind(emacs, KILL_LINE, ctrl('K')); + bind(emacs, CLEAR_SCREEN, ctrl('L')); + bind(emacs, ACCEPT_LINE, ctrl('M')); + bind(emacs, DOWN_LINE_OR_HISTORY, ctrl('N')); + bind(emacs, ACCEPT_LINE_AND_DOWN_HISTORY, ctrl('O')); + bind(emacs, UP_LINE_OR_HISTORY, ctrl('P')); + bind(emacs, HISTORY_INCREMENTAL_SEARCH_BACKWARD, ctrl('R')); + bind(emacs, HISTORY_INCREMENTAL_SEARCH_FORWARD, ctrl('S')); + bind(emacs, TRANSPOSE_CHARS, ctrl('T')); + bind(emacs, KILL_WHOLE_LINE, ctrl('U')); + bind(emacs, QUOTED_INSERT, ctrl('V')); + bind(emacs, BACKWARD_KILL_WORD, ctrl('W')); + bind(emacs, YANK, ctrl('Y')); + bind(emacs, CHARACTER_SEARCH, ctrl(']')); + bind(emacs, UNDO, ctrl('_')); + bind(emacs, SELF_INSERT, range(" -~")); + bind(emacs, INSERT_CLOSE_PAREN, ")"); + bind(emacs, INSERT_CLOSE_SQUARE, "]"); + bind(emacs, INSERT_CLOSE_CURLY, "}"); + bind(emacs, BACKWARD_DELETE_CHAR, del()); + bind(emacs, VI_MATCH_BRACKET, translate("^X^B")); + bind(emacs, SEND_BREAK, translate("^X^G")); + bind(emacs, EDIT_AND_EXECUTE_COMMAND, translate("^X^E")); + bind(emacs, VI_FIND_NEXT_CHAR, translate("^X^F")); + bind(emacs, VI_JOIN, translate("^X^J")); + bind(emacs, KILL_BUFFER, translate("^X^K")); + bind(emacs, INFER_NEXT_HISTORY, translate("^X^N")); + bind(emacs, OVERWRITE_MODE, translate("^X^O")); + bind(emacs, REDO, translate("^X^R")); + bind(emacs, UNDO, translate("^X^U")); + bind(emacs, VI_CMD_MODE, translate("^X^V")); + bind(emacs, EXCHANGE_POINT_AND_MARK, translate("^X^X")); + bind(emacs, DO_LOWERCASE_VERSION, translate("^XA-^XZ")); + bind(emacs, WHAT_CURSOR_POSITION, translate("^X=")); + bind(emacs, KILL_LINE, translate("^X^?")); + bind(emacs, SEND_BREAK, alt(ctrl('G'))); + bind(emacs, BACKWARD_KILL_WORD, alt(ctrl('H'))); + bind(emacs, SELF_INSERT_UNMETA, alt(ctrl('M'))); + bind(emacs, COMPLETE_WORD, alt(esc())); + bind(emacs, CHARACTER_SEARCH_BACKWARD, alt(ctrl(']'))); + bind(emacs, COPY_PREV_WORD, alt(ctrl('_'))); + bind(emacs, SET_MARK_COMMAND, alt(' ')); + bind(emacs, NEG_ARGUMENT, alt('-')); + bind(emacs, DIGIT_ARGUMENT, range("\\E0-\\E9")); + bind(emacs, BEGINNING_OF_HISTORY, alt('<')); + bind(emacs, LIST_CHOICES, alt('=')); + bind(emacs, END_OF_HISTORY, alt('>')); + bind(emacs, LIST_CHOICES, alt('?')); + bind(emacs, DO_LOWERCASE_VERSION, range("^[A-^[Z")); + bind(emacs, ACCEPT_AND_HOLD, alt('a')); + bind(emacs, BACKWARD_WORD, alt('b')); + bind(emacs, CAPITALIZE_WORD, alt('c')); + bind(emacs, KILL_WORD, alt('d')); + bind(emacs, KILL_WORD, translate("^[[3;5~")); // ctrl-delete + bind(emacs, FORWARD_WORD, alt('f')); + bind(emacs, DOWN_CASE_WORD, alt('l')); + bind(emacs, HISTORY_SEARCH_FORWARD, alt('n')); + bind(emacs, HISTORY_SEARCH_BACKWARD, alt('p')); + bind(emacs, TRANSPOSE_WORDS, alt('t')); + bind(emacs, UP_CASE_WORD, alt('u')); + bind(emacs, YANK_POP, alt('y')); + bind(emacs, BACKWARD_KILL_WORD, alt(del())); bindArrowKeys(emacs); - bind(emacs, FORWARD_WORD, translate("^[[1;5C")); // ctrl-left - bind(emacs, BACKWARD_WORD, translate("^[[1;5D")); // ctrl-right - bind(emacs, FORWARD_WORD, alt(key(Capability.key_right))); - bind(emacs, BACKWARD_WORD, alt(key(Capability.key_left))); - bind(emacs, FORWARD_WORD, alt(translate("^[[C"))); - bind(emacs, BACKWARD_WORD, alt(translate("^[[D"))); + bind(emacs, FORWARD_WORD, translate("^[[1;5C")); // ctrl-left + bind(emacs, BACKWARD_WORD, translate("^[[1;5D")); // ctrl-right + bind(emacs, FORWARD_WORD, alt(key(Capability.key_right))); + bind(emacs, BACKWARD_WORD, alt(key(Capability.key_left))); + bind(emacs, FORWARD_WORD, alt(translate("^[[C"))); + bind(emacs, BACKWARD_WORD, alt(translate("^[[D"))); return emacs; } public KeyMap viInsertion() { KeyMap viins = new KeyMap<>(); bindKeys(viins); - bind(viins, SELF_INSERT, range("^@-^_")); - bind(viins, LIST_CHOICES, ctrl('D')); - bind(viins, SEND_BREAK, ctrl('G')); - bind(viins, BACKWARD_DELETE_CHAR, ctrl('H')); - bind(viins, EXPAND_OR_COMPLETE, ctrl('I')); - bind(viins, ACCEPT_LINE, ctrl('J')); - bind(viins, CLEAR_SCREEN, ctrl('L')); - bind(viins, ACCEPT_LINE, ctrl('M')); - bind(viins, MENU_COMPLETE, ctrl('N')); - bind(viins, REVERSE_MENU_COMPLETE, ctrl('P')); - bind(viins, HISTORY_INCREMENTAL_SEARCH_BACKWARD, ctrl('R')); - bind(viins, HISTORY_INCREMENTAL_SEARCH_FORWARD, ctrl('S')); - bind(viins, TRANSPOSE_CHARS, ctrl('T')); - bind(viins, KILL_WHOLE_LINE, ctrl('U')); - bind(viins, QUOTED_INSERT, ctrl('V')); - bind(viins, BACKWARD_KILL_WORD, ctrl('W')); - bind(viins, YANK, ctrl('Y')); - bind(viins, VI_CMD_MODE, ctrl('[')); - bind(viins, UNDO, ctrl('_')); - bind(viins, HISTORY_INCREMENTAL_SEARCH_BACKWARD, ctrl('X') + "r"); - bind(viins, HISTORY_INCREMENTAL_SEARCH_FORWARD, ctrl('X') + "s"); - bind(viins, SELF_INSERT, range(" -~")); - bind(viins, INSERT_CLOSE_PAREN, ")"); - bind(viins, INSERT_CLOSE_SQUARE, "]"); - bind(viins, INSERT_CLOSE_CURLY, "}"); - bind(viins, BACKWARD_DELETE_CHAR, del()); + bind(viins, SELF_INSERT, range("^@-^_")); + bind(viins, LIST_CHOICES, ctrl('D')); + bind(viins, SEND_BREAK, ctrl('G')); + bind(viins, BACKWARD_DELETE_CHAR, ctrl('H')); + bind(viins, EXPAND_OR_COMPLETE, ctrl('I')); + bind(viins, ACCEPT_LINE, ctrl('J')); + bind(viins, CLEAR_SCREEN, ctrl('L')); + bind(viins, ACCEPT_LINE, ctrl('M')); + bind(viins, MENU_COMPLETE, ctrl('N')); + bind(viins, REVERSE_MENU_COMPLETE, ctrl('P')); + bind(viins, HISTORY_INCREMENTAL_SEARCH_BACKWARD, ctrl('R')); + bind(viins, HISTORY_INCREMENTAL_SEARCH_FORWARD, ctrl('S')); + bind(viins, TRANSPOSE_CHARS, ctrl('T')); + bind(viins, KILL_WHOLE_LINE, ctrl('U')); + bind(viins, QUOTED_INSERT, ctrl('V')); + bind(viins, BACKWARD_KILL_WORD, ctrl('W')); + bind(viins, YANK, ctrl('Y')); + bind(viins, VI_CMD_MODE, ctrl('[')); + bind(viins, UNDO, ctrl('_')); + bind(viins, HISTORY_INCREMENTAL_SEARCH_BACKWARD, ctrl('X') + "r"); + bind(viins, HISTORY_INCREMENTAL_SEARCH_FORWARD, ctrl('X') + "s"); + bind(viins, SELF_INSERT, range(" -~")); + bind(viins, INSERT_CLOSE_PAREN, ")"); + bind(viins, INSERT_CLOSE_SQUARE, "]"); + bind(viins, INSERT_CLOSE_CURLY, "}"); + bind(viins, BACKWARD_DELETE_CHAR, del()); bindArrowKeys(viins); return viins; } public KeyMap viCmd() { KeyMap vicmd = new KeyMap<>(); - bind(vicmd, LIST_CHOICES, ctrl('D')); - bind(vicmd, EMACS_EDITING_MODE, ctrl('E')); - bind(vicmd, SEND_BREAK, ctrl('G')); - bind(vicmd, VI_BACKWARD_CHAR, ctrl('H')); - bind(vicmd, ACCEPT_LINE, ctrl('J')); - bind(vicmd, KILL_LINE, ctrl('K')); - bind(vicmd, CLEAR_SCREEN, ctrl('L')); - bind(vicmd, ACCEPT_LINE, ctrl('M')); - bind(vicmd, VI_DOWN_LINE_OR_HISTORY, ctrl('N')); - bind(vicmd, VI_UP_LINE_OR_HISTORY, ctrl('P')); - bind(vicmd, QUOTED_INSERT, ctrl('Q')); - bind(vicmd, HISTORY_INCREMENTAL_SEARCH_BACKWARD, ctrl('R')); - bind(vicmd, HISTORY_INCREMENTAL_SEARCH_FORWARD, ctrl('S')); - bind(vicmd, TRANSPOSE_CHARS, ctrl('T')); - bind(vicmd, KILL_WHOLE_LINE, ctrl('U')); - bind(vicmd, QUOTED_INSERT, ctrl('V')); - bind(vicmd, BACKWARD_KILL_WORD, ctrl('W')); - bind(vicmd, YANK, ctrl('Y')); - bind(vicmd, HISTORY_INCREMENTAL_SEARCH_BACKWARD, ctrl('X') + "r"); - bind(vicmd, HISTORY_INCREMENTAL_SEARCH_FORWARD, ctrl('X') + "s"); - bind(vicmd, SEND_BREAK, alt(ctrl('G'))); - bind(vicmd, BACKWARD_KILL_WORD, alt(ctrl('H'))); - bind(vicmd, SELF_INSERT_UNMETA, alt(ctrl('M'))); - bind(vicmd, COMPLETE_WORD, alt(esc())); - bind(vicmd, CHARACTER_SEARCH_BACKWARD, alt(ctrl(']'))); - bind(vicmd, SET_MARK_COMMAND, alt(' ')); -// bind(vicmd, INSERT_COMMENT, alt('#')); -// bind(vicmd, INSERT_COMPLETIONS, alt('*')); - bind(vicmd, DIGIT_ARGUMENT, alt('-')); - bind(vicmd, BEGINNING_OF_HISTORY, alt('<')); - bind(vicmd, LIST_CHOICES, alt('=')); - bind(vicmd, END_OF_HISTORY, alt('>')); - bind(vicmd, LIST_CHOICES, alt('?')); - bind(vicmd, DO_LOWERCASE_VERSION, range("^[A-^[Z")); - bind(vicmd, BACKWARD_WORD, alt('b')); - bind(vicmd, CAPITALIZE_WORD, alt('c')); - bind(vicmd, KILL_WORD, alt('d')); - bind(vicmd, FORWARD_WORD, alt('f')); - bind(vicmd, DOWN_CASE_WORD, alt('l')); - bind(vicmd, HISTORY_SEARCH_FORWARD, alt('n')); - bind(vicmd, HISTORY_SEARCH_BACKWARD, alt('p')); - bind(vicmd, TRANSPOSE_WORDS, alt('t')); - bind(vicmd, UP_CASE_WORD, alt('u')); - bind(vicmd, YANK_POP, alt('y')); - bind(vicmd, BACKWARD_KILL_WORD, alt(del())); - - bind(vicmd, FORWARD_CHAR, " "); - bind(vicmd, VI_INSERT_COMMENT, "#"); - bind(vicmd, END_OF_LINE, "$"); - bind(vicmd, VI_MATCH_BRACKET, "%"); - bind(vicmd, VI_DOWN_LINE_OR_HISTORY, "+"); - bind(vicmd, VI_REV_REPEAT_FIND, ","); - bind(vicmd, VI_UP_LINE_OR_HISTORY, "-"); - bind(vicmd, VI_REPEAT_CHANGE, "."); - bind(vicmd, VI_HISTORY_SEARCH_BACKWARD, "/"); - bind(vicmd, VI_DIGIT_OR_BEGINNING_OF_LINE, "0"); - bind(vicmd, DIGIT_ARGUMENT, range("1-9")); - bind(vicmd, VI_REPEAT_FIND, ";"); - bind(vicmd, LIST_CHOICES, "="); - bind(vicmd, VI_HISTORY_SEARCH_FORWARD, "?"); - bind(vicmd, VI_ADD_EOL, "A"); - bind(vicmd, VI_BACKWARD_BLANK_WORD, "B"); - bind(vicmd, VI_CHANGE_EOL, "C"); - bind(vicmd, VI_KILL_EOL, "D"); - bind(vicmd, VI_FORWARD_BLANK_WORD_END, "E"); - bind(vicmd, VI_FIND_PREV_CHAR, "F"); - bind(vicmd, VI_FETCH_HISTORY, "G"); - bind(vicmd, VI_INSERT_BOL, "I"); - bind(vicmd, VI_JOIN, "J"); - bind(vicmd, VI_REV_REPEAT_SEARCH, "N"); - bind(vicmd, VI_OPEN_LINE_ABOVE, "O"); - bind(vicmd, VI_PUT_BEFORE, "P"); - bind(vicmd, VI_REPLACE, "R"); - bind(vicmd, VI_KILL_LINE, "S"); - bind(vicmd, VI_FIND_PREV_CHAR_SKIP, "T"); - bind(vicmd, REDO, "U"); - bind(vicmd, VISUAL_LINE_MODE, "V"); - bind(vicmd, VI_FORWARD_BLANK_WORD, "W"); - bind(vicmd, VI_BACKWARD_DELETE_CHAR, "X"); - bind(vicmd, VI_YANK_WHOLE_LINE, "Y"); - bind(vicmd, VI_FIRST_NON_BLANK, "^"); - bind(vicmd, VI_ADD_NEXT, "a"); - bind(vicmd, VI_BACKWARD_WORD, "b"); - bind(vicmd, VI_CHANGE, "c"); - bind(vicmd, VI_DELETE, "d"); - bind(vicmd, VI_FORWARD_WORD_END, "e"); - bind(vicmd, VI_FIND_NEXT_CHAR, "f"); - bind(vicmd, WHAT_CURSOR_POSITION, "ga"); - bind(vicmd, VI_BACKWARD_BLANK_WORD_END, "gE"); - bind(vicmd, VI_BACKWARD_WORD_END, "ge"); - bind(vicmd, VI_BACKWARD_CHAR, "h"); - bind(vicmd, VI_INSERT, "i"); - bind(vicmd, DOWN_LINE_OR_HISTORY, "j"); - bind(vicmd, UP_LINE_OR_HISTORY, "k"); - bind(vicmd, VI_FORWARD_CHAR, "l"); - bind(vicmd, VI_REPEAT_SEARCH, "n"); - bind(vicmd, VI_OPEN_LINE_BELOW, "o"); - bind(vicmd, VI_PUT_AFTER, "p"); - bind(vicmd, VI_REPLACE_CHARS, "r"); - bind(vicmd, VI_SUBSTITUTE, "s"); - bind(vicmd, VI_FIND_NEXT_CHAR_SKIP, "t"); - bind(vicmd, UNDO, "u"); - bind(vicmd, VISUAL_MODE, "v"); - bind(vicmd, VI_FORWARD_WORD, "w"); - bind(vicmd, VI_DELETE_CHAR, "x"); - bind(vicmd, VI_YANK, "y"); - bind(vicmd, VI_GOTO_COLUMN, "|"); - bind(vicmd, VI_SWAP_CASE, "~"); - bind(vicmd, VI_BACKWARD_CHAR, del()); + bind(vicmd, LIST_CHOICES, ctrl('D')); + bind(vicmd, EMACS_EDITING_MODE, ctrl('E')); + bind(vicmd, SEND_BREAK, ctrl('G')); + bind(vicmd, VI_BACKWARD_CHAR, ctrl('H')); + bind(vicmd, ACCEPT_LINE, ctrl('J')); + bind(vicmd, KILL_LINE, ctrl('K')); + bind(vicmd, CLEAR_SCREEN, ctrl('L')); + bind(vicmd, ACCEPT_LINE, ctrl('M')); + bind(vicmd, VI_DOWN_LINE_OR_HISTORY, ctrl('N')); + bind(vicmd, VI_UP_LINE_OR_HISTORY, ctrl('P')); + bind(vicmd, QUOTED_INSERT, ctrl('Q')); + bind(vicmd, HISTORY_INCREMENTAL_SEARCH_BACKWARD, ctrl('R')); + bind(vicmd, HISTORY_INCREMENTAL_SEARCH_FORWARD, ctrl('S')); + bind(vicmd, TRANSPOSE_CHARS, ctrl('T')); + bind(vicmd, KILL_WHOLE_LINE, ctrl('U')); + bind(vicmd, QUOTED_INSERT, ctrl('V')); + bind(vicmd, BACKWARD_KILL_WORD, ctrl('W')); + bind(vicmd, YANK, ctrl('Y')); + bind(vicmd, HISTORY_INCREMENTAL_SEARCH_BACKWARD, ctrl('X') + "r"); + bind(vicmd, HISTORY_INCREMENTAL_SEARCH_FORWARD, ctrl('X') + "s"); + bind(vicmd, SEND_BREAK, alt(ctrl('G'))); + bind(vicmd, BACKWARD_KILL_WORD, alt(ctrl('H'))); + bind(vicmd, SELF_INSERT_UNMETA, alt(ctrl('M'))); + bind(vicmd, COMPLETE_WORD, alt(esc())); + bind(vicmd, CHARACTER_SEARCH_BACKWARD, alt(ctrl(']'))); + bind(vicmd, SET_MARK_COMMAND, alt(' ')); + // bind(vicmd, INSERT_COMMENT, alt('#')); + // bind(vicmd, INSERT_COMPLETIONS, alt('*')); + bind(vicmd, DIGIT_ARGUMENT, alt('-')); + bind(vicmd, BEGINNING_OF_HISTORY, alt('<')); + bind(vicmd, LIST_CHOICES, alt('=')); + bind(vicmd, END_OF_HISTORY, alt('>')); + bind(vicmd, LIST_CHOICES, alt('?')); + bind(vicmd, DO_LOWERCASE_VERSION, range("^[A-^[Z")); + bind(vicmd, BACKWARD_WORD, alt('b')); + bind(vicmd, CAPITALIZE_WORD, alt('c')); + bind(vicmd, KILL_WORD, alt('d')); + bind(vicmd, FORWARD_WORD, alt('f')); + bind(vicmd, DOWN_CASE_WORD, alt('l')); + bind(vicmd, HISTORY_SEARCH_FORWARD, alt('n')); + bind(vicmd, HISTORY_SEARCH_BACKWARD, alt('p')); + bind(vicmd, TRANSPOSE_WORDS, alt('t')); + bind(vicmd, UP_CASE_WORD, alt('u')); + bind(vicmd, YANK_POP, alt('y')); + bind(vicmd, BACKWARD_KILL_WORD, alt(del())); + + bind(vicmd, FORWARD_CHAR, " "); + bind(vicmd, VI_INSERT_COMMENT, "#"); + bind(vicmd, END_OF_LINE, "$"); + bind(vicmd, VI_MATCH_BRACKET, "%"); + bind(vicmd, VI_DOWN_LINE_OR_HISTORY, "+"); + bind(vicmd, VI_REV_REPEAT_FIND, ","); + bind(vicmd, VI_UP_LINE_OR_HISTORY, "-"); + bind(vicmd, VI_REPEAT_CHANGE, "."); + bind(vicmd, VI_HISTORY_SEARCH_BACKWARD, "/"); + bind(vicmd, VI_DIGIT_OR_BEGINNING_OF_LINE, "0"); + bind(vicmd, DIGIT_ARGUMENT, range("1-9")); + bind(vicmd, VI_REPEAT_FIND, ";"); + bind(vicmd, LIST_CHOICES, "="); + bind(vicmd, VI_HISTORY_SEARCH_FORWARD, "?"); + bind(vicmd, VI_ADD_EOL, "A"); + bind(vicmd, VI_BACKWARD_BLANK_WORD, "B"); + bind(vicmd, VI_CHANGE_EOL, "C"); + bind(vicmd, VI_KILL_EOL, "D"); + bind(vicmd, VI_FORWARD_BLANK_WORD_END, "E"); + bind(vicmd, VI_FIND_PREV_CHAR, "F"); + bind(vicmd, VI_FETCH_HISTORY, "G"); + bind(vicmd, VI_INSERT_BOL, "I"); + bind(vicmd, VI_JOIN, "J"); + bind(vicmd, VI_REV_REPEAT_SEARCH, "N"); + bind(vicmd, VI_OPEN_LINE_ABOVE, "O"); + bind(vicmd, VI_PUT_BEFORE, "P"); + bind(vicmd, VI_REPLACE, "R"); + bind(vicmd, VI_KILL_LINE, "S"); + bind(vicmd, VI_FIND_PREV_CHAR_SKIP, "T"); + bind(vicmd, REDO, "U"); + bind(vicmd, VISUAL_LINE_MODE, "V"); + bind(vicmd, VI_FORWARD_BLANK_WORD, "W"); + bind(vicmd, VI_BACKWARD_DELETE_CHAR, "X"); + bind(vicmd, VI_YANK_WHOLE_LINE, "Y"); + bind(vicmd, VI_FIRST_NON_BLANK, "^"); + bind(vicmd, VI_ADD_NEXT, "a"); + bind(vicmd, VI_BACKWARD_WORD, "b"); + bind(vicmd, VI_CHANGE, "c"); + bind(vicmd, VI_DELETE, "d"); + bind(vicmd, VI_FORWARD_WORD_END, "e"); + bind(vicmd, VI_FIND_NEXT_CHAR, "f"); + bind(vicmd, WHAT_CURSOR_POSITION, "ga"); + bind(vicmd, VI_BACKWARD_BLANK_WORD_END, "gE"); + bind(vicmd, VI_BACKWARD_WORD_END, "ge"); + bind(vicmd, VI_BACKWARD_CHAR, "h"); + bind(vicmd, VI_INSERT, "i"); + bind(vicmd, DOWN_LINE_OR_HISTORY, "j"); + bind(vicmd, UP_LINE_OR_HISTORY, "k"); + bind(vicmd, VI_FORWARD_CHAR, "l"); + bind(vicmd, VI_REPEAT_SEARCH, "n"); + bind(vicmd, VI_OPEN_LINE_BELOW, "o"); + bind(vicmd, VI_PUT_AFTER, "p"); + bind(vicmd, VI_REPLACE_CHARS, "r"); + bind(vicmd, VI_SUBSTITUTE, "s"); + bind(vicmd, VI_FIND_NEXT_CHAR_SKIP, "t"); + bind(vicmd, UNDO, "u"); + bind(vicmd, VISUAL_MODE, "v"); + bind(vicmd, VI_FORWARD_WORD, "w"); + bind(vicmd, VI_DELETE_CHAR, "x"); + bind(vicmd, VI_YANK, "y"); + bind(vicmd, VI_GOTO_COLUMN, "|"); + bind(vicmd, VI_SWAP_CASE, "~"); + bind(vicmd, VI_BACKWARD_CHAR, del()); bindArrowKeys(vicmd); return vicmd; @@ -6150,38 +6303,46 @@ public KeyMap viCmd() { public KeyMap menu() { KeyMap menu = new KeyMap<>(); - bind(menu, MENU_COMPLETE, "\t"); - bind(menu, REVERSE_MENU_COMPLETE, key(Capability.back_tab)); - bind(menu, ACCEPT_LINE, "\r", "\n"); + bind(menu, MENU_COMPLETE, "\t"); + bind(menu, REVERSE_MENU_COMPLETE, key(Capability.back_tab)); + bind(menu, ACCEPT_LINE, "\r", "\n"); bindArrowKeys(menu); return menu; } public KeyMap safe() { KeyMap safe = new KeyMap<>(); - bind(safe, SELF_INSERT, range("^@-^?")); - bind(safe, ACCEPT_LINE, "\r", "\n"); - bind(safe, SEND_BREAK, ctrl('G')); + bind(safe, SELF_INSERT, range("^@-^?")); + bind(safe, ACCEPT_LINE, "\r", "\n"); + bind(safe, SEND_BREAK, ctrl('G')); return safe; } + public KeyMap dumb() { + KeyMap dumb = new KeyMap<>(); + bind(dumb, SELF_INSERT, range("^@-^?")); + bind(dumb, ACCEPT_LINE, "\r", "\n"); + bind(dumb, BEEP, ctrl('G')); + return dumb; + } + public KeyMap visual() { KeyMap visual = new KeyMap<>(); - bind(visual, UP_LINE, key(Capability.key_up), "k"); - bind(visual, DOWN_LINE, key(Capability.key_down), "j"); - bind(visual, this::deactivateRegion, esc()); - bind(visual, EXCHANGE_POINT_AND_MARK, "o"); - bind(visual, PUT_REPLACE_SELECTION, "p"); - bind(visual, VI_DELETE, "x"); - bind(visual, VI_OPER_SWAP_CASE, "~"); + bind(visual, UP_LINE, key(Capability.key_up), "k"); + bind(visual, DOWN_LINE, key(Capability.key_down), "j"); + bind(visual, this::deactivateRegion, esc()); + bind(visual, EXCHANGE_POINT_AND_MARK, "o"); + bind(visual, PUT_REPLACE_SELECTION, "p"); + bind(visual, VI_DELETE, "x"); + bind(visual, VI_OPER_SWAP_CASE, "~"); return visual; } public KeyMap viOpp() { KeyMap viOpp = new KeyMap<>(); - bind(viOpp, UP_LINE, key(Capability.key_up), "k"); - bind(viOpp, DOWN_LINE, key(Capability.key_down), "j"); - bind(viOpp, VI_CMD_MODE, esc()); + bind(viOpp, UP_LINE, key(Capability.key_up), "k"); + bind(viOpp, DOWN_LINE, key(Capability.key_down), "j"); + bind(viOpp, VI_CMD_MODE, esc()); return viOpp; } @@ -6210,19 +6371,19 @@ private void bindKeys(KeyMap emacs) { } private void bindArrowKeys(KeyMap map) { - bind(map, UP_LINE_OR_SEARCH, key(Capability.key_up)); - bind(map, DOWN_LINE_OR_SEARCH, key(Capability.key_down)); - bind(map, BACKWARD_CHAR, key(Capability.key_left)); - bind(map, FORWARD_CHAR, key(Capability.key_right)); - bind(map, BEGINNING_OF_LINE, key(Capability.key_home)); - bind(map, END_OF_LINE, key(Capability.key_end)); - bind(map, DELETE_CHAR, key(Capability.key_dc)); - bind(map, KILL_WHOLE_LINE, key(Capability.key_dl)); - bind(map, OVERWRITE_MODE, key(Capability.key_ic)); - bind(map, MOUSE, key(Capability.key_mouse)); - bind(map, BEGIN_PASTE, BRACKETED_PASTE_BEGIN); - bind(map, FOCUS_IN, FOCUS_IN_SEQ); - bind(map, FOCUS_OUT, FOCUS_OUT_SEQ); + bind(map, UP_LINE_OR_SEARCH, key(Capability.key_up)); + bind(map, DOWN_LINE_OR_SEARCH, key(Capability.key_down)); + bind(map, BACKWARD_CHAR, key(Capability.key_left)); + bind(map, FORWARD_CHAR, key(Capability.key_right)); + bind(map, BEGINNING_OF_LINE, key(Capability.key_home)); + bind(map, END_OF_LINE, key(Capability.key_end)); + bind(map, DELETE_CHAR, key(Capability.key_dc)); + bind(map, KILL_WHOLE_LINE, key(Capability.key_dl)); + bind(map, OVERWRITE_MODE, key(Capability.key_ic)); + bind(map, MOUSE, key(Capability.key_mouse)); + bind(map, BEGIN_PASTE, BRACKETED_PASTE_BEGIN); + bind(map, FOCUS_IN, FOCUS_IN_SEQ); + bind(map, FOCUS_OUT, FOCUS_OUT_SEQ); } /** @@ -6231,14 +6392,10 @@ private void bindArrowKeys(KeyMap map) { */ private void bindConsoleChars(KeyMap keyMap, Attributes attr) { if (attr != null) { - rebind(keyMap, BACKWARD_DELETE_CHAR, - del(), (char) attr.getControlChar(ControlChar.VERASE)); - rebind(keyMap, BACKWARD_KILL_WORD, - ctrl('W'), (char) attr.getControlChar(ControlChar.VWERASE)); - rebind(keyMap, KILL_WHOLE_LINE, - ctrl('U'), (char) attr.getControlChar(ControlChar.VKILL)); - rebind(keyMap, QUOTED_INSERT, - ctrl('V'), (char) attr.getControlChar(ControlChar.VLNEXT)); + rebind(keyMap, BACKWARD_DELETE_CHAR, del(), (char) attr.getControlChar(ControlChar.VERASE)); + rebind(keyMap, BACKWARD_KILL_WORD, ctrl('W'), (char) attr.getControlChar(ControlChar.VWERASE)); + rebind(keyMap, KILL_WHOLE_LINE, ctrl('U'), (char) attr.getControlChar(ControlChar.VKILL)); + rebind(keyMap, QUOTED_INSERT, ctrl('V'), (char) attr.getControlChar(ControlChar.VLNEXT)); } } @@ -6250,4 +6407,8 @@ private void rebind(KeyMap keyMap, String operation, String prevBinding } } + @Override + public void zeroOut() { + buf.zeroOut(); + } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/ReaderUtils.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/ReaderUtils.java index 0ae9475bd57..cdc60dccccf 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/ReaderUtils.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/ReaderUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2020, the original author or authors. + * Copyright (c) 2002-2020, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -13,7 +13,7 @@ public class ReaderUtils { - private ReaderUtils() { } + private ReaderUtils() {} public static boolean isSet(LineReader reader, LineReader.Option option) { return reader != null && reader.isSet(option); @@ -30,8 +30,7 @@ public static boolean getBoolean(LineReader reader, String name, boolean def) { return (Boolean) v; } else if (v != null) { String s = v.toString(); - return s.isEmpty() || s.equalsIgnoreCase("on") - || s.equalsIgnoreCase("1") || s.equalsIgnoreCase("true"); + return s.isEmpty() || s.equalsIgnoreCase("on") || s.equalsIgnoreCase("1") || s.equalsIgnoreCase("true"); } return def; } @@ -77,5 +76,4 @@ public static int distance(String word, String cand) { return Levenshtein.distance(word, cand); } } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/SimpleMaskingCallback.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/SimpleMaskingCallback.java index fd6c2663c05..423497f3dc4 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/SimpleMaskingCallback.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/SimpleMaskingCallback.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2017, the original author or authors. + * Copyright (c) 2002-2017, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -8,10 +8,10 @@ */ package jdk.internal.org.jline.reader.impl; -import jdk.internal.org.jline.reader.MaskingCallback; - import java.util.Objects; +import jdk.internal.org.jline.reader.MaskingCallback; + /** * Simple {@link MaskingCallback} that will replace all the characters in the line with the given mask. * If the given mask is equal to {@link LineReaderImpl#NULL_MASK} then the line will be replaced with an empty String. @@ -29,7 +29,7 @@ public String display(String line) { return ""; } else { StringBuilder sb = new StringBuilder(line.length()); - for (int i = line.length(); i-- > 0;) { + for (int i = line.length(); i-- > 0; ) { sb.append((char) mask); } return sb.toString(); @@ -40,5 +40,4 @@ public String display(String line) { public String history(String line) { return null; } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/UndoTree.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/UndoTree.java index 0a467f9d7ba..3b193f9eb65 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/UndoTree.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/UndoTree.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -20,6 +20,7 @@ public class UndoTree { private final Node parent; private Node current; + @SuppressWarnings("this-escape") public UndoTree(Consumer s) { state = s; parent = new Node(null); @@ -71,5 +72,4 @@ public Node(T s) { state = s; } } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/AggregateCompleter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/AggregateCompleter.java index e8e41088c59..145823c53ce 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/AggregateCompleter.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/AggregateCompleter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -24,9 +24,7 @@ * @author Jason Dillon * @since 2.3 */ -public class AggregateCompleter - implements Completer -{ +public class AggregateCompleter implements Completer { private final Collection completers; /** @@ -78,9 +76,6 @@ public void complete(LineReader reader, final ParsedLine line, final ListJason Dillon * @since 2.3 */ -public class ArgumentCompleter implements Completer -{ +public class ArgumentCompleter implements Completer { private final List completers = new ArrayList<>(); private boolean strict = true; @@ -108,12 +107,12 @@ public void complete(LineReader reader, ParsedLine line, final List c // if we are beyond the end of the completers, just use the last one if (line.wordIndex() >= completers.size()) { completer = completers.get(completers.size() - 1); - } - else { + } else { completer = completers.get(line.wordIndex()); } - // ensure that all the previous completers are successful before allowing this completer to pass (only if strict). + // ensure that all the previous completers are successful before allowing this completer to pass (only if + // strict). for (int i = strictCommand ? 0 : 1; isStrict() && (i < line.wordIndex()); i++) { int idx = i >= completers.size() ? (completers.size() - 1) : i; if (idx == 0 && !strictCommand) { diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/EnumCompleter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/EnumCompleter.java index 6a18d3cfd93..a701f2e3560 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/EnumCompleter.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/EnumCompleter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -19,8 +19,7 @@ * @author Jason Dillon * @since 2.3 */ -public class EnumCompleter extends StringsCompleter -{ +public class EnumCompleter extends StringsCompleter { public EnumCompleter(Class> source) { Objects.requireNonNull(source); for (Enum n : source.getEnumConstants()) { diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/FileNameCompleter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/FileNameCompleter.java index 3d173f72ec7..32bf6e3493e 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/FileNameCompleter.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/FileNameCompleter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -9,6 +9,7 @@ package jdk.internal.org.jline.reader.impl.completer; import java.io.IOException; +import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -41,11 +42,10 @@ * @author Marc Prud'hommeaux * @author Jason Dillon * @since 2.3 - * @deprecated use jdk.internal.org.jline.builtins.Completers$FileNameCompleter instead + * @deprecated use org.jline.builtins.Completers$FileNameCompleter instead */ @Deprecated -public class FileNameCompleter implements Completer -{ +public class FileNameCompleter implements Completer { public void complete(LineReader reader, ParsedLine commandLine, final List candidates) { assert commandLine != null; @@ -72,20 +72,21 @@ public void complete(LineReader reader, ParsedLine commandLine, final List { + try (DirectoryStream directoryStream = Files.newDirectoryStream(current, this::accept)) { + directoryStream.forEach(p -> { String value = curBuf + p.getFileName().toString(); if (Files.isDirectory(p)) { candidates.add(new Candidate( value + (reader.isSet(Option.AUTO_PARAM_SLASH) ? sep : ""), getDisplay(reader.getTerminal(), p), - null, null, + null, + null, reader.isSet(Option.AUTO_REMOVE_SLASH) ? sep : null, null, false)); } else { - candidates.add(new Candidate(value, getDisplay(reader.getTerminal(), p), - null, null, null, null, true)); + candidates.add( + new Candidate(value, getDisplay(reader.getTerminal(), p), null, null, null, null, true)); } }); } catch (IOException e) { @@ -125,5 +126,4 @@ protected String getDisplay(Terminal terminal, Path p) { } return name; } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/NullCompleter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/NullCompleter.java index f3efefdc929..21ce836a32f 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/NullCompleter.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/NullCompleter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -22,11 +22,8 @@ * @author Jason Dillon * @since 2.3 */ -public final class NullCompleter - implements Completer -{ +public final class NullCompleter implements Completer { public static final NullCompleter INSTANCE = new NullCompleter(); - public void complete(LineReader reader, final ParsedLine line, final List candidates) { - } + public void complete(LineReader reader, final ParsedLine line, final List candidates) {} } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/StringsCompleter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/StringsCompleter.java index 8baac657b93..c791ef68e72 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/StringsCompleter.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/StringsCompleter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2019, the original author or authors. + * Copyright (c) 2002-2019, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -27,8 +27,7 @@ * @author Jason Dillon * @since 2.3 */ -public class StringsCompleter implements Completer -{ +public class StringsCompleter implements Completer { protected Collection candidates; protected Supplier> stringsSupplier; @@ -54,7 +53,7 @@ public StringsCompleter(Iterable strings) { } } - public StringsCompleter(Candidate ... candidates) { + public StringsCompleter(Candidate... candidates) { this(Arrays.asList(candidates)); } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/SystemCompleter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/SystemCompleter.java index a17a356bf0e..2fe6f8df492 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/SystemCompleter.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/completer/SystemCompleter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2020, the original author or authors. + * Copyright (c) 2002-2020, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -22,8 +22,8 @@ * @author Matti Rinta-Nikkola */ public class SystemCompleter implements Completer { - private Map> completers = new HashMap<>(); - private Map aliasCommand = new HashMap<>(); + private Map> completers = new HashMap<>(); + private Map aliasCommand = new HashMap<>(); private StringsCompleter commands; private boolean compiled = false; @@ -44,9 +44,9 @@ public void complete(LineReader reader, ParsedLine commandLine, List commands.complete(reader, commandLine, candidates); } else if (reader.getParser().validVariableName(buffer.substring(0, eq))) { String curBuf = buffer.substring(0, eq + 1); - for (String c: completers.keySet()) { - candidates.add(new Candidate(AttributedString.stripAnsi(curBuf+c) - , c, null, null, null, null, true)); + for (String c : completers.keySet()) { + candidates.add( + new Candidate(AttributedString.stripAnsi(curBuf + c), c, null, null, null, null, true)); } } } else { @@ -81,7 +81,7 @@ public void add(String command, List completers) { } public void add(List commands, Completer completer) { - for (String c: commands) { + for (String c : commands) { add(c, completer); } } @@ -104,22 +104,22 @@ public void add(SystemCompleter other) { if (other.isCompiled()) { throw new IllegalStateException(); } - for (Map.Entry> entry: other.getCompleters().entrySet()) { - for (Completer c: entry.getValue()) { + for (Map.Entry> entry : other.getCompleters().entrySet()) { + for (Completer c : entry.getValue()) { add(entry.getKey(), c); } } addAliases(other.getAliases()); } - public void addAliases(Map aliasCommand) { + public void addAliases(Map aliasCommand) { if (compiled) { throw new IllegalStateException(); } this.aliasCommand.putAll(aliasCommand); } - private Map getAliases() { + private Map getAliases() { return aliasCommand; } @@ -128,7 +128,7 @@ public void compile() { return; } Map> compiledCompleters = new HashMap<>(); - for (Map.Entry> entry: completers.entrySet()) { + for (Map.Entry> entry : completers.entrySet()) { if (entry.getValue().size() == 1) { compiledCompleters.put(entry.getKey(), entry.getValue()); } else { @@ -143,8 +143,7 @@ public void compile() { compiled = true; } - public Map> getCompleters() { + public Map> getCompleters() { return completers; } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/history/DefaultHistory.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/history/DefaultHistory.java index cdd1bc520dd..c696b33ba9e 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/history/DefaultHistory.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/reader/impl/history/DefaultHistory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2021, the original author or authors. + * Copyright (c) 2002-2021, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -41,9 +41,9 @@ public class DefaultHistory implements History { private int offset = 0; private int index = 0; - public DefaultHistory() { - } + public DefaultHistory() {} + @SuppressWarnings("this-escape") public DefaultHistory(LineReader reader) { attach(reader); } @@ -67,8 +67,7 @@ public void attach(LineReader reader) { this.reader = reader; try { load(); - } - catch (IllegalArgumentException | IOException e) { + } catch (IllegalArgumentException | IOException e) { Log.warn("Failed to load history", e); } } @@ -117,13 +116,13 @@ public void read(Path file, boolean checkDuplicates) throws IOException { } } - private String doHistoryFileDataKey (Path path){ + private String doHistoryFileDataKey(Path path) { return path != null ? path.toAbsolutePath().toString() : null; } private HistoryFileData getHistoryFileData(Path path) { String key = doHistoryFileDataKey(path); - if (!historyFiles.containsKey(key)){ + if (!historyFiles.containsKey(key)) { historyFiles.put(key, new HistoryFileData()); } return historyFiles.get(key); @@ -133,7 +132,7 @@ private void setHistoryFileData(Path path, HistoryFileData historyFileData) { historyFiles.put(doHistoryFileDataKey(path), historyFileData); } - private boolean isLineReaderHistory (Path path) throws IOException { + private boolean isLineReaderHistory(Path path) throws IOException { Path lrp = getPath(); if (lrp == null) { return path == null; @@ -141,23 +140,23 @@ private boolean isLineReaderHistory (Path path) throws IOException { return Files.isSameFile(lrp, path); } - private void setLastLoaded(Path path, int lastloaded){ + private void setLastLoaded(Path path, int lastloaded) { getHistoryFileData(path).setLastLoaded(lastloaded); } - private void setEntriesInFile(Path path, int entriesInFile){ + private void setEntriesInFile(Path path, int entriesInFile) { getHistoryFileData(path).setEntriesInFile(entriesInFile); } - private void incEntriesInFile(Path path, int amount){ + private void incEntriesInFile(Path path, int amount) { getHistoryFileData(path).incEntriesInFile(amount); } - private int getLastLoaded(Path path){ + private int getLastLoaded(Path path) { return getHistoryFileData(path).getLastLoaded(); } - private int getEntriesInFile(Path path){ + private int getEntriesInFile(Path path) { return getHistoryFileData(path).getEntriesInFile(); } @@ -168,9 +167,8 @@ protected void addHistoryLine(Path path, String line) { protected void addHistoryLine(Path path, String line, boolean checkDuplicates) { if (reader.isSet(LineReader.Option.HISTORY_TIMESTAMPED)) { int idx = line.indexOf(':'); - final String badHistoryFileSyntax = "Bad history file syntax! " + - "The history file `" + path + "` may be an older history: " + - "please remove it or use a different history file."; + final String badHistoryFileSyntax = "Bad history file syntax! " + "The history file `" + path + + "` may be an older history: " + "please remove it or use a different history file."; if (idx < 0) { throw new IllegalArgumentException(badHistoryFileSyntax); } @@ -183,8 +181,7 @@ protected void addHistoryLine(Path path, String line, boolean checkDuplicates) { String unescaped = unescape(line.substring(idx + 1)); internalAdd(time, unescaped, checkDuplicates); - } - else { + } else { internalAdd(Instant.now(), unescape(line), checkDuplicates); } } @@ -210,8 +207,7 @@ public void write(Path file, boolean incremental) throws IOException { @Override public void append(Path file, boolean incremental) throws IOException { - internalWrite(file != null ? file : getPath(), - incremental ? getLastLoaded(file) : 0); + internalWrite(file != null ? file : getPath(), incremental ? getLastLoaded(file) : 0); } @Override @@ -227,8 +223,11 @@ private void internalWrite(Path path, int from) throws IOException { Files.createDirectories(parent); } // Append new items to the history file - try (BufferedWriter writer = Files.newBufferedWriter(path.toAbsolutePath(), - StandardOpenOption.WRITE, StandardOpenOption.APPEND, StandardOpenOption.CREATE)) { + try (BufferedWriter writer = Files.newBufferedWriter( + path.toAbsolutePath(), + StandardOpenOption.WRITE, + StandardOpenOption.APPEND, + StandardOpenOption.CREATE)) { for (Entry entry : items.subList(from, items.size())) { if (isPersistable(entry)) { writer.append(format(entry)); @@ -248,18 +247,23 @@ protected void trimHistory(Path path, int max) throws IOException { Log.trace("Trimming history path: ", path); // Load all history entries LinkedList allItems = new LinkedList<>(); - try (BufferedReader reader = Files.newBufferedReader(path)) { - reader.lines().forEach(l -> { - int idx = l.indexOf(':'); - Instant time = Instant.ofEpochMilli(Long.parseLong(l.substring(0, idx))); - String line = unescape(l.substring(idx + 1)); - allItems.add(createEntry(allItems.size(), time, line)); + try (BufferedReader historyFileReader = Files.newBufferedReader(path)) { + historyFileReader.lines().forEach(l -> { + if (reader.isSet(LineReader.Option.HISTORY_TIMESTAMPED)) { + int idx = l.indexOf(':'); + Instant time = Instant.ofEpochMilli(Long.parseLong(l.substring(0, idx))); + String line = unescape(l.substring(idx + 1)); + allItems.add(createEntry(allItems.size(), time, line)); + } else { + allItems.add(createEntry(allItems.size(), Instant.now(), unescape(l))); + } }); } // Remove duplicates List trimmedItems = doTrimHistory(allItems, max); // Write history - Path temp = Files.createTempFile(path.toAbsolutePath().getParent(), path.getFileName().toString(), ".tmp"); + Path temp = Files.createTempFile( + path.toAbsolutePath().getParent(), path.getFileName().toString(), ".tmp"); try (BufferedWriter writer = Files.newBufferedWriter(temp, StandardOpenOption.WRITE)) { for (Entry entry : trimmedItems) { writer.append(format(entry)); @@ -351,7 +355,7 @@ private String format(Entry entry) { public String get(final int index) { int idx = index - offset; if (idx >= items.size() || idx < 0) { - throw new IllegalArgumentException("IndexOutOfBounds: Index:" + idx +", Size:" + items.size()); + throw new IllegalArgumentException("IndexOutOfBounds: Index:" + idx + ", Size:" + items.size()); } return items.get(idx).line(); } @@ -382,8 +386,7 @@ public void add(Instant time, String line) { if (isSet(reader, LineReader.Option.HISTORY_INCREMENTAL)) { try { save(); - } - catch (IOException e) { + } catch (IOException e) { Log.warn("Failed to save history", e); } } @@ -417,7 +420,7 @@ protected void internalAdd(Instant time, String line) { protected void internalAdd(Instant time, String line, boolean checkDuplicates) { Entry entry = new EntryImpl(offset + items.size(), time, line); if (checkDuplicates) { - for (Entry e: items) { + for (Entry e : items) { if (e.line().trim().equals(line.trim())) { return; } @@ -430,7 +433,7 @@ protected void internalAdd(Instant time, String line, boolean checkDuplicates) { private void maybeResize() { while (size() > getInt(reader, LineReader.HISTORY_SIZE, DEFAULT_HISTORY_SIZE)) { items.removeFirst(); - for (HistoryFileData hfd: historyFiles.values()) { + for (HistoryFileData hfd : historyFiles.values()) { hfd.decLastLoaded(); } offset++; @@ -633,8 +636,7 @@ private static class HistoryFileData { private int lastLoaded = 0; private int entriesInFile = 0; - public HistoryFileData() { - } + public HistoryFileData() {} public HistoryFileData(int lastLoaded, int entriesInFile) { this.lastLoaded = lastLoaded; @@ -667,8 +669,5 @@ public void setEntriesInFile(int entriesInFile) { public void incEntriesInFile(int amount) { entriesInFile = entriesInFile + amount; } - } - } - diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Attributes.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Attributes.java index b1bab287e79..04959488cf1 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Attributes.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Attributes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -43,63 +43,65 @@ public enum ControlChar { * Input flags - software input processing */ public enum InputFlag { - IGNBRK, /* ignore BREAK condition */ - BRKINT, /* map BREAK to SIGINTR */ - IGNPAR, /* ignore (discard) parity errors */ - PARMRK, /* mark parity and framing errors */ - INPCK, /* enable checking of parity errors */ - ISTRIP, /* strip 8th bit off chars */ - INLCR, /* map NL into CR */ - IGNCR, /* ignore CR */ - ICRNL, /* map CR to NL (ala CRMOD) */ - IXON, /* enable output flow control */ - IXOFF, /* enable input flow control */ - IXANY, /* any char will restart after stop */ - IMAXBEL, /* ring bell on input queue full */ - IUTF8 /* maintain state for UTF-8 VERASE */ + IGNBRK, /* ignore BREAK condition */ + BRKINT, /* map BREAK to SIGINTR */ + IGNPAR, /* ignore (discard) parity errors */ + PARMRK, /* mark parity and framing errors */ + INPCK, /* enable checking of parity errors */ + ISTRIP, /* strip 8th bit off chars */ + INLCR, /* map NL into CR */ + IGNCR, /* ignore CR */ + ICRNL, /* map CR to NL (ala CRMOD) */ + IXON, /* enable output flow control */ + IXOFF, /* enable input flow control */ + IXANY, /* any char will restart after stop */ + IMAXBEL, /* ring bell on input queue full */ + IUTF8, /* maintain state for UTF-8 VERASE */ + + INORMEOL /* normalize end-of-line */ } /* * Output flags - software output processing */ public enum OutputFlag { - OPOST, /* enable following output processing */ - ONLCR, /* map NL to CR-NL (ala CRMOD) */ - OXTABS, /* expand tabs to spaces */ - ONOEOT, /* discard EOT's (^D) on output) */ - OCRNL, /* map CR to NL on output */ - ONOCR, /* no CR output at column 0 */ - ONLRET, /* NL performs CR function */ - OFILL, /* use fill characters for delay */ - NLDLY, /* \n delay */ - TABDLY, /* horizontal tab delay */ - CRDLY, /* \r delay */ - FFDLY, /* form feed delay */ - BSDLY, /* \b delay */ - VTDLY, /* vertical tab delay */ - OFDEL /* fill is DEL, else NUL */ + OPOST, /* enable following output processing */ + ONLCR, /* map NL to CR-NL (ala CRMOD) */ + OXTABS, /* expand tabs to spaces */ + ONOEOT, /* discard EOT's (^D) on output) */ + OCRNL, /* map CR to NL on output */ + ONOCR, /* no CR output at column 0 */ + ONLRET, /* NL performs CR function */ + OFILL, /* use fill characters for delay */ + NLDLY, /* \n delay */ + TABDLY, /* horizontal tab delay */ + CRDLY, /* \r delay */ + FFDLY, /* form feed delay */ + BSDLY, /* \b delay */ + VTDLY, /* vertical tab delay */ + OFDEL /* fill is DEL, else NUL */ } /* * Control flags - hardware control of terminal */ public enum ControlFlag { - CIGNORE, /* ignore control flags */ - CS5, /* 5 bits (pseudo) */ - CS6, /* 6 bits */ - CS7, /* 7 bits */ - CS8, /* 8 bits */ - CSTOPB, /* send 2 stop bits */ - CREAD, /* enable receiver */ - PARENB, /* parity enable */ - PARODD, /* odd parity, else even */ - HUPCL, /* hang up on last close */ - CLOCAL, /* ignore modem status lines */ - CCTS_OFLOW, /* CTS flow control of output */ - CRTS_IFLOW, /* RTS flow control of input */ - CDTR_IFLOW, /* DTR flow control of input */ - CDSR_OFLOW, /* DSR flow control of output */ - CCAR_OFLOW /* DCD flow control of output */ + CIGNORE, /* ignore control flags */ + CS5, /* 5 bits (pseudo) */ + CS6, /* 6 bits */ + CS7, /* 7 bits */ + CS8, /* 8 bits */ + CSTOPB, /* send 2 stop bits */ + CREAD, /* enable receiver */ + PARENB, /* parity enable */ + PARODD, /* odd parity, else even */ + HUPCL, /* hang up on last close */ + CLOCAL, /* ignore modem status lines */ + CCTS_OFLOW, /* CTS flow control of output */ + CRTS_IFLOW, /* RTS flow control of input */ + CDTR_IFLOW, /* DTR flow control of input */ + CDSR_OFLOW, /* DSR flow control of output */ + CCAR_OFLOW /* DCD flow control of output */ } /* @@ -110,23 +112,23 @@ public enum ControlFlag { * input flag. */ public enum LocalFlag { - ECHOKE, /* visual erase for line kill */ - ECHOE, /* visually erase chars */ - ECHOK, /* echo NL after line kill */ - ECHO, /* enable echoing */ - ECHONL, /* echo NL even if ECHO is off */ - ECHOPRT, /* visual erase mode for hardcopy */ - ECHOCTL, /* echo control chars as ^(Char) */ - ISIG, /* enable signals INTR, QUIT, [D]SUSP */ - ICANON, /* canonicalize input lines */ - ALTWERASE, /* use alternate WERASE algorithm */ - IEXTEN, /* enable DISCARD and LNEXT */ - EXTPROC, /* external processing */ - TOSTOP, /* stop background jobs from output */ - FLUSHO, /* output being flushed (state) */ - NOKERNINFO, /* no kernel output from VSTATUS */ - PENDIN, /* XXX retype pending input (state) */ - NOFLSH /* don't flush after interrupt */ + ECHOKE, /* visual erase for line kill */ + ECHOE, /* visually erase chars */ + ECHOK, /* echo NL after line kill */ + ECHO, /* enable echoing */ + ECHONL, /* echo NL even if ECHO is off */ + ECHOPRT, /* visual erase mode for hardcopy */ + ECHOCTL, /* echo control chars as ^(Char) */ + ISIG, /* enable signals INTR, QUIT, [D]SUSP */ + ICANON, /* canonicalize input lines */ + ALTWERASE, /* use alternate WERASE algorithm */ + IEXTEN, /* enable DISCARD and LNEXT */ + EXTPROC, /* external processing */ + TOSTOP, /* stop background jobs from output */ + FLUSHO, /* output being flushed (state) */ + NOKERNINFO, /* no kernel output from VSTATUS */ + PENDIN, /* XXX retype pending input (state) */ + NOFLSH /* don't flush after interrupt */ } final EnumSet iflag = EnumSet.noneOf(InputFlag.class); @@ -135,9 +137,9 @@ public enum LocalFlag { final EnumSet lflag = EnumSet.noneOf(LocalFlag.class); final EnumMap cchars = new EnumMap<>(ControlChar.class); - public Attributes() { - } + public Attributes() {} + @SuppressWarnings("this-escape") public Attributes(Attributes attr) { copy(attr); } @@ -310,13 +312,12 @@ public void copy(Attributes attributes) { @Override public String toString() { - return "Attributes[" + - "lflags: " + append(lflag) + ", " + - "iflags: " + append(iflag) + ", " + - "oflags: " + append(oflag) + ", " + - "cflags: " + append(cflag) + ", " + - "cchars: " + append(EnumSet.allOf(ControlChar.class), this::display) + - "]"; + return "Attributes[" + "lflags: " + + append(lflag) + ", " + "iflags: " + + append(iflag) + ", " + "oflags: " + + append(oflag) + ", " + "cflags: " + + append(cflag) + ", " + "cchars: " + + append(EnumSet.allOf(ControlChar.class), this::display) + "]"; } private String display(ControlChar c) { @@ -345,5 +346,4 @@ private > String append(EnumSet set) { private > String append(EnumSet set, Function toString) { return set.stream().map(toString).collect(Collectors.joining(" ")); } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Cursor.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Cursor.java index c561349cb0f..9bc3d902849 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Cursor.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Cursor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/MouseEvent.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/MouseEvent.java index df59e3f41b2..059b43c51ae 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/MouseEvent.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/MouseEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -71,12 +71,11 @@ public int getY() { @Override public String toString() { - return "MouseEvent[" + - "type=" + type + - ", button=" + button + - ", modifiers=" + modifiers + - ", x=" + x + - ", y=" + y + - ']'; + return "MouseEvent[" + "type=" + + type + ", button=" + + button + ", modifiers=" + + modifiers + ", x=" + + x + ", y=" + + y + ']'; } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Size.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Size.java index 29870ad626c..fde3bf35959 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Size.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Size.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -13,9 +13,9 @@ public class Size { private int rows; private int cols; - public Size() { - } + public Size() {} + @SuppressWarnings("this-escape") public Size(int columns, int rows) { this(); setColumns(columns); @@ -50,7 +50,7 @@ public void setRows(int rows) { * @return the cursor position */ public int cursorPos(int row, int col) { - return row * (cols+1) + col; + return row * (cols + 1) + col; } public void copy(Size size) { diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Terminal.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Terminal.java index 38ffb029f60..054915e133d 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Terminal.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/Terminal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -34,6 +34,7 @@ public interface Terminal extends Closeable, Flushable { * Type used for dumb terminals. */ String TYPE_DUMB = "dumb"; + String TYPE_DUMB_COLOR = "dumb-color"; String getName(); @@ -42,6 +43,9 @@ public interface Terminal extends Closeable, Flushable { // Signal support // + /** + * Types of signals. + */ enum Signal { INT, QUIT, @@ -51,16 +55,55 @@ enum Signal { WINCH } + /** + * The SignalHandler defines the interface used to trap signals and perform specific behaviors. + * @see Terminal.Signal + * @see Terminal#handle(Signal, SignalHandler) + */ interface SignalHandler { + /** + * The {@code SIG_DFL} value can be used to specify that the JVM default behavior + * should be used to handle this signal. + */ SignalHandler SIG_DFL = NativeSignalHandler.SIG_DFL; + + /** + * The {@code SIG_IGN} value can be used to ignore this signal and not perform + * any special processing. + */ SignalHandler SIG_IGN = NativeSignalHandler.SIG_IGN; + /** + * Handle the signal. + * @param signal the signal + */ void handle(Signal signal); } + /** + * Registers a handler for the given {@link Signal}. + *

+ * Note that the JVM does not easily allow catching the {@link Signal#QUIT} signal, which causes a thread dump + * to be displayed. This signal is mainly used when connecting through an SSH socket to a virtual terminal. + * + * @param signal the signal to register a handler for + * @param handler the handler + * @return the previous signal handler + */ SignalHandler handle(Signal signal, SignalHandler handler); + /** + * Raise the specific signal. + * This is not method usually called by non system terminals. + * When accessing a terminal through a SSH or Telnet connection, signals may be + * conveyed by the protocol and thus need to be raised when reaching the terminal code. + * The terminals do that automatically when the terminal input stream has a character + * mapped to {@link Attributes.ControlChar#VINTR}, {@link Attributes.ControlChar#VQUIT}, + * or {@link Attributes.ControlChar#VSUSP}. + * + * @param signal the signal to raise + */ void raise(Signal signal); // @@ -180,8 +223,21 @@ interface SignalHandler { boolean echo(boolean echo); + /** + * Returns the terminal attributes. + * The returned object can be safely modified + * further used in a call to {@link #setAttributes(Attributes)}. + * + * @return the terminal attributes. + */ Attributes getAttributes(); + /** + * Set the terminal attributes. + * The terminal will perform a copy of the given attributes. + * + * @param attr the new attributes + */ void setAttributes(Attributes attr); /** @@ -334,5 +390,4 @@ enum MouseTracking { * Color support */ ColorPalette getPalette(); - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/TerminalBuilder.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/TerminalBuilder.java index 8c047e37342..3b02ec2d8d8 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/TerminalBuilder.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/TerminalBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2021, the original author or authors. + * Copyright (c) 2002-2021, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -8,9 +8,6 @@ */ package jdk.internal.org.jline.terminal; -import java.io.FileDescriptor; -import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -19,11 +16,16 @@ import java.nio.charset.StandardCharsets; import java.nio.charset.UnsupportedCharsetException; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Optional; import java.util.ServiceLoader; +import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Function; import java.util.stream.Collectors; @@ -31,8 +33,10 @@ import jdk.internal.org.jline.terminal.impl.AbstractPosixTerminal; import jdk.internal.org.jline.terminal.impl.AbstractTerminal; -import jdk.internal.org.jline.terminal.impl.AbstractWindowsTerminal; import jdk.internal.org.jline.terminal.impl.DumbTerminal; +import jdk.internal.org.jline.terminal.impl.DumbTerminalProvider; +import jdk.internal.org.jline.terminal.spi.SystemStream; +import jdk.internal.org.jline.terminal.spi.TerminalExt; import jdk.internal.org.jline.terminal.spi.TerminalProvider; import jdk.internal.org.jline.utils.Log; import jdk.internal.org.jline.utils.OSUtils; @@ -49,16 +53,30 @@ public final class TerminalBuilder { public static final String PROP_ENCODING = "org.jline.terminal.encoding"; public static final String PROP_CODEPAGE = "org.jline.terminal.codepage"; public static final String PROP_TYPE = "org.jline.terminal.type"; - public static final String PROP_JNA = "org.jline.terminal.jna"; - public static final String PROP_JANSI = "org.jline.terminal.jansi"; - public static final String PROP_EXEC = "org.jline.terminal.exec"; - public static final String PROP_DUMB = "org.jline.terminal.dumb"; + public static final String PROP_PROVIDER = "org.jline.terminal.provider"; + public static final String PROP_PROVIDERS = "org.jline.terminal.providers"; + public static final String PROP_PROVIDER_FFM = "ffm"; + public static final String PROP_PROVIDER_JNI = "jni"; + public static final String PROP_PROVIDER_JANSI = "jansi"; + public static final String PROP_PROVIDER_JNA = "jna"; + public static final String PROP_PROVIDER_EXEC = "exec"; + public static final String PROP_PROVIDER_DUMB = "dumb"; + public static final String PROP_PROVIDERS_DEFAULT = String.join( + ",", PROP_PROVIDER_FFM, PROP_PROVIDER_JNI, PROP_PROVIDER_JANSI, PROP_PROVIDER_JNA, PROP_PROVIDER_EXEC); + public static final String PROP_FFM = "org.jline.terminal." + PROP_PROVIDER_FFM; + public static final String PROP_JNI = "org.jline.terminal." + PROP_PROVIDER_JNI; + public static final String PROP_JANSI = "org.jline.terminal." + PROP_PROVIDER_JANSI; + public static final String PROP_JNA = "org.jline.terminal." + PROP_PROVIDER_JNA; + public static final String PROP_EXEC = "org.jline.terminal." + PROP_PROVIDER_EXEC; + public static final String PROP_DUMB = "org.jline.terminal." + PROP_PROVIDER_DUMB; public static final String PROP_DUMB_COLOR = "org.jline.terminal.dumb.color"; public static final String PROP_OUTPUT = "org.jline.terminal.output"; public static final String PROP_OUTPUT_OUT = "out"; public static final String PROP_OUTPUT_ERR = "err"; public static final String PROP_OUTPUT_OUT_ERR = "out-err"; public static final String PROP_OUTPUT_ERR_OUT = "err-out"; + public static final String PROP_OUTPUT_FORCED_OUT = "forced-out"; + public static final String PROP_OUTPUT_FORCED_ERR = "forced-err"; // // Other system properties controlling various jline parts @@ -68,6 +86,32 @@ public final class TerminalBuilder { public static final String PROP_COLOR_DISTANCE = "org.jline.utils.colorDistance"; public static final String PROP_DISABLE_ALTERNATE_CHARSET = "org.jline.utils.disableAlternateCharset"; + // + // System properties controlling how FileDescriptor are create. + // The value can be a comma separated list of defined mechanisms. + // + public static final String PROP_FILE_DESCRIPTOR_CREATION_MODE = "org.jline.terminal.pty.fileDescriptorCreationMode"; + public static final String PROP_FILE_DESCRIPTOR_CREATION_MODE_NATIVE = "native"; + public static final String PROP_FILE_DESCRIPTOR_CREATION_MODE_REFLECTION = "reflection"; + public static final String PROP_FILE_DESCRIPTOR_CREATION_MODE_DEFAULT = + String.join(",", PROP_FILE_DESCRIPTOR_CREATION_MODE_REFLECTION, PROP_FILE_DESCRIPTOR_CREATION_MODE_NATIVE); + + // + // System properties controlling how RedirectPipe are created. + // The value can be a comma separated list of defined mechanisms. + // + public static final String PROP_REDIRECT_PIPE_CREATION_MODE = "org.jline.terminal.exec.redirectPipeCreationMode"; + public static final String PROP_REDIRECT_PIPE_CREATION_MODE_NATIVE = "native"; + public static final String PROP_REDIRECT_PIPE_CREATION_MODE_REFLECTION = "reflection"; + public static final String PROP_REDIRECT_PIPE_CREATION_MODE_DEFAULT = + String.join(",", PROP_REDIRECT_PIPE_CREATION_MODE_REFLECTION, PROP_REDIRECT_PIPE_CREATION_MODE_NATIVE); + + public static final Set DEPRECATED_PROVIDERS = + Collections.unmodifiableSet(new HashSet<>(Arrays.asList(PROP_PROVIDER_JNA, PROP_PROVIDER_JANSI))); + + public static final String PROP_DISABLE_DEPRECATED_PROVIDER_WARNING = + "org.jline.terminal.disableDeprecatedProviderWarning"; + // // Terminal output control // @@ -75,7 +119,9 @@ public enum SystemOutput { SysOut, SysErr, SysOutOrSysErr, - SysErrOrSysOut + SysErrOrSysOut, + ForcedSysOut, + ForcedSysErr } /** @@ -115,20 +161,23 @@ public static TerminalBuilder builder() { private int codepage; private Boolean system; private SystemOutput systemOutput; + private String provider; + private String providers; private Boolean jna; private Boolean jansi; + private Boolean jni; private Boolean exec; + private Boolean ffm; private Boolean dumb; private Boolean color; private Attributes attributes; private Size size; - private boolean nativeSignals = false; + private boolean nativeSignals = true; private Function inputStreamWrapper = in -> in; private Terminal.SignalHandler signalHandler = Terminal.SignalHandler.SIG_DFL; private boolean paused = false; - private TerminalBuilder() { - } + private TerminalBuilder() {} public TerminalBuilder name(String name) { this.name = name; @@ -160,6 +209,16 @@ public TerminalBuilder systemOutput(SystemOutput systemOutput) { return this; } + public TerminalBuilder provider(String provider) { + this.provider = provider; + return this; + } + + public TerminalBuilder providers(String providers) { + this.providers = providers; + return this; + } + public TerminalBuilder jna(boolean jna) { this.jna = jna; return this; @@ -170,11 +229,21 @@ public TerminalBuilder jansi(boolean jansi) { return this; } + public TerminalBuilder jni(boolean jni) { + this.jni = jni; + return this; + } + public TerminalBuilder exec(boolean exec) { this.exec = exec; return this; } + public TerminalBuilder ffm(boolean ffm) { + this.ffm = ffm; + return this; + } + public TerminalBuilder dumb(boolean dumb) { this.dumb = dumb; return this; @@ -280,6 +349,12 @@ public TerminalBuilder nativeSignals(boolean nativeSignals) { return this; } + /** + * Determines the default value for signal handlers. + * All signals will be mapped to the given handler. + * @param signalHandler the default signal handler + * @return The builder + */ public TerminalBuilder signalHandler(Terminal.SignalHandler signalHandler) { this.signalHandler = signalHandler; return this; @@ -305,6 +380,11 @@ public TerminalBuilder paused(boolean paused) { return this; } + /** + * Builds the terminal. + * @return the newly created terminal, never {@code null} + * @throws IOException if an error occurs + */ public Terminal build() throws IOException { Terminal override = TERMINAL_OVERRIDE.get(); Terminal terminal = override != null ? override : doBuild(); @@ -313,7 +393,8 @@ public Terminal build() throws IOException { } Log.debug(() -> "Using terminal " + terminal.getClass().getSimpleName()); if (terminal instanceof AbstractPosixTerminal) { - Log.debug(() -> "Using pty " + ((AbstractPosixTerminal) terminal).getPty().getClass().getSimpleName()); + Log.debug(() -> "Using pty " + + ((AbstractPosixTerminal) terminal).getPty().getClass().getSimpleName()); } return terminal; } @@ -323,144 +404,76 @@ private Terminal doBuild() throws IOException { if (name == null) { name = "JLine terminal"; } - Charset encoding = this.encoding; - if (encoding == null) { - String charsetName = System.getProperty(PROP_ENCODING); - if (charsetName != null && Charset.isSupported(charsetName)) { - encoding = Charset.forName(charsetName); - } - } - if (encoding == null) { - int codepage = this.codepage; - if (codepage <= 0) { - String str = System.getProperty(PROP_CODEPAGE); - if (str != null) { - codepage = Integer.parseInt(str); - } - } - if (codepage >= 0) { - encoding = getCodepageCharset(codepage); - } else { - encoding = StandardCharsets.UTF_8; - } - } - String type = this.type; - if (type == null) { - type = System.getProperty(PROP_TYPE); - } - if (type == null) { - type = System.getenv("TERM"); - } - Boolean jna = this.jna; - if (jna == null) { - jna = getBoolean(PROP_JNA, true); - } - Boolean jansi = this.jansi; - if (jansi == null) { - jansi = getBoolean(PROP_JANSI, true); - } - Boolean exec = this.exec; - if (exec == null) { - exec = getBoolean(PROP_EXEC, true); + Charset encoding = computeEncoding(); + String type = computeType(); + + String provider = this.provider; + if (provider == null) { + provider = System.getProperty(PROP_PROVIDER, null); } + + boolean forceDumb = + (DumbTerminal.TYPE_DUMB.equals(type) || type != null && type.startsWith(DumbTerminal.TYPE_DUMB_COLOR)) + || (provider != null && provider.equals(PROP_PROVIDER_DUMB)); Boolean dumb = this.dumb; if (dumb == null) { dumb = getBoolean(PROP_DUMB, null); } IllegalStateException exception = new IllegalStateException("Unable to create a terminal"); - List providers = new ArrayList<>(); - if (jna) { - try { - TerminalProvider provider = TerminalProvider.load("jna"); - providers.add(provider); - } catch (Throwable t) { - Log.debug("Unable to load JNA support: ", t); - exception.addSuppressed(t); - } - } - if (jansi) { - try { - TerminalProvider provider = TerminalProvider.load("jansi"); - providers.add(provider); - } catch (Throwable t) { - Log.debug("Unable to load JANSI support: ", t); - exception.addSuppressed(t); - } - } - if (exec) - { - try { - TerminalProvider provider = TerminalProvider.load("exec"); - providers.add(provider); - } catch (Throwable t) { - Log.debug("Unable to load EXEC support: ", t); - exception.addSuppressed(t); - } - } - + List providers = getProviders(provider, exception); Terminal terminal = null; if ((system != null && system) || (system == null && in == null && out == null)) { - if (system != null && ((in != null && !in.equals(System.in)) || - (out != null && !out.equals(System.out) && !out.equals(System.err)))) { + if (system != null + && ((in != null && !in.equals(System.in)) + || (out != null && !out.equals(System.out) && !out.equals(System.err)))) { throw new IllegalArgumentException("Cannot create a system terminal using non System streams"); } if (attributes != null || size != null) { Log.warn("Attributes and size fields are ignored when creating a system terminal"); } - if (out != null) { - if (out.equals(System.out)) { - systemOutput = SystemOutput.SysOut; - } else if (out.equals(System.err)) { - systemOutput = SystemOutput.SysErr; - } - } - if (systemOutput == null) { - String str = System.getProperty(PROP_OUTPUT); - if (str != null) { - switch (str.trim().toLowerCase(Locale.ROOT)) { - case PROP_OUTPUT_OUT: systemOutput = SystemOutput.SysOut; break; - case PROP_OUTPUT_ERR: systemOutput = SystemOutput.SysErr; break; - case PROP_OUTPUT_OUT_ERR: systemOutput = SystemOutput.SysOutOrSysErr; break; - case PROP_OUTPUT_ERR_OUT: systemOutput = SystemOutput.SysErrOrSysOut; break; - default: - Log.debug("Unsupported value for " + PROP_OUTPUT + ": " + str + ". Supported values are: " - + String.join(", ", PROP_OUTPUT_OUT, PROP_OUTPUT_ERR, PROP_OUTPUT_OUT_ERR,PROP_OUTPUT_ERR_OUT) - + "."); - } - } - } - if (systemOutput == null) { - systemOutput = SystemOutput.SysOutOrSysErr; - } - Map system = Stream.of(TerminalProvider.Stream.values()) - .collect(Collectors.toMap(stream -> stream, stream -> providers.stream().anyMatch(p -> p.isSystemStream(stream)))); - TerminalProvider.Stream console = select(system, systemOutput); + SystemOutput systemOutput = computeSystemOutput(); + Map system = Stream.of(SystemStream.values()) + .collect(Collectors.toMap( + stream -> stream, stream -> providers.stream().anyMatch(p -> p.isSystemStream(stream)))); + SystemStream systemStream = select(system, systemOutput); - if (system.get(TerminalProvider.Stream.Input) && console != null) { + if (!forceDumb && system.get(SystemStream.Input) && systemStream != null) { if (attributes != null || size != null) { Log.warn("Attributes and size fields are ignored when creating a system terminal"); } boolean ansiPassThrough = OSUtils.IS_CONEMU; // Cygwin defaults to XTERM, but actually supports 256 colors, // so if the value comes from the environment, change it to xterm-256color - if ((OSUtils.IS_CYGWIN || OSUtils.IS_MSYSTEM) && "xterm".equals(type) - && this.type == null && System.getProperty(PROP_TYPE) == null) { + if ((OSUtils.IS_CYGWIN || OSUtils.IS_MSYSTEM) + && "xterm".equals(type) + && this.type == null + && System.getProperty(PROP_TYPE) == null) { type = "xterm-256color"; } - for ( TerminalProvider provider : providers) { + for (TerminalProvider prov : providers) { if (terminal == null) { try { - terminal = provider.sysTerminal(name, type, ansiPassThrough, encoding, - nativeSignals, signalHandler, paused, console, inputStreamWrapper); + terminal = prov.sysTerminal( + name, + type, + ansiPassThrough, + encoding, + nativeSignals, + signalHandler, + paused, + systemStream, + inputStreamWrapper); } catch (Throwable t) { - Log.debug("Error creating " + provider.name() + " based terminal: ", t.getMessage(), t); + Log.debug("Error creating " + prov.name() + " based terminal: ", t.getMessage(), t); exception.addSuppressed(t); } } } - if (terminal == null && OSUtils.IS_WINDOWS && !jna && !jansi && (dumb == null || !dumb)) { - throw new IllegalStateException("Unable to create a system terminal. On windows, either " - + "JNA or JANSI library is required. Make sure to add one of those in the classpath."); + if (terminal == null && OSUtils.IS_WINDOWS && providers.isEmpty() && (dumb == null || !dumb)) { + throw new IllegalStateException( + "Unable to create a system terminal. On Windows, either JLine's native libraries, JNA " + + "or Jansi library is required. Make sure to add one of those in the classpath.", + exception); } } if (terminal instanceof AbstractTerminal) { @@ -468,54 +481,42 @@ private Terminal doBuild() throws IOException { if (SYSTEM_TERMINAL.compareAndSet(null, t)) { t.setOnClose(() -> SYSTEM_TERMINAL.compareAndSet(t, null)); } else { - exception.addSuppressed(new IllegalStateException("A system terminal is already running. " + - "Make sure to use the created system Terminal on the LineReaderBuilder if you're using one " + - "or that previously created system Terminals have been correctly closed.")); + exception.addSuppressed(new IllegalStateException("A system terminal is already running. " + + "Make sure to use the created system Terminal on the LineReaderBuilder if you're using one " + + "or that previously created system Terminals have been correctly closed.")); terminal.close(); terminal = null; } } - if (terminal == null && (dumb == null || dumb)) { - // forced colored dumb terminal - Boolean color = this.color; - if (color == null) { - color = getBoolean(PROP_DUMB_COLOR, false); - // detect emacs using the env variable - if (!color) { - String emacs = System.getenv("INSIDE_EMACS"); - color = emacs != null && emacs.contains("comint"); - } - // detect Intellij Idea - if (!color) { - String command = getParentProcessCommand(); - color = command != null && command.contains("idea"); - } - if (!color) { - color = system.get(TerminalProvider.Stream.Output) && System.getenv("TERM") != null; - } - if (!color && dumb == null) { - if (Log.isDebugEnabled()) { - Log.warn("input is tty: {}", system.get(TerminalProvider.Stream.Input)); - Log.warn("output is tty: {}", system.get(TerminalProvider.Stream.Output)); - Log.warn("error is tty: {}", system.get(TerminalProvider.Stream.Error)); - Log.warn("Creating a dumb terminal", exception); - } else { - Log.warn("Unable to create a system terminal, creating a dumb terminal (enable debug logging for more information)"); - } + if (terminal == null && (forceDumb || dumb == null || dumb)) { + if (!forceDumb && dumb == null) { + if (Log.isDebugEnabled()) { + Log.warn("input is tty: " + system.get(SystemStream.Input)); + Log.warn("output is tty: " + system.get(SystemStream.Output)); + Log.warn("error is tty: " + system.get(SystemStream.Error)); + Log.warn("Creating a dumb terminal", exception); + } else { + Log.warn( + "Unable to create a system terminal, creating a dumb terminal (enable debug logging for more information)"); } } - terminal = new DumbTerminal(name, color ? Terminal.TYPE_DUMB_COLOR : Terminal.TYPE_DUMB, - new FileInputStream(FileDescriptor.in), - new FileOutputStream(console == TerminalProvider.Stream.Output ? FileDescriptor.out : FileDescriptor.err), - encoding, signalHandler); + type = getDumbTerminalType(dumb, systemStream); + terminal = new DumbTerminalProvider() + .sysTerminal(name, type, false, encoding, nativeSignals, signalHandler, paused, systemStream, inputStreamWrapper); + if (OSUtils.IS_WINDOWS) { + Attributes attr = terminal.getAttributes(); + attr.setInputFlag(Attributes.InputFlag.IGNCR, true); + terminal.setAttributes(attr); + } } } else { - for ( TerminalProvider provider : providers) { + for (TerminalProvider prov : providers) { if (terminal == null) { try { - terminal = provider.newTerminal(name, type, inputStreamWrapper.apply(in), out, encoding, signalHandler, paused, attributes, size); + terminal = prov.newTerminal( + name, type, in, out, encoding, signalHandler, paused, attributes, size); } catch (Throwable t) { - Log.debug("Error creating " + provider.name() + " based terminal: ", t.getMessage(), t); + Log.debug("Error creating " + prov.name() + " based terminal: ", t.getMessage(), t); exception.addSuppressed(t); } } @@ -524,25 +525,220 @@ private Terminal doBuild() throws IOException { if (terminal == null) { throw exception; } + if (terminal instanceof TerminalExt) { + TerminalExt te = (TerminalExt) terminal; + if (DEPRECATED_PROVIDERS.contains(te.getProvider().name()) + && !getBoolean(PROP_DISABLE_DEPRECATED_PROVIDER_WARNING, false)) { + Log.warn("The terminal provider " + te.getProvider().name() + + " has been deprecated, check your configuration. This warning can be disabled by setting the system property " + + PROP_DISABLE_DEPRECATED_PROVIDER_WARNING + " to true."); + } + } return terminal; } - private TerminalProvider.Stream select(Map system, SystemOutput systemOutput) { + private String getDumbTerminalType(Boolean dumb, SystemStream systemStream) { + // forced colored dumb terminal + Boolean color = this.color; + if (color == null) { + color = getBoolean(PROP_DUMB_COLOR, null); + } + if (dumb == null) { + // detect emacs using the env variable + if (color == null) { + String emacs = System.getenv("INSIDE_EMACS"); + if (emacs != null && emacs.contains("comint")) { + color = true; + } + } + // detect Intellij Idea + if (color == null) { + // using the env variable on windows + String ideHome = System.getenv("IDE_HOME"); + if (ideHome != null) { + color = true; + } else { + // using the parent process command on unix/mac + String command = getParentProcessCommand(); + if (command != null && command.endsWith("/idea")) { + color = true; + } + } + } + if (color == null) { + color = systemStream != null && System.getenv("TERM") != null; + } + } else { + if (color == null) { + color = false; + } + } + return color ? Terminal.TYPE_DUMB_COLOR : Terminal.TYPE_DUMB; + } + + public SystemOutput computeSystemOutput() { + SystemOutput systemOutput = null; + if (out != null) { + if (out.equals(System.out)) { + systemOutput = SystemOutput.SysOut; + } else if (out.equals(System.err)) { + systemOutput = SystemOutput.SysErr; + } + } + if (systemOutput == null) { + systemOutput = this.systemOutput; + } + if (systemOutput == null) { + String str = System.getProperty(PROP_OUTPUT); + if (str != null) { + switch (str.trim().toLowerCase(Locale.ROOT)) { + case PROP_OUTPUT_OUT: + systemOutput = SystemOutput.SysOut; + break; + case PROP_OUTPUT_ERR: + systemOutput = SystemOutput.SysErr; + break; + case PROP_OUTPUT_OUT_ERR: + systemOutput = SystemOutput.SysOutOrSysErr; + break; + case PROP_OUTPUT_ERR_OUT: + systemOutput = SystemOutput.SysErrOrSysOut; + break; + case PROP_OUTPUT_FORCED_OUT: + systemOutput = SystemOutput.ForcedSysOut; + break; + case PROP_OUTPUT_FORCED_ERR: + systemOutput = SystemOutput.ForcedSysErr; + break; + default: + Log.debug("Unsupported value for " + PROP_OUTPUT + ": " + str + ". Supported values are: " + + String.join( + ", ", + PROP_OUTPUT_OUT, + PROP_OUTPUT_ERR, + PROP_OUTPUT_OUT_ERR, + PROP_OUTPUT_ERR_OUT) + + "."); + } + } + } + if (systemOutput == null) { + systemOutput = SystemOutput.SysOutOrSysErr; + } + return systemOutput; + } + + public String computeType() { + String type = this.type; + if (type == null) { + type = System.getProperty(PROP_TYPE); + } + if (type == null) { + type = System.getenv("TERM"); + } + return type; + } + + public Charset computeEncoding() { + Charset encoding = this.encoding; + if (encoding == null) { + String charsetName = System.getProperty(PROP_ENCODING); + if (charsetName != null && Charset.isSupported(charsetName)) { + encoding = Charset.forName(charsetName); + } + } + if (encoding == null) { + int codepage = this.codepage; + if (codepage <= 0) { + String str = System.getProperty(PROP_CODEPAGE); + if (str != null) { + codepage = Integer.parseInt(str); + } + } + if (codepage >= 0) { + encoding = getCodepageCharset(codepage); + } else { + encoding = StandardCharsets.UTF_8; + } + } + return encoding; + } + + /** + * Get the list of available terminal providers. + * This list is sorted according to the {@link #PROP_PROVIDERS} system property. + * @param provider if not {@code null}, only this provider will be checked + * @param exception if a provider throws an exception, it will be added to this exception as a suppressed exception + * @return a list of terminal providers + */ + public List getProviders(String provider, IllegalStateException exception) { + List providers = new ArrayList<>(); + // Check ffm provider + checkProvider(provider, exception, providers, ffm, PROP_FFM, PROP_PROVIDER_FFM); + // Check jni provider + checkProvider(provider, exception, providers, jni, PROP_JNI, PROP_PROVIDER_JNI); + // Check jansi provider + checkProvider(provider, exception, providers, jansi, PROP_JANSI, PROP_PROVIDER_JANSI); + // Check jna provider + checkProvider(provider, exception, providers, jna, PROP_JNA, PROP_PROVIDER_JNA); + // Check exec provider + checkProvider(provider, exception, providers, exec, PROP_EXEC, PROP_PROVIDER_EXEC); + // Order providers + List order = Arrays.asList( + (this.providers != null ? this.providers : System.getProperty(PROP_PROVIDERS, PROP_PROVIDERS_DEFAULT)) + .split(",")); + providers.sort(Comparator.comparing(l -> { + int idx = order.indexOf(l.name()); + return idx >= 0 ? idx : Integer.MAX_VALUE; + })); + String names = providers.stream().map(TerminalProvider::name).collect(Collectors.joining(", ")); + Log.debug("Available providers: " + names); + return providers; + } + + private void checkProvider( + String provider, + IllegalStateException exception, + List providers, + Boolean load, + String property, + String name) { + Boolean doLoad = provider != null ? (Boolean) name.equals(provider) : load; + if (doLoad == null) { + doLoad = getBoolean(property, true); + } + if (doLoad) { + try { + TerminalProvider prov = TerminalProvider.load(name); + prov.isSystemStream(SystemStream.Output); + providers.add(prov); + } catch (Throwable t) { + Log.debug("Unable to load " + name + " provider: ", t); + exception.addSuppressed(t); + } + } + } + + private SystemStream select(Map system, SystemOutput systemOutput) { switch (systemOutput) { case SysOut: - return select(system, TerminalProvider.Stream.Output); + return select(system, SystemStream.Output); case SysErr: - return select(system, TerminalProvider.Stream.Error); + return select(system, SystemStream.Error); case SysOutOrSysErr: - return select(system, TerminalProvider.Stream.Output, TerminalProvider.Stream.Error); + return select(system, SystemStream.Output, SystemStream.Error); case SysErrOrSysOut: - return select(system, TerminalProvider.Stream.Error, TerminalProvider.Stream.Output); + return select(system, SystemStream.Error, SystemStream.Output); + case ForcedSysOut: + return SystemStream.Output; + case ForcedSysErr: + return SystemStream.Error; } return null; } - private static TerminalProvider.Stream select(Map system, TerminalProvider.Stream... streams) { - for (TerminalProvider.Stream s : streams) { + private static SystemStream select(Map system, SystemStream... streams) { + for (SystemStream s : streams) { if (system.get(s)) { return s; } @@ -557,7 +753,9 @@ private static String getParentProcessCommand() { Object parent = ((Optional) phClass.getMethod("parent").invoke(current)).orElse(null); Method infoMethod = phClass.getMethod("info"); Object info = infoMethod.invoke(parent); - Object command = ((Optional) infoMethod.getReturnType().getMethod("command").invoke(info)).orElse(null); + Object command = ((Optional) + infoMethod.getReturnType().getMethod("command").invoke(info)) + .orElse(null); return (String) command; } catch (Throwable t) { return null; @@ -582,7 +780,7 @@ private static S load(Class clazz) { private static final int UTF8_CODE_PAGE = 65001; private static Charset getCodepageCharset(int codepage) { - //http://docs.oracle.com/javase/6/docs/technotes/guides/intl/encoding.doc.html + // http://docs.oracle.com/javase/6/docs/technotes/guides/intl/encoding.doc.html if (codepage == UTF8_CODE_PAGE) { return StandardCharsets.UTF_8; } @@ -629,5 +827,4 @@ private static Charset getCodepageCharset(int codepage) { public static void setTerminalOverride(final Terminal terminal) { TERMINAL_OVERRIDE.set(terminal); } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractPosixTerminal.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractPosixTerminal.java index b5f55b80f1e..5d000d07083 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractPosixTerminal.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractPosixTerminal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -18,6 +18,8 @@ import jdk.internal.org.jline.terminal.Cursor; import jdk.internal.org.jline.terminal.Size; import jdk.internal.org.jline.terminal.spi.Pty; +import jdk.internal.org.jline.terminal.spi.SystemStream; +import jdk.internal.org.jline.terminal.spi.TerminalProvider; public abstract class AbstractPosixTerminal extends AbstractTerminal { @@ -28,7 +30,8 @@ public AbstractPosixTerminal(String name, String type, Pty pty) throws IOExcepti this(name, type, pty, null, SignalHandler.SIG_DFL); } - public AbstractPosixTerminal(String name, String type, Pty pty, Charset encoding, SignalHandler signalHandler) throws IOException { + public AbstractPosixTerminal(String name, String type, Pty pty, Charset encoding, SignalHandler signalHandler) + throws IOException { super(name, type, encoding, signalHandler); Objects.requireNonNull(pty); this.pty = pty; @@ -82,4 +85,13 @@ public Cursor getCursorPosition(IntConsumer discarded) { return CursorSupport.getCursorPosition(this, discarded); } + @Override + public TerminalProvider getProvider() { + return getPty().getProvider(); + } + + @Override + public SystemStream getSystemStream() { + return getPty().getSystemStream(); + } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractPty.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractPty.java index 0feab84fc7e..3fbe63f3c5d 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractPty.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractPty.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2019, the original author or authors. + * Copyright (c) 2002-2019, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -8,20 +8,39 @@ */ package jdk.internal.org.jline.terminal.impl; -import jdk.internal.org.jline.terminal.Attributes; -import jdk.internal.org.jline.terminal.spi.Pty; -import jdk.internal.org.jline.utils.NonBlockingInputStream; - +import java.io.FileDescriptor; +import java.io.FilterInputStream; import java.io.IOError; import java.io.IOException; import java.io.InputStream; import java.io.InterruptedIOException; +import java.lang.reflect.Field; + +//import jdk.internal.org.jline.nativ.JLineLibrary; +//import jdk.internal.org.jline.nativ.JLineNativeLoader; +import jdk.internal.org.jline.terminal.Attributes; +import jdk.internal.org.jline.terminal.spi.Pty; +import jdk.internal.org.jline.terminal.spi.SystemStream; +import jdk.internal.org.jline.terminal.spi.TerminalProvider; +import jdk.internal.org.jline.utils.NonBlockingInputStream; +import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_FILE_DESCRIPTOR_CREATION_MODE; +import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_FILE_DESCRIPTOR_CREATION_MODE_DEFAULT; +import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_FILE_DESCRIPTOR_CREATION_MODE_NATIVE; +import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_FILE_DESCRIPTOR_CREATION_MODE_REFLECTION; import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_NON_BLOCKING_READS; public abstract class AbstractPty implements Pty { + protected final TerminalProvider provider; + protected final SystemStream systemStream; private Attributes current; + private boolean skipNextLf; + + public AbstractPty(TerminalProvider provider, SystemStream systemStream) { + this.provider = provider; + this.systemStream = systemStream; + } @Override public void setAttr(Attributes attr) throws IOException { @@ -32,10 +51,32 @@ public void setAttr(Attributes attr) throws IOException { @Override public InputStream getSlaveInput() throws IOException { InputStream si = doGetSlaveInput(); + InputStream nsi = new FilterInputStream(si) { + @Override + public int read() throws IOException { + for (; ; ) { + int c = super.read(); + if (current.getInputFlag(Attributes.InputFlag.INORMEOL)) { + if (c == '\r') { + skipNextLf = true; + c = '\n'; + } else if (c == '\n') { + if (skipNextLf) { + skipNextLf = false; + continue; + } + } else { + skipNextLf = false; + } + } + return c; + } + } + }; if (Boolean.parseBoolean(System.getProperty(PROP_NON_BLOCKING_READS, "true"))) { - return new PtyInputStream(si); + return new PtyInputStream(nsi); } else { - return si; + return nsi; } } @@ -49,6 +90,16 @@ protected void checkInterrupted() throws InterruptedIOException { } } + @Override + public TerminalProvider getProvider() { + return provider; + } + + @Override + public SystemStream getSystemStream() { + return systemStream; + } + class PtyInputStream extends NonBlockingInputStream { final InputStream in; int c = 0; @@ -102,4 +153,103 @@ private void setNonBlocking() { } } + private static FileDescriptorCreator fileDescriptorCreator; + + protected static FileDescriptor newDescriptor(int fd) { + if (fileDescriptorCreator == null) { + String str = + System.getProperty(PROP_FILE_DESCRIPTOR_CREATION_MODE, PROP_FILE_DESCRIPTOR_CREATION_MODE_DEFAULT); + String[] modes = str.split(","); + IllegalStateException ise = new IllegalStateException("Unable to create FileDescriptor"); + for (String mode : modes) { + try { + switch (mode) { + case PROP_FILE_DESCRIPTOR_CREATION_MODE_NATIVE: + fileDescriptorCreator = null;//new NativeFileDescriptorCreator(); + break; + case PROP_FILE_DESCRIPTOR_CREATION_MODE_REFLECTION: + fileDescriptorCreator = new ReflectionFileDescriptorCreator(); + break; + } + } catch (Throwable t) { + // ignore + ise.addSuppressed(t); + } + if (fileDescriptorCreator != null) { + break; + } + } + if (fileDescriptorCreator == null) { + throw ise; + } + } + return fileDescriptorCreator.newDescriptor(fd); + } + + interface FileDescriptorCreator { + FileDescriptor newDescriptor(int fd); + } + + /* + * Class that could be used on OpenJDK 17. However, it requires the following JVM option + * --add-exports java.base/jdk.internal.access=ALL-UNNAMED + * so the benefit does not seem important enough to warrant the problems caused + * by access the jdk.internal.access package at compile time, which itself requires + * custom compiler options and a different maven module, or at least a different compile + * phase with a JDK 17 compiler. + * So, just keep the ReflectionFileDescriptorCreator for now. + * + static class Jdk17FileDescriptorCreator implements FileDescriptorCreator { + private final jdk.internal.access.JavaIOFileDescriptorAccess fdAccess; + Jdk17FileDescriptorCreator() { + fdAccess = jdk.internal.access.SharedSecrets.getJavaIOFileDescriptorAccess(); + } + + @Override + public FileDescriptor newDescriptor(int fd) { + FileDescriptor descriptor = new FileDescriptor(); + fdAccess.set(descriptor, fd); + return descriptor; + } + } + */ + + /** + * Reflection based file descriptor creator. + * This requires the following option + * --add-opens java.base/java.io=ALL-UNNAMED + */ + static class ReflectionFileDescriptorCreator implements FileDescriptorCreator { + private final Field fileDescriptorField; + + ReflectionFileDescriptorCreator() throws Exception { + Field field = FileDescriptor.class.getDeclaredField("fd"); + field.setAccessible(true); + fileDescriptorField = field; + } + + @Override + public FileDescriptor newDescriptor(int fd) { + FileDescriptor descriptor = new FileDescriptor(); + try { + fileDescriptorField.set(descriptor, fd); + } catch (IllegalAccessException e) { + // This should not happen as the field has been set accessible + throw new IllegalStateException(e); + } + return descriptor; + } + } + +// static class NativeFileDescriptorCreator implements FileDescriptorCreator { +// NativeFileDescriptorCreator() { +// // Force load the library +// JLineNativeLoader.initialize(); +// } +// +// @Override +// public FileDescriptor newDescriptor(int fd) { +// return JLineLibrary.newFileDescriptor(fd); +// } +// } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractTerminal.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractTerminal.java index e92233c7b4f..4fb49b29b3f 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractTerminal.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractTerminal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2021, the original author or authors. + * Copyright (c) 2002-2021, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -27,7 +27,7 @@ import jdk.internal.org.jline.terminal.Attributes.LocalFlag; import jdk.internal.org.jline.terminal.Cursor; import jdk.internal.org.jline.terminal.MouseEvent; -import jdk.internal.org.jline.terminal.Terminal; +import jdk.internal.org.jline.terminal.spi.TerminalExt; import jdk.internal.org.jline.utils.ColorPalette; import jdk.internal.org.jline.utils.Curses; import jdk.internal.org.jline.utils.InfoCmp; @@ -35,7 +35,7 @@ import jdk.internal.org.jline.utils.Log; import jdk.internal.org.jline.utils.Status; -public abstract class AbstractTerminal implements Terminal { +public abstract class AbstractTerminal implements TerminalExt { protected final String name; protected final String type; @@ -44,7 +44,7 @@ public abstract class AbstractTerminal implements Terminal { protected final Set bools = new HashSet<>(); protected final Map ints = new HashMap<>(); protected final Map strings = new HashMap<>(); - protected final ColorPalette palette = new ColorPalette(this); + protected final ColorPalette palette; protected Status status; protected Runnable onClose; @@ -52,10 +52,13 @@ public AbstractTerminal(String name, String type) throws IOException { this(name, type, null, SignalHandler.SIG_DFL); } - public AbstractTerminal(String name, String type, Charset encoding, SignalHandler signalHandler) throws IOException { + @SuppressWarnings("this-escape") + public AbstractTerminal(String name, String type, Charset encoding, SignalHandler signalHandler) + throws IOException { this.name = name; this.type = type != null ? type : "ansi"; this.encoding = encoding != null ? encoding : Charset.defaultCharset(); + this.palette = new ColorPalette(this); for (Signal signal : Signal.values()) { handlers.put(signal, signalHandler); } @@ -85,12 +88,13 @@ public SignalHandler handle(Signal signal, SignalHandler handler) { public void raise(Signal signal) { Objects.requireNonNull(signal); SignalHandler handler = handlers.get(signal); - if (handler != SignalHandler.SIG_DFL && handler != SignalHandler.SIG_IGN) { + if (handler == SignalHandler.SIG_DFL) { + if (status != null && signal == Signal.WINCH) { + status.resize(); + } + } else if (handler != SignalHandler.SIG_IGN) { handler.handle(signal); } - if (status != null && signal == Signal.WINCH) { - status.resize(); - } } public final void close() throws IOException { @@ -105,8 +109,7 @@ public final void close() throws IOException { protected void doClose() throws IOException { if (status != null) { - status.update(null); - flush(); + status.close(); } } @@ -126,7 +129,7 @@ protected void echoSignal(Signal signal) { if (cc != null) { int vcc = getAttributes().getControlChar(cc); if (vcc > 0 && vcc < 32) { - writer().write(new char[]{'^', (char) (vcc + '@')}, 0, 2); + writer().write(new char[] {'^', (char) (vcc + '@')}, 0, 2); } } } @@ -217,8 +220,7 @@ public Cursor getCursorPosition(IntConsumer discarded) { } private MouseEvent lastMouseEvent = new MouseEvent( - MouseEvent.Type.Moved, MouseEvent.Button.NoButton, - EnumSet.noneOf(MouseEvent.Modifier.class), 0, 0); + MouseEvent.Type.Moved, MouseEvent.Button.NoButton, EnumSet.noneOf(MouseEvent.Modifier.class), 0, 0); @Override public boolean hasMouseSupport() { @@ -268,16 +270,13 @@ public boolean canPauseResume() { } @Override - public void pause() { - } + public void pause() {} @Override - public void pause(boolean wait) throws InterruptedException { - } + public void pause(boolean wait) throws InterruptedException {} @Override - public void resume() { - } + public void resume() {} @Override public boolean paused() { diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsConsoleWriter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsConsoleWriter.java index 0c36902a1a7..301b89eb796 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsConsoleWriter.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsConsoleWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2017, the original author or authors. + * Copyright (c) 2002-2017, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -29,11 +29,8 @@ public void write(char[] cbuf, int off, int len) throws IOException { } @Override - public void flush() { - } + public void flush() {} @Override - public void close() { - } - + public void close() {} } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsTerminal.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsTerminal.java index 57cfb5d50b4..03c42fb19f7 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsTerminal.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsTerminal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2019, the original author or authors. + * Copyright (c) 2002-2023, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -8,8 +8,20 @@ */ package jdk.internal.org.jline.terminal.impl; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.Writer; +import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; + import jdk.internal.org.jline.terminal.Attributes; import jdk.internal.org.jline.terminal.Size; +import jdk.internal.org.jline.terminal.spi.SystemStream; +import jdk.internal.org.jline.terminal.spi.TerminalProvider; import jdk.internal.org.jline.utils.Curses; import jdk.internal.org.jline.utils.InfoCmp; import jdk.internal.org.jline.utils.Log; @@ -21,17 +33,6 @@ import jdk.internal.org.jline.utils.Signals; import jdk.internal.org.jline.utils.WriterOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PrintWriter; -import java.io.Writer; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.Map; -import java.util.function.Function; - /** * The AbstractWindowsTerminal is used as the base class for windows terminal. * Due to windows limitations, mostly the missing support for ansi sequences, @@ -44,7 +45,7 @@ * the writer() becomes the primary output, while the output() is bridged * to the writer() using a WriterOutputStream wrapper. */ -public abstract class AbstractWindowsTerminal extends AbstractTerminal { +public abstract class AbstractWindowsTerminal extends AbstractTerminal { public static final String TYPE_WINDOWS = "windows"; public static final String TYPE_WINDOWS_256_COLOR = "windows-256color"; @@ -56,12 +57,13 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal { private static final int UTF8_CODE_PAGE = 65001; protected static final int ENABLE_PROCESSED_INPUT = 0x0001; - protected static final int ENABLE_LINE_INPUT = 0x0002; - protected static final int ENABLE_ECHO_INPUT = 0x0004; - protected static final int ENABLE_WINDOW_INPUT = 0x0008; - protected static final int ENABLE_MOUSE_INPUT = 0x0010; - protected static final int ENABLE_INSERT_MODE = 0x0020; + protected static final int ENABLE_LINE_INPUT = 0x0002; + protected static final int ENABLE_ECHO_INPUT = 0x0004; + protected static final int ENABLE_WINDOW_INPUT = 0x0008; + protected static final int ENABLE_MOUSE_INPUT = 0x0010; + protected static final int ENABLE_INSERT_MODE = 0x0020; protected static final int ENABLE_QUICK_EDIT_MODE = 0x0040; + protected static final int ENABLE_EXTENDED_FLAGS = 0x0080; protected final Writer slaveInputPipe; protected final InputStream input; @@ -71,7 +73,12 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal { protected final Map nativeHandlers = new HashMap<>(); protected final ShutdownHooks.Task closer; protected final Attributes attributes = new Attributes(); - protected final int originalConsoleMode; + protected final Console inConsole; + protected final Console outConsole; + protected final int originalInConsoleMode; + protected final int originalOutConsoleMode; + private final TerminalProvider provider; + private final SystemStream systemStream; protected final Object lock = new Object(); protected boolean paused = true; @@ -80,21 +87,42 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal { protected MouseTracking tracking = MouseTracking.Off; protected boolean focusTracking = false; private volatile boolean closing; - - public AbstractWindowsTerminal(Writer writer, String name, String type, Charset encoding, boolean nativeSignals, SignalHandler signalHandler, Function inputStreamWrapper) throws IOException { + protected boolean skipNextLf; + + @SuppressWarnings("this-escape") + public AbstractWindowsTerminal( + TerminalProvider provider, + SystemStream systemStream, + Writer writer, + String name, + String type, + Charset encoding, + boolean nativeSignals, + SignalHandler signalHandler, + Console inConsole, + int inConsoleMode, + Console outConsole, + int outConsoleMode, + Function inputStreamWrapper) + throws IOException { super(name, type, encoding, signalHandler); + this.provider = provider; + this.systemStream = systemStream; NonBlockingPumpReader reader = NonBlocking.nonBlockingPumpReader(); this.slaveInputPipe = reader.getWriter(); this.input = inputStreamWrapper.apply(NonBlocking.nonBlockingStream(reader, encoding())); this.reader = NonBlocking.nonBlocking(name, input, encoding()); this.writer = new PrintWriter(writer); this.output = new WriterOutputStream(writer, encoding()); + this.inConsole = inConsole; + this.outConsole = outConsole; parseInfoCmp(); // Attributes - originalConsoleMode = getConsoleMode(); + this.originalInConsoleMode = inConsoleMode; + this.originalOutConsoleMode = outConsoleMode; attributes.setLocalFlag(Attributes.LocalFlag.ISIG, true); attributes.setControlChar(Attributes.ControlChar.VINTR, ctrl('C')); - attributes.setControlChar(Attributes.ControlChar.VEOF, ctrl('D')); + attributes.setControlChar(Attributes.ControlChar.VEOF, ctrl('D')); attributes.setControlChar(Attributes.ControlChar.VSUSP, ctrl('Z')); // Handle signals if (nativeSignals) { @@ -148,7 +176,7 @@ public OutputStream output() { } public Attributes getAttributes() { - int mode = getConsoleMode(); + int mode = getConsoleMode(inConsole); if ((mode & ENABLE_ECHO_INPUT) != 0) { attributes.setLocalFlag(Attributes.LocalFlag.ECHO, true); } @@ -173,8 +201,11 @@ protected void updateConsoleMode() { } if (tracking != MouseTracking.Off) { mode |= ENABLE_MOUSE_INPUT; + // mouse events not send with quick edit mode + // to disable ENABLE_QUICK_EDIT_MODE just set extended flag + mode |= ENABLE_EXTENDED_FLAGS; } - setConsoleMode(mode); + setConsoleMode(inConsole, mode); } protected int ctrl(char key) { @@ -197,23 +228,26 @@ protected void doClose() throws IOException { } reader.close(); writer.close(); - setConsoleMode(originalConsoleMode); + setConsoleMode(inConsole, originalInConsoleMode); + setConsoleMode(outConsole, originalOutConsoleMode); } static final int SHIFT_FLAG = 0x01; - static final int ALT_FLAG = 0x02; - static final int CTRL_FLAG = 0x04; - - static final int RIGHT_ALT_PRESSED = 0x0001; - static final int LEFT_ALT_PRESSED = 0x0002; - static final int RIGHT_CTRL_PRESSED = 0x0004; - static final int LEFT_CTRL_PRESSED = 0x0008; - static final int SHIFT_PRESSED = 0x0010; - static final int NUMLOCK_ON = 0x0020; - static final int SCROLLLOCK_ON = 0x0040; - static final int CAPSLOCK_ON = 0x0080; - - protected void processKeyEvent(final boolean isKeyDown, final short virtualKeyCode, char ch, final int controlKeyState) throws IOException { + static final int ALT_FLAG = 0x02; + static final int CTRL_FLAG = 0x04; + + static final int RIGHT_ALT_PRESSED = 0x0001; + static final int LEFT_ALT_PRESSED = 0x0002; + static final int RIGHT_CTRL_PRESSED = 0x0004; + static final int LEFT_CTRL_PRESSED = 0x0008; + static final int SHIFT_PRESSED = 0x0010; + static final int NUMLOCK_ON = 0x0020; + static final int SCROLLLOCK_ON = 0x0040; + static final int CAPSLOCK_ON = 0x0080; + + protected void processKeyEvent( + final boolean isKeyDown, final short virtualKeyCode, char ch, final int controlKeyState) + throws IOException { final boolean isCtrl = (controlKeyState & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)) > 0; final boolean isAlt = (controlKeyState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) > 0; final boolean isShift = (controlKeyState & SHIFT_PRESSED) > 0; @@ -222,11 +256,13 @@ protected void processKeyEvent(final boolean isKeyDown, final short virtualKeyCo // Pressing "Alt Gr" is translated to Alt-Ctrl, hence it has to be checked that Ctrl is _not_ pressed, // otherwise inserting of "Alt Gr" codes on non-US keyboards would yield errors if (ch != 0 - && (controlKeyState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED | RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED | SHIFT_PRESSED)) - == (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED)) { + && (controlKeyState + & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED | RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)) + == (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED)) { processInputChar(ch); } else { - final String keySeq = getEscapeSequence(virtualKeyCode, (isCtrl ? CTRL_FLAG : 0) + (isAlt ? ALT_FLAG : 0) + (isShift ? SHIFT_FLAG : 0)); + final String keySeq = getEscapeSequence( + virtualKeyCode, (isCtrl ? CTRL_FLAG : 0) + (isAlt ? ALT_FLAG : 0) + (isShift ? SHIFT_FLAG : 0)); if (keySeq != null) { for (char c : keySeq.toCharArray()) { processInputChar(c); @@ -240,7 +276,7 @@ protected void processKeyEvent(final boolean isKeyDown, final short virtualKeyCo * 4). Ctrl + Space(0x20) : uchar=0x20 * 5). Ctrl + : uchar=0 * 6). Ctrl + Alt + : uchar=0 - */ + */ if (ch > 0) { if (isAlt) { processInputChar('\033'); @@ -254,10 +290,10 @@ protected void processKeyEvent(final boolean isKeyDown, final short virtualKeyCo } else { processInputChar(ch); } - } else if (isCtrl) { //Handles the ctrl key events(uchar=0) + } else if (isCtrl) { // Handles the ctrl key events(uchar=0) if (virtualKeyCode >= 'A' && virtualKeyCode <= 'Z') { ch = (char) (virtualKeyCode - 0x40); - } else if (virtualKeyCode == 191) { //? + } else if (virtualKeyCode == 191) { // ? ch = 127; } if (ch > 0) { @@ -275,7 +311,7 @@ protected void processKeyEvent(final boolean isKeyDown, final short virtualKeyCo else { // support ALT+NumPad input method if (virtualKeyCode == 0x12 /*VK_MENU ALT key*/ && ch > 0) { - processInputChar(ch); // no such combination in Windows + processInputChar(ch); // no such combination in Windows } } } @@ -468,7 +504,19 @@ public void processInputChar(char c) throws IOException { raise(Signal.INFO); } } - if (c == '\r') { + if (attributes.getInputFlag(Attributes.InputFlag.INORMEOL)) { + if (c == '\r') { + skipNextLf = true; + c = '\n'; + } else if (c == '\n') { + if (skipNextLf) { + skipNextLf = false; + return; + } + } else { + skipNextLf = false; + } + } else if (c == '\r') { if (attributes.getInputFlag(Attributes.InputFlag.IGNCR)) { return; } @@ -478,10 +526,10 @@ public void processInputChar(char c) throws IOException { } else if (c == '\n' && attributes.getInputFlag(Attributes.InputFlag.INLCR)) { c = '\r'; } -// if (attributes.getLocalFlag(Attributes.LocalFlag.ECHO)) { -// processOutputByte(c); -// masterOutput.flush(); -// } + // if (attributes.getLocalFlag(Attributes.LocalFlag.ECHO)) { + // processOutputByte(c); + // masterOutput.flush(); + // } slaveInputPipe.write(c); } @@ -492,9 +540,9 @@ public boolean trackMouse(MouseTracking tracking) { return true; } - protected abstract int getConsoleMode(); + protected abstract int getConsoleMode(Console console); - protected abstract void setConsoleMode(int mode); + protected abstract void setConsoleMode(Console console, int mode); /** * Read a single input event from the input buffer and process it. @@ -504,5 +552,13 @@ public boolean trackMouse(MouseTracking tracking) { */ protected abstract boolean processConsoleInput() throws IOException; -} + @Override + public TerminalProvider getProvider() { + return provider; + } + @Override + public SystemStream getSystemStream() { + return systemStream; + } +} diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/CursorSupport.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/CursorSupport.java index ef22cd0a7d8..14253d8c1d1 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/CursorSupport.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/CursorSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -8,17 +8,17 @@ */ package jdk.internal.org.jline.terminal.impl; -import jdk.internal.org.jline.terminal.Cursor; -import jdk.internal.org.jline.terminal.Terminal; -import jdk.internal.org.jline.utils.Curses; -import jdk.internal.org.jline.utils.InfoCmp; - import java.io.IOError; import java.io.IOException; import java.util.function.IntConsumer; import java.util.regex.Matcher; import java.util.regex.Pattern; +import jdk.internal.org.jline.terminal.Cursor; +import jdk.internal.org.jline.terminal.Terminal; +import jdk.internal.org.jline.utils.Curses; +import jdk.internal.org.jline.utils.InfoCmp; + public class CursorSupport { public static Cursor getCursorPosition(Terminal terminal, IntConsumer discarded) { @@ -105,5 +105,4 @@ public static Cursor getCursorPosition(Terminal terminal, IntConsumer discarded) throw new IOError(e); } } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/Diag.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/Diag.java index dfa784c29f3..dc54ea2157d 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/Diag.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/Diag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, the original author or authors. + * Copyright (c) 2022, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -17,6 +17,7 @@ import jdk.internal.org.jline.terminal.Attributes; import jdk.internal.org.jline.terminal.Terminal; +import jdk.internal.org.jline.terminal.spi.SystemStream; import jdk.internal.org.jline.terminal.spi.TerminalProvider; import jdk.internal.org.jline.utils.OSUtils; @@ -26,7 +27,7 @@ public static void main(String[] args) { diag(System.out); } - static void diag(PrintStream out) { + public static void diag(PrintStream out) { out.println("System properties"); out.println("================="); out.println("os.name = " + System.getProperty("os.name")); @@ -50,6 +51,17 @@ static void diag(PrintStream out) { out.println("IS_OSX = " + OSUtils.IS_OSX); out.println(); + // FFM + out.println("FFM Support"); + out.println("================="); + try { + TerminalProvider provider = TerminalProvider.load("ffm"); + testProvider(out, provider); + } catch (Throwable t) { + out.println("FFM support not available: " + t); + } + out.println(); + out.println("JnaSupport"); out.println("================="); try { @@ -60,13 +72,23 @@ static void diag(PrintStream out) { } out.println(); - out.println("JansiSupport"); + out.println("Jansi2Support"); out.println("================="); try { TerminalProvider provider = TerminalProvider.load("jansi"); testProvider(out, provider); } catch (Throwable t) { - out.println("Jansi support not available: " + t); + out.println("Jansi 2 support not available: " + t); + } + out.println(); + + out.println("JniSupport"); + out.println("================="); + try { + TerminalProvider provider = TerminalProvider.load("jni"); + testProvider(out, provider); + } catch (Throwable t) { + out.println("JNI support not available: " + t); } out.println(); @@ -83,32 +105,45 @@ static void diag(PrintStream out) { private static void testProvider(PrintStream out, TerminalProvider provider) { try { - out.println("StdIn stream = " + provider.isSystemStream(TerminalProvider.Stream.Input)); - out.println("StdOut stream = " + provider.isSystemStream(TerminalProvider.Stream.Output)); - out.println("StdErr stream = " + provider.isSystemStream(TerminalProvider.Stream.Error)); + out.println("StdIn stream = " + provider.isSystemStream(SystemStream.Input)); + out.println("StdOut stream = " + provider.isSystemStream(SystemStream.Output)); + out.println("StdErr stream = " + provider.isSystemStream(SystemStream.Error)); } catch (Throwable t2) { out.println("Unable to check stream: " + t2); } try { - out.println("StdIn stream name = " + provider.systemStreamName(TerminalProvider.Stream.Input)); - out.println("StdOut stream name = " + provider.systemStreamName(TerminalProvider.Stream.Output)); - out.println("StdErr stream name = " + provider.systemStreamName(TerminalProvider.Stream.Error)); + out.println("StdIn stream name = " + provider.systemStreamName(SystemStream.Input)); + out.println("StdOut stream name = " + provider.systemStreamName(SystemStream.Output)); + out.println("StdErr stream name = " + provider.systemStreamName(SystemStream.Error)); } catch (Throwable t2) { out.println("Unable to check stream names: " + t2); } - try (Terminal terminal = provider.sysTerminal("diag", "xterm", false, StandardCharsets.UTF_8, - false, Terminal.SignalHandler.SIG_DFL, false, TerminalProvider.Stream.Output, input -> input) ) { + try (Terminal terminal = provider.sysTerminal( + "diag", + "xterm", + false, + StandardCharsets.UTF_8, + false, + Terminal.SignalHandler.SIG_DFL, + false, + SystemStream.Output, + input -> input)) { if (terminal != null) { Attributes attr = terminal.enterRawMode(); try { out.println("Terminal size: " + terminal.getSize()); - ForkJoinTask t = new ForkJoinPool(1).submit(() -> terminal.reader().read(1) ); + ForkJoinTask t = + new ForkJoinPool(1).submit(() -> terminal.reader().read(1)); int r = t.get(1000, TimeUnit.MILLISECONDS); StringBuilder sb = new StringBuilder(); sb.append("The terminal seems to work: "); sb.append("terminal ").append(terminal.getClass().getName()); if (terminal instanceof AbstractPosixTerminal) { - sb.append(" with pty ").append(((AbstractPosixTerminal) terminal).getPty().getClass().getName()); + sb.append(" with pty ") + .append(((AbstractPosixTerminal) terminal) + .getPty() + .getClass() + .getName()); } out.println(sb); } catch (Throwable t3) { @@ -129,5 +164,4 @@ private static void testProvider(PrintStream out, TerminalProvider provider) { static S load(Class clazz) { return ServiceLoader.load(clazz, clazz.getClassLoader()).iterator().next(); } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/DumbTerminal.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/DumbTerminal.java index 0b8cb57cbbf..2922132c1bf 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/DumbTerminal.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/DumbTerminal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -14,38 +14,58 @@ import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.nio.charset.Charset; +import java.util.function.Function; import jdk.internal.org.jline.terminal.Attributes; import jdk.internal.org.jline.terminal.Attributes.ControlChar; import jdk.internal.org.jline.terminal.Size; +import jdk.internal.org.jline.terminal.spi.SystemStream; +import jdk.internal.org.jline.terminal.spi.TerminalProvider; import jdk.internal.org.jline.utils.NonBlocking; import jdk.internal.org.jline.utils.NonBlockingInputStream; import jdk.internal.org.jline.utils.NonBlockingReader; public class DumbTerminal extends AbstractTerminal { + private final TerminalProvider provider; + private final SystemStream systemStream; private final NonBlockingInputStream input; private final OutputStream output; private final NonBlockingReader reader; private final PrintWriter writer; private final Attributes attributes; private final Size size; + private boolean skipNextLf; - public DumbTerminal(InputStream in, OutputStream out) throws IOException { - this(TYPE_DUMB, TYPE_DUMB, in, out, null); + public DumbTerminal(InputStream in, OutputStream out, Function inputStreamWrapper) throws IOException { + this(TYPE_DUMB, TYPE_DUMB, in, out, null, inputStreamWrapper); } - public DumbTerminal(String name, String type, InputStream in, OutputStream out, Charset encoding) throws IOException { - this(name, type, in, out, encoding, SignalHandler.SIG_DFL); + public DumbTerminal(String name, String type, InputStream in, OutputStream out, Charset encoding, Function inputStreamWrapper) + throws IOException { + this(null, null, name, type, in, out, encoding, SignalHandler.SIG_DFL, inputStreamWrapper); } - public DumbTerminal(String name, String type, InputStream in, OutputStream out, Charset encoding, SignalHandler signalHandler) throws IOException { + @SuppressWarnings("this-escape") + public DumbTerminal( + TerminalProvider provider, + SystemStream systemStream, + String name, + String type, + InputStream in, + OutputStream out, + Charset encoding, + SignalHandler signalHandler, + Function inputStreamWrapper) + throws IOException { super(name, type, encoding, signalHandler); - NonBlockingInputStream nbis = NonBlocking.nonBlocking(getName(), in); + this.provider = provider; + this.systemStream = systemStream; + NonBlockingInputStream nbis = NonBlocking.nonBlocking(getName(), inputStreamWrapper.apply(in)); this.input = new NonBlockingInputStream() { @Override public int read(long timeout, boolean isPeek) throws IOException { - for (;;) { + for (; ; ) { int c = nbis.read(timeout, isPeek); if (attributes.getLocalFlag(Attributes.LocalFlag.ISIG)) { if (c == attributes.getControlChar(ControlChar.VINTR)) { @@ -62,7 +82,19 @@ public int read(long timeout, boolean isPeek) throws IOException { continue; } } - if (c == '\r') { + if (attributes.getInputFlag(Attributes.InputFlag.INORMEOL)) { + if (c == '\r') { + skipNextLf = true; + c = '\n'; + } else if (c == '\n') { + if (skipNextLf) { + skipNextLf = false; + continue; + } + } else { + skipNextLf = false; + } + } else if (c == '\r') { if (attributes.getInputFlag(Attributes.InputFlag.IGNCR)) { continue; } @@ -80,10 +112,10 @@ public int read(long timeout, boolean isPeek) throws IOException { this.reader = NonBlocking.nonBlocking(getName(), input, encoding()); this.writer = new PrintWriter(new OutputStreamWriter(output, encoding())); this.attributes = new Attributes(); - this.attributes.setControlChar(ControlChar.VERASE, (char) 127); + this.attributes.setControlChar(ControlChar.VERASE, (char) 127); this.attributes.setControlChar(ControlChar.VWERASE, (char) 23); - this.attributes.setControlChar(ControlChar.VKILL, (char) 21); - this.attributes.setControlChar(ControlChar.VLNEXT, (char) 22); + this.attributes.setControlChar(ControlChar.VKILL, (char) 21); + this.attributes.setControlChar(ControlChar.VLNEXT, (char) 22); this.size = new Size(); parseInfoCmp(); } @@ -107,9 +139,7 @@ public OutputStream output() { } public Attributes getAttributes() { - Attributes attr = new Attributes(); - attr.copy(attributes); - return attr; + return new Attributes(attributes); } public void setAttributes(Attributes attr) { @@ -126,4 +156,13 @@ public void setSize(Size sz) { size.copy(sz); } + @Override + public TerminalProvider getProvider() { + return provider; + } + + @Override + public SystemStream getSystemStream() { + return systemStream; + } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/DumbTerminalProvider.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/DumbTerminalProvider.java new file mode 100644 index 00000000000..b99185d3dc9 --- /dev/null +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/DumbTerminalProvider.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2023, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * https://opensource.org/licenses/BSD-3-Clause + */ +package jdk.internal.org.jline.terminal.impl; + +import java.io.FileDescriptor; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.charset.Charset; +import java.util.function.Function; + +import jdk.internal.org.jline.terminal.Attributes; +import jdk.internal.org.jline.terminal.Size; +import jdk.internal.org.jline.terminal.Terminal; +import jdk.internal.org.jline.terminal.TerminalBuilder; +import jdk.internal.org.jline.terminal.spi.SystemStream; +import jdk.internal.org.jline.terminal.spi.TerminalProvider; + +public class DumbTerminalProvider implements TerminalProvider { + + @Override + public String name() { + return TerminalBuilder.PROP_PROVIDER_DUMB; + } + + @Override + public Terminal sysTerminal( + String name, + String type, + boolean ansiPassThrough, + Charset encoding, + boolean nativeSignals, + Terminal.SignalHandler signalHandler, + boolean paused, + SystemStream systemStream, + Function inputStreamWrapper) + throws IOException { + return new DumbTerminal( + this, + systemStream, + name, + type, + new FileInputStream(FileDescriptor.in), + new FileOutputStream(systemStream == SystemStream.Error ? FileDescriptor.err : FileDescriptor.out), + encoding, + signalHandler, + inputStreamWrapper); + } + + @Override + public Terminal newTerminal( + String name, + String type, + InputStream masterInput, + OutputStream masterOutput, + Charset encoding, + Terminal.SignalHandler signalHandler, + boolean paused, + Attributes attributes, + Size size) + throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isSystemStream(SystemStream stream) { + return false; + } + + @Override + public String systemStreamName(SystemStream stream) { + return null; + } + + //@Override + //public int systemStreamWidth(SystemStream stream) { + // return 0; + //} + + @Override + public String toString() { + return "TerminalProvider[" + name() + "]"; + } +} diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ExternalTerminal.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ExternalTerminal.java index 2814b52c7cc..5033fd61279 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ExternalTerminal.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ExternalTerminal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -8,10 +8,6 @@ */ package jdk.internal.org.jline.terminal.impl; -import jdk.internal.org.jline.terminal.Attributes; -import jdk.internal.org.jline.terminal.Cursor; -import jdk.internal.org.jline.terminal.Size; - import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -19,6 +15,11 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.IntConsumer; +import jdk.internal.org.jline.terminal.Attributes; +import jdk.internal.org.jline.terminal.Cursor; +import jdk.internal.org.jline.terminal.Size; +import jdk.internal.org.jline.terminal.spi.TerminalProvider; + /** * Console implementation with embedded line disciplined. * @@ -32,45 +33,59 @@ */ public class ExternalTerminal extends LineDisciplineTerminal { + private final TerminalProvider provider; protected final AtomicBoolean closed = new AtomicBoolean(); protected final InputStream masterInput; protected final Object lock = new Object(); protected boolean paused = true; protected Thread pumpThread; - public ExternalTerminal(String name, String type, - InputStream masterInput, - OutputStream masterOutput, - Charset encoding) throws IOException { - this(name, type, masterInput, masterOutput, encoding, SignalHandler.SIG_DFL); + public ExternalTerminal( + String name, String type, InputStream masterInput, OutputStream masterOutput, Charset encoding) + throws IOException { + this(null, name, type, masterInput, masterOutput, encoding, SignalHandler.SIG_DFL); } - public ExternalTerminal(String name, String type, - InputStream masterInput, - OutputStream masterOutput, - Charset encoding, - SignalHandler signalHandler) throws IOException { - this(name, type, masterInput, masterOutput, encoding, signalHandler, false); + public ExternalTerminal( + TerminalProvider provider, + String name, + String type, + InputStream masterInput, + OutputStream masterOutput, + Charset encoding, + SignalHandler signalHandler) + throws IOException { + this(provider, name, type, masterInput, masterOutput, encoding, signalHandler, false); } - public ExternalTerminal(String name, String type, - InputStream masterInput, - OutputStream masterOutput, - Charset encoding, - SignalHandler signalHandler, - boolean paused) throws IOException { - this(name, type, masterInput, masterOutput, encoding, signalHandler, paused, null, null); + public ExternalTerminal( + TerminalProvider provider, + String name, + String type, + InputStream masterInput, + OutputStream masterOutput, + Charset encoding, + SignalHandler signalHandler, + boolean paused) + throws IOException { + this(provider, name, type, masterInput, masterOutput, encoding, signalHandler, paused, null, null); } - public ExternalTerminal(String name, String type, - InputStream masterInput, - OutputStream masterOutput, - Charset encoding, - SignalHandler signalHandler, - boolean paused, - Attributes attributes, - Size size) throws IOException { + @SuppressWarnings("this-escape") + public ExternalTerminal( + TerminalProvider provider, + String name, + String type, + InputStream masterInput, + OutputStream masterOutput, + Charset encoding, + SignalHandler signalHandler, + boolean paused, + Attributes attributes, + Size size) + throws IOException { super(name, type, masterOutput, encoding, signalHandler); + this.provider = provider; this.masterInput = masterInput; if (attributes != null) { setAttributes(attributes); @@ -171,4 +186,8 @@ public Cursor getCursorPosition(IntConsumer discarded) { return CursorSupport.getCursorPosition(this, discarded); } + @Override + public TerminalProvider getProvider() { + return provider; + } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/LineDisciplineTerminal.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/LineDisciplineTerminal.java index 0f290379bbf..4e7a396bbc3 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/LineDisciplineTerminal.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/LineDisciplineTerminal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -14,6 +14,7 @@ import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.nio.charset.Charset; +import java.util.EnumSet; import java.util.Objects; import jdk.internal.org.jline.terminal.Attributes; @@ -23,6 +24,8 @@ import jdk.internal.org.jline.terminal.Attributes.OutputFlag; import jdk.internal.org.jline.terminal.Size; import jdk.internal.org.jline.terminal.Terminal; +import jdk.internal.org.jline.terminal.spi.SystemStream; +import jdk.internal.org.jline.terminal.spi.TerminalProvider; import jdk.internal.org.jline.utils.NonBlocking; import jdk.internal.org.jline.utils.NonBlockingPumpInputStream; import jdk.internal.org.jline.utils.NonBlockingReader; @@ -45,21 +48,6 @@ */ public class LineDisciplineTerminal extends AbstractTerminal { - private static final String DEFAULT_TERMINAL_ATTRIBUTES = - "speed 9600 baud; 24 rows; 80 columns;\n" + - "lflags: icanon isig iexten echo echoe -echok echoke -echonl echoctl\n" + - "\t-echoprt -altwerase -noflsh -tostop -flusho pendin -nokerninfo\n" + - "\t-extproc\n" + - "iflags: -istrip icrnl -inlcr -igncr ixon -ixoff ixany imaxbel iutf8\n" + - "\t-ignbrk brkint -inpck -ignpar -parmrk\n" + - "oflags: opost onlcr -oxtabs -onocr -onlret\n" + - "cflags: cread cs8 -parenb -parodd hupcl -clocal -cstopb -crtscts -dsrflow\n" + - "\t-dtrflow -mdmbuf\n" + - "cchars: discard = ^O; dsusp = ^Y; eof = ^D; eol = ;\n" + - "\teol2 = ; erase = ^?; intr = ^C; kill = ^U; lnext = ^V;\n" + - "\tmin = 1; quit = ^\\; reprint = ^R; start = ^Q; status = ^T;\n" + - "\tstop = ^S; susp = ^Z; time = 0; werase = ^W;\n"; - private static final int PIPE_SIZE = 1024; /* @@ -84,20 +72,20 @@ public class LineDisciplineTerminal extends AbstractTerminal { * Console data */ protected final Attributes attributes; + protected final Size size; - public LineDisciplineTerminal(String name, - String type, - OutputStream masterOutput, - Charset encoding) throws IOException { + protected boolean skipNextLf; + + public LineDisciplineTerminal(String name, String type, OutputStream masterOutput, Charset encoding) + throws IOException { this(name, type, masterOutput, encoding, SignalHandler.SIG_DFL); } - public LineDisciplineTerminal(String name, - String type, - OutputStream masterOutput, - Charset encoding, - SignalHandler signalHandler) throws IOException { + @SuppressWarnings("this-escape") + public LineDisciplineTerminal( + String name, String type, OutputStream masterOutput, Charset encoding, SignalHandler signalHandler) + throws IOException { super(name, type, encoding, signalHandler); NonBlockingPumpInputStream input = NonBlocking.nonBlockingPumpInputStream(PIPE_SIZE); this.slaveInputPipe = input.getOutputStream(); @@ -106,11 +94,66 @@ public LineDisciplineTerminal(String name, this.slaveOutput = new FilteringOutputStream(); this.slaveWriter = new PrintWriter(new OutputStreamWriter(slaveOutput, encoding())); this.masterOutput = masterOutput; - this.attributes = ExecPty.doGetAttr(DEFAULT_TERMINAL_ATTRIBUTES); + this.attributes = getDefaultTerminalAttributes(); this.size = new Size(160, 50); parseInfoCmp(); } + private static Attributes getDefaultTerminalAttributes() { + // speed 9600 baud; 24 rows; 80 columns; + // lflags: icanon isig iexten echo echoe -echok echoke -echonl echoctl + // -echoprt -altwerase -noflsh -tostop -flusho pendin -nokerninfo + // -extproc + // iflags: -istrip icrnl -inlcr -igncr ixon -ixoff ixany imaxbel iutf8 + // -ignbrk brkint -inpck -ignpar -parmrk + // oflags: opost onlcr -oxtabs -onocr -onlret + // cflags: cread cs8 -parenb -parodd hupcl -clocal -cstopb -crtscts -dsrflow + // -dtrflow -mdmbuf + // cchars: discard = ^O; dsusp = ^Y; eof = ^D; eol = ; + // eol2 = ; erase = ^?; intr = ^C; kill = ^U; lnext = ^V; + // min = 1; quit = ^\\; reprint = ^R; start = ^Q; status = ^T; + // stop = ^S; susp = ^Z; time = 0; werase = ^W; + Attributes attr = new Attributes(); + attr.setLocalFlags(EnumSet.of( + LocalFlag.ICANON, + LocalFlag.ISIG, + LocalFlag.IEXTEN, + LocalFlag.ECHO, + LocalFlag.ECHOE, + LocalFlag.ECHOKE, + LocalFlag.ECHOCTL, + LocalFlag.PENDIN)); + attr.setInputFlags(EnumSet.of( + InputFlag.ICRNL, + InputFlag.IXON, + InputFlag.IXANY, + InputFlag.IMAXBEL, + InputFlag.IUTF8, + InputFlag.BRKINT)); + attr.setOutputFlags(EnumSet.of(OutputFlag.OPOST, OutputFlag.ONLCR)); + attr.setControlChar(ControlChar.VDISCARD, ctrl('O')); + attr.setControlChar(ControlChar.VDSUSP, ctrl('Y')); + attr.setControlChar(ControlChar.VEOF, ctrl('D')); + attr.setControlChar(ControlChar.VERASE, ctrl('?')); + attr.setControlChar(ControlChar.VINTR, ctrl('C')); + attr.setControlChar(ControlChar.VKILL, ctrl('U')); + attr.setControlChar(ControlChar.VLNEXT, ctrl('V')); + attr.setControlChar(ControlChar.VMIN, 1); + attr.setControlChar(ControlChar.VQUIT, ctrl('\\')); + attr.setControlChar(ControlChar.VREPRINT, ctrl('R')); + attr.setControlChar(ControlChar.VSTART, ctrl('Q')); + attr.setControlChar(ControlChar.VSTATUS, ctrl('T')); + attr.setControlChar(ControlChar.VSTOP, ctrl('S')); + attr.setControlChar(ControlChar.VSUSP, ctrl('Z')); + attr.setControlChar(ControlChar.VTIME, 0); + attr.setControlChar(ControlChar.VWERASE, ctrl('W')); + return attr; + } + + private static int ctrl(char c) { + return c == '?' ? 177 : c - 64; + } + public NonBlockingReader reader() { return slaveReader; } @@ -130,9 +173,7 @@ public OutputStream output() { } public Attributes getAttributes() { - Attributes attr = new Attributes(); - attr.copy(attributes); - return attr; + return new Attributes(attributes); } public void setAttributes(Attributes attr) { @@ -149,9 +190,9 @@ public void setSize(Size sz) { size.copy(sz); } - @Override + @Override public void raise(Signal signal) { - Objects.requireNonNull(signal); + Objects.requireNonNull(signal); // Do not call clear() atm as this can cause // deadlock between reading / writing threads // TODO: any way to fix that ? @@ -214,7 +255,19 @@ protected boolean doProcessInputByte(int c) throws IOException { raise(Signal.INFO); } } - if (c == '\r') { + if (attributes.getInputFlag(InputFlag.INORMEOL)) { + if (c == '\r') { + skipNextLf = true; + c = '\n'; + } else if (c == '\n') { + if (skipNextLf) { + skipNextLf = false; + return false; + } + } else { + skipNextLf = false; + } + } else if (c == '\r') { if (attributes.getInputFlag(InputFlag.IGNCR)) { return false; } @@ -273,6 +326,16 @@ protected void doClose() throws IOException { } } + @Override + public TerminalProvider getProvider() { + return null; + } + + @Override + public SystemStream getSystemStream() { + return null; + } + private class FilteringOutputStream extends OutputStream { @Override public void write(int b) throws IOException { @@ -284,13 +347,12 @@ public void write(int b) throws IOException { public void write(byte[] b, int off, int len) throws IOException { if (b == null) { throw new NullPointerException(); - } else if ((off < 0) || (off > b.length) || (len < 0) || - ((off + len) > b.length) || ((off + len) < 0)) { + } else if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return; } - for (int i = 0 ; i < len ; i++) { + for (int i = 0; i < len; i++) { processOutputByte(b[off + i]); } flush(); diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/MouseSupport.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/MouseSupport.java index 89ae6e5b74a..eef25c90d8f 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/MouseSupport.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/MouseSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -8,11 +8,6 @@ */ package jdk.internal.org.jline.terminal.impl; -import jdk.internal.org.jline.terminal.MouseEvent; -import jdk.internal.org.jline.terminal.Terminal; -import jdk.internal.org.jline.utils.InfoCmp; -import jdk.internal.org.jline.utils.InputStreamReader; - import java.io.EOFException; import java.io.IOError; import java.io.IOException; @@ -20,6 +15,11 @@ import java.util.EnumSet; import java.util.function.IntSupplier; +import jdk.internal.org.jline.terminal.MouseEvent; +import jdk.internal.org.jline.terminal.Terminal; +import jdk.internal.org.jline.utils.InfoCmp; +import jdk.internal.org.jline.utils.InputStreamReader; + public class MouseSupport { public static boolean hasMouseSupport(Terminal terminal) { @@ -78,7 +78,8 @@ public static MouseEvent readMouse(IntSupplier reader, MouseEvent last) { case 0: button = MouseEvent.Button.Button1; if (last.getButton() == button - && (last.getType() == MouseEvent.Type.Pressed || last.getType() == MouseEvent.Type.Dragged)) { + && (last.getType() == MouseEvent.Type.Pressed + || last.getType() == MouseEvent.Type.Dragged)) { type = MouseEvent.Type.Dragged; } else { type = MouseEvent.Type.Pressed; @@ -87,7 +88,8 @@ public static MouseEvent readMouse(IntSupplier reader, MouseEvent last) { case 1: button = MouseEvent.Button.Button2; if (last.getButton() == button - && (last.getType() == MouseEvent.Type.Pressed || last.getType() == MouseEvent.Type.Dragged)) { + && (last.getType() == MouseEvent.Type.Pressed + || last.getType() == MouseEvent.Type.Dragged)) { type = MouseEvent.Type.Dragged; } else { type = MouseEvent.Type.Pressed; @@ -96,7 +98,8 @@ public static MouseEvent readMouse(IntSupplier reader, MouseEvent last) { case 2: button = MouseEvent.Button.Button3; if (last.getButton() == button - && (last.getType() == MouseEvent.Type.Pressed || last.getType() == MouseEvent.Type.Dragged)) { + && (last.getType() == MouseEvent.Type.Pressed + || last.getType() == MouseEvent.Type.Dragged)) { type = MouseEvent.Type.Dragged; } else { type = MouseEvent.Type.Pressed; @@ -134,5 +137,4 @@ private static int readExt(Terminal terminal) { throw new IOError(e); } } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/NativeSignalHandler.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/NativeSignalHandler.java index 00c584c6cb9..bba177794a5 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/NativeSignalHandler.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/NativeSignalHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -17,8 +17,7 @@ public final class NativeSignalHandler implements SignalHandler { public static final NativeSignalHandler SIG_IGN = new NativeSignalHandler(); - private NativeSignalHandler() { - } + private NativeSignalHandler() {} public void handle(Signal signal) { throw new UnsupportedOperationException(); diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixPtyTerminal.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixPtyTerminal.java index f85e3fe0b0c..d34103e4d5e 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixPtyTerminal.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixPtyTerminal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -38,15 +38,34 @@ public class PosixPtyTerminal extends AbstractPosixTerminal { private Thread outputPumpThread; private boolean paused = true; - public PosixPtyTerminal(String name, String type, Pty pty, InputStream in, OutputStream out, Charset encoding) throws IOException { + public PosixPtyTerminal(String name, String type, Pty pty, InputStream in, OutputStream out, Charset encoding) + throws IOException { this(name, type, pty, in, out, encoding, SignalHandler.SIG_DFL); } - public PosixPtyTerminal(String name, String type, Pty pty, InputStream in, OutputStream out, Charset encoding, SignalHandler signalHandler) throws IOException { + public PosixPtyTerminal( + String name, + String type, + Pty pty, + InputStream in, + OutputStream out, + Charset encoding, + SignalHandler signalHandler) + throws IOException { this(name, type, pty, in, out, encoding, signalHandler, false); } - public PosixPtyTerminal(String name, String type, Pty pty, InputStream in, OutputStream out, Charset encoding, SignalHandler signalHandler, boolean paused) throws IOException { + @SuppressWarnings("this-escape") + public PosixPtyTerminal( + String name, + String type, + Pty pty, + InputStream in, + OutputStream out, + Charset encoding, + SignalHandler signalHandler, + boolean paused) + throws IOException { super(name, type, pty, encoding, signalHandler); this.in = Objects.requireNonNull(in); this.out = Objects.requireNonNull(out); @@ -113,7 +132,7 @@ public void pause(boolean wait) throws InterruptedException { if (p1 != null) { p1.join(); } - if (p2 !=null) { + if (p2 != null) { p2.join(); } } @@ -167,7 +186,7 @@ public void close() throws IOException { private void pumpIn() { try { - for (;;) { + for (; ; ) { synchronized (lock) { if (paused) { inputPumpThread = null; @@ -193,7 +212,7 @@ private void pumpIn() { private void pumpOut() { try { - for (;;) { + for (; ; ) { synchronized (lock) { if (paused) { outputPumpThread = null; @@ -221,5 +240,4 @@ private void pumpOut() { // Ignore } } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixSysTerminal.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixSysTerminal.java index a55f3d4a748..135ed0bb0c0 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixSysTerminal.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/PosixSysTerminal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -18,8 +18,9 @@ import java.util.Map; import java.util.function.Function; -import jdk.internal.org.jline.utils.NonBlocking; import jdk.internal.org.jline.terminal.spi.Pty; +import jdk.internal.org.jline.utils.FastBufferedOutputStream; +import jdk.internal.org.jline.utils.NonBlocking; import jdk.internal.org.jline.utils.NonBlockingInputStream; import jdk.internal.org.jline.utils.NonBlockingReader; import jdk.internal.org.jline.utils.ShutdownHooks; @@ -35,12 +36,14 @@ public class PosixSysTerminal extends AbstractPosixTerminal { protected final Map nativeHandlers = new HashMap<>(); protected final Task closer; - public PosixSysTerminal(String name, String type, Pty pty, Charset encoding, - boolean nativeSignals, SignalHandler signalHandler, - Function inputStreamWrapper) throws IOException { + @SuppressWarnings("this-escape") + public PosixSysTerminal( + String name, String type, Pty pty, Charset encoding, boolean nativeSignals, SignalHandler signalHandler, + Function inputStreamWrapper) + throws IOException { super(name, type, pty, encoding, signalHandler); this.input = NonBlocking.nonBlocking(getName(), inputStreamWrapper.apply(pty.getSlaveInput())); - this.output = pty.getSlaveOutput(); + this.output = new FastBufferedOutputStream(pty.getSlaveOutput()); this.reader = NonBlocking.nonBlocking(getName(), input, encoding()); this.writer = new PrintWriter(new OutputStreamWriter(output, encoding())); parseInfoCmp(); @@ -98,5 +101,4 @@ protected void doClose() throws IOException { // Do not call reader.close() reader.shutdown(); } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ExecPty.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/exec/ExecPty.java similarity index 71% rename from src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ExecPty.java rename to src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/exec/ExecPty.java index 5377b4acdb8..c0a35cbd6a2 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/ExecPty.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/exec/ExecPty.java @@ -1,18 +1,18 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. * * https://opensource.org/licenses/BSD-3-Clause */ -package jdk.internal.org.jline.terminal.impl; +package jdk.internal.org.jline.terminal.impl.exec; +import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; -import java.io.FileDescriptor; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; @@ -26,8 +26,10 @@ import jdk.internal.org.jline.terminal.Attributes.LocalFlag; import jdk.internal.org.jline.terminal.Attributes.OutputFlag; import jdk.internal.org.jline.terminal.Size; -import jdk.internal.org.jline.terminal.spi.TerminalProvider; +import jdk.internal.org.jline.terminal.impl.AbstractPty; import jdk.internal.org.jline.terminal.spi.Pty; +import jdk.internal.org.jline.terminal.spi.SystemStream; +import jdk.internal.org.jline.terminal.spi.TerminalProvider; import jdk.internal.org.jline.utils.OSUtils; import static jdk.internal.org.jline.utils.ExecHelper.exec; @@ -35,28 +37,26 @@ public class ExecPty extends AbstractPty implements Pty { private final String name; - private final TerminalProvider.Stream console; - public static Pty current(TerminalProvider.Stream console) throws IOException { + public static Pty current(TerminalProvider provider, SystemStream systemStream) throws IOException { try { String result = exec(true, OSUtils.TTY_COMMAND); - if (console != TerminalProvider.Stream.Output && console != TerminalProvider.Stream.Error) { - throw new IllegalArgumentException("console should be Output or Error: " + console); + if (systemStream != SystemStream.Output && systemStream != SystemStream.Error) { + throw new IllegalArgumentException("systemStream should be Output or Error: " + systemStream); } - return new ExecPty(result.trim(), console); + return new ExecPty(provider, systemStream, result.trim()); } catch (IOException e) { throw new IOException("Not a tty", e); } } - protected ExecPty(String name, TerminalProvider.Stream console) { + protected ExecPty(TerminalProvider provider, SystemStream systemStream, String name) { + super(provider, systemStream); this.name = name; - this.console = console; } @Override - public void close() throws IOException { - } + public void close() throws IOException {} public String getName() { return name; @@ -74,18 +74,16 @@ public OutputStream getMasterOutput() { @Override protected InputStream doGetSlaveInput() throws IOException { - return console != null - ? new FileInputStream(FileDescriptor.in) - : new FileInputStream(getName()); + return systemStream != null ? new FileInputStream(FileDescriptor.in) : new FileInputStream(getName()); } @Override public OutputStream getSlaveOutput() throws IOException { - return console == TerminalProvider.Stream.Output + return systemStream == SystemStream.Output ? new FileOutputStream(FileDescriptor.out) - : console == TerminalProvider.Stream.Error - ? new FileOutputStream(FileDescriptor.err) - : new FileOutputStream(getName()); + : systemStream == SystemStream.Error + ? new FileOutputStream(FileDescriptor.err) + : new FileOutputStream(getName()); } @Override @@ -99,18 +97,30 @@ protected void doSetAttr(Attributes attr) throws IOException { List commands = getFlagsToSet(attr, getAttr()); if (!commands.isEmpty()) { commands.add(0, OSUtils.STTY_COMMAND); - if (console == null) { + if (systemStream == null) { commands.add(1, OSUtils.STTY_F_OPTION); commands.add(2, getName()); } - exec(console != null, commands.toArray(new String[0])); + try { + exec(systemStream != null, commands.toArray(new String[0])); + } catch (IOException e) { + // Handle partial failures with GNU stty, see #97 + if (e.toString().contains("unable to perform all requested operations")) { + commands = getFlagsToSet(attr, getAttr()); + if (!commands.isEmpty()) { + throw new IOException("Could not set the following flags: " + String.join(", ", commands), e); + } + } else { + throw e; + } + } } } protected List getFlagsToSet(Attributes attr, Attributes current) { List commands = new ArrayList<>(); for (InputFlag flag : InputFlag.values()) { - if (attr.getInputFlag(flag) != current.getInputFlag(flag)) { + if (attr.getInputFlag(flag) != current.getInputFlag(flag) && flag != InputFlag.INORMEOL) { commands.add((attr.getInputFlag(flag) ? flag.name() : "-" + flag.name()).toLowerCase()); } } @@ -137,11 +147,9 @@ protected List getFlagsToSet(Attributes attr, Attributes current) { commands.add(cchar.name().toLowerCase().substring(1)); if (cchar == ControlChar.VMIN || cchar == ControlChar.VTIME) { commands.add(Integer.toString(v)); - } - else if (v == 0) { + } else if (v == 0) { commands.add(undef); - } - else { + } else { if (v >= 128) { v -= 128; str += "M-"; @@ -165,12 +173,12 @@ public Size getSize() throws IOException { } protected String doGetConfig() throws IOException { - return console != null - ? exec(true, OSUtils.STTY_COMMAND, "-a") + return systemStream != null + ? exec(true, OSUtils.STTY_COMMAND, "-a") : exec(false, OSUtils.STTY_COMMAND, OSUtils.STTY_F_OPTION, getName(), "-a"); } - static Attributes doGetAttr(String cfg) throws IOException { + public static Attributes doGetAttr(String cfg) throws IOException { Attributes attributes = new Attributes(); for (InputFlag flag : InputFlag.values()) { Boolean value = doGetFlag(cfg, flag); @@ -201,16 +209,19 @@ static Attributes doGetAttr(String cfg) throws IOException { if ("reprint".endsWith(name)) { name = "(?:reprint|rprnt)"; } - Matcher matcher = Pattern.compile("[\\s;]" + name + "\\s*=\\s*(.+?)[\\s;]").matcher(cfg); + Matcher matcher = + Pattern.compile("[\\s;]" + name + "\\s*=\\s*(.+?)[\\s;]").matcher(cfg); if (matcher.find()) { - attributes.setControlChar(cchar, parseControlChar(matcher.group(1).toUpperCase())); + attributes.setControlChar( + cchar, parseControlChar(matcher.group(1).toUpperCase())); } } return attributes; } private static Boolean doGetFlag(String cfg, Enum flag) { - Matcher matcher = Pattern.compile("(?:^|[\\s;])(\\-?" + flag.name().toLowerCase() + ")(?:[\\s;]|$)").matcher(cfg); + Matcher matcher = Pattern.compile("(?:^|[\\s;])(\\-?" + flag.name().toLowerCase() + ")(?:[\\s;]|$)") + .matcher(cfg); return matcher.find() ? !matcher.group(1).startsWith("-") : null; } @@ -259,9 +270,7 @@ static Size doGetSize(String cfg) throws IOException { static int doGetInt(String name, String cfg) throws IOException { String[] patterns = new String[] { - "\\b([0-9]+)\\s+" + name + "\\b", - "\\b" + name + "\\s+([0-9]+)\\b", - "\\b" + name + "\\s*=\\s*([0-9]+)\\b" + "\\b([0-9]+)\\s+" + name + "\\b", "\\b" + name + "\\s+([0-9]+)\\b", "\\b" + name + "\\s*=\\s*([0-9]+)\\b" }; for (String pattern : patterns) { Matcher matcher = Pattern.compile(pattern).matcher(cfg); @@ -274,23 +283,29 @@ static int doGetInt(String name, String cfg) throws IOException { @Override public void setSize(Size size) throws IOException { - if (console != null) { - exec(true, - OSUtils.STTY_COMMAND, - "columns", Integer.toString(size.getColumns()), - "rows", Integer.toString(size.getRows())); + if (systemStream != null) { + exec( + true, + OSUtils.STTY_COMMAND, + "columns", + Integer.toString(size.getColumns()), + "rows", + Integer.toString(size.getRows())); } else { - exec(false, - OSUtils.STTY_COMMAND, - OSUtils.STTY_F_OPTION, getName(), - "columns", Integer.toString(size.getColumns()), - "rows", Integer.toString(size.getRows())); + exec( + false, + OSUtils.STTY_COMMAND, + OSUtils.STTY_F_OPTION, + getName(), + "columns", + Integer.toString(size.getColumns()), + "rows", + Integer.toString(size.getRows())); } } @Override public String toString() { - return "ExecPty[" + getName() + (console != null ? ", system]" : "]"); + return "ExecPty[" + getName() + (systemStream != null ? ", system]" : "]"); } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/exec/ExecTerminalProvider.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/exec/ExecTerminalProvider.java index 8bdeede2e1b..36ff4a63579 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/exec/ExecTerminalProvider.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/exec/ExecTerminalProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, the original author or authors. + * Copyright (c) 2022, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -17,117 +17,249 @@ import java.nio.charset.Charset; import java.util.function.Function; +//import jdk.internal.org.jline.nativ.JLineLibrary; +//import jdk.internal.org.jline.nativ.JLineNativeLoader; import jdk.internal.org.jline.terminal.Attributes; import jdk.internal.org.jline.terminal.Size; import jdk.internal.org.jline.terminal.Terminal; -import jdk.internal.org.jline.terminal.impl.ExecPty; +import jdk.internal.org.jline.terminal.TerminalBuilder; import jdk.internal.org.jline.terminal.impl.ExternalTerminal; import jdk.internal.org.jline.terminal.impl.PosixSysTerminal; import jdk.internal.org.jline.terminal.spi.Pty; +import jdk.internal.org.jline.terminal.spi.SystemStream; import jdk.internal.org.jline.terminal.spi.TerminalProvider; import jdk.internal.org.jline.utils.ExecHelper; +import jdk.internal.org.jline.utils.Log; import jdk.internal.org.jline.utils.OSUtils; -public class ExecTerminalProvider implements TerminalProvider -{ +import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_REDIRECT_PIPE_CREATION_MODE; +import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_REDIRECT_PIPE_CREATION_MODE_DEFAULT; +import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_REDIRECT_PIPE_CREATION_MODE_NATIVE; +import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_REDIRECT_PIPE_CREATION_MODE_REFLECTION; + +public class ExecTerminalProvider implements TerminalProvider { + + private static boolean warned; public String name() { - return "exec"; + return TerminalBuilder.PROP_PROVIDER_EXEC; } - public Pty current(Stream consoleStream) throws IOException { - return ExecPty.current(consoleStream); + public Pty current(SystemStream systemStream) throws IOException { + return ExecPty.current(this, systemStream); } @Override - public Terminal sysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, - boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused, - Stream consoleStream, Function inputStreamWrapper) throws IOException { + public Terminal sysTerminal( + String name, + String type, + boolean ansiPassThrough, + Charset encoding, + boolean nativeSignals, + Terminal.SignalHandler signalHandler, + boolean paused, + SystemStream systemStream, + Function inputStreamWrapper) + throws IOException { if (OSUtils.IS_WINDOWS) { - return winSysTerminal(name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, consoleStream, inputStreamWrapper ); + return winSysTerminal( + name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, systemStream, inputStreamWrapper); } else { - return posixSysTerminal(name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, consoleStream, inputStreamWrapper ); + return posixSysTerminal( + name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, systemStream, inputStreamWrapper); } } - public Terminal winSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, - boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused, - Stream consoleStream, Function inputStreamWrapper ) throws IOException { + public Terminal winSysTerminal( + String name, + String type, + boolean ansiPassThrough, + Charset encoding, + boolean nativeSignals, + Terminal.SignalHandler signalHandler, + boolean paused, + SystemStream systemStream, + Function inputStreamWrapper) + throws IOException { if (OSUtils.IS_CYGWIN || OSUtils.IS_MSYSTEM) { - Pty pty = current(consoleStream); + Pty pty = current(systemStream); return new PosixSysTerminal(name, type, pty, encoding, nativeSignals, signalHandler, inputStreamWrapper); } else { return null; } } - public Terminal posixSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, - boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused, - Stream consoleStream, Function inputStreamWrapper) throws IOException { - Pty pty = current(consoleStream); + public Terminal posixSysTerminal( + String name, + String type, + boolean ansiPassThrough, + Charset encoding, + boolean nativeSignals, + Terminal.SignalHandler signalHandler, + boolean paused, + SystemStream systemStream, + Function inputStreamWrapper) + throws IOException { + Pty pty = current(systemStream); return new PosixSysTerminal(name, type, pty, encoding, nativeSignals, signalHandler, inputStreamWrapper); } @Override - public Terminal newTerminal(String name, String type, InputStream in, OutputStream out, - Charset encoding, Terminal.SignalHandler signalHandler, boolean paused, - Attributes attributes, Size size) throws IOException - { - return new ExternalTerminal(name, type, in, out, encoding, signalHandler, paused, attributes, size); + public Terminal newTerminal( + String name, + String type, + InputStream in, + OutputStream out, + Charset encoding, + Terminal.SignalHandler signalHandler, + boolean paused, + Attributes attributes, + Size size) + throws IOException { + return new ExternalTerminal(this, name, type, in, out, encoding, signalHandler, paused, attributes, size); } @Override - public boolean isSystemStream(Stream stream) { + public boolean isSystemStream(SystemStream stream) { try { - return isWindowsSystemStream(stream) || isPosixSystemStream(stream); + return isPosixSystemStream(stream) || isWindowsSystemStream(stream); } catch (Throwable t) { return false; } } - public boolean isWindowsSystemStream(Stream stream) { - return systemStreamName( stream ) != null; + public boolean isWindowsSystemStream(SystemStream stream) { + return systemStreamName(stream) != null; } - public boolean isPosixSystemStream(Stream stream) { + public boolean isPosixSystemStream(SystemStream stream) { try { Process p = new ProcessBuilder(OSUtils.TEST_COMMAND, "-t", Integer.toString(stream.ordinal())) - .inheritIO().start(); + .inheritIO() + .start(); return p.waitFor() == 0; } catch (Throwable t) { + Log.debug("ExecTerminalProvider failed 'test -t' for " + stream, t); // ignore } return false; } @Override - public String systemStreamName(Stream stream) { + public String systemStreamName(SystemStream stream) { try { - ProcessBuilder.Redirect input = stream == Stream.Input - ? ProcessBuilder.Redirect.INHERIT - : getRedirect(stream == Stream.Output ? FileDescriptor.out : FileDescriptor.err); - Process p = new ProcessBuilder(OSUtils.TTY_COMMAND).redirectInput(input).start(); + ProcessBuilder.Redirect input = stream == SystemStream.Input + ? ProcessBuilder.Redirect.INHERIT + : newDescriptor(stream == SystemStream.Output ? FileDescriptor.out : FileDescriptor.err); + Process p = + new ProcessBuilder(OSUtils.TTY_COMMAND).redirectInput(input).start(); String result = ExecHelper.waitAndCapture(p); if (p.exitValue() == 0) { return result.trim(); } } catch (Throwable t) { + if ("java.lang.reflect.InaccessibleObjectException" + .equals(t.getClass().getName()) + && !warned) { + Log.warn( + "The ExecTerminalProvider requires the JVM options: '--add-opens java.base/java.lang=ALL-UNNAMED'"); + warned = true; + } // ignore } return null; } - private ProcessBuilder.Redirect getRedirect(FileDescriptor fd) throws ReflectiveOperationException { - // This is not really allowed, but this is the only way to redirect the output or error stream - // to the input. This is definitely not something you'd usually want to do, but in the case of - // the `tty` utility, it provides a way to get - Class rpi = Class.forName("java.lang.ProcessBuilder$RedirectPipeImpl"); - Constructor cns = rpi.getDeclaredConstructor(); - cns.setAccessible(true); - ProcessBuilder.Redirect input = (ProcessBuilder.Redirect) cns.newInstance(); - Field f = rpi.getDeclaredField("fd"); - f.setAccessible(true); - f.set(input, fd); - return input; +// @Override +// public int systemStreamWidth(SystemStream stream) { +// try (ExecPty pty = new ExecPty(this, stream, null)) { +// return pty.getSize().getColumns(); +// } catch (Throwable t) { +// return -1; +// } +// } + + private static RedirectPipeCreator redirectPipeCreator; + + protected static ProcessBuilder.Redirect newDescriptor(FileDescriptor fd) { + if (redirectPipeCreator == null) { + String str = System.getProperty(PROP_REDIRECT_PIPE_CREATION_MODE, PROP_REDIRECT_PIPE_CREATION_MODE_DEFAULT); + String[] modes = str.split(","); + IllegalStateException ise = new IllegalStateException("Unable to create RedirectPipe"); + for (String mode : modes) { + try { + switch (mode) { + case PROP_REDIRECT_PIPE_CREATION_MODE_NATIVE: + redirectPipeCreator = null;//new NativeRedirectPipeCreator(); + break; + case PROP_REDIRECT_PIPE_CREATION_MODE_REFLECTION: + redirectPipeCreator = new ReflectionRedirectPipeCreator(); + break; + } + } catch (Throwable t) { + // ignore + ise.addSuppressed(t); + } + if (redirectPipeCreator != null) { + break; + } + } + if (redirectPipeCreator == null) { + throw ise; + } + } + return redirectPipeCreator.newRedirectPipe(fd); + } + + interface RedirectPipeCreator { + ProcessBuilder.Redirect newRedirectPipe(FileDescriptor fd); + } + + /** + * Reflection based file descriptor creator. + * This requires the following option + * --add-opens java.base/java.lang=ALL-UNNAMED + */ + static class ReflectionRedirectPipeCreator implements RedirectPipeCreator { + private final Constructor constructor; + private final Field fdField; + + @SuppressWarnings("unchecked") + ReflectionRedirectPipeCreator() throws Exception { + Class rpi = Class.forName("java.lang.ProcessBuilder$RedirectPipeImpl"); + constructor = (Constructor) rpi.getDeclaredConstructor(); + constructor.setAccessible(true); + fdField = rpi.getDeclaredField("fd"); + fdField.setAccessible(true); + } + + @Override + public ProcessBuilder.Redirect newRedirectPipe(FileDescriptor fd) { + try { + ProcessBuilder.Redirect input = constructor.newInstance(); + fdField.set(input, fd); + return input; + } catch (ReflectiveOperationException e) { + // This should not happen as the field has been set accessible + throw new IllegalStateException(e); + } + } + } + +// static class NativeRedirectPipeCreator implements RedirectPipeCreator { +// public NativeRedirectPipeCreator() { +// // Force load the library +// JLineNativeLoader.initialize(); +// } +// +// @Override +// public ProcessBuilder.Redirect newRedirectPipe(FileDescriptor fd) { +// return JLineLibrary.newRedirectPipe(fd); +// } +// } + + @Override + public String toString() { + return "TerminalProvider[" + name() + "]"; } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/Pty.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/Pty.java index b1e22056702..d72e0e669d1 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/Pty.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/Pty.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -34,4 +34,7 @@ public interface Pty extends Closeable { void setSize(Size size) throws IOException; + SystemStream getSystemStream(); + + TerminalProvider getProvider(); } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/SystemStream.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/SystemStream.java new file mode 100644 index 00000000000..5f950248295 --- /dev/null +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/SystemStream.java @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2023, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * https://opensource.org/licenses/BSD-3-Clause + */ +package jdk.internal.org.jline.terminal.spi; + +public enum SystemStream { + Input, + Output, + Error +} diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/TerminalExt.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/TerminalExt.java new file mode 100644 index 00000000000..00cfb2e9d47 --- /dev/null +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/TerminalExt.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * https://opensource.org/licenses/BSD-3-Clause + */ +package jdk.internal.org.jline.terminal.spi; + +import jdk.internal.org.jline.terminal.Terminal; + +/** + * The {@code TerminalExt} interface is implemented by {@code Terminal}s + * and provides access to the Terminal's internals. + */ +public interface TerminalExt extends Terminal { + + /** + * Returns the {@code TerminalProvider} that created this terminal + * or {@code null} if the terminal was created with no provider. + */ + TerminalProvider getProvider(); + + /** + * The underlying system stream, may be {@link SystemStream#Output}, + * {@link SystemStream#Error}, or {@code null} if this terminal is not bound + * to a system stream. + */ + SystemStream getSystemStream(); +} diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/TerminalProvider.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/TerminalProvider.java index 69f353c5719..272df6fedac 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/TerminalProvider.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/spi/TerminalProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, the original author or authors. + * Copyright (c) 2022, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -11,10 +11,8 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.net.URL; import java.nio.charset.Charset; import java.util.Properties; -import java.util.ServiceLoader; import java.util.function.Function; import jdk.internal.org.jline.terminal.Attributes; @@ -22,30 +20,39 @@ import jdk.internal.org.jline.terminal.Terminal; import jdk.internal.org.jline.terminal.impl.exec.ExecTerminalProvider; -public interface TerminalProvider -{ - - enum Stream { - Input, - Output, - Error - } +public interface TerminalProvider { String name(); - Terminal sysTerminal(String name, String type, boolean ansiPassThrough, - Charset encoding, boolean nativeSignals, - Terminal.SignalHandler signalHandler, boolean paused, - Stream consoleStream, Function inputStreamWrapper) throws IOException; + Terminal sysTerminal( + String name, + String type, + boolean ansiPassThrough, + Charset encoding, + boolean nativeSignals, + Terminal.SignalHandler signalHandler, + boolean paused, + SystemStream systemStream, + Function inputStreamWrapper) + throws IOException; - Terminal newTerminal(String name, String type, - InputStream masterInput, OutputStream masterOutput, - Charset encoding, Terminal.SignalHandler signalHandler, - boolean paused, Attributes attributes, Size size) throws IOException; + Terminal newTerminal( + String name, + String type, + InputStream masterInput, + OutputStream masterOutput, + Charset encoding, + Terminal.SignalHandler signalHandler, + boolean paused, + Attributes attributes, + Size size) + throws IOException; - boolean isSystemStream(Stream stream); + boolean isSystemStream(SystemStream stream); - String systemStreamName(Stream stream); + String systemStreamName(SystemStream stream); + + //int systemStreamWidth(SystemStream stream); static TerminalProvider load(String name) throws IOException { switch (name) { @@ -62,7 +69,7 @@ static TerminalProvider load(String name) throws IOException { if (cl == null) { cl = ClassLoader.getSystemClassLoader(); } - InputStream is = cl.getResourceAsStream( "META-INF/services/org/jline/terminal/provider/" + name); + InputStream is = cl.getResourceAsStream("META-INF/services/org/jline/terminal/provider/" + name); if (is != null) { Properties props = new Properties(); try { @@ -71,14 +78,13 @@ static TerminalProvider load(String name) throws IOException { if (className == null) { throw new IOException("No class defined in terminal provider file " + name); } - Class clazz = cl.loadClass( className ); + Class clazz = cl.loadClass(className); return (TerminalProvider) clazz.getConstructor().newInstance(); - } catch ( Exception e ) { - throw new IOException("Unable to load terminal provider " + name, e); + } catch (Exception e) { + throw new IOException("Unable to load terminal provider " + name + ": " + e.getMessage(), e); } } else { throw new IOException("Unable to find terminal provider " + name); } } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AnsiWriter.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AnsiWriter.java index 958d0ec74e9..302406dde89 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AnsiWriter.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AnsiWriter.java @@ -1,17 +1,10 @@ /* - * Copyright (C) 2009-2018 the original author(s). + * Copyright (c) 2009-2018, the original author(s). * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * https://opensource.org/licenses/BSD-3-Clause */ package jdk.internal.org.jline.utils; @@ -252,12 +245,10 @@ private void reset(boolean skipBuffer) throws IOException { * @throws IOException if no more non-null values left */ private int getNextOptionInt(Iterator optionsIterator) throws IOException { - for (;;) { - if (!optionsIterator.hasNext()) - throw new IllegalArgumentException(); + for (; ; ) { + if (!optionsIterator.hasNext()) throw new IllegalArgumentException(); Object arg = optionsIterator.next(); - if (arg != null) - return (Integer) arg; + if (arg != null) return (Integer) arg; } } @@ -346,27 +337,21 @@ private boolean processEscapeCommand(ArrayList options, int command) thr int g = getNextOptionInt(optionsIterator); int b = getNextOptionInt(optionsIterator); if (r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255) { - if (value == 38) - processSetForegroundColorExt(r, g, b); - else - processSetBackgroundColorExt(r, g, b); + if (value == 38) processSetForegroundColorExt(r, g, b); + else processSetBackgroundColorExt(r, g, b); } else { throw new IllegalArgumentException(); } - } - else if (arg2or5 == 5) { + } else if (arg2or5 == 5) { // 256 color style like `esc[38;5;m` int paletteIndex = getNextOptionInt(optionsIterator); if (paletteIndex >= 0 && paletteIndex <= 255) { - if (value == 38) - processSetForegroundColorExt(paletteIndex); - else - processSetBackgroundColorExt(paletteIndex); + if (value == 38) processSetForegroundColorExt(paletteIndex); + else processSetBackgroundColorExt(paletteIndex); } else { throw new IllegalArgumentException(); } - } - else { + } else { throw new IllegalArgumentException(); } } else { @@ -449,47 +434,41 @@ private boolean processOperatingSystemCommand(ArrayList options) throws * Process CSI u ANSI code, corresponding to RCP \u2013 Restore Cursor Position * @throws IOException if an error occurs */ - protected void processRestoreCursorPosition() throws IOException { - } + protected void processRestoreCursorPosition() throws IOException {} /** * Process CSI s ANSI code, corresponding to SCP \u2013 Save Cursor Position * @throws IOException if an error occurs */ - protected void processSaveCursorPosition() throws IOException { - } + protected void processSaveCursorPosition() throws IOException {} /** * Process CSI s ANSI code, corresponding to IL \u2013 Insert Line * @param optionInt the option * @throws IOException if an error occurs */ - protected void processInsertLine(int optionInt) throws IOException { - } + protected void processInsertLine(int optionInt) throws IOException {} /** * Process CSI s ANSI code, corresponding to DL \u2013 Delete Line * @param optionInt the option * @throws IOException if an error occurs */ - protected void processDeleteLine(int optionInt) throws IOException { - } + protected void processDeleteLine(int optionInt) throws IOException {} /** * Process CSI n T ANSI code, corresponding to SD \u2013 Scroll Down * @param optionInt the option * @throws IOException if an error occurs */ - protected void processScrollDown(int optionInt) throws IOException { - } + protected void processScrollDown(int optionInt) throws IOException {} /** * Process CSI n U ANSI code, corresponding to SU \u2013 Scroll Up * @param optionInt the option * @throws IOException if an error occurs */ - protected void processScrollUp(int optionInt) throws IOException { - } + protected void processScrollUp(int optionInt) throws IOException {} protected static final int ERASE_SCREEN_TO_END = 0; protected static final int ERASE_SCREEN_TO_BEGINING = 1; @@ -500,8 +479,7 @@ protected void processScrollUp(int optionInt) throws IOException { * @param eraseOption the erase option * @throws IOException if an error occurs */ - protected void processEraseScreen(int eraseOption) throws IOException { - } + protected void processEraseScreen(int eraseOption) throws IOException {} protected static final int ERASE_LINE_TO_END = 0; protected static final int ERASE_LINE_TO_BEGINING = 1; @@ -512,25 +490,27 @@ protected void processEraseScreen(int eraseOption) throws IOException { * @param eraseOption the erase option * @throws IOException if an error occurs */ - protected void processEraseLine(int eraseOption) throws IOException { - } + protected void processEraseLine(int eraseOption) throws IOException {} + + protected static final int ATTRIBUTE_INTENSITY_BOLD = 1; // Intensity: Bold + protected static final int ATTRIBUTE_INTENSITY_FAINT = 2; // Intensity; Faint not widely supported + protected static final int ATTRIBUTE_ITALIC = 3; // Italic; on not widely supported. Sometimes treated as inverse. + protected static final int ATTRIBUTE_UNDERLINE = 4; // Underline; Single + protected static final int ATTRIBUTE_BLINK_SLOW = 5; // Blink; Slow less than 150 per minute + protected static final int ATTRIBUTE_BLINK_FAST = 6; // Blink; Rapid MS-DOS ANSI.SYS; 150 per minute or more + protected static final int ATTRIBUTE_NEGATIVE_ON = + 7; // Image; Negative inverse or reverse; swap foreground and background + protected static final int ATTRIBUTE_CONCEAL_ON = 8; // Conceal on + protected static final int ATTRIBUTE_UNDERLINE_DOUBLE = 21; // Underline; Double not widely supported + protected static final int ATTRIBUTE_INTENSITY_NORMAL = 22; // Intensity; Normal not bold and not faint + protected static final int ATTRIBUTE_UNDERLINE_OFF = 24; // Underline; None + protected static final int ATTRIBUTE_BLINK_OFF = 25; // Blink; off - protected static final int ATTRIBUTE_INTENSITY_BOLD = 1; // Intensity: Bold - protected static final int ATTRIBUTE_INTENSITY_FAINT = 2; // Intensity; Faint not widely supported - protected static final int ATTRIBUTE_ITALIC = 3; // Italic; on not widely supported. Sometimes treated as inverse. - protected static final int ATTRIBUTE_UNDERLINE = 4; // Underline; Single - protected static final int ATTRIBUTE_BLINK_SLOW = 5; // Blink; Slow less than 150 per minute - protected static final int ATTRIBUTE_BLINK_FAST = 6; // Blink; Rapid MS-DOS ANSI.SYS; 150 per minute or more - protected static final int ATTRIBUTE_NEGATIVE_ON = 7; // Image; Negative inverse or reverse; swap foreground and background - protected static final int ATTRIBUTE_CONCEAL_ON = 8; // Conceal on - protected static final int ATTRIBUTE_UNDERLINE_DOUBLE = 21; // Underline; Double not widely supported - protected static final int ATTRIBUTE_INTENSITY_NORMAL = 22; // Intensity; Normal not bold and not faint - protected static final int ATTRIBUTE_UNDERLINE_OFF = 24; // Underline; None - protected static final int ATTRIBUTE_BLINK_OFF = 25; // Blink; off @Deprecated protected static final int ATTRIBUTE_NEGATIVE_Off = 27; // Image; Positive + protected static final int ATTRIBUTE_NEGATIVE_OFF = 27; // Image; Positive - protected static final int ATTRIBUTE_CONCEAL_OFF = 28; // Reveal conceal off + protected static final int ATTRIBUTE_CONCEAL_OFF = 28; // Reveal conceal off /** * process SGR other than 0 (reset), 30-39 (foreground), @@ -546,8 +526,7 @@ protected void processEraseLine(int eraseOption) throws IOException { * @see #processDefaultTextColor() * @see #processDefaultBackgroundColor() */ - protected void processSetAttribute(int attribute) throws IOException { - } + protected void processSetAttribute(int attribute) throws IOException {} protected static final int BLACK = 0; protected static final int RED = 1; @@ -584,8 +563,7 @@ protected void processSetForegroundColor(int color, boolean bright) throws IOExc * @param paletteIndex the text color in the palette * @throws IOException if an error occurs */ - protected void processSetForegroundColorExt(int paletteIndex) throws IOException { - } + protected void processSetForegroundColorExt(int paletteIndex) throws IOException {} /** * process SGR 38 corresponding to extended set text color (foreground) @@ -625,8 +603,7 @@ protected void processSetBackgroundColor(int color, boolean bright) throws IOExc * @param paletteIndex the background color in the palette * @throws IOException if an error occurs */ - protected void processSetBackgroundColorExt(int paletteIndex) throws IOException { - } + protected void processSetBackgroundColorExt(int paletteIndex) throws IOException {} /** * process SGR 48 corresponding to extended set background color @@ -644,22 +621,19 @@ protected void processSetBackgroundColorExt(int r, int g, int b) throws IOExcept * process SGR 39 corresponding to Default text color (foreground) * @throws IOException if an error occurs */ - protected void processDefaultTextColor() throws IOException { - } + protected void processDefaultTextColor() throws IOException {} /** * process SGR 49 corresponding to Default background color * @throws IOException if an error occurs */ - protected void processDefaultBackgroundColor() throws IOException { - } + protected void processDefaultBackgroundColor() throws IOException {} /** * process SGR 0 corresponding to Reset / Normal * @throws IOException if an error occurs */ - protected void processAttributeRest() throws IOException { - } + protected void processAttributeRest() throws IOException {} /** * process CSI n ; m H corresponding to CUP \u2013 Cursor Position or @@ -668,24 +642,21 @@ protected void processAttributeRest() throws IOException { * @param col the column * @throws IOException if an error occurs */ - protected void processCursorTo(int row, int col) throws IOException { - } + protected void processCursorTo(int row, int col) throws IOException {} /** * process CSI n G corresponding to CHA \u2013 Cursor Horizontal Absolute * @param x the column * @throws IOException if an error occurs */ - protected void processCursorToColumn(int x) throws IOException { - } + protected void processCursorToColumn(int x) throws IOException {} /** * process CSI n F corresponding to CPL \u2013 Cursor Previous Line * @param count line count * @throws IOException if an error occurs */ - protected void processCursorUpLine(int count) throws IOException { - } + protected void processCursorUpLine(int count) throws IOException {} /** * process CSI n E corresponding to CNL \u2013 Cursor Next Line @@ -704,8 +675,7 @@ protected void processCursorDownLine(int count) throws IOException { * @param count the count * @throws IOException if an error occurs */ - protected void processCursorLeft(int count) throws IOException { - } + protected void processCursorLeft(int count) throws IOException {} /** * process CSI n C corresponding to CUF \u2013 Cursor Forward @@ -724,19 +694,16 @@ protected void processCursorRight(int count) throws IOException { * @param count the count * @throws IOException if an error occurs */ - protected void processCursorDown(int count) throws IOException { - } + protected void processCursorDown(int count) throws IOException {} /** * process CSI n A corresponding to CUU \u2013 Cursor Up * @param count the count * @throws IOException if an error occurs */ - protected void processCursorUp(int count) throws IOException { - } + protected void processCursorUp(int count) throws IOException {} - protected void processUnknownExtension(ArrayList options, int command) { - } + protected void processUnknownExtension(ArrayList options, int command) {} /** * process OSC 0;text BEL corresponding to Change Window and Icon label @@ -751,23 +718,20 @@ protected void processChangeIconNameAndWindowTitle(String label) { * process OSC 1;text BEL corresponding to Change Icon label * @param name the icon name */ - protected void processChangeIconName(String name) { - } + protected void processChangeIconName(String name) {} /** * process OSC 2;text BEL corresponding to Change Window title * @param title the title */ - protected void processChangeWindowTitle(String title) { - } + protected void processChangeWindowTitle(String title) {} /** * Process unknown OSC command. * @param command the command * @param param the param */ - protected void processUnknownOperatingSystemCommand(int command, String param) { - } + protected void processUnknownOperatingSystemCommand(int command, String param) {} /** * Process character set sequence. @@ -781,17 +745,13 @@ private boolean processCharsetSelect(ArrayList options) throws IOExcepti return true; } - protected void processCharsetSelect(int set, char seq) { - } + protected void processCharsetSelect(int set, char seq) {} private int optionInt(ArrayList options, int index) { - if (options.size() <= index) - throw new IllegalArgumentException(); + if (options.size() <= index) throw new IllegalArgumentException(); Object value = options.get(index); - if (value == null) - throw new IllegalArgumentException(); - if (!value.getClass().equals(Integer.class)) - throw new IllegalArgumentException(); + if (value == null) throw new IllegalArgumentException(); + if (!value.getClass().equals(Integer.class)) throw new IllegalArgumentException(); return (Integer) value; } @@ -828,5 +788,4 @@ public void close() throws IOException { flush(); super.close(); } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedCharSequence.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedCharSequence.java index ccb0aaf689b..6386f5bba39 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedCharSequence.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedCharSequence.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2021, the original author or authors. + * Copyright (c) 2002-2021, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -15,6 +15,7 @@ import jdk.internal.org.jline.terminal.impl.AbstractWindowsTerminal; import jdk.internal.org.jline.utils.InfoCmp.Capability; +import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_DISABLE_ALTERNATE_CHARSET; import static jdk.internal.org.jline.utils.AttributedStyle.BG_COLOR; import static jdk.internal.org.jline.utils.AttributedStyle.BG_COLOR_EXP; import static jdk.internal.org.jline.utils.AttributedStyle.FG_COLOR; @@ -30,12 +31,11 @@ import static jdk.internal.org.jline.utils.AttributedStyle.F_FOREGROUND; import static jdk.internal.org.jline.utils.AttributedStyle.F_FOREGROUND_IND; import static jdk.internal.org.jline.utils.AttributedStyle.F_FOREGROUND_RGB; +import static jdk.internal.org.jline.utils.AttributedStyle.F_HIDDEN; import static jdk.internal.org.jline.utils.AttributedStyle.F_INVERSE; import static jdk.internal.org.jline.utils.AttributedStyle.F_ITALIC; import static jdk.internal.org.jline.utils.AttributedStyle.F_UNDERLINE; -import static jdk.internal.org.jline.utils.AttributedStyle.F_HIDDEN; import static jdk.internal.org.jline.utils.AttributedStyle.MASK; -import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_DISABLE_ALTERNATE_CHARSET; public abstract class AttributedCharSequence implements CharSequence { @@ -120,6 +120,7 @@ public String toAnsi(int colors, ForceMode force, ColorPalette palette, String a char c = charAt(i); if (altIn != null && altOut != null) { char pc = c; + // @spotless:off switch (c) { case '\u2518': c = 'j'; break; case '\u2510': c = 'k'; break; @@ -133,15 +134,16 @@ public String toAnsi(int colors, ForceMode force, ColorPalette palette, String a case '\u252C': c = 'w'; break; case '\u2502': c = 'x'; break; } + // @spotless:on boolean oldalt = alt; alt = c != pc; if (oldalt ^ alt) { sb.append(alt ? altIn : altOut); } } - long s = styleCodeAt(i) & ~F_HIDDEN; // The hidden flag does not change the ansi styles + long s = styleCodeAt(i) & ~F_HIDDEN; // The hidden flag does not change the ansi styles if (style != s) { - long d = (style ^ s) & MASK; + long d = (style ^ s) & MASK; long fg = (s & F_FOREGROUND) != 0 ? s & (FG_COLOR | F_FOREGROUND) : 0; long bg = (s & F_BACKGROUND) != 0 ? s & (BG_COLOR | F_BACKGROUND) : 0; if (s == 0) { @@ -172,16 +174,16 @@ public String toAnsi(int colors, ForceMode force, ColorPalette palette, String a if (fg > 0) { int rounded = -1; if ((fg & F_FOREGROUND_RGB) != 0) { - int r = (int)(fg >> (FG_COLOR_EXP + 16)) & 0xFF; - int g = (int)(fg >> (FG_COLOR_EXP + 8)) & 0xFF; - int b = (int)(fg >> FG_COLOR_EXP) & 0xFF; + int r = (int) (fg >> (FG_COLOR_EXP + 16)) & 0xFF; + int g = (int) (fg >> (FG_COLOR_EXP + 8)) & 0xFF; + int b = (int) (fg >> FG_COLOR_EXP) & 0xFF; if (colors >= HIGH_COLORS) { first = attr(sb, "38;2;" + r + ";" + g + ";" + b, first); } else { rounded = palette.round(r, g, b); } } else if ((fg & F_FOREGROUND_IND) != 0) { - rounded = palette.round((int)(fg >> FG_COLOR_EXP) & 0xFF); + rounded = palette.round((int) (fg >> FG_COLOR_EXP) & 0xFF); } if (rounded >= 0) { if (colors >= HIGH_COLORS && force == ForceMode.ForceTrueColors) { @@ -211,16 +213,16 @@ public String toAnsi(int colors, ForceMode force, ColorPalette palette, String a if (bg > 0) { int rounded = -1; if ((bg & F_BACKGROUND_RGB) != 0) { - int r = (int)(bg >> (BG_COLOR_EXP + 16)) & 0xFF; - int g = (int)(bg >> (BG_COLOR_EXP + 8)) & 0xFF; - int b = (int)(bg >> BG_COLOR_EXP) & 0xFF; + int r = (int) (bg >> (BG_COLOR_EXP + 16)) & 0xFF; + int g = (int) (bg >> (BG_COLOR_EXP + 8)) & 0xFF; + int b = (int) (bg >> BG_COLOR_EXP) & 0xFF; if (colors >= HIGH_COLORS) { first = attr(sb, "48;2;" + r + ";" + g + ";" + b, first); } else { rounded = palette.round(r, g, b); } } else if ((bg & F_BACKGROUND_IND) != 0) { - rounded = palette.round((int)(bg >> BG_COLOR_EXP) & 0xFF); + rounded = palette.round((int) (bg >> BG_COLOR_EXP) & 0xFF); } if (rounded >= 0) { if (colors >= HIGH_COLORS && force == ForceMode.ForceTrueColors) { @@ -243,8 +245,7 @@ public String toAnsi(int colors, ForceMode force, ColorPalette palette, String a background = bg; } if ((d & (F_BOLD | F_FAINT)) != 0) { - if ( (d & F_BOLD) != 0 && (s & F_BOLD) == 0 - || (d & F_FAINT) != 0 && (s & F_FAINT) == 0) { + if ((d & F_BOLD) != 0 && (s & F_BOLD) == 0 || (d & F_FAINT) != 0 && (s & F_FAINT) == 0) { first = attr(sb, "22", first); } if ((d & F_BOLD) != 0 && (s & F_BOLD) != 0) { @@ -360,8 +361,7 @@ public int columnLength() { int len = length(); for (int cur = 0; cur < len; ) { int cp = codePointAt(cur); - if (!isHidden(cur)) - cols += WCWidth.wcwidth(cp); + if (!isHidden(cur)) cols += WCWidth.wcwidth(cp); cur += Character.charCount(cp); } return cols; @@ -382,8 +382,7 @@ public AttributedString columnSubSequence(int start, int stop) { int end = begin; while (end < this.length()) { int cp = codePointAt(end); - if (cp == '\n') - break; + if (cp == '\n') break; int w = isHidden(end) ? 0 : WCWidth.wcwidth(cp); if (col + w > stop) { break; @@ -407,7 +406,7 @@ public List columnSplitLength(int columns, boolean includeNewl int cp = codePointAt(cur); int w = isHidden(cur) ? 0 : WCWidth.wcwidth(cp); if (cp == '\n') { - strings.add(subSequence(beg, includeNewlines ? cur+1 : cur)); + strings.add(subSequence(beg, includeNewlines ? cur + 1 : cur)); beg = cur + 1; col = 0; } else if ((col += w) > columns) { @@ -429,5 +428,4 @@ public String toString() { public AttributedString toAttributedString() { return substring(0, length()); } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedString.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedString.java index 47492b72e76..3c70a6d0e7b 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedString.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedString.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -15,6 +15,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import jdk.internal.org.jline.terminal.Terminal; + /** * Attributed string. * Instances of this class are immutables. @@ -103,11 +105,28 @@ public static AttributedString fromAnsi(String ansi, int tabs) { } public static AttributedString fromAnsi(String ansi, List tabs) { + return fromAnsi(ansi, tabs, null, null); + } + + public static AttributedString fromAnsi(String ansi, Terminal terminal) { + String alternateIn, alternateOut; + if (!DISABLE_ALTERNATE_CHARSET) { + alternateIn = Curses.tputs(terminal.getStringCapability(InfoCmp.Capability.enter_alt_charset_mode)); + alternateOut = Curses.tputs(terminal.getStringCapability(InfoCmp.Capability.exit_alt_charset_mode)); + } else { + alternateIn = null; + alternateOut = null; + } + return fromAnsi(ansi, Arrays.asList(0), alternateIn, alternateOut); + } + + public static AttributedString fromAnsi(String ansi, List tabs, String altIn, String altOut) { if (ansi == null) { return null; } return new AttributedStringBuilder(ansi.length()) .tabs(tabs) + .altCharset(altIn, altOut) .ansiAppend(ansi) .toAttributedString(); } @@ -116,9 +135,7 @@ public static String stripAnsi(String ansi) { if (ansi == null) { return null; } - return new AttributedStringBuilder(ansi.length()) - .ansiAppend(ansi) - .toString(); + return new AttributedStringBuilder(ansi.length()).ansiAppend(ansi).toString(); } @Override @@ -162,7 +179,7 @@ public AttributedString styleMatches(Pattern pattern, AttributedStyle style) { } result = matcher.find(); } while (result); - return new AttributedString(buffer, newstyle, start , end); + return new AttributedString(buffer, newstyle, start, end); } return this; } @@ -179,15 +196,16 @@ && arrEq(buffer, that.buffer, start, that.start, end - start) private boolean arrEq(char[] a1, char[] a2, int s1, int s2, int l) { for (int i = 0; i < l; i++) { - if (a1[s1+i] != a2[s2+i]) { + if (a1[s1 + i] != a2[s2 + i]) { return false; } } return true; } + private boolean arrEq(long[] a1, long[] a2, int s1, int s2, int l) { for (int i = 0; i < l; i++) { - if (a1[s1+i] != a2[s2+i]) { + if (a1[s1 + i] != a2[s2 + i]) { return false; } } @@ -221,5 +239,4 @@ public static AttributedString join(AttributedString delimiter, Iterable 0) { + append(s); + } + return this; + } + public AttributedStringBuilder append(CharSequence csq, AttributedStyle style) { return append(new AttributedString(csq, style)); } @@ -117,12 +125,12 @@ public AttributedStringBuilder style(AttributedStyle style) { return this; } - public AttributedStringBuilder style(Function style) { + public AttributedStringBuilder style(Function style) { current = style.apply(current); return this; } - public AttributedStringBuilder styled(Function style, CharSequence cs) { + public AttributedStringBuilder styled(Function style, CharSequence cs) { return styled(style, sb -> sb.append(cs)); } @@ -130,7 +138,8 @@ public AttributedStringBuilder styled(AttributedStyle style, CharSequence cs) { return styled(s -> style, sb -> sb.append(cs)); } - public AttributedStringBuilder styled(Function style, Consumer consumer) { + public AttributedStringBuilder styled( + Function style, Consumer consumer) { AttributedStyle prev = current; current = style.apply(prev); consumer.accept(this); @@ -338,23 +347,90 @@ public AttributedStringBuilder ansiAppend(String ansi) { // This is not a SGR code, so ignore ansiState = 0; } - } else if (c == '\t' && tabs.defined()) { - insertTab(current); } else { - ensureCapacity(length + 1); - buffer[length] = c; - style[length] = this.current.getStyle(); - if (c == '\n') { - lastLineLength = 0; + if (ansiState >= 1) { + ensureCapacity(length + 1); + buffer[length++] = 27; + if (ansiState >= 2) { + ensureCapacity(length + 1); + buffer[length++] = '['; + } + ansiState = 0; + } + if (c == '\t' && tabs.defined()) { + insertTab(current); } else { - lastLineLength++; + ensureCapacity(length + 1); + if (inAltCharset) { + switch (c) { + case 'j': + c = '\u2518'; + break; + case 'k': + c = '\u2510'; + break; + case 'l': + c = '\u250C'; + break; + case 'm': + c = '\u2514'; + break; + case 'n': + c = '\u253C'; + break; + case 'q': + c = '\u2500'; + break; + case 't': + c = '\u251C'; + break; + case 'u': + c = '\u2524'; + break; + case 'v': + c = '\u2534'; + break; + case 'w': + c = '\u252C'; + break; + case 'x': + c = '\u2502'; + break; + } + } + buffer[length] = c; + style[length] = this.current.getStyle(); + if (c == '\n') { + lastLineLength = 0; + } else { + lastLineLength++; + } + length++; + if (altIn != null && altOut != null) { + char[] alt = inAltCharset ? altOut : altIn; + if (equals(buffer, length - alt.length, alt, 0, alt.length)) { + inAltCharset = !inAltCharset; + length -= alt.length; + } + } } - length++; } } return this; } + private static boolean equals(char[] a, int aFromIndex, char[] b, int bFromIndex, int length) { + if (aFromIndex < 0 || bFromIndex < 0 || aFromIndex + length > a.length || bFromIndex + length > b.length) { + return false; + } + for (int i = 0; i < length; i++) { + if (a[aFromIndex + i] != b[bFromIndex + i]) { + return false; + } + } + return true; + } + protected void insertTab(AttributedStyle s) { int nb = tabs.spaces(lastLineLength); ensureCapacity(length + nb); @@ -393,6 +469,15 @@ public AttributedStringBuilder tabs(List tabs) { return this; } + public AttributedStringBuilder altCharset(String altIn, String altOut) { + if (length > 0) { + throw new IllegalStateException("Cannot change alternative charset after appending text"); + } + this.altIn = altIn != null ? altIn.toCharArray() : null; + this.altOut = altOut != null ? altOut.toCharArray() : null; + return this; + } + public AttributedStringBuilder styleMatches(Pattern pattern, AttributedStyle s) { Matcher matcher = pattern.matcher(this); while (matcher.find()) { @@ -416,7 +501,7 @@ public AttributedStringBuilder styleMatches(Pattern pattern, List tabs = new ArrayList<>(); private int lastStop = 0; private int lastSize = 0; @@ -428,7 +513,7 @@ public TabStops(int tabs) { public TabStops(List tabs) { this.tabs = tabs; int p = 0; - for (int s: tabs) { + for (int s : tabs) { if (s <= p) { continue; } @@ -447,7 +532,7 @@ int spaces(int lastLineLength) { if (lastLineLength >= lastStop) { out = lastSize - (lastLineLength - lastStop) % lastSize; } else { - for (int s: tabs) { + for (int s : tabs) { if (s > lastLineLength) { out = s - lastLineLength; break; @@ -456,7 +541,5 @@ int spaces(int lastLineLength) { } return out; } - } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedStyle.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedStyle.java index 902e2e1f3b8..7845e99e0b0 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedStyle.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/AttributedStyle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2021, the original author or authors. + * Copyright (c) 2002-2021, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -15,39 +15,39 @@ */ public class AttributedStyle { - public static final int BLACK = 0; - public static final int RED = 1; - public static final int GREEN = 2; - public static final int YELLOW = 3; - public static final int BLUE = 4; - public static final int MAGENTA = 5; - public static final int CYAN = 6; - public static final int WHITE = 7; - - public static final int BRIGHT = 8; - - static final long F_BOLD = 0x00000001; - static final long F_FAINT = 0x00000002; - static final long F_ITALIC = 0x00000004; - static final long F_UNDERLINE = 0x00000008; - static final long F_BLINK = 0x00000010; - static final long F_INVERSE = 0x00000020; - static final long F_CONCEAL = 0x00000040; - static final long F_CROSSED_OUT = 0x00000080; - static final long F_FOREGROUND_IND = 0x00000100; - static final long F_FOREGROUND_RGB = 0x00000200; - static final long F_FOREGROUND = F_FOREGROUND_IND | F_FOREGROUND_RGB; - static final long F_BACKGROUND_IND = 0x00000400; - static final long F_BACKGROUND_RGB = 0x00000800; - static final long F_BACKGROUND = F_BACKGROUND_IND | F_BACKGROUND_RGB; - static final long F_HIDDEN = 0x00001000; - - static final long MASK = 0x00001FFF; - - static final int FG_COLOR_EXP = 15; - static final int BG_COLOR_EXP = 39; - static final long FG_COLOR = 0xFFFFFFL << FG_COLOR_EXP; - static final long BG_COLOR = 0xFFFFFFL << BG_COLOR_EXP; + public static final int BLACK = 0; + public static final int RED = 1; + public static final int GREEN = 2; + public static final int YELLOW = 3; + public static final int BLUE = 4; + public static final int MAGENTA = 5; + public static final int CYAN = 6; + public static final int WHITE = 7; + + public static final int BRIGHT = 8; + + static final long F_BOLD = 0x00000001; + static final long F_FAINT = 0x00000002; + static final long F_ITALIC = 0x00000004; + static final long F_UNDERLINE = 0x00000008; + static final long F_BLINK = 0x00000010; + static final long F_INVERSE = 0x00000020; + static final long F_CONCEAL = 0x00000040; + static final long F_CROSSED_OUT = 0x00000080; + static final long F_FOREGROUND_IND = 0x00000100; + static final long F_FOREGROUND_RGB = 0x00000200; + static final long F_FOREGROUND = F_FOREGROUND_IND | F_FOREGROUND_RGB; + static final long F_BACKGROUND_IND = 0x00000400; + static final long F_BACKGROUND_RGB = 0x00000800; + static final long F_BACKGROUND = F_BACKGROUND_IND | F_BACKGROUND_RGB; + static final long F_HIDDEN = 0x00001000; + + static final long MASK = 0x00001FFF; + + static final int FG_COLOR_EXP = 15; + static final int BG_COLOR_EXP = 39; + static final long FG_COLOR = 0xFFFFFFL << FG_COLOR_EXP; + static final long BG_COLOR = 0xFFFFFFL << BG_COLOR_EXP; public static final AttributedStyle DEFAULT = new AttributedStyle(); public static final AttributedStyle BOLD = DEFAULT.bold(); @@ -70,8 +70,9 @@ public AttributedStyle(AttributedStyle s) { public AttributedStyle(long style, long mask) { this.style = style; - this.mask = mask & MASK | ((style & F_FOREGROUND) != 0 ? FG_COLOR : 0) - | ((style & F_BACKGROUND) != 0 ? BG_COLOR : 0); + this.mask = mask & MASK + | ((style & F_FOREGROUND) != 0 ? FG_COLOR : 0) + | ((style & F_BACKGROUND) != 0 ? BG_COLOR : 0); } public AttributedStyle bold() { @@ -176,7 +177,9 @@ public AttributedStyle crossedOutDefault() { } public AttributedStyle foreground(int color) { - return new AttributedStyle(style & ~FG_COLOR | F_FOREGROUND_IND | (((long) color << FG_COLOR_EXP) & FG_COLOR), mask | F_FOREGROUND_IND); + return new AttributedStyle( + style & ~FG_COLOR | F_FOREGROUND_IND | (((long) color << FG_COLOR_EXP) & FG_COLOR), + mask | F_FOREGROUND_IND); } public AttributedStyle foreground(int r, int g, int b) { @@ -184,7 +187,9 @@ public AttributedStyle foreground(int r, int g, int b) { } public AttributedStyle foregroundRgb(int color) { - return new AttributedStyle(style & ~FG_COLOR | F_FOREGROUND_RGB | ((((long) color & 0xFFFFFF) << FG_COLOR_EXP) & FG_COLOR), mask | F_FOREGROUND_RGB); + return new AttributedStyle( + style & ~FG_COLOR | F_FOREGROUND_RGB | ((((long) color & 0xFFFFFF) << FG_COLOR_EXP) & FG_COLOR), + mask | F_FOREGROUND_RGB); } public AttributedStyle foregroundOff() { @@ -196,7 +201,9 @@ public AttributedStyle foregroundDefault() { } public AttributedStyle background(int color) { - return new AttributedStyle(style & ~BG_COLOR | F_BACKGROUND_IND | (((long) color << BG_COLOR_EXP) & BG_COLOR), mask | F_BACKGROUND_IND); + return new AttributedStyle( + style & ~BG_COLOR | F_BACKGROUND_IND | (((long) color << BG_COLOR_EXP) & BG_COLOR), + mask | F_BACKGROUND_IND); } public AttributedStyle background(int r, int g, int b) { @@ -204,7 +211,9 @@ public AttributedStyle background(int r, int g, int b) { } public AttributedStyle backgroundRgb(int color) { - return new AttributedStyle(style & ~BG_COLOR | F_BACKGROUND_RGB | ((((long) color & 0xFFFFFF) << BG_COLOR_EXP) & BG_COLOR), mask | F_BACKGROUND_RGB); + return new AttributedStyle( + style & ~BG_COLOR | F_BACKGROUND_RGB | ((((long) color & 0xFFFFFF) << BG_COLOR_EXP) & BG_COLOR), + mask | F_BACKGROUND_RGB); } public AttributedStyle backgroundOff() { @@ -249,7 +258,6 @@ public boolean equals(Object o) { AttributedStyle that = (AttributedStyle) o; if (style != that.style) return false; return mask == that.mask; - } @Override @@ -266,10 +274,6 @@ public String toAnsi() { @Override public String toString() { - return "AttributedStyle{" + - "style=" + style + - ", mask=" + mask + - ", ansi=" + toAnsi() + - '}'; + return "AttributedStyle{" + "style=" + style + ", mask=" + mask + ", ansi=" + toAnsi() + '}'; } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ClosedException.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ClosedException.java index f2adb0878c7..a6f5bfb5b54 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ClosedException.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ClosedException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -14,8 +14,7 @@ public class ClosedException extends IOException { private static final long serialVersionUID = 3085420657077696L; - public ClosedException() { - } + public ClosedException() {} public ClosedException(String message) { super(message); diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ColorPalette.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ColorPalette.java index 6f55273a7b9..b4175fe13ce 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ColorPalette.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ColorPalette.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2020, the original author or authors. + * Copyright (c) 2002-2020, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -21,7 +21,8 @@ */ public class ColorPalette { - public static final String XTERM_INITC = "\\E]4;%p1%d;rgb\\:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\\E\\\\"; + public static final String XTERM_INITC = + "\\E]4;%p1%d;rgb\\:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\\E\\\\"; public static final ColorPalette DEFAULT = new ColorPalette(); @@ -41,6 +42,7 @@ public ColorPalette(Terminal terminal) throws IOException { this(terminal, null); } + @SuppressWarnings("this-escape") public ColorPalette(Terminal terminal, String distance) throws IOException { this.terminal = terminal; this.distanceName = distance; @@ -245,10 +247,13 @@ private static int[] doLoad(Terminal terminal) throws IOException { if (rgb.size() != 3) { return null; } - double r = Integer.parseInt(rgb.get(0), 16) / ((1 << (4 * rgb.get(0).length())) - 1.0); - double g = Integer.parseInt(rgb.get(1), 16) / ((1 << (4 * rgb.get(1).length())) - 1.0); - double b = Integer.parseInt(rgb.get(2), 16) / ((1 << (4 * rgb.get(2).length())) - 1.0); - palette[idx] = (int)((Math.round(r * 255) << 16) + (Math.round(g * 255) << 8) + Math.round(b * 255)); + double r = Integer.parseInt(rgb.get(0), 16) + / ((1 << (4 * rgb.get(0).length())) - 1.0); + double g = Integer.parseInt(rgb.get(1), 16) + / ((1 << (4 * rgb.get(1).length())) - 1.0); + double b = Integer.parseInt(rgb.get(2), 16) + / ((1 << (4 * rgb.get(2).length())) - 1.0); + palette[idx] = (int) ((Math.round(r * 255) << 16) + (Math.round(g * 255) << 8) + Math.round(b * 255)); black &= palette[idx] == 0; } if (black) { @@ -256,7 +261,13 @@ private static int[] doLoad(Terminal terminal) throws IOException { } } int max = 256; - while (max > 0 && palette[--max] == 0); + while (max > 0 && palette[--max] == 0) + ; return Arrays.copyOfRange(palette, 0, max + 1); } + + @Override + public String toString() { + return "ColorPalette[" + "length=" + getLength() + ", " + "distance='" + getDist() + "\']"; + } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Colors.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Colors.java index dc452e10364..d5e7644d3cb 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Colors.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Colors.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -21,6 +21,8 @@ public class Colors { + // @spotless:off + /** * Default 256 colors palette */ @@ -111,24 +113,26 @@ public class Colors { 0x2e2e2e, 0x5c5c5c, 0x737373, 0x8b8b8b, 0xa2a2a2, 0xb9b9b9, 0xd0d0d0, 0xe7e7e7, }; + // @spotless:on + /** D50 illuminant for CAM color spaces */ - public static final double[] D50 = new double[] { 96.422f, 100.0f, 82.521f }; + public static final double[] D50 = new double[] {96.422f, 100.0f, 82.521f}; /** D65 illuminant for CAM color spaces */ - public static final double[] D65 = new double[] { 95.047, 100.0, 108.883 }; + public static final double[] D65 = new double[] {95.047, 100.0, 108.883}; /** Average surrounding for CAM color spaces */ - public static final double[] averageSurrounding = new double[] { 1.0, 0.690, 1.0 }; + public static final double[] averageSurrounding = new double[] {1.0, 0.690, 1.0}; /** Dim surrounding for CAM color spaces */ - public static final double[] dimSurrounding = new double[] { 0.9, 0.590, 0.9 }; + public static final double[] dimSurrounding = new double[] {0.9, 0.590, 0.9}; /** Dark surrounding for CAM color spaces */ - public static final double[] darkSurrounding = new double[] { 0.8, 0.525, 0.8 }; + public static final double[] darkSurrounding = new double[] {0.8, 0.525, 0.8}; /** sRGB encoding environment */ - public static final double[] sRGB_encoding_environment = vc(D50, 64.0, 64.0/5, dimSurrounding); + public static final double[] sRGB_encoding_environment = vc(D50, 64.0, 64.0 / 5, dimSurrounding); /** sRGB typical environment */ - public static final double[] sRGB_typical_environment = vc(D50, 200.0, 200.0/5, averageSurrounding); + public static final double[] sRGB_typical_environment = vc(D50, 200.0, 200.0 / 5, averageSurrounding); /** Adobe RGB environment */ - public static final double[] AdobeRGB_environment = vc(D65, 160.0, 160.0/5, averageSurrounding); + public static final double[] AdobeRGB_environment = vc(D65, 160.0, 160.0 / 5, averageSurrounding); private static int[] COLORS_256 = DEFAULT_COLORS_256; @@ -149,8 +153,9 @@ public static Integer rgbColor(String name) { if (COLOR_NAMES == null) { Map colors = new LinkedHashMap<>(); try (InputStream is = InfoCmp.class.getResourceAsStream("colors.txt"); - BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) { - br.lines().map(String::trim) + BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) { + br.lines() + .map(String::trim) .filter(s -> !s.startsWith("#")) .filter(s -> !s.isEmpty()) .forEachOrdered(s -> { @@ -206,7 +211,7 @@ static Distance getDistance(String dist) { if (dist == null) { dist = System.getProperty(PROP_COLOR_DISTANCE, "cie76"); } - return doGetDistance(dist); + return new NamedDistance(dist, doGetDistance(dist)); } private static Distance doGetDistance(String dist) { @@ -216,7 +221,7 @@ private static Distance doGetDistance(String dist) { double[] c1 = rgb(p1); double[] c2 = rgb(p2); double rmean = (c1[0] + c2[0]) / 2.0; - double[] w = { 2.0 + rmean, 4.0, 3.0 - rmean }; + double[] w = {2.0 + rmean, 4.0, 3.0 - rmean}; return scalar(c1, c2, w); }; } @@ -228,7 +233,7 @@ private static Distance doGetDistance(String dist) { } if (dist.matches("lab\\(([0-9]+(\\.[0-9]+)?),([0-9]+(\\.[0-9]+)?)\\)")) { double[] w = getWeights(dist); - return (p1, p2) -> scalar(rgb2cielab(p1), rgb2cielab(p2), new double[] { w[0], w[1], w[1] }); + return (p1, p2) -> scalar(rgb2cielab(p1), rgb2cielab(p2), new double[] {w[0], w[1], w[1]}); } if (dist.equals("cie94")) { return (p1, p2) -> cie94(rgb2cielab(p1), rgb2cielab(p2)); @@ -251,7 +256,7 @@ private static Distance doGetDistance(String dist) { double[] c1 = camlab(p1, sRGB_typical_environment); double[] c2 = camlab(p2, sRGB_typical_environment); double[] w = getWeights(dist); - return scalar(c1, c2, new double[] { w[0], w[1], w[1] }); + return scalar(c1, c2, new double[] {w[0], w[1], w[1]}); }; } if (dist.matches("camlch")) { @@ -273,20 +278,37 @@ private static Distance doGetDistance(String dist) { } private static double[] getWeights(String dist) { - String[] weights = dist.substring(dist.indexOf('(') + 1, dist.length() - 1).split(","); + String[] weights = + dist.substring(dist.indexOf('(') + 1, dist.length() - 1).split(","); return Stream.of(weights).mapToDouble(Double::parseDouble).toArray(); } private static double scalar(double[] c1, double[] c2, double[] w) { - return sqr((c1[0] - c2[0]) * w[0]) - + sqr((c1[1] - c2[1]) * w[1]) - + sqr((c1[2] - c2[2]) * w[2]); + return sqr((c1[0] - c2[0]) * w[0]) + sqr((c1[1] - c2[1]) * w[1]) + sqr((c1[2] - c2[2]) * w[2]); } private static double scalar(double[] c1, double[] c2) { - return sqr(c1[0] - c2[0]) - + sqr(c1[1] - c2[1]) - + sqr(c1[2] - c2[2]); + return sqr(c1[0] - c2[0]) + sqr(c1[1] - c2[1]) + sqr(c1[2] - c2[2]); + } + + private static class NamedDistance implements Distance { + private final String name; + private final Distance delegate; + + public NamedDistance(String name, Distance delegate) { + this.name = name; + this.delegate = delegate; + } + + @Override + public double compute(int c1, int c2) { + return delegate.compute(c1, c2); + } + + @Override + public String toString() { + return name; + } } private static final int L = 0; @@ -325,7 +347,7 @@ private static double cie00(double[] lab1, double[] lab2) { double c_star_average_ab = (c_star_1_ab + c_star_2_ab) / 2.0; double c_star_average_ab_pot_3 = c_star_average_ab * c_star_average_ab * c_star_average_ab; double c_star_average_ab_pot_7 = c_star_average_ab_pot_3 * c_star_average_ab_pot_3 * c_star_average_ab; - double G = 0.5 * (1.0 - Math.sqrt(c_star_average_ab_pot_7 / (c_star_average_ab_pot_7 + 6103515625.0))); //25^7 + double G = 0.5 * (1.0 - Math.sqrt(c_star_average_ab_pot_7 / (c_star_average_ab_pot_7 + 6103515625.0))); // 25^7 double a1_prime = (1.0 + G) * lab1[A]; double a2_prime = (1.0 + G) * lab2[A]; double C_prime_1 = Math.sqrt(a1_prime * a1_prime + lab1[B] * lab1[B]); @@ -365,16 +387,18 @@ private static double cie00(double[] lab1, double[] lab2) { + 0.24 * Math.cos(Math.toRadians(h_prime_average * 2.0)) + 0.32 * Math.cos(Math.toRadians(h_prime_average * 3.0 + 6.0)) - 0.20 * Math.cos(Math.toRadians(h_prime_average * 4.0 - 63.0)); - double S_L = 1.0 + ((0.015 * L_prime_average_minus_50_square) / Math.sqrt(20.0 + L_prime_average_minus_50_square)); + double S_L = + 1.0 + ((0.015 * L_prime_average_minus_50_square) / Math.sqrt(20.0 + L_prime_average_minus_50_square)); double S_C = 1.0 + 0.045 * C_prime_average; double S_H = 1.0 + 0.015 * T * C_prime_average; double h_prime_average_minus_275_div_25 = (h_prime_average - 275.0) / (25.0); - double h_prime_average_minus_275_div_25_square = h_prime_average_minus_275_div_25 * h_prime_average_minus_275_div_25; + double h_prime_average_minus_275_div_25_square = + h_prime_average_minus_275_div_25 * h_prime_average_minus_275_div_25; double delta_theta = 30.0 * Math.exp(-h_prime_average_minus_275_div_25_square); double C_prime_average_pot_3 = C_prime_average * C_prime_average * C_prime_average; double C_prime_average_pot_7 = C_prime_average_pot_3 * C_prime_average_pot_3 * C_prime_average; - double R_C = 2.0 * Math.sqrt(C_prime_average_pot_7 / (C_prime_average_pot_7 + 6103515625.0)); //25^7 - double R_T = - Math.sin(Math.toRadians(2.0 * delta_theta)) * R_C; + double R_C = 2.0 * Math.sqrt(C_prime_average_pot_7 / (C_prime_average_pot_7 + 6103515625.0)); // 25^7 + double R_T = -Math.sin(Math.toRadians(2.0 * delta_theta)) * R_C; double dLKlsl = delta_L_prime / (kl * S_L); double dCkcsc = delta_C_prime / (kc * S_C); double dHkhsh = delta_H_prime / (kh * S_H); @@ -392,11 +416,11 @@ private static double[] jmh2ucs(double[] lch) { double sM = ((1.0 / 0.0228) * Math.log(1.0 + 0.0228 * lch[1])); double a = sM * Math.cos(Math.toRadians(lch[2])); double b = sM * Math.sin(Math.toRadians(lch[2])); - return new double[] {sJ, a, b }; + return new double[] {sJ, a, b}; } static double camlch(double[] c1, double[] c2) { - return camlch(c1, c2, new double[] { 1.0, 1.0, 1.0 }); + return camlch(c1, c2, new double[] {1.0, 1.0, 1.0}); } static double camlch(double[] c1, double[] c2, double[] w) { @@ -414,18 +438,16 @@ static double camlch(double[] c1, double[] c2, double[] w) { private static double hueDifference(double hue1, double hue2, double c) { double difference = (hue2 - hue1) % c; double ch = c / 2; - if (difference > ch) - difference -= c; - if (difference < -ch) - difference += c; + if (difference > ch) difference -= c; + if (difference < -ch) difference += c; return difference; } private static double[] rgb(int color) { int r = (color >> 16) & 0xFF; - int g = (color >> 8) & 0xFF; - int b = (color >> 0) & 0xFF; - return new double[] { r / 255.0, g / 255.0, b / 255.0 }; + int g = (color >> 8) & 0xFF; + int b = (color >> 0) & 0xFF; + return new double[] {r / 255.0, g / 255.0, b / 255.0}; } static double[] rgb2xyz(int color) { @@ -454,13 +476,13 @@ static double[] camlab(int color, double[] vc) { static double[] lch2lab(double[] lch) { double toRad = Math.PI / 180; - return new double[] { lch[0], lch[1] * Math.cos(lch[2] * toRad), lch[1] * Math.sin(lch[2] * toRad) }; + return new double[] {lch[0], lch[1] * Math.cos(lch[2] * toRad), lch[1] * Math.sin(lch[2] * toRad)}; } private static double[] xyz2camlch(double[] xyz, double[] vc) { double[] XYZ = new double[] {xyz[0] * 100.0, xyz[1] * 100.0, xyz[2] * 100.0}; double[] cam = forwardTransform(XYZ, vc); - return new double[] { cam[J], cam[M], cam[h] }; + return new double[] {cam[J], cam[M], cam[h]}; } /** Lightness */ @@ -478,12 +500,12 @@ private static double[] xyz2camlch(double[] xyz, double[] vc) { /** Hue */ public static final int h = 6; - /** CIECAM02 appearance correlates */ private static double[] forwardTransform(double[] XYZ, double[] vc) { // calculate sharpened cone response double[] RGB = forwardPreAdaptationConeResponse(XYZ); - // calculate corresponding (sharpened) cone response considering various luminance level and surround conditions in D + // calculate corresponding (sharpened) cone response considering various luminance level and surround conditions + // in D double[] RGB_c = forwardPostAdaptationConeResponse(RGB, vc); // calculate HPE equal area cone fundamentals double[] RGBPrime = CAT02toHPE(RGB_c); @@ -501,37 +523,40 @@ private static double[] forwardTransform(double[] XYZ, double[] vc) { // calculate eccentricity double e = ((12500.0 / 13.0) * vc[VC_N_C] * vc[VC_N_CB]) * (Math.cos(Math.toRadians(h) + 2.0) + 3.8); // get t - double t = e * Math.sqrt(Math.pow(a, 2.0) + Math.pow(b, 2.0)) / (RGBPrime_a[0] + RGBPrime_a[1] + 1.05 * RGBPrime_a[2]); + double t = e + * Math.sqrt(Math.pow(a, 2.0) + Math.pow(b, 2.0)) + / (RGBPrime_a[0] + RGBPrime_a[1] + 1.05 * RGBPrime_a[2]); // calculate brightness double Q = (4.0 / vc[VC_C]) * Math.sqrt(J / 100.0) * (vc[VC_A_W] + 4.0) * Math.pow(vc[VC_F_L], 0.25); // calculate the correlates of chroma, colorfulness, and saturation - double C = Math.signum(t) * Math.pow(Math.abs(t), 0.9) * Math.sqrt(J / 100.0) * Math.pow(1.64- Math.pow(0.29, vc[VC_N]), 0.73); + double C = Math.signum(t) + * Math.pow(Math.abs(t), 0.9) + * Math.sqrt(J / 100.0) + * Math.pow(1.64 - Math.pow(0.29, vc[VC_N]), 0.73); double M = C * Math.pow(vc[VC_F_L], 0.25); double s = 100.0 * Math.sqrt(M / Q); // calculate hue composition double H = calculateH(h); - return new double[] { J, Q, C, M, s, H, h }; + return new double[] {J, Q, C, M, s, H, h}; } private static double calculateH(double h) { - if (h < 20.14) - h = h + 360; + if (h < 20.14) h = h + 360; double i; - if (h >= 20.14 && h < 90.0) { // index i = 1 + if (h >= 20.14 && h < 90.0) { // index i = 1 i = (h - 20.14) / 0.8; return 100.0 * i / (i + (90 - h) / 0.7); } else if (h < 164.25) { // index i = 2 i = (h - 90) / 0.7; return 100.0 + 100.0 * i / (i + (164.25 - h) / 1); - } else if (h < 237.53) { // index i = 3 + } else if (h < 237.53) { // index i = 3 i = (h - 164.25) / 1.0; return 200.0 + 100.0 * i / (i + (237.53 - h) / 1.2); - } else if (h <= 380.14) { // index i = 4 + } else if (h <= 380.14) { // index i = 4 i = (h - 237.53) / 1.2; double H = 300.0 + 100.0 * i / (i + (380.14 - h) / 0.8); // don't use 400 if we can use 0 - if (H <= 400.0 && H >= 399.999) - H = 0; + if (H <= 400.0 && H >= 399.999) H = 0; return H; } else { throw new IllegalArgumentException("h outside assumed range 0..360: " + h); @@ -540,8 +565,8 @@ private static double calculateH(double h) { private static double[] forwardResponseCompression(double[] RGB, double[] vc) { double[] result = new double[3]; - for(int channel = 0; channel < RGB.length; channel++) { - if(RGB[channel] >= 0) { + for (int channel = 0; channel < RGB.length; channel++) { + if (RGB[channel] >= 0) { double n = Math.pow(vc[VC_F_L] * RGB[channel] / 100.0, 0.42); result[channel] = 400.0 * n / (n + 27.13) + 0.1; } else { @@ -553,22 +578,22 @@ private static double[] forwardResponseCompression(double[] RGB, double[] vc) { } private static double[] forwardPostAdaptationConeResponse(double[] RGB, double[] vc) { - return new double[] { vc[VC_D_RGB_R] * RGB[0], vc[VC_D_RGB_G] * RGB[1], vc[VC_D_RGB_B] * RGB[2] }; + return new double[] {vc[VC_D_RGB_R] * RGB[0], vc[VC_D_RGB_G] * RGB[1], vc[VC_D_RGB_B] * RGB[2]}; } public static double[] CAT02toHPE(double[] RGB) { double[] RGBPrime = new double[3]; - RGBPrime[0] = 0.7409792 * RGB[0] + 0.2180250 * RGB[1] + 0.0410058 * RGB[2]; - RGBPrime[1] = 0.2853532 * RGB[0] + 0.6242014 * RGB[1] + 0.0904454 * RGB[2]; + RGBPrime[0] = 0.7409792 * RGB[0] + 0.2180250 * RGB[1] + 0.0410058 * RGB[2]; + RGBPrime[1] = 0.2853532 * RGB[0] + 0.6242014 * RGB[1] + 0.0904454 * RGB[2]; RGBPrime[2] = -0.0096280 * RGB[0] - 0.0056980 * RGB[1] + 1.0153260 * RGB[2]; return RGBPrime; } private static double[] forwardPreAdaptationConeResponse(double[] XYZ) { double[] RGB = new double[3]; - RGB[0] = 0.7328 * XYZ[0] + 0.4296 * XYZ[1] - 0.1624 * XYZ[2]; + RGB[0] = 0.7328 * XYZ[0] + 0.4296 * XYZ[1] - 0.1624 * XYZ[2]; RGB[1] = -0.7036 * XYZ[0] + 1.6975 * XYZ[1] + 0.0061 * XYZ[2]; - RGB[2] = 0.0030 * XYZ[0] + 0.0136 * XYZ[1] + 0.9834 * XYZ[2]; + RGB[2] = 0.0030 * XYZ[0] + 0.0136 * XYZ[1] + 0.9834 * XYZ[2]; return RGB; } @@ -581,8 +606,8 @@ private static double[] forwardPreAdaptationConeResponse(double[] XYZ) { static final int VC_Z_W = 2; static final int VC_L_A = 3; static final int VC_Y_B = 4; - static final int VC_F = 5; - static final int VC_C = 6; + static final int VC_F = 5; + static final int VC_C = 6; static final int VC_N_C = 7; static final int VC_Z = 8; @@ -607,33 +632,33 @@ static double[] vc(double[] xyz_w, double L_A, double Y_b, double[] surrounding) vc[VC_N_C] = surrounding[SUR_N_C]; double[] RGB_w = forwardPreAdaptationConeResponse(xyz_w); - double D = Math.max(0.0, Math.min(1.0, vc[VC_F] * (1.0 - (1.0 / 3.6) * Math.pow(Math.E, (-L_A - 42.0) / 92.0)))); + double D = + Math.max(0.0, Math.min(1.0, vc[VC_F] * (1.0 - (1.0 / 3.6) * Math.pow(Math.E, (-L_A - 42.0) / 92.0)))); double Yw = xyz_w[1]; double[] RGB_c = new double[] { - (D * Yw / RGB_w[0]) + (1.0 - D), - (D * Yw / RGB_w[1]) + (1.0 - D), - (D * Yw / RGB_w[2]) + (1.0 - D), + (D * Yw / RGB_w[0]) + (1.0 - D), (D * Yw / RGB_w[1]) + (1.0 - D), (D * Yw / RGB_w[2]) + (1.0 - D), }; // calculate increase in brightness and colorfulness caused by brighter viewing environments double L_Ax5 = 5.0 * L_A; double k = 1.0 / (L_Ax5 + 1.0); double kpow4 = Math.pow(k, 4.0); - vc[VC_F_L] = 0.2 * kpow4 * (L_Ax5) + 0.1 * Math.pow(1.0 - kpow4, 2.0) * Math.pow(L_Ax5, 1.0/3.0); + vc[VC_F_L] = 0.2 * kpow4 * (L_Ax5) + 0.1 * Math.pow(1.0 - kpow4, 2.0) * Math.pow(L_Ax5, 1.0 / 3.0); // calculate response compression on J and C caused by background lightness. vc[VC_N] = Y_b / Yw; vc[VC_Z] = 1.48 + Math.sqrt(vc[VC_N]); vc[VC_N_BB] = 0.725 * Math.pow(1.0 / vc[VC_N], 0.2); - vc[VC_N_CB] = vc[VC_N_BB]; // chromatic contrast factors (calculate increase in J, Q, and C caused by dark backgrounds) + vc[VC_N_CB] = vc[ + VC_N_BB]; // chromatic contrast factors (calculate increase in J, Q, and C caused by dark backgrounds) // calculate achromatic response to white double[] RGB_wc = new double[] {RGB_c[0] * RGB_w[0], RGB_c[1] * RGB_w[1], RGB_c[2] * RGB_w[2]}; double[] RGBPrime_w = CAT02toHPE(RGB_wc); double[] RGBPrime_aw = new double[3]; - for(int channel = 0; channel < RGBPrime_w.length; channel++) { - if(RGBPrime_w[channel] >= 0) { + for (int channel = 0; channel < RGBPrime_w.length; channel++) { + if (RGBPrime_w[channel] >= 0) { double n = Math.pow(vc[VC_F_L] * RGBPrime_w[channel] / 100.0, 0.42); RGBPrime_aw[channel] = 400.0 * n / (n + 27.13) + 0.1; } else { @@ -660,7 +685,7 @@ private static double[] rgb2xyz(double[] rgb) { double x = vr * 0.4124564 + vg * 0.3575761 + vb * 0.1804375; double y = vr * 0.2126729 + vg * 0.7151522 + vb * 0.0721750; double z = vr * 0.0193339 + vg * 0.1191920 + vb * 0.9503041; - return new double[] { x, y, z }; + return new double[] {x, y, z}; } private static double pivotRgb(double n) { @@ -674,11 +699,12 @@ private static double[] xyz2lab(double[] xyz) { double l = 116.0 * fy - 16.0; double a = 500.0 * (fx - fy); double b = 200.0 * (fy - fz); - return new double[] { l, a, b }; + return new double[] {l, a, b}; } private static final double epsilon = 216.0 / 24389.0; private static final double kappa = 24389.0 / 27.0; + private static double pivotXyz(double n) { return n > epsilon ? Math.cbrt(n) : (kappa * n + 16) / 116; } @@ -686,5 +712,4 @@ private static double pivotXyz(double n) { private static double sqr(double n) { return n * n; } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Curses.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Curses.java index bdfd4c37bc2..b9ada270705 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Curses.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Curses.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -29,8 +29,7 @@ public final class Curses { private static final int IFTE_THEN = 2; private static final int IFTE_ELSE = 3; - private Curses() { - } + private Curses() {} /** * Print the given terminal capabilities @@ -95,9 +94,9 @@ private static void doTputs(Appendable out, String str, Object... params) throws case 'n': out.append('\n'); break; -// case 'l': -// rawPrint('\l'); -// break; + // case 'l': + // rawPrint('\l'); + // break; case 'r': if (exec) { out.append('\r'); @@ -138,7 +137,7 @@ private static void doTputs(Appendable out, String str, Object... params) throws case '^': ch = str.charAt(index++); if (exec) { - out.append((char)(ch - '@')); + out.append((char) (ch - '@')); } break; case '%': @@ -195,7 +194,8 @@ private static void doTputs(Appendable out, String str, Object... params) throws break; case '{': int start = index; - while (str.charAt(index++) != '}') ; + while (str.charAt(index++) != '}') + ; if (exec) { int v = Integer.parseInt(str.substring(start, index - 1)); stack.push(v); @@ -364,10 +364,18 @@ private static void doTputs(Appendable out, String str, Object... params) throws int cnv; while ("-+# ".indexOf(ch) >= 0) { switch (ch) { - case '-': left = true; break; - case '+': plus = true; break; - case '#': alternate = true; break; - case ' ': space = true; break; + case '-': + left = true; + break; + case '+': + plus = true; + break; + case '#': + alternate = true; + break; + case ' ': + space = true; + break; } ch = str.charAt(index++); } @@ -473,5 +481,4 @@ private static int toInteger(Object pop) { return Integer.parseInt(pop.toString()); } } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/DiffHelper.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/DiffHelper.java index 3852f572746..93b065395de 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/DiffHelper.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/DiffHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -25,7 +25,9 @@ public class DiffHelper { * which means: delete "Hello", add "Goodbye" and keep " world." */ public enum Operation { - DELETE, INSERT, EQUAL + DELETE, + INSERT, + EQUAL } /** @@ -86,16 +88,13 @@ public static List diff(AttributedString text1, AttributedString text2) { && text1.charAt(commonStart) == text2.charAt(commonStart) && text1.styleAt(commonStart).equals(text2.styleAt(commonStart))) { if (text1.isHidden(commonStart)) { - if (startHiddenRange < 0) - startHiddenRange = commonStart; - } else - startHiddenRange = -1; + if (startHiddenRange < 0) startHiddenRange = commonStart; + } else startHiddenRange = -1; commonStart++; } if (startHiddenRange >= 0 - && ((l1 > commonStart && text1.isHidden(commonStart)) - || (l2 > commonStart && text2.isHidden(commonStart)))) - commonStart = startHiddenRange; + && ((l1 > commonStart && text1.isHidden(commonStart)) + || (l2 > commonStart && text2.isHidden(commonStart)))) commonStart = startHiddenRange; startHiddenRange = -1; int commonEnd = 0; @@ -103,32 +102,24 @@ public static List diff(AttributedString text1, AttributedString text2) { && text1.charAt(l1 - commonEnd - 1) == text2.charAt(l2 - commonEnd - 1) && text1.styleAt(l1 - commonEnd - 1).equals(text2.styleAt(l2 - commonEnd - 1))) { if (text1.isHidden(l1 - commonEnd - 1)) { - if (startHiddenRange < 0) - startHiddenRange = commonEnd; - } else - startHiddenRange = -1; + if (startHiddenRange < 0) startHiddenRange = commonEnd; + } else startHiddenRange = -1; commonEnd++; } - if (startHiddenRange >= 0) - commonEnd = startHiddenRange; + if (startHiddenRange >= 0) commonEnd = startHiddenRange; LinkedList diffs = new LinkedList<>(); if (commonStart > 0) { - diffs.add(new Diff(DiffHelper.Operation.EQUAL, - text1.subSequence(0, commonStart))); + diffs.add(new Diff(DiffHelper.Operation.EQUAL, text1.subSequence(0, commonStart))); } if (l2 > commonStart + commonEnd) { - diffs.add(new Diff(DiffHelper.Operation.INSERT, - text2.subSequence(commonStart, l2 - commonEnd))); + diffs.add(new Diff(DiffHelper.Operation.INSERT, text2.subSequence(commonStart, l2 - commonEnd))); } if (l1 > commonStart + commonEnd) { - diffs.add(new Diff(DiffHelper.Operation.DELETE, - text1.subSequence(commonStart, l1 - commonEnd))); + diffs.add(new Diff(DiffHelper.Operation.DELETE, text1.subSequence(commonStart, l1 - commonEnd))); } if (commonEnd > 0) { - diffs.add(new Diff(DiffHelper.Operation.EQUAL, - text1.subSequence(l1 - commonEnd, l1))); + diffs.add(new Diff(DiffHelper.Operation.EQUAL, text1.subSequence(l1 - commonEnd, l1))); } return diffs; } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Display.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Display.java index aaeab9b71ff..557024a121e 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Display.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Display.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2020, the original author or authors. + * Copyright (c) 2002-2020, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -37,8 +37,8 @@ public class Display { protected final boolean fullScreen; protected List oldLines = Collections.emptyList(); protected int cursorPos; - private int columns; - private int columns1; // columns+1 + protected int columns; + protected int columns1; // columns+1 protected int rows; protected boolean reset; protected boolean delayLineWrap; @@ -49,15 +49,15 @@ public class Display { protected final boolean delayedWrapAtEol; protected final boolean cursorDownIsNewLine; + @SuppressWarnings("this-escape") public Display(Terminal terminal, boolean fullscreen) { this.terminal = terminal; this.fullScreen = fullscreen; this.canScroll = can(Capability.insert_line, Capability.parm_insert_line) - && can(Capability.delete_line, Capability.parm_delete_line); + && can(Capability.delete_line, Capability.parm_delete_line); this.wrapAtEol = terminal.getBooleanCapability(Capability.auto_right_margin); - this.delayedWrapAtEol = this.wrapAtEol - && terminal.getBooleanCapability(Capability.eat_newline_glitch); + this.delayedWrapAtEol = this.wrapAtEol && terminal.getBooleanCapability(Capability.eat_newline_glitch); this.cursorDownIsNewLine = "\n".equals(Curses.tputs(terminal.getStringCapability(Capability.cursor_down))); } @@ -69,18 +69,22 @@ public Display(Terminal terminal, boolean fullscreen) { public boolean delayLineWrap() { return delayLineWrap; } - public void setDelayLineWrap(boolean v) { delayLineWrap = v; } + + public void setDelayLineWrap(boolean v) { + delayLineWrap = v; + } public void resize(int rows, int columns) { if (rows == 0 || columns == 0) { - columns = Integer.MAX_VALUE - 1; + columns = 1; rows = 1; } if (this.rows != rows || this.columns != columns) { this.rows = rows; this.columns = columns; this.columns1 = columns + 1; - oldLines = AttributedString.join(AttributedString.EMPTY, oldLines).columnSplitLength(columns, true, delayLineWrap()); + oldLines = AttributedString.join(AttributedString.EMPTY, oldLines) + .columnSplitLength(columns, true, delayLineWrap()); } } @@ -128,7 +132,8 @@ public void update(List newLines, int targetCursorPos, boolean // If dumb display, get rid of ansi sequences now Integer cols = terminal.getNumericCapability(Capability.max_colors); if (cols == null || cols < 8) { - newLines = newLines.stream().map(s -> new AttributedString(s.toString())) + newLines = newLines.stream() + .map(s -> new AttributedString(s.toString())) .collect(Collectors.toList()); } @@ -138,12 +143,13 @@ public void update(List newLines, int targetCursorPos, boolean int nbFooters = 0; // Find common headers and footers int l = newLines.size(); - while (nbHeaders < l - && Objects.equals(newLines.get(nbHeaders), oldLines.get(nbHeaders))) { + while (nbHeaders < l && Objects.equals(newLines.get(nbHeaders), oldLines.get(nbHeaders))) { nbHeaders++; } while (nbFooters < l - nbHeaders - 1 - && Objects.equals(newLines.get(newLines.size() - nbFooters - 1), oldLines.get(oldLines.size() - nbFooters - 1))) { + && Objects.equals( + newLines.get(newLines.size() - nbFooters - 1), + oldLines.get(oldLines.size() - nbFooters - 1))) { nbFooters++; } List o1 = newLines.subList(nbHeaders, newLines.size() - nbFooters); @@ -190,18 +196,14 @@ public void update(List newLines, int targetCursorPos, boolean int numLines = Math.min(rows, Math.max(oldLines.size(), newLines.size())); boolean wrapNeeded = false; while (lineIndex < numLines) { - AttributedString oldLine = - lineIndex < oldLines.size() ? oldLines.get(lineIndex) - : AttributedString.NEWLINE; - AttributedString newLine = - lineIndex < newLines.size() ? newLines.get(lineIndex) - : AttributedString.NEWLINE; + AttributedString oldLine = lineIndex < oldLines.size() ? oldLines.get(lineIndex) : AttributedString.NEWLINE; + AttributedString newLine = lineIndex < newLines.size() ? newLines.get(lineIndex) : AttributedString.NEWLINE; currentPos = lineIndex * columns1; int curCol = currentPos; int oldLength = oldLine.length(); int newLength = newLine.length(); - boolean oldNL = oldLength > 0 && oldLine.charAt(oldLength-1)=='\n'; - boolean newNL = newLength > 0 && newLine.charAt(newLength-1)=='\n'; + boolean oldNL = oldLength > 0 && oldLine.charAt(oldLength - 1) == '\n'; + boolean newNL = newLength > 0 && newLine.charAt(newLength - 1) == '\n'; if (oldNL) { oldLength--; oldLine = oldLine.substring(0, oldLength); @@ -210,9 +212,7 @@ public void update(List newLines, int targetCursorPos, boolean newLength--; newLine = newLine.substring(0, newLength); } - if (wrapNeeded - && lineIndex == (cursorPos + 1) / columns1 - && lineIndex < newLines.size()) { + if (wrapNeeded && lineIndex == (cursorPos + 1) / columns1 && lineIndex < newLines.size()) { // move from right margin to next line's left margin cursorPos++; if (newLength == 0 || newLine.isHidden(0)) { @@ -250,8 +250,7 @@ public void update(List newLines, int targetCursorPos, boolean } break; case INSERT: - if (i <= diffs.size() - 2 - && diffs.get(i + 1).operation == DiffHelper.Operation.EQUAL) { + if (i <= diffs.size() - 2 && diffs.get(i + 1).operation == DiffHelper.Operation.EQUAL) { cursorPos = moveVisualCursorTo(currentPos); if (insertChars(width)) { rawPrint(diff.text); @@ -282,8 +281,7 @@ public void update(List newLines, int targetCursorPos, boolean if (currentPos - curCol >= columns) { continue; } - if (i <= diffs.size() - 2 - && diffs.get(i + 1).operation == DiffHelper.Operation.EQUAL) { + if (i <= diffs.size() - 2 && diffs.get(i + 1).operation == DiffHelper.Operation.EQUAL) { if (currentPos + diffs.get(i + 1).text.columnLength() < columns) { moveVisualCursorTo(currentPos); if (deleteChars(width)) { @@ -305,25 +303,23 @@ public void update(List newLines, int targetCursorPos, boolean } } lineIndex++; - boolean newWrap = ! newNL && lineIndex < newLines.size(); - if (targetCursorPos + 1 == lineIndex * columns1 - && (newWrap || ! delayLineWrap)) - targetCursorPos++; + boolean newWrap = !newNL && lineIndex < newLines.size(); + if (targetCursorPos + 1 == lineIndex * columns1 && (newWrap || !delayLineWrap)) targetCursorPos++; boolean atRight = (cursorPos - curCol) % columns1 == columns; wrapNeeded = false; if (this.delayedWrapAtEol) { - boolean oldWrap = ! oldNL && lineIndex < oldLines.size(); - if (newWrap != oldWrap && ! (oldWrap && cleared)) { - moveVisualCursorTo(lineIndex*columns1-1, newLines); - if (newWrap) - wrapNeeded = true; - else - terminal.puts(Capability.clr_eol); + boolean oldWrap = !oldNL && lineIndex < oldLines.size(); + if (newWrap != oldWrap && !(oldWrap && cleared)) { + moveVisualCursorTo(lineIndex * columns1 - 1, newLines); + if (newWrap) wrapNeeded = true; + else terminal.puts(Capability.clr_eol); } } else if (atRight) { if (this.wrapAtEol) { - terminal.writer().write(" \b"); - cursorPos++; + if (!fullScreen || (fullScreen && lineIndex < numLines)) { + terminal.writer().write(" \b"); + cursorPos++; + } } else { terminal.puts(Capability.carriage_return); // CR / not newline. cursorPos = curCol; @@ -358,8 +354,7 @@ protected boolean deleteChars(int nb) { } protected boolean can(Capability single, Capability multi) { - return terminal.getStringCapability(single) != null - || terminal.getStringCapability(multi) != null; + return terminal.getStringCapability(single) != null || terminal.getStringCapability(multi) != null; } protected boolean perform(Capability single, Capability multi, int nb) { @@ -405,7 +400,7 @@ private static int[] longestCommon(List l1, List l1, List newLines) { + protected void moveVisualCursorTo(int targetPos, List newLines) { if (cursorPos != targetPos) { boolean atRight = (targetPos % columns1) == columns; moveVisualCursorTo(targetPos - (atRight ? 1 : 0)); @@ -422,12 +416,11 @@ protected void moveVisualCursorTo(int targetPos, // There is no portable way to move to the right margin // except by writing a character in the right-most column. int row = targetPos / columns1; - AttributedString lastChar = row >= newLines.size() ? AttributedString.EMPTY - : newLines.get(row).columnSubSequence(columns-1, columns); - if (lastChar.length() == 0) - rawPrint((int) ' '); - else - rawPrint(lastChar); + AttributedString lastChar = row >= newLines.size() + ? AttributedString.EMPTY + : newLines.get(row).columnSubSequence(columns - 1, columns); + if (lastChar.length() == 0) rawPrint((int) ' '); + else rawPrint(lastChar); cursorPos++; } } @@ -499,5 +492,4 @@ void rawPrint(AttributedString str) { public int wcwidth(String str) { return str != null ? AttributedString.fromAnsi(str).columnLength() : 0; } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ExecHelper.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ExecHelper.java index 9fce26fcf35..5d3c235661b 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ExecHelper.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ExecHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -22,8 +22,7 @@ */ public final class ExecHelper { - private ExecHelper() { - } + private ExecHelper() {} public static String exec(boolean redirectInput, final String... cmd) throws IOException { Objects.requireNonNull(cmd); @@ -31,7 +30,7 @@ public static String exec(boolean redirectInput, final String... cmd) throws IOE Log.trace("Running: ", cmd); ProcessBuilder pb = new ProcessBuilder(cmd); if (OSUtils.IS_AIX) { - Map env = pb.environment(); + Map env = pb.environment(); env.put("PATH", "/opt/freeware/bin:" + env.get("PATH")); env.put("LANG", "C"); env.put("LC_ALL", "C"); @@ -90,4 +89,3 @@ private static void close(final Closeable... closeables) { } } } - diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/FastBufferedOutputStream.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/FastBufferedOutputStream.java new file mode 100644 index 00000000000..62c29c17f78 --- /dev/null +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/FastBufferedOutputStream.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2009-2023, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * https://opensource.org/licenses/BSD-3-Clause + */ +package jdk.internal.org.jline.utils; + +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * A simple buffering output stream with no synchronization. + */ +public class FastBufferedOutputStream extends FilterOutputStream { + + protected final byte[] buf = new byte[8192]; + protected int count; + + public FastBufferedOutputStream(OutputStream out) { + super(out); + } + + @Override + public void write(int b) throws IOException { + if (count >= buf.length) { + flushBuffer(); + } + buf[count++] = (byte) b; + } + + @Override + public void write(byte b[], int off, int len) throws IOException { + if (len >= buf.length) { + flushBuffer(); + out.write(b, off, len); + return; + } + if (len > buf.length - count) { + flushBuffer(); + } + System.arraycopy(b, off, buf, count, len); + count += len; + } + + private void flushBuffer() throws IOException { + if (count > 0) { + out.write(buf, 0, count); + count = 0; + } + } + + @Override + public void flush() throws IOException { + flushBuffer(); + out.flush(); + } +} diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/InfoCmp.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/InfoCmp.java index 23a76071486..32cf3f56318 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/InfoCmp.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/InfoCmp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2019, the original author or authors. + * Copyright (c) 2002-2019, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -28,476 +28,474 @@ public final class InfoCmp { private static final Map CAPS = new HashMap<>(); - private InfoCmp() { - } + private InfoCmp() {} @SuppressWarnings("unused") public enum Capability { - - auto_left_margin, // auto_left_margin, bw, bw - auto_right_margin, // auto_right_margin, am, am - back_color_erase, // back_color_erase, bce, ut - can_change, // can_change, ccc, cc - ceol_standout_glitch, // ceol_standout_glitch, xhp, xs - col_addr_glitch, // col_addr_glitch, xhpa, YA - cpi_changes_res, // cpi_changes_res, cpix, YF - cr_cancels_micro_mode, // cr_cancels_micro_mode, crxm, YB - dest_tabs_magic_smso, // dest_tabs_magic_smso, xt, xt - eat_newline_glitch, // eat_newline_glitch, xenl, xn - erase_overstrike, // erase_overstrike, eo, eo - generic_type, // generic_type, gn, gn - hard_copy, // hard_copy, hc, hc - hard_cursor, // hard_cursor, chts, HC - has_meta_key, // has_meta_key, km, km - has_print_wheel, // has_print_wheel, daisy, YC - has_status_line, // has_status_line, hs, hs - hue_lightness_saturation, // hue_lightness_saturation, hls, hl - insert_null_glitch, // insert_null_glitch, in, in - lpi_changes_res, // lpi_changes_res, lpix, YG - memory_above, // memory_above, da, da - memory_below, // memory_below, db, db - move_insert_mode, // move_insert_mode, mir, mi - move_standout_mode, // move_standout_mode, msgr, ms - needs_xon_xoff, // needs_xon_xoff, nxon, nx - no_esc_ctlc, // no_esc_ctlc, xsb, xb - no_pad_char, // no_pad_char, npc, NP - non_dest_scroll_region, // non_dest_scroll_region, ndscr, ND - non_rev_rmcup, // non_rev_rmcup, nrrmc, NR - over_strike, // over_strike, os, os - prtr_silent, // prtr_silent, mc5i, 5i - row_addr_glitch, // row_addr_glitch, xvpa, YD - semi_auto_right_margin, // semi_auto_right_margin, sam, YE - status_line_esc_ok, // status_line_esc_ok, eslok, es - tilde_glitch, // tilde_glitch, hz, hz - transparent_underline, // transparent_underline, ul, ul - xon_xoff, // xon_xoff, xon, xo - columns, // columns, cols, co - init_tabs, // init_tabs, it, it - label_height, // label_height, lh, lh - label_width, // label_width, lw, lw - lines, // lines, lines, li - lines_of_memory, // lines_of_memory, lm, lm - magic_cookie_glitch, // magic_cookie_glitch, xmc, sg - max_attributes, // max_attributes, ma, ma - max_colors, // max_colors, colors, Co - max_pairs, // max_pairs, pairs, pa - maximum_windows, // maximum_windows, wnum, MW - no_color_video, // no_color_video, ncv, NC - num_labels, // num_labels, nlab, Nl - padding_baud_rate, // padding_baud_rate, pb, pb - virtual_terminal, // virtual_terminal, vt, vt - width_status_line, // width_status_line, wsl, ws - bit_image_entwining, // bit_image_entwining, bitwin, Yo - bit_image_type, // bit_image_type, bitype, Yp - buffer_capacity, // buffer_capacity, bufsz, Ya - buttons, // buttons, btns, BT - dot_horz_spacing, // dot_horz_spacing, spinh, Yc - dot_vert_spacing, // dot_vert_spacing, spinv, Yb - max_micro_address, // max_micro_address, maddr, Yd - max_micro_jump, // max_micro_jump, mjump, Ye - micro_col_size, // micro_col_size, mcs, Yf - micro_line_size, // micro_line_size, mls, Yg - number_of_pins, // number_of_pins, npins, Yh - output_res_char, // output_res_char, orc, Yi - output_res_horz_inch, // output_res_horz_inch, orhi, Yk - output_res_line, // output_res_line, orl, Yj - output_res_vert_inch, // output_res_vert_inch, orvi, Yl - print_rate, // print_rate, cps, Ym - wide_char_size, // wide_char_size, widcs, Yn - acs_chars, // acs_chars, acsc, ac - back_tab, // back_tab, cbt, bt - bell, // bell, bel, bl - carriage_return, // carriage_return, cr, cr - change_char_pitch, // change_char_pitch, cpi, ZA - change_line_pitch, // change_line_pitch, lpi, ZB - change_res_horz, // change_res_horz, chr, ZC - change_res_vert, // change_res_vert, cvr, ZD - change_scroll_region, // change_scroll_region, csr, cs - char_padding, // char_padding, rmp, rP - clear_all_tabs, // clear_all_tabs, tbc, ct - clear_margins, // clear_margins, mgc, MC - clear_screen, // clear_screen, clear, cl - clr_bol, // clr_bol, el1, cb - clr_eol, // clr_eol, el, ce - clr_eos, // clr_eos, ed, cd - column_address, // column_address, hpa, ch - command_character, // command_character, cmdch, CC - create_window, // create_window, cwin, CW - cursor_address, // cursor_address, cup, cm - cursor_down, // cursor_down, cud1, do - cursor_home, // cursor_home, home, ho - cursor_invisible, // cursor_invisible, civis, vi - cursor_left, // cursor_left, cub1, le - cursor_mem_address, // cursor_mem_address, mrcup, CM - cursor_normal, // cursor_normal, cnorm, ve - cursor_right, // cursor_right, cuf1, nd - cursor_to_ll, // cursor_to_ll, ll, ll - cursor_up, // cursor_up, cuu1, up - cursor_visible, // cursor_visible, cvvis, vs - define_char, // define_char, defc, ZE - delete_character, // delete_character, dch1, dc - delete_line, // delete_line, dl1, dl - dial_phone, // dial_phone, dial, DI - dis_status_line, // dis_status_line, dsl, ds - display_clock, // display_clock, dclk, DK - down_half_line, // down_half_line, hd, hd - ena_acs, // ena_acs, enacs, eA - enter_alt_charset_mode, // enter_alt_charset_mode, smacs, as - enter_am_mode, // enter_am_mode, smam, SA - enter_blink_mode, // enter_blink_mode, blink, mb - enter_bold_mode, // enter_bold_mode, bold, md - enter_ca_mode, // enter_ca_mode, smcup, ti - enter_delete_mode, // enter_delete_mode, smdc, dm - enter_dim_mode, // enter_dim_mode, dim, mh - enter_doublewide_mode, // enter_doublewide_mode, swidm, ZF - enter_draft_quality, // enter_draft_quality, sdrfq, ZG - enter_insert_mode, // enter_insert_mode, smir, im - enter_italics_mode, // enter_italics_mode, sitm, ZH - enter_leftward_mode, // enter_leftward_mode, slm, ZI - enter_micro_mode, // enter_micro_mode, smicm, ZJ - enter_near_letter_quality, // enter_near_letter_quality, snlq, ZK - enter_normal_quality, // enter_normal_quality, snrmq, ZL - enter_protected_mode, // enter_protected_mode, prot, mp - enter_reverse_mode, // enter_reverse_mode, rev, mr - enter_secure_mode, // enter_secure_mode, invis, mk - enter_shadow_mode, // enter_shadow_mode, sshm, ZM - enter_standout_mode, // enter_standout_mode, smso, so - enter_subscript_mode, // enter_subscript_mode, ssubm, ZN - enter_superscript_mode, // enter_superscript_mode, ssupm, ZO - enter_underline_mode, // enter_underline_mode, smul, us - enter_upward_mode, // enter_upward_mode, sum, ZP - enter_xon_mode, // enter_xon_mode, smxon, SX - erase_chars, // erase_chars, ech, ec - exit_alt_charset_mode, // exit_alt_charset_mode, rmacs, ae - exit_am_mode, // exit_am_mode, rmam, RA - exit_attribute_mode, // exit_attribute_mode, sgr0, me - exit_ca_mode, // exit_ca_mode, rmcup, te - exit_delete_mode, // exit_delete_mode, rmdc, ed - exit_doublewide_mode, // exit_doublewide_mode, rwidm, ZQ - exit_insert_mode, // exit_insert_mode, rmir, ei - exit_italics_mode, // exit_italics_mode, ritm, ZR - exit_leftward_mode, // exit_leftward_mode, rlm, ZS - exit_micro_mode, // exit_micro_mode, rmicm, ZT - exit_shadow_mode, // exit_shadow_mode, rshm, ZU - exit_standout_mode, // exit_standout_mode, rmso, se - exit_subscript_mode, // exit_subscript_mode, rsubm, ZV - exit_superscript_mode, // exit_superscript_mode, rsupm, ZW - exit_underline_mode, // exit_underline_mode, rmul, ue - exit_upward_mode, // exit_upward_mode, rum, ZX - exit_xon_mode, // exit_xon_mode, rmxon, RX - fixed_pause, // fixed_pause, pause, PA - flash_hook, // flash_hook, hook, fh - flash_screen, // flash_screen, flash, vb - form_feed, // form_feed, ff, ff - from_status_line, // from_status_line, fsl, fs - goto_window, // goto_window, wingo, WG - hangup, // hangup, hup, HU - init_1string, // init_1string, is1, i1 - init_2string, // init_2string, is2, is - init_3string, // init_3string, is3, i3 - init_file, // init_file, if, if - init_prog, // init_prog, iprog, iP - initialize_color, // initialize_color, initc, Ic - initialize_pair, // initialize_pair, initp, Ip - insert_character, // insert_character, ich1, ic - insert_line, // insert_line, il1, al - insert_padding, // insert_padding, ip, ip - key_a1, // key_a1, ka1, K1 - key_a3, // key_a3, ka3, K3 - key_b2, // key_b2, kb2, K2 - key_backspace, // key_backspace, kbs, kb - key_beg, // key_beg, kbeg, @1 - key_btab, // key_btab, kcbt, kB - key_c1, // key_c1, kc1, K4 - key_c3, // key_c3, kc3, K5 - key_cancel, // key_cancel, kcan, @2 - key_catab, // key_catab, ktbc, ka - key_clear, // key_clear, kclr, kC - key_close, // key_close, kclo, @3 - key_command, // key_command, kcmd, @4 - key_copy, // key_copy, kcpy, @5 - key_create, // key_create, kcrt, @6 - key_ctab, // key_ctab, kctab, kt - key_dc, // key_dc, kdch1, kD - key_dl, // key_dl, kdl1, kL - key_down, // key_down, kcud1, kd - key_eic, // key_eic, krmir, kM - key_end, // key_end, kend, @7 - key_enter, // key_enter, kent, @8 - key_eol, // key_eol, kel, kE - key_eos, // key_eos, ked, kS - key_exit, // key_exit, kext, @9 - key_f0, // key_f0, kf0, k0 - key_f1, // key_f1, kf1, k1 - key_f10, // key_f10, kf10, k; - key_f11, // key_f11, kf11, F1 - key_f12, // key_f12, kf12, F2 - key_f13, // key_f13, kf13, F3 - key_f14, // key_f14, kf14, F4 - key_f15, // key_f15, kf15, F5 - key_f16, // key_f16, kf16, F6 - key_f17, // key_f17, kf17, F7 - key_f18, // key_f18, kf18, F8 - key_f19, // key_f19, kf19, F9 - key_f2, // key_f2, kf2, k2 - key_f20, // key_f20, kf20, FA - key_f21, // key_f21, kf21, FB - key_f22, // key_f22, kf22, FC - key_f23, // key_f23, kf23, FD - key_f24, // key_f24, kf24, FE - key_f25, // key_f25, kf25, FF - key_f26, // key_f26, kf26, FG - key_f27, // key_f27, kf27, FH - key_f28, // key_f28, kf28, FI - key_f29, // key_f29, kf29, FJ - key_f3, // key_f3, kf3, k3 - key_f30, // key_f30, kf30, FK - key_f31, // key_f31, kf31, FL - key_f32, // key_f32, kf32, FM - key_f33, // key_f33, kf33, FN - key_f34, // key_f34, kf34, FO - key_f35, // key_f35, kf35, FP - key_f36, // key_f36, kf36, FQ - key_f37, // key_f37, kf37, FR - key_f38, // key_f38, kf38, FS - key_f39, // key_f39, kf39, FT - key_f4, // key_f4, kf4, k4 - key_f40, // key_f40, kf40, FU - key_f41, // key_f41, kf41, FV - key_f42, // key_f42, kf42, FW - key_f43, // key_f43, kf43, FX - key_f44, // key_f44, kf44, FY - key_f45, // key_f45, kf45, FZ - key_f46, // key_f46, kf46, Fa - key_f47, // key_f47, kf47, Fb - key_f48, // key_f48, kf48, Fc - key_f49, // key_f49, kf49, Fd - key_f5, // key_f5, kf5, k5 - key_f50, // key_f50, kf50, Fe - key_f51, // key_f51, kf51, Ff - key_f52, // key_f52, kf52, Fg - key_f53, // key_f53, kf53, Fh - key_f54, // key_f54, kf54, Fi - key_f55, // key_f55, kf55, Fj - key_f56, // key_f56, kf56, Fk - key_f57, // key_f57, kf57, Fl - key_f58, // key_f58, kf58, Fm - key_f59, // key_f59, kf59, Fn - key_f6, // key_f6, kf6, k6 - key_f60, // key_f60, kf60, Fo - key_f61, // key_f61, kf61, Fp - key_f62, // key_f62, kf62, Fq - key_f63, // key_f63, kf63, Fr - key_f7, // key_f7, kf7, k7 - key_f8, // key_f8, kf8, k8 - key_f9, // key_f9, kf9, k9 - key_find, // key_find, kfnd, @0 - key_help, // key_help, khlp, %1 - key_home, // key_home, khome, kh - key_ic, // key_ic, kich1, kI - key_il, // key_il, kil1, kA - key_left, // key_left, kcub1, kl - key_ll, // key_ll, kll, kH - key_mark, // key_mark, kmrk, %2 - key_message, // key_message, kmsg, %3 - key_move, // key_move, kmov, %4 - key_next, // key_next, knxt, %5 - key_npage, // key_npage, knp, kN - key_open, // key_open, kopn, %6 - key_options, // key_options, kopt, %7 - key_ppage, // key_ppage, kpp, kP - key_previous, // key_previous, kprv, %8 - key_print, // key_print, kprt, %9 - key_redo, // key_redo, krdo, %0 - key_reference, // key_reference, kref, &1 - key_refresh, // key_refresh, krfr, &2 - key_replace, // key_replace, krpl, &3 - key_restart, // key_restart, krst, &4 - key_resume, // key_resume, kres, &5 - key_right, // key_right, kcuf1, kr - key_save, // key_save, ksav, &6 - key_sbeg, // key_sbeg, kBEG, &9 - key_scancel, // key_scancel, kCAN, &0 - key_scommand, // key_scommand, kCMD, *1 - key_scopy, // key_scopy, kCPY, *2 - key_screate, // key_screate, kCRT, *3 - key_sdc, // key_sdc, kDC, *4 - key_sdl, // key_sdl, kDL, *5 - key_select, // key_select, kslt, *6 - key_send, // key_send, kEND, *7 - key_seol, // key_seol, kEOL, *8 - key_sexit, // key_sexit, kEXT, *9 - key_sf, // key_sf, kind, kF - key_sfind, // key_sfind, kFND, *0 - key_shelp, // key_shelp, kHLP, #1 - key_shome, // key_shome, kHOM, #2 - key_sic, // key_sic, kIC, #3 - key_sleft, // key_sleft, kLFT, #4 - key_smessage, // key_smessage, kMSG, %a - key_smove, // key_smove, kMOV, %b - key_snext, // key_snext, kNXT, %c - key_soptions, // key_soptions, kOPT, %d - key_sprevious, // key_sprevious, kPRV, %e - key_sprint, // key_sprint, kPRT, %f - key_sr, // key_sr, kri, kR - key_sredo, // key_sredo, kRDO, %g - key_sreplace, // key_sreplace, kRPL, %h - key_sright, // key_sright, kRIT, %i - key_srsume, // key_srsume, kRES, %j - key_ssave, // key_ssave, kSAV, !1 - key_ssuspend, // key_ssuspend, kSPD, !2 - key_stab, // key_stab, khts, kT - key_sundo, // key_sundo, kUND, !3 - key_suspend, // key_suspend, kspd, &7 - key_undo, // key_undo, kund, &8 - key_up, // key_up, kcuu1, ku - keypad_local, // keypad_local, rmkx, ke - keypad_xmit, // keypad_xmit, smkx, ks - lab_f0, // lab_f0, lf0, l0 - lab_f1, // lab_f1, lf1, l1 - lab_f10, // lab_f10, lf10, la - lab_f2, // lab_f2, lf2, l2 - lab_f3, // lab_f3, lf3, l3 - lab_f4, // lab_f4, lf4, l4 - lab_f5, // lab_f5, lf5, l5 - lab_f6, // lab_f6, lf6, l6 - lab_f7, // lab_f7, lf7, l7 - lab_f8, // lab_f8, lf8, l8 - lab_f9, // lab_f9, lf9, l9 - label_format, // label_format, fln, Lf - label_off, // label_off, rmln, LF - label_on, // label_on, smln, LO - meta_off, // meta_off, rmm, mo - meta_on, // meta_on, smm, mm - micro_column_address, // micro_column_address, mhpa, ZY - micro_down, // micro_down, mcud1, ZZ - micro_left, // micro_left, mcub1, Za - micro_right, // micro_right, mcuf1, Zb - micro_row_address, // micro_row_address, mvpa, Zc - micro_up, // micro_up, mcuu1, Zd - newline, // newline, nel, nw - order_of_pins, // order_of_pins, porder, Ze - orig_colors, // orig_colors, oc, oc - orig_pair, // orig_pair, op, op - pad_char, // pad_char, pad, pc - parm_dch, // parm_dch, dch, DC - parm_delete_line, // parm_delete_line, dl, DL - parm_down_cursor, // parm_down_cursor, cud, DO - parm_down_micro, // parm_down_micro, mcud, Zf - parm_ich, // parm_ich, ich, IC - parm_index, // parm_index, indn, SF - parm_insert_line, // parm_insert_line, il, AL - parm_left_cursor, // parm_left_cursor, cub, LE - parm_left_micro, // parm_left_micro, mcub, Zg - parm_right_cursor, // parm_right_cursor, cuf, RI - parm_right_micro, // parm_right_micro, mcuf, Zh - parm_rindex, // parm_rindex, rin, SR - parm_up_cursor, // parm_up_cursor, cuu, UP - parm_up_micro, // parm_up_micro, mcuu, Zi - pkey_key, // pkey_key, pfkey, pk - pkey_local, // pkey_local, pfloc, pl - pkey_xmit, // pkey_xmit, pfx, px - plab_norm, // plab_norm, pln, pn - print_screen, // print_screen, mc0, ps - prtr_non, // prtr_non, mc5p, pO - prtr_off, // prtr_off, mc4, pf - prtr_on, // prtr_on, mc5, po - pulse, // pulse, pulse, PU - quick_dial, // quick_dial, qdial, QD - remove_clock, // remove_clock, rmclk, RC - repeat_char, // repeat_char, rep, rp - req_for_input, // req_for_input, rfi, RF - reset_1string, // reset_1string, rs1, r1 - reset_2string, // reset_2string, rs2, r2 - reset_3string, // reset_3string, rs3, r3 - reset_file, // reset_file, rf, rf - restore_cursor, // restore_cursor, rc, rc - row_address, // row_address, vpa, cv - save_cursor, // save_cursor, sc, sc - scroll_forward, // scroll_forward, ind, sf - scroll_reverse, // scroll_reverse, ri, sr - select_char_set, // select_char_set, scs, Zj - set_attributes, // set_attributes, sgr, sa - set_background, // set_background, setb, Sb - set_bottom_margin, // set_bottom_margin, smgb, Zk - set_bottom_margin_parm, // set_bottom_margin_parm, smgbp, Zl - set_clock, // set_clock, sclk, SC - set_color_pair, // set_color_pair, scp, sp - set_foreground, // set_foreground, setf, Sf - set_left_margin, // set_left_margin, smgl, ML - set_left_margin_parm, // set_left_margin_parm, smglp, Zm - set_right_margin, // set_right_margin, smgr, MR - set_right_margin_parm, // set_right_margin_parm, smgrp, Zn - set_tab, // set_tab, hts, st - set_top_margin, // set_top_margin, smgt, Zo - set_top_margin_parm, // set_top_margin_parm, smgtp, Zp - set_window, // set_window, wind, wi - start_bit_image, // start_bit_image, sbim, Zq - start_char_set_def, // start_char_set_def, scsd, Zr - stop_bit_image, // stop_bit_image, rbim, Zs - stop_char_set_def, // stop_char_set_def, rcsd, Zt - subscript_characters, // subscript_characters, subcs, Zu - superscript_characters, // superscript_characters, supcs, Zv - tab, // tab, ht, ta - these_cause_cr, // these_cause_cr, docr, Zw - to_status_line, // to_status_line, tsl, ts - tone, // tone, tone, TO - underline_char, // underline_char, uc, uc - up_half_line, // up_half_line, hu, hu - user0, // user0, u0, u0 - user1, // user1, u1, u1 - user2, // user2, u2, u2 - user3, // user3, u3, u3 - user4, // user4, u4, u4 - user5, // user5, u5, u5 - user6, // user6, u6, u6 - user7, // user7, u7, u7 - user8, // user8, u8, u8 - user9, // user9, u9, u9 - wait_tone, // wait_tone, wait, WA - xoff_character, // xoff_character, xoffc, XF - xon_character, // xon_character, xonc, XN - zero_motion, // zero_motion, zerom, Zx - alt_scancode_esc, // alt_scancode_esc, scesa, S8 - bit_image_carriage_return, // bit_image_carriage_return, bicr, Yv - bit_image_newline, // bit_image_newline, binel, Zz - bit_image_repeat, // bit_image_repeat, birep, Xy - char_set_names, // char_set_names, csnm, Zy - code_set_init, // code_set_init, csin, ci - color_names, // color_names, colornm, Yw - define_bit_image_region, // define_bit_image_region, defbi, Yx - device_type, // device_type, devt, dv - display_pc_char, // display_pc_char, dispc, S1 - end_bit_image_region, // end_bit_image_region, endbi, Yy - enter_pc_charset_mode, // enter_pc_charset_mode, smpch, S2 - enter_scancode_mode, // enter_scancode_mode, smsc, S4 - exit_pc_charset_mode, // exit_pc_charset_mode, rmpch, S3 - exit_scancode_mode, // exit_scancode_mode, rmsc, S5 - get_mouse, // get_mouse, getm, Gm - key_mouse, // key_mouse, kmous, Km - mouse_info, // mouse_info, minfo, Mi - pc_term_options, // pc_term_options, pctrm, S6 - pkey_plab, // pkey_plab, pfxl, xl - req_mouse_pos, // req_mouse_pos, reqmp, RQ - scancode_escape, // scancode_escape, scesc, S7 - set0_des_seq, // set0_des_seq, s0ds, s0 - set1_des_seq, // set1_des_seq, s1ds, s1 - set2_des_seq, // set2_des_seq, s2ds, s2 - set3_des_seq, // set3_des_seq, s3ds, s3 - set_a_background, // set_a_background, setab, AB - set_a_foreground, // set_a_foreground, setaf, AF - set_color_band, // set_color_band, setcolor, Yz - set_lr_margin, // set_lr_margin, smglr, ML - set_page_length, // set_page_length, slines, YZ - set_tb_margin, // set_tb_margin, smgtb, MT - enter_horizontal_hl_mode, // enter_horizontal_hl_mode, ehhlm, Xh - enter_left_hl_mode, // enter_left_hl_mode, elhlm, Xl - enter_low_hl_mode, // enter_low_hl_mode, elohlm, Xo - enter_right_hl_mode, // enter_right_hl_mode, erhlm, Xr - enter_top_hl_mode, // enter_top_hl_mode, ethlm, Xt - enter_vertical_hl_mode, // enter_vertical_hl_mode, evhlm, Xv - set_a_attributes, // set_a_attributes, sgr1, sA - set_pglen_inch, // set_pglen_inch, slength, sL) + auto_left_margin, // auto_left_margin, bw, bw + auto_right_margin, // auto_right_margin, am, am + back_color_erase, // back_color_erase, bce, ut + can_change, // can_change, ccc, cc + ceol_standout_glitch, // ceol_standout_glitch, xhp, xs + col_addr_glitch, // col_addr_glitch, xhpa, YA + cpi_changes_res, // cpi_changes_res, cpix, YF + cr_cancels_micro_mode, // cr_cancels_micro_mode, crxm, YB + dest_tabs_magic_smso, // dest_tabs_magic_smso, xt, xt + eat_newline_glitch, // eat_newline_glitch, xenl, xn + erase_overstrike, // erase_overstrike, eo, eo + generic_type, // generic_type, gn, gn + hard_copy, // hard_copy, hc, hc + hard_cursor, // hard_cursor, chts, HC + has_meta_key, // has_meta_key, km, km + has_print_wheel, // has_print_wheel, daisy, YC + has_status_line, // has_status_line, hs, hs + hue_lightness_saturation, // hue_lightness_saturation, hls, hl + insert_null_glitch, // insert_null_glitch, in, in + lpi_changes_res, // lpi_changes_res, lpix, YG + memory_above, // memory_above, da, da + memory_below, // memory_below, db, db + move_insert_mode, // move_insert_mode, mir, mi + move_standout_mode, // move_standout_mode, msgr, ms + needs_xon_xoff, // needs_xon_xoff, nxon, nx + no_esc_ctlc, // no_esc_ctlc, xsb, xb + no_pad_char, // no_pad_char, npc, NP + non_dest_scroll_region, // non_dest_scroll_region, ndscr, ND + non_rev_rmcup, // non_rev_rmcup, nrrmc, NR + over_strike, // over_strike, os, os + prtr_silent, // prtr_silent, mc5i, 5i + row_addr_glitch, // row_addr_glitch, xvpa, YD + semi_auto_right_margin, // semi_auto_right_margin, sam, YE + status_line_esc_ok, // status_line_esc_ok, eslok, es + tilde_glitch, // tilde_glitch, hz, hz + transparent_underline, // transparent_underline, ul, ul + xon_xoff, // xon_xoff, xon, xo + columns, // columns, cols, co + init_tabs, // init_tabs, it, it + label_height, // label_height, lh, lh + label_width, // label_width, lw, lw + lines, // lines, lines, li + lines_of_memory, // lines_of_memory, lm, lm + magic_cookie_glitch, // magic_cookie_glitch, xmc, sg + max_attributes, // max_attributes, ma, ma + max_colors, // max_colors, colors, Co + max_pairs, // max_pairs, pairs, pa + maximum_windows, // maximum_windows, wnum, MW + no_color_video, // no_color_video, ncv, NC + num_labels, // num_labels, nlab, Nl + padding_baud_rate, // padding_baud_rate, pb, pb + virtual_terminal, // virtual_terminal, vt, vt + width_status_line, // width_status_line, wsl, ws + bit_image_entwining, // bit_image_entwining, bitwin, Yo + bit_image_type, // bit_image_type, bitype, Yp + buffer_capacity, // buffer_capacity, bufsz, Ya + buttons, // buttons, btns, BT + dot_horz_spacing, // dot_horz_spacing, spinh, Yc + dot_vert_spacing, // dot_vert_spacing, spinv, Yb + max_micro_address, // max_micro_address, maddr, Yd + max_micro_jump, // max_micro_jump, mjump, Ye + micro_col_size, // micro_col_size, mcs, Yf + micro_line_size, // micro_line_size, mls, Yg + number_of_pins, // number_of_pins, npins, Yh + output_res_char, // output_res_char, orc, Yi + output_res_horz_inch, // output_res_horz_inch, orhi, Yk + output_res_line, // output_res_line, orl, Yj + output_res_vert_inch, // output_res_vert_inch, orvi, Yl + print_rate, // print_rate, cps, Ym + wide_char_size, // wide_char_size, widcs, Yn + acs_chars, // acs_chars, acsc, ac + back_tab, // back_tab, cbt, bt + bell, // bell, bel, bl + carriage_return, // carriage_return, cr, cr + change_char_pitch, // change_char_pitch, cpi, ZA + change_line_pitch, // change_line_pitch, lpi, ZB + change_res_horz, // change_res_horz, chr, ZC + change_res_vert, // change_res_vert, cvr, ZD + change_scroll_region, // change_scroll_region, csr, cs + char_padding, // char_padding, rmp, rP + clear_all_tabs, // clear_all_tabs, tbc, ct + clear_margins, // clear_margins, mgc, MC + clear_screen, // clear_screen, clear, cl + clr_bol, // clr_bol, el1, cb + clr_eol, // clr_eol, el, ce + clr_eos, // clr_eos, ed, cd + column_address, // column_address, hpa, ch + command_character, // command_character, cmdch, CC + create_window, // create_window, cwin, CW + cursor_address, // cursor_address, cup, cm + cursor_down, // cursor_down, cud1, do + cursor_home, // cursor_home, home, ho + cursor_invisible, // cursor_invisible, civis, vi + cursor_left, // cursor_left, cub1, le + cursor_mem_address, // cursor_mem_address, mrcup, CM + cursor_normal, // cursor_normal, cnorm, ve + cursor_right, // cursor_right, cuf1, nd + cursor_to_ll, // cursor_to_ll, ll, ll + cursor_up, // cursor_up, cuu1, up + cursor_visible, // cursor_visible, cvvis, vs + define_char, // define_char, defc, ZE + delete_character, // delete_character, dch1, dc + delete_line, // delete_line, dl1, dl + dial_phone, // dial_phone, dial, DI + dis_status_line, // dis_status_line, dsl, ds + display_clock, // display_clock, dclk, DK + down_half_line, // down_half_line, hd, hd + ena_acs, // ena_acs, enacs, eA + enter_alt_charset_mode, // enter_alt_charset_mode, smacs, as + enter_am_mode, // enter_am_mode, smam, SA + enter_blink_mode, // enter_blink_mode, blink, mb + enter_bold_mode, // enter_bold_mode, bold, md + enter_ca_mode, // enter_ca_mode, smcup, ti + enter_delete_mode, // enter_delete_mode, smdc, dm + enter_dim_mode, // enter_dim_mode, dim, mh + enter_doublewide_mode, // enter_doublewide_mode, swidm, ZF + enter_draft_quality, // enter_draft_quality, sdrfq, ZG + enter_insert_mode, // enter_insert_mode, smir, im + enter_italics_mode, // enter_italics_mode, sitm, ZH + enter_leftward_mode, // enter_leftward_mode, slm, ZI + enter_micro_mode, // enter_micro_mode, smicm, ZJ + enter_near_letter_quality, // enter_near_letter_quality, snlq, ZK + enter_normal_quality, // enter_normal_quality, snrmq, ZL + enter_protected_mode, // enter_protected_mode, prot, mp + enter_reverse_mode, // enter_reverse_mode, rev, mr + enter_secure_mode, // enter_secure_mode, invis, mk + enter_shadow_mode, // enter_shadow_mode, sshm, ZM + enter_standout_mode, // enter_standout_mode, smso, so + enter_subscript_mode, // enter_subscript_mode, ssubm, ZN + enter_superscript_mode, // enter_superscript_mode, ssupm, ZO + enter_underline_mode, // enter_underline_mode, smul, us + enter_upward_mode, // enter_upward_mode, sum, ZP + enter_xon_mode, // enter_xon_mode, smxon, SX + erase_chars, // erase_chars, ech, ec + exit_alt_charset_mode, // exit_alt_charset_mode, rmacs, ae + exit_am_mode, // exit_am_mode, rmam, RA + exit_attribute_mode, // exit_attribute_mode, sgr0, me + exit_ca_mode, // exit_ca_mode, rmcup, te + exit_delete_mode, // exit_delete_mode, rmdc, ed + exit_doublewide_mode, // exit_doublewide_mode, rwidm, ZQ + exit_insert_mode, // exit_insert_mode, rmir, ei + exit_italics_mode, // exit_italics_mode, ritm, ZR + exit_leftward_mode, // exit_leftward_mode, rlm, ZS + exit_micro_mode, // exit_micro_mode, rmicm, ZT + exit_shadow_mode, // exit_shadow_mode, rshm, ZU + exit_standout_mode, // exit_standout_mode, rmso, se + exit_subscript_mode, // exit_subscript_mode, rsubm, ZV + exit_superscript_mode, // exit_superscript_mode, rsupm, ZW + exit_underline_mode, // exit_underline_mode, rmul, ue + exit_upward_mode, // exit_upward_mode, rum, ZX + exit_xon_mode, // exit_xon_mode, rmxon, RX + fixed_pause, // fixed_pause, pause, PA + flash_hook, // flash_hook, hook, fh + flash_screen, // flash_screen, flash, vb + form_feed, // form_feed, ff, ff + from_status_line, // from_status_line, fsl, fs + goto_window, // goto_window, wingo, WG + hangup, // hangup, hup, HU + init_1string, // init_1string, is1, i1 + init_2string, // init_2string, is2, is + init_3string, // init_3string, is3, i3 + init_file, // init_file, if, if + init_prog, // init_prog, iprog, iP + initialize_color, // initialize_color, initc, Ic + initialize_pair, // initialize_pair, initp, Ip + insert_character, // insert_character, ich1, ic + insert_line, // insert_line, il1, al + insert_padding, // insert_padding, ip, ip + key_a1, // key_a1, ka1, K1 + key_a3, // key_a3, ka3, K3 + key_b2, // key_b2, kb2, K2 + key_backspace, // key_backspace, kbs, kb + key_beg, // key_beg, kbeg, @1 + key_btab, // key_btab, kcbt, kB + key_c1, // key_c1, kc1, K4 + key_c3, // key_c3, kc3, K5 + key_cancel, // key_cancel, kcan, @2 + key_catab, // key_catab, ktbc, ka + key_clear, // key_clear, kclr, kC + key_close, // key_close, kclo, @3 + key_command, // key_command, kcmd, @4 + key_copy, // key_copy, kcpy, @5 + key_create, // key_create, kcrt, @6 + key_ctab, // key_ctab, kctab, kt + key_dc, // key_dc, kdch1, kD + key_dl, // key_dl, kdl1, kL + key_down, // key_down, kcud1, kd + key_eic, // key_eic, krmir, kM + key_end, // key_end, kend, @7 + key_enter, // key_enter, kent, @8 + key_eol, // key_eol, kel, kE + key_eos, // key_eos, ked, kS + key_exit, // key_exit, kext, @9 + key_f0, // key_f0, kf0, k0 + key_f1, // key_f1, kf1, k1 + key_f10, // key_f10, kf10, k; + key_f11, // key_f11, kf11, F1 + key_f12, // key_f12, kf12, F2 + key_f13, // key_f13, kf13, F3 + key_f14, // key_f14, kf14, F4 + key_f15, // key_f15, kf15, F5 + key_f16, // key_f16, kf16, F6 + key_f17, // key_f17, kf17, F7 + key_f18, // key_f18, kf18, F8 + key_f19, // key_f19, kf19, F9 + key_f2, // key_f2, kf2, k2 + key_f20, // key_f20, kf20, FA + key_f21, // key_f21, kf21, FB + key_f22, // key_f22, kf22, FC + key_f23, // key_f23, kf23, FD + key_f24, // key_f24, kf24, FE + key_f25, // key_f25, kf25, FF + key_f26, // key_f26, kf26, FG + key_f27, // key_f27, kf27, FH + key_f28, // key_f28, kf28, FI + key_f29, // key_f29, kf29, FJ + key_f3, // key_f3, kf3, k3 + key_f30, // key_f30, kf30, FK + key_f31, // key_f31, kf31, FL + key_f32, // key_f32, kf32, FM + key_f33, // key_f33, kf33, FN + key_f34, // key_f34, kf34, FO + key_f35, // key_f35, kf35, FP + key_f36, // key_f36, kf36, FQ + key_f37, // key_f37, kf37, FR + key_f38, // key_f38, kf38, FS + key_f39, // key_f39, kf39, FT + key_f4, // key_f4, kf4, k4 + key_f40, // key_f40, kf40, FU + key_f41, // key_f41, kf41, FV + key_f42, // key_f42, kf42, FW + key_f43, // key_f43, kf43, FX + key_f44, // key_f44, kf44, FY + key_f45, // key_f45, kf45, FZ + key_f46, // key_f46, kf46, Fa + key_f47, // key_f47, kf47, Fb + key_f48, // key_f48, kf48, Fc + key_f49, // key_f49, kf49, Fd + key_f5, // key_f5, kf5, k5 + key_f50, // key_f50, kf50, Fe + key_f51, // key_f51, kf51, Ff + key_f52, // key_f52, kf52, Fg + key_f53, // key_f53, kf53, Fh + key_f54, // key_f54, kf54, Fi + key_f55, // key_f55, kf55, Fj + key_f56, // key_f56, kf56, Fk + key_f57, // key_f57, kf57, Fl + key_f58, // key_f58, kf58, Fm + key_f59, // key_f59, kf59, Fn + key_f6, // key_f6, kf6, k6 + key_f60, // key_f60, kf60, Fo + key_f61, // key_f61, kf61, Fp + key_f62, // key_f62, kf62, Fq + key_f63, // key_f63, kf63, Fr + key_f7, // key_f7, kf7, k7 + key_f8, // key_f8, kf8, k8 + key_f9, // key_f9, kf9, k9 + key_find, // key_find, kfnd, @0 + key_help, // key_help, khlp, %1 + key_home, // key_home, khome, kh + key_ic, // key_ic, kich1, kI + key_il, // key_il, kil1, kA + key_left, // key_left, kcub1, kl + key_ll, // key_ll, kll, kH + key_mark, // key_mark, kmrk, %2 + key_message, // key_message, kmsg, %3 + key_move, // key_move, kmov, %4 + key_next, // key_next, knxt, %5 + key_npage, // key_npage, knp, kN + key_open, // key_open, kopn, %6 + key_options, // key_options, kopt, %7 + key_ppage, // key_ppage, kpp, kP + key_previous, // key_previous, kprv, %8 + key_print, // key_print, kprt, %9 + key_redo, // key_redo, krdo, %0 + key_reference, // key_reference, kref, &1 + key_refresh, // key_refresh, krfr, &2 + key_replace, // key_replace, krpl, &3 + key_restart, // key_restart, krst, &4 + key_resume, // key_resume, kres, &5 + key_right, // key_right, kcuf1, kr + key_save, // key_save, ksav, &6 + key_sbeg, // key_sbeg, kBEG, &9 + key_scancel, // key_scancel, kCAN, &0 + key_scommand, // key_scommand, kCMD, *1 + key_scopy, // key_scopy, kCPY, *2 + key_screate, // key_screate, kCRT, *3 + key_sdc, // key_sdc, kDC, *4 + key_sdl, // key_sdl, kDL, *5 + key_select, // key_select, kslt, *6 + key_send, // key_send, kEND, *7 + key_seol, // key_seol, kEOL, *8 + key_sexit, // key_sexit, kEXT, *9 + key_sf, // key_sf, kind, kF + key_sfind, // key_sfind, kFND, *0 + key_shelp, // key_shelp, kHLP, #1 + key_shome, // key_shome, kHOM, #2 + key_sic, // key_sic, kIC, #3 + key_sleft, // key_sleft, kLFT, #4 + key_smessage, // key_smessage, kMSG, %a + key_smove, // key_smove, kMOV, %b + key_snext, // key_snext, kNXT, %c + key_soptions, // key_soptions, kOPT, %d + key_sprevious, // key_sprevious, kPRV, %e + key_sprint, // key_sprint, kPRT, %f + key_sr, // key_sr, kri, kR + key_sredo, // key_sredo, kRDO, %g + key_sreplace, // key_sreplace, kRPL, %h + key_sright, // key_sright, kRIT, %i + key_srsume, // key_srsume, kRES, %j + key_ssave, // key_ssave, kSAV, !1 + key_ssuspend, // key_ssuspend, kSPD, !2 + key_stab, // key_stab, khts, kT + key_sundo, // key_sundo, kUND, !3 + key_suspend, // key_suspend, kspd, &7 + key_undo, // key_undo, kund, &8 + key_up, // key_up, kcuu1, ku + keypad_local, // keypad_local, rmkx, ke + keypad_xmit, // keypad_xmit, smkx, ks + lab_f0, // lab_f0, lf0, l0 + lab_f1, // lab_f1, lf1, l1 + lab_f10, // lab_f10, lf10, la + lab_f2, // lab_f2, lf2, l2 + lab_f3, // lab_f3, lf3, l3 + lab_f4, // lab_f4, lf4, l4 + lab_f5, // lab_f5, lf5, l5 + lab_f6, // lab_f6, lf6, l6 + lab_f7, // lab_f7, lf7, l7 + lab_f8, // lab_f8, lf8, l8 + lab_f9, // lab_f9, lf9, l9 + label_format, // label_format, fln, Lf + label_off, // label_off, rmln, LF + label_on, // label_on, smln, LO + meta_off, // meta_off, rmm, mo + meta_on, // meta_on, smm, mm + micro_column_address, // micro_column_address, mhpa, ZY + micro_down, // micro_down, mcud1, ZZ + micro_left, // micro_left, mcub1, Za + micro_right, // micro_right, mcuf1, Zb + micro_row_address, // micro_row_address, mvpa, Zc + micro_up, // micro_up, mcuu1, Zd + newline, // newline, nel, nw + order_of_pins, // order_of_pins, porder, Ze + orig_colors, // orig_colors, oc, oc + orig_pair, // orig_pair, op, op + pad_char, // pad_char, pad, pc + parm_dch, // parm_dch, dch, DC + parm_delete_line, // parm_delete_line, dl, DL + parm_down_cursor, // parm_down_cursor, cud, DO + parm_down_micro, // parm_down_micro, mcud, Zf + parm_ich, // parm_ich, ich, IC + parm_index, // parm_index, indn, SF + parm_insert_line, // parm_insert_line, il, AL + parm_left_cursor, // parm_left_cursor, cub, LE + parm_left_micro, // parm_left_micro, mcub, Zg + parm_right_cursor, // parm_right_cursor, cuf, RI + parm_right_micro, // parm_right_micro, mcuf, Zh + parm_rindex, // parm_rindex, rin, SR + parm_up_cursor, // parm_up_cursor, cuu, UP + parm_up_micro, // parm_up_micro, mcuu, Zi + pkey_key, // pkey_key, pfkey, pk + pkey_local, // pkey_local, pfloc, pl + pkey_xmit, // pkey_xmit, pfx, px + plab_norm, // plab_norm, pln, pn + print_screen, // print_screen, mc0, ps + prtr_non, // prtr_non, mc5p, pO + prtr_off, // prtr_off, mc4, pf + prtr_on, // prtr_on, mc5, po + pulse, // pulse, pulse, PU + quick_dial, // quick_dial, qdial, QD + remove_clock, // remove_clock, rmclk, RC + repeat_char, // repeat_char, rep, rp + req_for_input, // req_for_input, rfi, RF + reset_1string, // reset_1string, rs1, r1 + reset_2string, // reset_2string, rs2, r2 + reset_3string, // reset_3string, rs3, r3 + reset_file, // reset_file, rf, rf + restore_cursor, // restore_cursor, rc, rc + row_address, // row_address, vpa, cv + save_cursor, // save_cursor, sc, sc + scroll_forward, // scroll_forward, ind, sf + scroll_reverse, // scroll_reverse, ri, sr + select_char_set, // select_char_set, scs, Zj + set_attributes, // set_attributes, sgr, sa + set_background, // set_background, setb, Sb + set_bottom_margin, // set_bottom_margin, smgb, Zk + set_bottom_margin_parm, // set_bottom_margin_parm, smgbp, Zl + set_clock, // set_clock, sclk, SC + set_color_pair, // set_color_pair, scp, sp + set_foreground, // set_foreground, setf, Sf + set_left_margin, // set_left_margin, smgl, ML + set_left_margin_parm, // set_left_margin_parm, smglp, Zm + set_right_margin, // set_right_margin, smgr, MR + set_right_margin_parm, // set_right_margin_parm, smgrp, Zn + set_tab, // set_tab, hts, st + set_top_margin, // set_top_margin, smgt, Zo + set_top_margin_parm, // set_top_margin_parm, smgtp, Zp + set_window, // set_window, wind, wi + start_bit_image, // start_bit_image, sbim, Zq + start_char_set_def, // start_char_set_def, scsd, Zr + stop_bit_image, // stop_bit_image, rbim, Zs + stop_char_set_def, // stop_char_set_def, rcsd, Zt + subscript_characters, // subscript_characters, subcs, Zu + superscript_characters, // superscript_characters, supcs, Zv + tab, // tab, ht, ta + these_cause_cr, // these_cause_cr, docr, Zw + to_status_line, // to_status_line, tsl, ts + tone, // tone, tone, TO + underline_char, // underline_char, uc, uc + up_half_line, // up_half_line, hu, hu + user0, // user0, u0, u0 + user1, // user1, u1, u1 + user2, // user2, u2, u2 + user3, // user3, u3, u3 + user4, // user4, u4, u4 + user5, // user5, u5, u5 + user6, // user6, u6, u6 + user7, // user7, u7, u7 + user8, // user8, u8, u8 + user9, // user9, u9, u9 + wait_tone, // wait_tone, wait, WA + xoff_character, // xoff_character, xoffc, XF + xon_character, // xon_character, xonc, XN + zero_motion, // zero_motion, zerom, Zx + alt_scancode_esc, // alt_scancode_esc, scesa, S8 + bit_image_carriage_return, // bit_image_carriage_return, bicr, Yv + bit_image_newline, // bit_image_newline, binel, Zz + bit_image_repeat, // bit_image_repeat, birep, Xy + char_set_names, // char_set_names, csnm, Zy + code_set_init, // code_set_init, csin, ci + color_names, // color_names, colornm, Yw + define_bit_image_region, // define_bit_image_region, defbi, Yx + device_type, // device_type, devt, dv + display_pc_char, // display_pc_char, dispc, S1 + end_bit_image_region, // end_bit_image_region, endbi, Yy + enter_pc_charset_mode, // enter_pc_charset_mode, smpch, S2 + enter_scancode_mode, // enter_scancode_mode, smsc, S4 + exit_pc_charset_mode, // exit_pc_charset_mode, rmpch, S3 + exit_scancode_mode, // exit_scancode_mode, rmsc, S5 + get_mouse, // get_mouse, getm, Gm + key_mouse, // key_mouse, kmous, Km + mouse_info, // mouse_info, minfo, Mi + pc_term_options, // pc_term_options, pctrm, S6 + pkey_plab, // pkey_plab, pfxl, xl + req_mouse_pos, // req_mouse_pos, reqmp, RQ + scancode_escape, // scancode_escape, scesc, S7 + set0_des_seq, // set0_des_seq, s0ds, s0 + set1_des_seq, // set1_des_seq, s1ds, s1 + set2_des_seq, // set2_des_seq, s2ds, s2 + set3_des_seq, // set3_des_seq, s3ds, s3 + set_a_background, // set_a_background, setab, AB + set_a_foreground, // set_a_foreground, setaf, AF + set_color_band, // set_color_band, setcolor, Yz + set_lr_margin, // set_lr_margin, smglr, ML + set_page_length, // set_page_length, slines, YZ + set_tb_margin, // set_tb_margin, smgtb, MT + enter_horizontal_hl_mode, // enter_horizontal_hl_mode, ehhlm, Xh + enter_left_hl_mode, // enter_left_hl_mode, elhlm, Xl + enter_low_hl_mode, // enter_low_hl_mode, elohlm, Xo + enter_right_hl_mode, // enter_right_hl_mode, erhlm, Xr + enter_top_hl_mode, // enter_top_hl_mode, ethlm, Xt + enter_vertical_hl_mode, // enter_vertical_hl_mode, evhlm, Xv + set_a_attributes, // set_a_attributes, sgr1, sA + set_pglen_inch, // set_pglen_inch, slength, sL) ; public String[] getNames() { @@ -515,8 +513,9 @@ public static Capability byName(String name) { public static Map getCapabilitiesByName() { Map capabilities = new LinkedHashMap<>(); try (InputStream is = InfoCmp.class.getResourceAsStream("capabilities.txt"); - BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) { - br.lines().map(String::trim) + BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) { + br.lines() + .map(String::trim) .filter(s -> !s.startsWith("#")) .filter(s -> !s.isEmpty()) .forEach(s -> { @@ -539,9 +538,7 @@ public static void setDefaultInfoCmp(String terminal, Supplier caps) { CAPS.putIfAbsent(terminal, caps); } - public static String getInfoCmp( - String terminal - ) throws IOException, InterruptedException { + public static String getInfoCmp(String terminal) throws IOException, InterruptedException { String caps = getLoadedInfoCmp(terminal); if (caps == null) { Process p = new ProcessBuilder(OSUtils.INFOCMP_COMMAND, terminal).start(); @@ -563,8 +560,7 @@ public static void parseInfoCmp( String capabilities, Set bools, Map ints, - Map strings - ) { + Map strings) { Map capsByName = getCapabilitiesByName(); String[] lines = capabilities.split("\n"); for (int i = 1; i < lines.length; i++) { @@ -609,7 +605,7 @@ public static void parseInfoCmp( static String loadDefaultInfoCmp(String name) { try (InputStream is = InfoCmp.class.getResourceAsStream(name + ".caps"); - BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) { + BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) { return br.lines().collect(Collectors.joining("\n", "", "\n")); } catch (IOException e) { throw new IOError(e); @@ -617,11 +613,23 @@ static String loadDefaultInfoCmp(String name) { } static { - for (String s : Arrays.asList("dumb", "dumb-color", "ansi", "xterm", "xterm-256color", - "windows", "windows-256color", "windows-conemu", "windows-vtp", - "screen", "screen-256color", "rxvt-unicode", "rxvt-unicode-256color", "rxvt-basic", "rxvt")) { + for (String s : Arrays.asList( + "dumb", + "dumb-color", + "ansi", + "xterm", + "xterm-256color", + "windows", + "windows-256color", + "windows-conemu", + "windows-vtp", + "screen", + "screen-256color", + "rxvt-unicode", + "rxvt-unicode-256color", + "rxvt-basic", + "rxvt")) { setDefaultInfoCmp(s, () -> loadDefaultInfoCmp(s)); } } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/InputStreamReader.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/InputStreamReader.java index fda314fb9b4..449d6aa69c8 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/InputStreamReader.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/InputStreamReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -22,7 +22,6 @@ import java.nio.charset.MalformedInputException; import java.nio.charset.UnmappableCharacterException; - /** * * NOTE for JLine: the default InputStreamReader that comes from the JRE @@ -66,9 +65,10 @@ public class InputStreamReader extends Reader { public InputStreamReader(InputStream in) { super(in); this.in = in; - decoder = Charset.defaultCharset().newDecoder().onMalformedInput( - CodingErrorAction.REPLACE).onUnmappableCharacter( - CodingErrorAction.REPLACE); + decoder = Charset.defaultCharset() + .newDecoder() + .onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE); bytes.limit(0); } @@ -87,20 +87,19 @@ public InputStreamReader(InputStream in) { * @throws UnsupportedEncodingException * if the encoding specified by {@code enc} cannot be found. */ - public InputStreamReader(InputStream in, final String enc) - throws UnsupportedEncodingException { + public InputStreamReader(InputStream in, final String enc) throws UnsupportedEncodingException { super(in); if (enc == null) { throw new NullPointerException(); } this.in = in; try { - decoder = Charset.forName(enc).newDecoder().onMalformedInput( - CodingErrorAction.REPLACE).onUnmappableCharacter( - CodingErrorAction.REPLACE); + decoder = Charset.forName(enc) + .newDecoder() + .onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE); } catch (IllegalArgumentException e) { - throw (UnsupportedEncodingException) - new UnsupportedEncodingException(enc).initCause(e); + throw (UnsupportedEncodingException) new UnsupportedEncodingException(enc).initCause(e); } bytes.limit(0); } @@ -134,9 +133,9 @@ public InputStreamReader(InputStream in, CharsetDecoder dec) { public InputStreamReader(InputStream in, Charset charset) { super(in); this.in = in; - decoder = charset.newDecoder().onMalformedInput( - CodingErrorAction.REPLACE).onUnmappableCharacter( - CodingErrorAction.REPLACE); + decoder = charset.newDecoder() + .onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE); bytes.limit(0); } @@ -257,8 +256,7 @@ public int read(char[] buf, int offset, int length) throws IOException { // fill the buffer if needed if (needInput) { try { - if ((in.available() == 0) - && (out.position() > offset)) { + if ((in.available() == 0) && (out.position() > offset)) { // we could return the result without blocking read break; } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Levenshtein.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Levenshtein.java index cc95593ed80..015515f7d07 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Levenshtein.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Levenshtein.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -49,9 +49,8 @@ public static int distance(CharSequence lhs, CharSequence rhs) { return distance(lhs, rhs, 1, 1, 1, 1); } - public static int distance(CharSequence source, CharSequence target, - int deleteCost, int insertCost, - int replaceCost, int swapCost) { + public static int distance( + CharSequence source, CharSequence target, int deleteCost, int insertCost, int replaceCost, int swapCost) { /* * Required to facilitate the premise to the algorithm that two swaps of the * same character are never required for optimality. @@ -115,5 +114,4 @@ public static int distance(CharSequence source, CharSequence target, } return table[source.length() - 1][target.length() - 1]; } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Log.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Log.java index 91f18755e25..254173d5bd9 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Log.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Log.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2020, the original author or authors. + * Copyright (c) 2002-2020, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -73,8 +73,7 @@ static void render(final PrintStream out, final Object message) { } } out.print("]"); - } - else { + } else { out.print(message); } } @@ -84,11 +83,10 @@ static void render(final PrintStream out, final Object message) { // ByteArrayOutputStream baos = new ByteArrayOutputStream(); // PrintStream ps = new PrintStream(baos); // for (int i = 0; i < messages.length; i++) { -// // Special handling for the last message if its a throwable, render its stack on the next line +// // Special handling for the last message if it's a throwable, render its stack on the next line // if (i + 1 == messages.length && messages[i] instanceof Throwable) { // cause = (Throwable) messages[i]; -// } -// else { +// } else { // render(ps, messages[i]); // } // } @@ -122,5 +120,4 @@ static void render(final PrintStream out, final Object message) { // static boolean isEnabled(Level level) { // return logger.isLoggable(level); // } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlocking.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlocking.java index f8cb53489f9..4130634ca4b 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlocking.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlocking.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -84,8 +84,7 @@ private NonBlockingReaderInputStream(NonBlockingReader reader, Charset charset) @Override public int available() { - return (int) (reader.available() * this.encoder.averageBytesPerChar()) - + bytes.remaining(); + return (int) (reader.available() * this.encoder.averageBytesPerChar()) + bytes.remaining(); } @Override @@ -124,7 +123,6 @@ public int read(long timeout, boolean isPeek) throws IOException { return READ_EXPIRED; } } - } private static class NonBlockingInputStreamReader extends NonBlockingReader { @@ -135,10 +133,12 @@ private static class NonBlockingInputStreamReader extends NonBlockingReader { private final CharBuffer chars; public NonBlockingInputStreamReader(NonBlockingInputStream inputStream, Charset encoding) { - this(inputStream, - (encoding != null ? encoding : Charset.defaultCharset()).newDecoder() - .onMalformedInput(CodingErrorAction.REPLACE) - .onUnmappableCharacter(CodingErrorAction.REPLACE)); + this( + inputStream, + (encoding != null ? encoding : Charset.defaultCharset()) + .newDecoder() + .onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE)); } public NonBlockingInputStreamReader(NonBlockingInputStream input, CharsetDecoder decoder) { @@ -201,8 +201,8 @@ public int readBuffered(char[] b, int off, int len, long timeout) throws IOExcep bytes.position(0); bytes.limit(0); } - int nb = input.readBuffered(bytes.array(), bytes.limit(), - bytes.capacity() - bytes.limit(), t.timeout()); + int nb = input.readBuffered( + bytes.array(), bytes.limit(), bytes.capacity() - bytes.limit(), t.timeout()); if (nb < 0) { return nb; } @@ -227,5 +227,4 @@ public void close() throws IOException { input.close(); } } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStream.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStream.java index a4283eb7006..10ab68cfd28 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStream.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -74,7 +74,7 @@ public int read(byte b[], int off, int len) throws IOException { if (c == EOF) { return EOF; } - b[off] = (byte)c; + b[off] = (byte) c; return 1; } @@ -115,9 +115,7 @@ public int readBuffered(byte[] b, int off, int len, long timeout) throws IOExcep * thread is currently blocked waiting for I/O it may not actually * shut down until the I/O is received. */ - public void shutdown() { - } + public void shutdown() {} public abstract int read(long timeout, boolean isPeek) throws IOException; - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStreamImpl.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStreamImpl.java index 680047fbe60..24cf13a0ee5 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStreamImpl.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingInputStreamImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -26,17 +26,15 @@ * the thread that handles blocking I/O. * */ -public class NonBlockingInputStreamImpl - extends NonBlockingInputStream -{ - private InputStream in; // The actual input stream - private int b = READ_EXPIRED; // Recently read byte - - private String name; - private boolean threadIsReading = false; - private IOException exception = null; - private long threadDelay = 60 * 1000; - private Thread thread; +public class NonBlockingInputStreamImpl extends NonBlockingInputStream { + private InputStream in; // The actual input stream + private int b = READ_EXPIRED; // Recently read byte + + private String name; + private boolean threadIsReading = false; + private IOException exception = null; + private long threadDelay = 60 * 1000; + private Thread thread; /** * Creates a NonBlockingReader out of a normal blocking @@ -97,8 +95,7 @@ public synchronized int read(long timeout, boolean isPeek) throws IOException { if (exception != null) { assert b == READ_EXPIRED; IOException toBeThrown = exception; - if (!isPeek) - exception = null; + if (!isPeek) exception = null; throw toBeThrown; } @@ -109,11 +106,9 @@ public synchronized int read(long timeout, boolean isPeek) throws IOException { */ if (b >= -1) { assert exception == null; - } - else if (!isPeek && timeout <= 0L && !threadIsReading) { + } else if (!isPeek && timeout <= 0L && !threadIsReading) { b = in.read(); - } - else { + } else { /* * If the thread isn't reading already, then ask it to do so. */ @@ -128,14 +123,13 @@ else if (!isPeek && timeout <= 0L && !threadIsReading) { * now we play the waiting game. */ Timeout t = new Timeout(timeout); - while (!t.elapsed()) { + while (!t.elapsed()) { try { if (Thread.interrupted()) { throw new InterruptedException(); } wait(t.timeout()); - } - catch (InterruptedException e) { + } catch (InterruptedException e) { exception = (IOException) new InterruptedIOException().initCause(e); } @@ -143,8 +137,7 @@ else if (!isPeek && timeout <= 0L && !threadIsReading) { assert b == READ_EXPIRED; IOException toBeThrown = exception; - if (!isPeek) - exception = null; + if (!isPeek) exception = null; throw toBeThrown; } @@ -168,7 +161,7 @@ else if (!isPeek && timeout <= 0L && !threadIsReading) { return ret; } - private void run () { + private void run() { Log.debug("NonBlockingInputStream start"); boolean needToRead; @@ -236,5 +229,4 @@ private void run () { } } } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpInputStream.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpInputStream.java index 5a361344350..aad6e3d0f5a 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpInputStream.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2017, the original author or authors. + * Copyright (c) 2002-2017, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -57,11 +57,7 @@ private int wait(ByteBuffer buffer, long timeout) throws IOException { throw new InterruptedIOException(); } } - return buffer.hasRemaining() - ? 0 - : closed - ? EOF - : READ_EXPIRED; + return buffer.hasRemaining() ? 0 : closed ? EOF : READ_EXPIRED; } private static boolean rewind(ByteBuffer buffer, ByteBuffer other) { @@ -167,7 +163,7 @@ private class NbpOutputStream extends OutputStream { @Override public void write(int b) throws IOException { - NonBlockingPumpInputStream.this.write(new byte[] { (byte) b }, 0, 1); + NonBlockingPumpInputStream.this.write(new byte[] {(byte) b}, 0, 1); } @Override @@ -184,7 +180,5 @@ public void flush() throws IOException { public void close() throws IOException { NonBlockingPumpInputStream.this.close(); } - } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpReader.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpReader.java index f36423f03b8..63db6e5f5bf 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpReader.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingPumpReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2017, the original author or authors. + * Copyright (c) 2002-2017, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -121,7 +121,7 @@ public int readBuffered(char[] b, int off, int len, long timeout) throws IOExcep try { if (timeout > 0) { if (!notEmpty.await(timeout, TimeUnit.MILLISECONDS)) { - throw new IOException( "Timeout reading" ); + throw new IOException("Timeout reading"); } } else { notEmpty.await(); @@ -207,14 +207,11 @@ public void write(char[] cbuf, int off, int len) throws IOException { } @Override - public void flush() throws IOException { - } + public void flush() throws IOException {} @Override public void close() throws IOException { NonBlockingPumpReader.this.close(); } - } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReader.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReader.java index e2f664f2999..460f548b506 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReader.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -23,8 +23,7 @@ public abstract class NonBlockingReader extends Reader { * thread is currently blocked waiting for I/O it will not actually * shut down until the I/O is received. */ - public void shutdown() { - } + public void shutdown() {} @Override public int read() throws IOException { @@ -109,5 +108,4 @@ public int available() { * @throws IOException if anything wrong happens */ protected abstract int read(long timeout, boolean isPeek) throws IOException; - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReaderImpl.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReaderImpl.java index d384cc9a0dc..5aaabd1d3c0 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReaderImpl.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlockingReaderImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -28,19 +28,17 @@ * @since 2.7 * @author Scott C. Gray <scottgray1@gmail.com> */ -public class NonBlockingReaderImpl - extends NonBlockingReader -{ +public class NonBlockingReaderImpl extends NonBlockingReader { public static final int READ_EXPIRED = -2; - private Reader in; // The actual input stream - private int ch = READ_EXPIRED; // Recently read character + private Reader in; // The actual input stream + private int ch = READ_EXPIRED; // Recently read character - private String name; - private boolean threadIsReading = false; - private IOException exception = null; - private long threadDelay = 60 * 1000; - private Thread thread; + private String name; + private boolean threadIsReading = false; + private IOException exception = null; + private long threadDelay = 60 * 1000; + private Thread thread; /** * Creates a NonBlockingReader out of a normal blocking @@ -135,8 +133,7 @@ protected synchronized int read(long timeout, boolean isPeek) throws IOException if (exception != null) { assert ch == READ_EXPIRED; IOException toBeThrown = exception; - if (!isPeek) - exception = null; + if (!isPeek) exception = null; throw toBeThrown; } @@ -147,11 +144,9 @@ protected synchronized int read(long timeout, boolean isPeek) throws IOException */ if (ch >= -1) { assert exception == null; - } - else if (!isPeek && timeout <= 0L && !threadIsReading) { + } else if (!isPeek && timeout <= 0L && !threadIsReading) { ch = in.read(); - } - else { + } else { /* * If the thread isn't reading already, then ask it to do so. */ @@ -166,14 +161,13 @@ else if (!isPeek && timeout <= 0L && !threadIsReading) { * now we play the waiting game. */ Timeout t = new Timeout(timeout); - while (!t.elapsed()) { + while (!t.elapsed()) { try { if (Thread.interrupted()) { throw new InterruptedException(); } wait(t.timeout()); - } - catch (InterruptedException e) { + } catch (InterruptedException e) { exception = (IOException) new InterruptedIOException().initCause(e); } @@ -181,8 +175,7 @@ else if (!isPeek && timeout <= 0L && !threadIsReading) { assert ch == READ_EXPIRED; IOException toBeThrown = exception; - if (!isPeek) - exception = null; + if (!isPeek) exception = null; throw toBeThrown; } @@ -206,7 +199,7 @@ else if (!isPeek && timeout <= 0L && !threadIsReading) { return ret; } - private void run () { + private void run() { Log.debug("NonBlockingReader start"); boolean needToRead; @@ -245,12 +238,12 @@ private void run () { IOException failure = null; try { charRead = in.read(); -// if (charRead < 0) { -// continue; -// } + // if (charRead < 0) { + // continue; + // } } catch (IOException e) { failure = e; -// charRead = -1; + // charRead = -1; } /* diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/OSUtils.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/OSUtils.java index 97487731852..344d081c124 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/OSUtils.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/OSUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -9,16 +9,23 @@ package jdk.internal.org.jline.utils; import java.io.File; -import java.nio.file.Files; -import java.nio.file.Paths; public class OSUtils { - public static final boolean IS_WINDOWS = System.getProperty("os.name").toLowerCase().contains("win"); + public static final boolean IS_LINUX = + System.getProperty("os.name").toLowerCase().contains("linux"); - public static final boolean IS_CYGWIN = IS_WINDOWS - && System.getenv("PWD") != null - && System.getenv("PWD").startsWith("/"); + public static final boolean IS_WINDOWS = + System.getProperty("os.name").toLowerCase().contains("win"); + + public static final boolean IS_OSX = + System.getProperty("os.name").toLowerCase().contains("mac"); + + public static final boolean IS_AIX = + System.getProperty("os.name").toLowerCase().contains("aix"); + + public static final boolean IS_CYGWIN = + IS_WINDOWS && System.getenv("PWD") != null && System.getenv("PWD").startsWith("/"); @Deprecated public static final boolean IS_MINGW = IS_WINDOWS @@ -28,7 +35,7 @@ public class OSUtils { public static final boolean IS_MSYSTEM = IS_WINDOWS && System.getenv("MSYSTEM") != null && (System.getenv("MSYSTEM").startsWith("MINGW") - || System.getenv("MSYSTEM").equals("MSYS")); + || System.getenv("MSYSTEM").equals("MSYS")); public static final boolean IS_WSL = System.getenv("WSL_DISTRO_NAME") != null; @@ -36,11 +43,7 @@ public class OSUtils { public static final boolean IS_WSL2 = IS_WSL && !IS_WSL1; - public static final boolean IS_CONEMU = IS_WINDOWS - && System.getenv("ConEmuPID") != null; - - public static final boolean IS_OSX = System.getProperty("os.name").toLowerCase().contains("mac"); - public static final boolean IS_AIX = System.getProperty("os.name").equals("AIX"); + public static final boolean IS_CONEMU = IS_WINDOWS && System.getenv("ConEmuPID") != null; public static String TTY_COMMAND; public static String STTY_COMMAND; @@ -48,64 +51,57 @@ public class OSUtils { public static String INFOCMP_COMMAND; public static String TEST_COMMAND; + private static boolean isExecutable(File f) { + return f.canExecute() && !f.isDirectory(); + } + static { - String tty; - String stty; - String sttyfopt; - String infocmp; - String test; - if (OSUtils.IS_CYGWIN || OSUtils.IS_MSYSTEM) { - tty = null; - stty = null; - sttyfopt = null; - infocmp = null; - test = null; - String path = System.getenv("PATH"); - if (path != null) { - String[] paths = path.split(";"); - for (String p : paths) { - if (tty == null && new File(p, "tty.exe").exists()) { - tty = new File(p, "tty.exe").getAbsolutePath(); - } - if (stty == null && new File(p, "stty.exe").exists()) { - stty = new File(p, "stty.exe").getAbsolutePath(); - } - if (infocmp == null && new File(p, "infocmp.exe").exists()) { - infocmp = new File(p, "infocmp.exe").getAbsolutePath(); - } - if (test == null && new File(p, "test.exe").exists()) { - test = new File(p, "test.exe").getAbsolutePath(); - } + boolean cygwinOrMsys = OSUtils.IS_CYGWIN || OSUtils.IS_MSYSTEM; + String suffix = cygwinOrMsys ? ".exe" : ""; + String tty = null; + String stty = null; + String sttyfopt = null; + String infocmp = null; + String test = null; + String path = System.getenv("PATH"); + if (path != null) { + String[] paths = path.split(File.pathSeparator); + for (String p : paths) { + File ttyFile = new File(p, "tty" + suffix); + if (tty == null && isExecutable(ttyFile)) { + tty = ttyFile.getAbsolutePath(); + } + File sttyFile = new File(p, "stty" + suffix); + if (stty == null && isExecutable(sttyFile)) { + stty = sttyFile.getAbsolutePath(); + } + File infocmpFile = new File(p, "infocmp" + suffix); + if (infocmp == null && isExecutable(infocmpFile)) { + infocmp = infocmpFile.getAbsolutePath(); + } + File testFile = new File(p, "test" + suffix); + if (test == null && isExecutable(testFile)) { + test = testFile.getAbsolutePath(); } } - if (tty == null) { - tty = "tty.exe"; - } - if (stty == null) { - stty = "stty.exe"; - } - if (infocmp == null) { - infocmp = "infocmp.exe"; - } - if (test == null) { - test = "test.exe"; - } - } else { - tty = "tty"; - stty = IS_OSX ? "/bin/stty" : "stty"; - sttyfopt = IS_OSX ? "-f" : "-F"; - infocmp = "infocmp"; - test = isTestCommandValid("/usr/bin/test") ? "/usr/bin/test" - : "/bin/test"; } + if (tty == null) { + tty = "tty" + suffix; + } + if (stty == null) { + stty = "stty" + suffix; + } + if (infocmp == null) { + infocmp = "infocmp" + suffix; + } + if (test == null) { + test = "test" + suffix; + } + sttyfopt = IS_OSX ? "-f" : "-F"; TTY_COMMAND = tty; STTY_COMMAND = stty; STTY_F_OPTION = sttyfopt; INFOCMP_COMMAND = infocmp; TEST_COMMAND = test; } - - private static boolean isTestCommandValid(String command) { - return Files.isExecutable(Paths.get(command)); - } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/PumpReader.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/PumpReader.java index a6894e7672c..ce68fa5f84e 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/PumpReader.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/PumpReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2017, the original author or authors. + * Copyright (c) 2002-2017, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -378,7 +378,6 @@ public void flush() throws IOException { public void close() throws IOException { reader.close(); } - } private static class InputStream extends java.io.InputStream { @@ -464,7 +463,5 @@ public int read(byte[] b, int off, int len) throws IOException { public void close() throws IOException { reader.close(); } - } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ShutdownHooks.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ShutdownHooks.java index 8089de321cc..d5456df03d3 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ShutdownHooks.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/ShutdownHooks.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -18,8 +18,7 @@ * @author Jason Dillon * @since 2.7 */ -public final class ShutdownHooks -{ +public final class ShutdownHooks { private static final List tasks = new ArrayList<>(); private static Thread hook; @@ -29,8 +28,7 @@ public static synchronized T add(final T task) { // Install the hook thread if needed if (hook == null) { - hook = addHook(new Thread("JLine Shutdown Hook") - { + hook = addHook(new Thread("JLine Shutdown Hook") { @Override public void run() { runTasks(); @@ -53,8 +51,7 @@ private static synchronized void runTasks() { Log.debug("Running task: ", task); try { task.run(); - } - catch (Throwable e) { + } catch (Throwable e) { Log.warn("Task failed", e); } } @@ -91,8 +88,7 @@ private static void removeHook(final Thread thread) { try { Runtime.getRuntime().removeShutdownHook(thread); - } - catch (IllegalStateException e) { + } catch (IllegalStateException e) { // The VM is shutting down, not a big deal; ignore } } @@ -100,8 +96,7 @@ private static void removeHook(final Thread thread) { /** * Essentially a {@link Runnable} which allows running to throw an exception. */ - public interface Task - { + public interface Task { void run() throws Exception; } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Signals.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Signals.java index b94f1fa318e..9b25a804735 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Signals.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Signals.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2020, the original author or authors. + * Copyright (c) 2002-2020, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -21,8 +21,7 @@ */ public final class Signals { - private Signals() { - } + private Signals() {} /** * @@ -41,8 +40,8 @@ public static Object register(String name, final Runnable handler, ClassLoader l try { Class signalHandlerClass = Class.forName("sun.misc.SignalHandler"); // Implement signal handler - Object signalHandler = Proxy.newProxyInstance(loader, - new Class[]{signalHandlerClass}, (proxy, method, args) -> { + Object signalHandler = + Proxy.newProxyInstance(loader, new Class[] {signalHandlerClass}, (proxy, method, args) -> { // only method we are proxying is handle() if (method.getDeclaringClass() == Object.class) { if ("toString".equals(method.getName())) { @@ -101,8 +100,7 @@ private static Object doRegister(String name, Object handler) throws Exception { return null; } Class signalHandlerClass = Class.forName("sun.misc.SignalHandler"); - return signalClass.getMethod("handle", signalClass, signalHandlerClass) - .invoke(null, signal, handler); + return signalClass.getMethod("handle", signalClass, signalHandlerClass).invoke(null, signal, handler); } @SuppressWarnings("") @@ -120,5 +118,4 @@ private static String toString(Object handler) { } return handler != null ? handler.toString() : "null"; } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Status.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Status.java index e8d9e49e8b3..7348b1ea1c5 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Status.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Status.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2019, the original author or authors. + * Copyright (c) 2002-2019, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -8,187 +8,266 @@ */ package jdk.internal.org.jline.utils; -import java.util.Objects; -import java.util.Collections; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.Objects; +import java.util.Optional; + +import jdk.internal.org.jline.terminal.Size; import jdk.internal.org.jline.terminal.Terminal; import jdk.internal.org.jline.terminal.impl.AbstractTerminal; import jdk.internal.org.jline.utils.InfoCmp.Capability; -import jdk.internal.org.jline.terminal.Size; public class Status { - protected final AbstractTerminal terminal; + protected final Terminal terminal; protected final boolean supported; - protected List oldLines = Collections.emptyList(); - protected List linesToRestore = Collections.emptyList(); - protected int rows; - protected int columns; - protected boolean force; protected boolean suspended = false; protected AttributedString borderString; protected int border = 0; + protected Display display; + protected List lines = Collections.emptyList(); + protected int scrollRegion; public static Status getStatus(Terminal terminal) { return getStatus(terminal, true); } - public static Status getStatus(Terminal terminal, boolean create) { - return terminal instanceof AbstractTerminal - ? ((AbstractTerminal) terminal).getStatus(create) - : null; + public static Optional getExistingStatus(Terminal terminal) { + return Optional.ofNullable(getStatus(terminal, false)); } + public static Status getStatus(Terminal terminal, boolean create) { + return terminal instanceof AbstractTerminal ? ((AbstractTerminal) terminal).getStatus(create) : null; + } - public Status(AbstractTerminal terminal) { + @SuppressWarnings("this-escape") + public Status(Terminal terminal) { this.terminal = Objects.requireNonNull(terminal, "terminal can not be null"); this.supported = terminal.getStringCapability(Capability.change_scroll_region) != null - && terminal.getStringCapability(Capability.save_cursor) != null - && terminal.getStringCapability(Capability.restore_cursor) != null - && terminal.getStringCapability(Capability.cursor_address) != null; + && terminal.getStringCapability(Capability.save_cursor) != null + && terminal.getStringCapability(Capability.restore_cursor) != null + && terminal.getStringCapability(Capability.cursor_address) != null; if (supported) { - char borderChar = '\u2700'; - AttributedStringBuilder bb = new AttributedStringBuilder(); - for (int i = 0; i < 200; i++) { - bb.append(borderChar); - } - borderString = bb.toAttributedString(); + display = new MovingCursorDisplay(terminal); resize(); + display.reset(); + scrollRegion = display.rows - 1; } } + public void close() { + terminal.puts(Capability.save_cursor); + terminal.puts(Capability.change_scroll_region, 0, display.rows - 1); + terminal.puts(Capability.restore_cursor); + terminal.flush(); + } + public void setBorder(boolean border) { this.border = border ? 1 : 0; } public void resize() { - Size size = terminal.getSize(); - this.rows = size.getRows(); - this.columns = size.getColumns(); - this.force = true; + resize(terminal.getSize()); } - public void reset() { - this.force = true; + public void resize(Size size) { + display.resize(size.getRows(), size.getColumns()); } - public void hardReset() { - if (suspended) { - return; + public void reset() { + if (supported) { + display.reset(); + scrollRegion = display.rows; + terminal.puts(Capability.change_scroll_region, 0, scrollRegion); } - List lines = new ArrayList<>(oldLines); - int b = border; - update(null); - border = b; - update(lines); } public void redraw() { if (suspended) { return; } - update(oldLines); + update(lines); } - public void clear() { - privateClear(oldLines.size()); + public void hide() { + update(Collections.emptyList()); } - private void clearAll() { - int b = border; - border = 0; - privateClear(oldLines.size() + b); + public void update(List lines) { + update(lines, true); } - private void privateClear(int statusSize) { - List as = new ArrayList<>(); - for (int i = 0; i < statusSize; i++) { - as.add(new AttributedString("")); - } - if (!as.isEmpty()) { - update(as); - } - } + private final AttributedString ellipsis = + new AttributedStringBuilder().append("\u2026", AttributedStyle.INVERSE).toAttributedString(); - public void update(List lines) { + /** + * Returns true if the cursor may be misplaced and should + * be updated. + */ + public void update(List lines, boolean flush) { if (!supported) { return; } - if (lines == null) { - lines = Collections.emptyList(); - } + this.lines = new ArrayList<>(lines); if (suspended) { - linesToRestore = new ArrayList<>(lines); return; } - if (lines.isEmpty()) { - clearAll(); + + lines = new ArrayList<>(lines); + // add border + int rows = display.rows; + int columns = display.columns; + if (border == 1 && !lines.isEmpty() && rows > 1) { + lines.add(0, getBorderString(columns)); } - if (oldLines.equals(lines) && !force) { - return; + // trim or complete lines to the full width + for (int i = 0; i < lines.size(); i++) { + AttributedString str = lines.get(i); + if (str.columnLength() > columns) { + str = new AttributedStringBuilder(columns) + .append(lines.get(i).columnSubSequence(0, columns - ellipsis.columnLength())) + .append(ellipsis) + .toAttributedString(); + } else if (str.columnLength() < columns) { + str = new AttributedStringBuilder(columns) + .append(str) + .append(' ', columns - str.columnLength()) + .toAttributedString(); + } + lines.set(i, str); } - int statusSize = lines.size() + (lines.size() == 0 ? 0 : border); - int nb = statusSize - oldLines.size() - (oldLines.size() == 0 ? 0 : border); - if (nb > 0) { - for (int i = 0; i < nb; i++) { + + List oldLines = this.display.oldLines; + + int newScrollRegion = display.rows - 1 - lines.size(); + // Update the scroll region if needed. + // Note that settings the scroll region usually moves the cursor, so we need to get ready for that. + if (newScrollRegion < scrollRegion) { + // We need to scroll up to grow the status bar + terminal.puts(Capability.save_cursor); + for (int i = newScrollRegion; i < scrollRegion; i++) { terminal.puts(Capability.cursor_down); } - for (int i = 0; i < nb; i++) { + terminal.puts(Capability.change_scroll_region, 0, newScrollRegion); + terminal.puts(Capability.restore_cursor); + for (int i = newScrollRegion; i < scrollRegion; i++) { terminal.puts(Capability.cursor_up); } + scrollRegion = newScrollRegion; + } else if (newScrollRegion > scrollRegion) { + terminal.puts(Capability.save_cursor); + terminal.puts(Capability.change_scroll_region, 0, newScrollRegion); + terminal.puts(Capability.restore_cursor); + scrollRegion = newScrollRegion; } - terminal.puts(Capability.save_cursor); - terminal.puts(Capability.cursor_address, rows - statusSize, 0); - if (!terminal.puts(Capability.clr_eos)) { - for (int i = rows - statusSize; i < rows; i++) { - terminal.puts(Capability.cursor_address, i, 0); + + // if the display has more lines, we need to add empty ones to make sure they will be erased + List toDraw = new ArrayList<>(lines); + int nbToDraw = toDraw.size(); + int nbOldLines = oldLines.size(); + if (nbOldLines > nbToDraw) { + terminal.puts(Capability.save_cursor); + terminal.puts(Capability.cursor_address, display.rows - nbOldLines, 0); + for (int i = 0; i < nbOldLines - nbToDraw; i++) { terminal.puts(Capability.clr_eol); + if (i < nbOldLines - nbToDraw - 1) { + terminal.puts(Capability.cursor_down); + } + oldLines.remove(0); } + terminal.puts(Capability.restore_cursor); } - if (border == 1 && lines.size() > 0) { - terminal.puts(Capability.cursor_address, rows - statusSize, 0); - borderString.columnSubSequence(0, columns).print(terminal); - } - for (int i = 0; i < lines.size(); i++) { - terminal.puts(Capability.cursor_address, rows - lines.size() + i, 0); - if (lines.get(i).length() > columns) { - AttributedStringBuilder asb = new AttributedStringBuilder(); - asb.append(lines.get(i).substring(0, columns - 3)).append("...", new AttributedStyle(AttributedStyle.INVERSE)); - asb.toAttributedString().columnSubSequence(0, columns).print(terminal); - } else { - lines.get(i).columnSubSequence(0, columns).print(terminal); + // update display + display.update(lines, -1, flush); + } + + private AttributedString getBorderString(int columns) { + if (borderString == null || borderString.length() != columns) { + char borderChar = '\u2700'; + AttributedStringBuilder bb = new AttributedStringBuilder(); + for (int i = 0; i < columns; i++) { + bb.append(borderChar); } + borderString = bb.toAttributedString(); } - terminal.puts(Capability.change_scroll_region, 0, rows - 1 - statusSize); - terminal.puts(Capability.restore_cursor); - terminal.flush(); - oldLines = new ArrayList<>(lines); - force = false; + return borderString; } + /** + * The {@code suspend} method is used when a full-screen. + * If the status was not already suspended, the lines + * used by the status are cleared during this call. + */ public void suspend() { - if (suspended) { - return; + if (!suspended) { + suspended = true; } - linesToRestore = new ArrayList<>(oldLines); - int b = border; - update(null); - border = b; - suspended = true; } + /** + * The {@code restore()} call is the opposite of {@code suspend()} and + * will make the status bar be updated again. + * If the status was suspended, the lines + * used by the status will be drawn during this call. + */ public void restore() { - if (!suspended) { - return; + if (suspended) { + suspended = false; + update(this.lines); } - suspended = false; - update(linesToRestore); - linesToRestore = Collections.emptyList(); } public int size() { - return oldLines.size() + border; + return size(this.lines); + } + + private int size(List lines) { + int l = lines.size(); + return l > 0 ? l + border : 0; + } + + @Override + public String toString() { + return "Status[" + "supported=" + supported + ']'; } + static class MovingCursorDisplay extends Display { + protected int firstLine; + + public MovingCursorDisplay(Terminal terminal) { + super(terminal, false); + } + + @Override + public void update(List newLines, int targetCursorPos, boolean flush) { + cursorPos = -1; + firstLine = rows - newLines.size(); + super.update(newLines, targetCursorPos, flush); + if (cursorPos != -1) { + terminal.puts(Capability.restore_cursor); + } + } + + @Override + protected void moveVisualCursorTo(int targetPos, List newLines) { + initCursor(); + super.moveVisualCursorTo(targetPos, newLines); + } + + @Override + protected int moveVisualCursorTo(int i1) { + initCursor(); + return super.moveVisualCursorTo(i1); + } + + void initCursor() { + if (cursorPos == -1) { + terminal.puts(Capability.save_cursor); + terminal.puts(Capability.cursor_address, firstLine, 0); + cursorPos = 0; + } + } + } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/StyleResolver.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/StyleResolver.java index be1659957b4..29d87cbc3c8 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/StyleResolver.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/StyleResolver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -55,12 +55,12 @@ private static Integer colorRgb(String name) { return null; } } else { - // load indexed color - Integer color = color(name); - if (color != null && color != -1) { - color = Colors.DEFAULT_COLORS_256[color]; - } - return color; + // load indexed color + Integer color = color(name); + if (color != null && color != -1) { + color = Colors.DEFAULT_COLORS_256[color]; + } + return color; } } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Timeout.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Timeout.java index edea89cf2d9..1e3091e19a1 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Timeout.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/Timeout.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2018, the original author or authors. + * Copyright (c) 2002-2018, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -44,5 +44,4 @@ public boolean elapsed() { public long timeout() { return timeout > 0 ? Math.max(1, end - cur) : timeout; } - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/WCWidth.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/WCWidth.java index db3a8d3d990..7b0caf91c25 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/WCWidth.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/WCWidth.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016, the original author or authors. + * Copyright (c) 2002-2016, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -10,8 +10,7 @@ public final class WCWidth { - private WCWidth() { - } + private WCWidth() {} /* The following two functions define the column width of an ISO 10646 * character as follows: @@ -44,88 +43,86 @@ private WCWidth() { * This implementation assumes that wchar_t characters are encoded * in ISO 10646. */ - public static int wcwidth(int ucs) - { + public static int wcwidth(int ucs) { /* test for 8-bit control characters */ - if (ucs == 0) - return 0; - if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0)) - return -1; + if (ucs == 0) return 0; + if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0)) return -1; /* binary search in table of non-spacing characters */ - if (bisearch(ucs, combining, combining.length - 1)) - return 0; + if (bisearch(ucs, combining, combining.length - 1)) return 0; /* if we arrive here, ucs is not a combining or C0/C1 control character */ - return 1 + - ((ucs >= 0x1100 && - (ucs <= 0x115f || /* Hangul Jamo init. consonants */ - ucs == 0x2329 || ucs == 0x232a || - (ucs >= 0x2e80 && ucs <= 0xa4cf && - ucs != 0x303f) || /* CJK ... Yi */ - (ucs >= 0xac00 && ucs <= 0xd7a3) || /* Hangul Syllables */ - (ucs >= 0xf900 && ucs <= 0xfaff) || /* CJK Compatibility Ideographs */ - (ucs >= 0xfe10 && ucs <= 0xfe19) || /* Vertical forms */ - (ucs >= 0xfe30 && ucs <= 0xfe6f) || /* CJK Compatibility Forms */ - (ucs >= 0xff00 && ucs <= 0xff60) || /* Fullwidth Forms */ - (ucs >= 0xffe0 && ucs <= 0xffe6) || - (ucs >= 0x1f000 && ucs <= 0x1feee) || - (ucs >= 0x20000 && ucs <= 0x2fffd) || - (ucs >= 0x30000 && ucs <= 0x3fffd))) ? 1 : 0); + return 1 + + ((ucs >= 0x1100 + && (ucs <= 0x115f + || /* Hangul Jamo init. consonants */ ucs == 0x2329 + || ucs == 0x232a + || (ucs >= 0x2e80 && ucs <= 0xa4cf && ucs != 0x303f) + || /* CJK ... Yi */ (ucs >= 0xac00 && ucs <= 0xd7a3) + || /* Hangul Syllables */ (ucs >= 0xf900 && ucs <= 0xfaff) + || /* CJK Compatibility Ideographs */ (ucs >= 0xfe10 && ucs <= 0xfe19) + || /* Vertical forms */ (ucs >= 0xfe30 && ucs <= 0xfe6f) + || /* CJK Compatibility Forms */ (ucs >= 0xff00 && ucs <= 0xff60) + || /* Fullwidth Forms */ (ucs >= 0xffe0 && ucs <= 0xffe6) + || (ucs >= 0x1f000 && ucs <= 0x1feee) + || (ucs >= 0x20000 && ucs <= 0x2fffd) + || (ucs >= 0x30000 && ucs <= 0x3fffd))) + ? 1 + : 0); } /* sorted list of non-overlapping intervals of non-spacing characters */ /* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */ static Interval[] combining = { - new Interval( 0x0300, 0x036F ), new Interval( 0x0483, 0x0486 ), new Interval( 0x0488, 0x0489 ), - new Interval( 0x0591, 0x05BD ), new Interval( 0x05BF, 0x05BF ), new Interval( 0x05C1, 0x05C2 ), - new Interval( 0x05C4, 0x05C5 ), new Interval( 0x05C7, 0x05C7 ), new Interval( 0x0600, 0x0603 ), - new Interval( 0x0610, 0x0615 ), new Interval( 0x064B, 0x065E ), new Interval( 0x0670, 0x0670 ), - new Interval( 0x06D6, 0x06E4 ), new Interval( 0x06E7, 0x06E8 ), new Interval( 0x06EA, 0x06ED ), - new Interval( 0x070F, 0x070F ), new Interval( 0x0711, 0x0711 ), new Interval( 0x0730, 0x074A ), - new Interval( 0x07A6, 0x07B0 ), new Interval( 0x07EB, 0x07F3 ), new Interval( 0x0901, 0x0902 ), - new Interval( 0x093C, 0x093C ), new Interval( 0x0941, 0x0948 ), new Interval( 0x094D, 0x094D ), - new Interval( 0x0951, 0x0954 ), new Interval( 0x0962, 0x0963 ), new Interval( 0x0981, 0x0981 ), - new Interval( 0x09BC, 0x09BC ), new Interval( 0x09C1, 0x09C4 ), new Interval( 0x09CD, 0x09CD ), - new Interval( 0x09E2, 0x09E3 ), new Interval( 0x0A01, 0x0A02 ), new Interval( 0x0A3C, 0x0A3C ), - new Interval( 0x0A41, 0x0A42 ), new Interval( 0x0A47, 0x0A48 ), new Interval( 0x0A4B, 0x0A4D ), - new Interval( 0x0A70, 0x0A71 ), new Interval( 0x0A81, 0x0A82 ), new Interval( 0x0ABC, 0x0ABC ), - new Interval( 0x0AC1, 0x0AC5 ), new Interval( 0x0AC7, 0x0AC8 ), new Interval( 0x0ACD, 0x0ACD ), - new Interval( 0x0AE2, 0x0AE3 ), new Interval( 0x0B01, 0x0B01 ), new Interval( 0x0B3C, 0x0B3C ), - new Interval( 0x0B3F, 0x0B3F ), new Interval( 0x0B41, 0x0B43 ), new Interval( 0x0B4D, 0x0B4D ), - new Interval( 0x0B56, 0x0B56 ), new Interval( 0x0B82, 0x0B82 ), new Interval( 0x0BC0, 0x0BC0 ), - new Interval( 0x0BCD, 0x0BCD ), new Interval( 0x0C3E, 0x0C40 ), new Interval( 0x0C46, 0x0C48 ), - new Interval( 0x0C4A, 0x0C4D ), new Interval( 0x0C55, 0x0C56 ), new Interval( 0x0CBC, 0x0CBC ), - new Interval( 0x0CBF, 0x0CBF ), new Interval( 0x0CC6, 0x0CC6 ), new Interval( 0x0CCC, 0x0CCD ), - new Interval( 0x0CE2, 0x0CE3 ), new Interval( 0x0D41, 0x0D43 ), new Interval( 0x0D4D, 0x0D4D ), - new Interval( 0x0DCA, 0x0DCA ), new Interval( 0x0DD2, 0x0DD4 ), new Interval( 0x0DD6, 0x0DD6 ), - new Interval( 0x0E31, 0x0E31 ), new Interval( 0x0E34, 0x0E3A ), new Interval( 0x0E47, 0x0E4E ), - new Interval( 0x0EB1, 0x0EB1 ), new Interval( 0x0EB4, 0x0EB9 ), new Interval( 0x0EBB, 0x0EBC ), - new Interval( 0x0EC8, 0x0ECD ), new Interval( 0x0F18, 0x0F19 ), new Interval( 0x0F35, 0x0F35 ), - new Interval( 0x0F37, 0x0F37 ), new Interval( 0x0F39, 0x0F39 ), new Interval( 0x0F71, 0x0F7E ), - new Interval( 0x0F80, 0x0F84 ), new Interval( 0x0F86, 0x0F87 ), new Interval( 0x0F90, 0x0F97 ), - new Interval( 0x0F99, 0x0FBC ), new Interval( 0x0FC6, 0x0FC6 ), new Interval( 0x102D, 0x1030 ), - new Interval( 0x1032, 0x1032 ), new Interval( 0x1036, 0x1037 ), new Interval( 0x1039, 0x1039 ), - new Interval( 0x1058, 0x1059 ), new Interval( 0x1160, 0x11FF ), new Interval( 0x135F, 0x135F ), - new Interval( 0x1712, 0x1714 ), new Interval( 0x1732, 0x1734 ), new Interval( 0x1752, 0x1753 ), - new Interval( 0x1772, 0x1773 ), new Interval( 0x17B4, 0x17B5 ), new Interval( 0x17B7, 0x17BD ), - new Interval( 0x17C6, 0x17C6 ), new Interval( 0x17C9, 0x17D3 ), new Interval( 0x17DD, 0x17DD ), - new Interval( 0x180B, 0x180D ), new Interval( 0x18A9, 0x18A9 ), new Interval( 0x1920, 0x1922 ), - new Interval( 0x1927, 0x1928 ), new Interval( 0x1932, 0x1932 ), new Interval( 0x1939, 0x193B ), - new Interval( 0x1A17, 0x1A18 ), new Interval( 0x1B00, 0x1B03 ), new Interval( 0x1B34, 0x1B34 ), - new Interval( 0x1B36, 0x1B3A ), new Interval( 0x1B3C, 0x1B3C ), new Interval( 0x1B42, 0x1B42 ), - new Interval( 0x1B6B, 0x1B73 ), new Interval( 0x1DC0, 0x1DCA ), new Interval( 0x1DFE, 0x1DFF ), - new Interval( 0x200B, 0x200F ), new Interval( 0x202A, 0x202E ), new Interval( 0x2060, 0x2063 ), - new Interval( 0x206A, 0x206F ), new Interval( 0x20D0, 0x20EF ), new Interval( 0x302A, 0x302F ), - new Interval( 0x3099, 0x309A ), new Interval( 0xA806, 0xA806 ), new Interval( 0xA80B, 0xA80B ), - new Interval( 0xA825, 0xA826 ), new Interval( 0xFB1E, 0xFB1E ), new Interval( 0xFE00, 0xFE0F ), - new Interval( 0xFE20, 0xFE23 ), new Interval( 0xFEFF, 0xFEFF ), new Interval( 0xFFF9, 0xFFFB ), - new Interval( 0x10A01, 0x10A03 ), new Interval( 0x10A05, 0x10A06 ), new Interval( 0x10A0C, 0x10A0F ), - new Interval( 0x10A38, 0x10A3A ), new Interval( 0x10A3F, 0x10A3F ), new Interval( 0x1D167, 0x1D169 ), - new Interval( 0x1D173, 0x1D182 ), new Interval( 0x1D185, 0x1D18B ), new Interval( 0x1D1AA, 0x1D1AD ), - new Interval( 0x1D242, 0x1D244 ), new Interval( 0x1F3FB, 0x1F3FF ), new Interval( 0xE0001, 0xE0001 ), - new Interval( 0xE0020, 0xE007F ), new Interval( 0xE0100, 0xE01EF ) + new Interval(0x0300, 0x036F), new Interval(0x0483, 0x0486), new Interval(0x0488, 0x0489), + new Interval(0x0591, 0x05BD), new Interval(0x05BF, 0x05BF), new Interval(0x05C1, 0x05C2), + new Interval(0x05C4, 0x05C5), new Interval(0x05C7, 0x05C7), new Interval(0x0600, 0x0603), + new Interval(0x0610, 0x0615), new Interval(0x064B, 0x065E), new Interval(0x0670, 0x0670), + new Interval(0x06D6, 0x06E4), new Interval(0x06E7, 0x06E8), new Interval(0x06EA, 0x06ED), + new Interval(0x070F, 0x070F), new Interval(0x0711, 0x0711), new Interval(0x0730, 0x074A), + new Interval(0x07A6, 0x07B0), new Interval(0x07EB, 0x07F3), new Interval(0x0901, 0x0902), + new Interval(0x093C, 0x093C), new Interval(0x0941, 0x0948), new Interval(0x094D, 0x094D), + new Interval(0x0951, 0x0954), new Interval(0x0962, 0x0963), new Interval(0x0981, 0x0981), + new Interval(0x09BC, 0x09BC), new Interval(0x09C1, 0x09C4), new Interval(0x09CD, 0x09CD), + new Interval(0x09E2, 0x09E3), new Interval(0x0A01, 0x0A02), new Interval(0x0A3C, 0x0A3C), + new Interval(0x0A41, 0x0A42), new Interval(0x0A47, 0x0A48), new Interval(0x0A4B, 0x0A4D), + new Interval(0x0A70, 0x0A71), new Interval(0x0A81, 0x0A82), new Interval(0x0ABC, 0x0ABC), + new Interval(0x0AC1, 0x0AC5), new Interval(0x0AC7, 0x0AC8), new Interval(0x0ACD, 0x0ACD), + new Interval(0x0AE2, 0x0AE3), new Interval(0x0B01, 0x0B01), new Interval(0x0B3C, 0x0B3C), + new Interval(0x0B3F, 0x0B3F), new Interval(0x0B41, 0x0B43), new Interval(0x0B4D, 0x0B4D), + new Interval(0x0B56, 0x0B56), new Interval(0x0B82, 0x0B82), new Interval(0x0BC0, 0x0BC0), + new Interval(0x0BCD, 0x0BCD), new Interval(0x0C3E, 0x0C40), new Interval(0x0C46, 0x0C48), + new Interval(0x0C4A, 0x0C4D), new Interval(0x0C55, 0x0C56), new Interval(0x0CBC, 0x0CBC), + new Interval(0x0CBF, 0x0CBF), new Interval(0x0CC6, 0x0CC6), new Interval(0x0CCC, 0x0CCD), + new Interval(0x0CE2, 0x0CE3), new Interval(0x0D41, 0x0D43), new Interval(0x0D4D, 0x0D4D), + new Interval(0x0DCA, 0x0DCA), new Interval(0x0DD2, 0x0DD4), new Interval(0x0DD6, 0x0DD6), + new Interval(0x0E31, 0x0E31), new Interval(0x0E34, 0x0E3A), new Interval(0x0E47, 0x0E4E), + new Interval(0x0EB1, 0x0EB1), new Interval(0x0EB4, 0x0EB9), new Interval(0x0EBB, 0x0EBC), + new Interval(0x0EC8, 0x0ECD), new Interval(0x0F18, 0x0F19), new Interval(0x0F35, 0x0F35), + new Interval(0x0F37, 0x0F37), new Interval(0x0F39, 0x0F39), new Interval(0x0F71, 0x0F7E), + new Interval(0x0F80, 0x0F84), new Interval(0x0F86, 0x0F87), new Interval(0x0F90, 0x0F97), + new Interval(0x0F99, 0x0FBC), new Interval(0x0FC6, 0x0FC6), new Interval(0x102D, 0x1030), + new Interval(0x1032, 0x1032), new Interval(0x1036, 0x1037), new Interval(0x1039, 0x1039), + new Interval(0x1058, 0x1059), new Interval(0x1160, 0x11FF), new Interval(0x135F, 0x135F), + new Interval(0x1712, 0x1714), new Interval(0x1732, 0x1734), new Interval(0x1752, 0x1753), + new Interval(0x1772, 0x1773), new Interval(0x17B4, 0x17B5), new Interval(0x17B7, 0x17BD), + new Interval(0x17C6, 0x17C6), new Interval(0x17C9, 0x17D3), new Interval(0x17DD, 0x17DD), + new Interval(0x180B, 0x180D), new Interval(0x18A9, 0x18A9), new Interval(0x1920, 0x1922), + new Interval(0x1927, 0x1928), new Interval(0x1932, 0x1932), new Interval(0x1939, 0x193B), + new Interval(0x1A17, 0x1A18), new Interval(0x1B00, 0x1B03), new Interval(0x1B34, 0x1B34), + new Interval(0x1B36, 0x1B3A), new Interval(0x1B3C, 0x1B3C), new Interval(0x1B42, 0x1B42), + new Interval(0x1B6B, 0x1B73), new Interval(0x1DC0, 0x1DCA), new Interval(0x1DFE, 0x1DFF), + new Interval(0x200B, 0x200F), new Interval(0x202A, 0x202E), new Interval(0x2060, 0x2063), + new Interval(0x206A, 0x206F), new Interval(0x20D0, 0x20EF), new Interval(0x302A, 0x302F), + new Interval(0x3099, 0x309A), new Interval(0xA806, 0xA806), new Interval(0xA80B, 0xA80B), + new Interval(0xA825, 0xA826), new Interval(0xFB1E, 0xFB1E), new Interval(0xFE00, 0xFE0F), + new Interval(0xFE20, 0xFE23), new Interval(0xFEFF, 0xFEFF), new Interval(0xFFF9, 0xFFFB), + new Interval(0x10A01, 0x10A03), new Interval(0x10A05, 0x10A06), new Interval(0x10A0C, 0x10A0F), + new Interval(0x10A38, 0x10A3A), new Interval(0x10A3F, 0x10A3F), new Interval(0x1D167, 0x1D169), + new Interval(0x1D173, 0x1D182), new Interval(0x1D185, 0x1D18B), new Interval(0x1D1AA, 0x1D1AD), + new Interval(0x1D242, 0x1D244), new Interval(0x1F3FB, 0x1F3FF), new Interval(0xE0001, 0xE0001), + new Interval(0xE0020, 0xE007F), new Interval(0xE0100, 0xE01EF) }; private static class Interval { @@ -143,20 +140,14 @@ private static boolean bisearch(int ucs, Interval[] table, int max) { int min = 0; int mid; - if (ucs < table[0].first || ucs > table[max].last) - return false; + if (ucs < table[0].first || ucs > table[max].last) return false; while (max >= min) { mid = (min + max) / 2; - if (ucs > table[mid].last) - min = mid + 1; - else if (ucs < table[mid].first) - max = mid - 1; - else - return true; + if (ucs > table[mid].last) min = mid + 1; + else if (ucs < table[mid].first) max = mid - 1; + else return true; } return false; } - - } diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/WriterOutputStream.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/WriterOutputStream.java index 3ad63a8f381..b1285f9636e 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/WriterOutputStream.java +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/WriterOutputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2017, the original author or authors. + * Copyright (c) 2002-2017, the original author(s). * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. @@ -35,9 +35,11 @@ public class WriterOutputStream extends OutputStream { private final CharBuffer decoderOut = CharBuffer.allocate(128); public WriterOutputStream(Writer out, Charset charset) { - this(out, charset.newDecoder() - .onMalformedInput(CodingErrorAction.REPLACE) - .onUnmappableCharacter(CodingErrorAction.REPLACE)); + this( + out, + charset.newDecoder() + .onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE)); } public WriterOutputStream(Writer out, CharsetDecoder decoder) { @@ -47,7 +49,7 @@ public WriterOutputStream(Writer out, CharsetDecoder decoder) { @Override public void write(int b) throws IOException { - write(new byte[] { (byte)b }, 0, 1); + write(new byte[] {(byte) b}, 0, 1); } @Override diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/windows-conemu.caps b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/windows-conemu.caps index 719bcf86202..f5caa4402bc 100644 --- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/windows-conemu.caps +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/windows-conemu.caps @@ -5,6 +5,9 @@ windows-conemu|conemu windows terminal, cr=^M, cub=\E[%p1%dD, cub1=\E[D, cud=\E[%p1%dB, cud1=\E[B, cuf=\E[%p1%dC, cuf1=\E[C, cup=\E[%i%p1%d;%p2%dH, cuu=\E[%p1%dA, cuu1=\E[A, + civis=\E[?25l, cvvis=\E[?25h, + smcup=\E[?1049h, rmcup=\E[?1049l, + rc=\E8, sc=\E7, il=\E[%p1%dL, il1=\E[L, dl=\E[%p1%dM, dl1=\E[M, ech=\E[%p1%dX, diff --git a/src/jdk.internal.le/share/legal/jline.md b/src/jdk.internal.le/share/legal/jline.md index 6840c69cfc0..5b813c0af2f 100644 --- a/src/jdk.internal.le/share/legal/jline.md +++ b/src/jdk.internal.le/share/legal/jline.md @@ -1,9 +1,9 @@ -## JLine v3.22.0 +## JLine v3.26.1 ### JLine License
 
-Copyright (c) 2002-2018, the original author or authors.
+Copyright (c) 2002-2023, the original author or authors.
 All rights reserved.
 
 https://opensource.org/licenses/BSD-3-Clause
diff --git a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/JnaTerminalProvider.java b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/JnaTerminalProvider.java
index b820ce2187e..4137643c7ac 100644
--- a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/JnaTerminalProvider.java
+++ b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/JnaTerminalProvider.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2020, the original author or authors.
+ * Copyright (c) 2002-2020, the original author(s).
  *
  * This software is distributable under the BSD license. See the terms of the
  * BSD license in the documentation provided with this software.
@@ -8,99 +8,146 @@
  */
 package jdk.internal.org.jline.terminal.impl.jna;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.charset.Charset;
+import java.util.function.Function;
+
 import jdk.internal.org.jline.terminal.Attributes;
 import jdk.internal.org.jline.terminal.Size;
 import jdk.internal.org.jline.terminal.Terminal;
-import jdk.internal.org.jline.terminal.impl.PosixPtyTerminal;
-import jdk.internal.org.jline.terminal.impl.PosixSysTerminal;
+import jdk.internal.org.jline.terminal.TerminalBuilder;
+//import jdk.internal.org.jline.terminal.impl.PosixPtyTerminal;
+//import jdk.internal.org.jline.terminal.impl.PosixSysTerminal;
 import jdk.internal.org.jline.terminal.impl.jna.win.JnaWinSysTerminal;
-import jdk.internal.org.jline.terminal.spi.TerminalProvider;
 import jdk.internal.org.jline.terminal.spi.Pty;
+import jdk.internal.org.jline.terminal.spi.SystemStream;
+import jdk.internal.org.jline.terminal.spi.TerminalProvider;
 import jdk.internal.org.jline.utils.OSUtils;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.charset.Charset;
-import java.util.function.Function;
+public class JnaTerminalProvider implements TerminalProvider {
+
+    public JnaTerminalProvider() {
+        checkSystemStream(SystemStream.Output);
+    }
 
-public class JnaTerminalProvider implements TerminalProvider
-{
     @Override
     public String name() {
-        return "jna";
+        return TerminalBuilder.PROP_PROVIDER_JNA;
     }
 
-//    public Pty current(TerminalProvider.Stream console) throws IOException {
-//        return JnaNativePty.current(console);
+//    public Pty current(SystemStream systemStream) throws IOException {
+//        return JnaNativePty.current(this, systemStream);
 //    }
 //
 //    public Pty open(Attributes attributes, Size size) throws IOException {
-//        return JnaNativePty.open(attributes, size);
+//        return JnaNativePty.open(this, attributes, size);
 //    }
 
     @Override
-    public Terminal sysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding,
-                                boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused,
-                                Stream consoleStream, Function inputStreamWrapper) throws IOException {
+    public Terminal sysTerminal(
+            String name,
+            String type,
+            boolean ansiPassThrough,
+            Charset encoding,
+            boolean nativeSignals,
+            Terminal.SignalHandler signalHandler,
+            boolean paused,
+            SystemStream systemStream,
+            Function inputStreamWrapper)
+            throws IOException {
         if (OSUtils.IS_WINDOWS) {
-            return winSysTerminal(name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, consoleStream, inputStreamWrapper );
+            return winSysTerminal(name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, systemStream, inputStreamWrapper );
         } else {
             return null;
         }
     }
 
-    public Terminal winSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding,
-                                   boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused,
-                                   Stream console, Function inputStreamWrapper) throws IOException {
-        return JnaWinSysTerminal.createTerminal(name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, console, inputStreamWrapper);
+    public Terminal winSysTerminal(
+            String name,
+            String type,
+            boolean ansiPassThrough,
+            Charset encoding,
+            boolean nativeSignals,
+            Terminal.SignalHandler signalHandler,
+            boolean paused,
+            SystemStream systemStream,
+            Function inputStreamWrapper)
+            throws IOException {
+        return JnaWinSysTerminal.createTerminal(
+                this, systemStream, name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, inputStreamWrapper);
     }
 
-//    public Terminal posixSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding,
-//                                     boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused,
-//                                     Stream consoleStream) throws IOException {
-//        Pty pty = current(consoleStream);
+//    public Terminal posixSysTerminal(
+//            String name,
+//            String type,
+//            boolean ansiPassThrough,
+//            Charset encoding,
+//            boolean nativeSignals,
+//            Terminal.SignalHandler signalHandler,
+//            boolean paused,
+//            SystemStream systemStream)
+//            throws IOException {
+//        Pty pty = current(systemStream);
 //        return new PosixSysTerminal(name, type, pty, encoding, nativeSignals, signalHandler);
 //    }
 
     @Override
-    public Terminal newTerminal(String name, String type, InputStream in, OutputStream out,
-                                Charset encoding, Terminal.SignalHandler signalHandler, boolean paused,
-                                Attributes attributes, Size size) throws IOException
-    {
+    public Terminal newTerminal(
+            String name,
+            String type,
+            InputStream in,
+            OutputStream out,
+            Charset encoding,
+            Terminal.SignalHandler signalHandler,
+            boolean paused,
+            Attributes attributes,
+            Size size)
+            throws IOException {
 //        Pty pty = open(attributes, size);
 //        return new PosixPtyTerminal(name, type, pty, in, out, encoding, signalHandler, paused);
         return null;
     }
 
     @Override
-    public boolean isSystemStream(Stream stream) {
+    public boolean isSystemStream(SystemStream stream) {
         try {
-            if (OSUtils.IS_WINDOWS) {
-                return isWindowsSystemStream(stream);
-            } else {
-//                return isPosixSystemStream(stream);
-                return false;
-            }
+            return checkSystemStream(stream);
         } catch (Throwable t) {
             return false;
         }
     }
 
-    public boolean isWindowsSystemStream(Stream stream) {
-        return JnaWinSysTerminal.isWindowsSystemStream(stream);
+    private boolean checkSystemStream(SystemStream stream) {
+        if (OSUtils.IS_WINDOWS) {
+            return JnaWinSysTerminal.isWindowsSystemStream(stream);
+        } else {
+//            return JnaNativePty.isPosixSystemStream(stream);
+            return false;
+        }
     }
 
-//    public boolean isPosixSystemStream(Stream stream) {
-//        return JnaNativePty.isPosixSystemStream(stream);
-//    }
-
     @Override
-    public String systemStreamName(Stream stream) {
+    public String systemStreamName(SystemStream stream) {
 //        if (OSUtils.IS_WINDOWS) {
             return null;
 //        } else {
 //            return JnaNativePty.posixSystemStreamName(stream);
 //        }
     }
+
+//    @Override
+//    public int systemStreamWidth(SystemStream stream) {
+//        try (Pty pty = current(stream)) {
+//            return pty.getSize().getColumns();
+//        } catch (Throwable t) {
+//            return -1;
+//        }
+//    }
+
+    @Override
+    public String toString() {
+        return "TerminalProvider[" + name() + "]";
+    }
 }
diff --git a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinConsoleWriter.java b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinConsoleWriter.java
index a4469003c16..8dad17d7cc7 100644
--- a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinConsoleWriter.java
+++ b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinConsoleWriter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2017, the original author or authors.
+ * Copyright (c) 2002-2017, the original author(s).
  *
  * This software is distributable under the BSD license. See the terms of the
  * BSD license in the documentation provided with this software.
@@ -8,12 +8,13 @@
  */
 package jdk.internal.org.jline.terminal.impl.jna.win;
 
+import java.io.IOException;
+
+import jdk.internal.org.jline.terminal.impl.AbstractWindowsConsoleWriter;
+
 //import com.sun.jna.LastErrorException;
 //import com.sun.jna.Pointer;
 //import com.sun.jna.ptr.IntByReference;
-import jdk.internal.org.jline.terminal.impl.AbstractWindowsConsoleWriter;
-
-import java.io.IOException;
 
 class JnaWinConsoleWriter extends AbstractWindowsConsoleWriter {
 
@@ -32,5 +33,4 @@ protected void writeConsole(char[] text, int len) throws IOException {
             throw new IOException("Failed to write to console", e);
         }
     }
-
 }
diff --git a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinSysTerminal.java b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinSysTerminal.java
index 5ffc5d714ed..8afa327120e 100644
--- a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinSysTerminal.java
+++ b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/JnaWinSysTerminal.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2020, the original author or authors.
+ * Copyright (c) 2002-2020, the original author(s).
  *
  * This software is distributable under the BSD license. See the terms of the
  * BSD license in the documentation provided with this software.
@@ -16,25 +16,43 @@
 import java.util.function.Function;
 import java.util.function.IntConsumer;
 
-//import com.sun.jna.LastErrorException;
-//import com.sun.jna.Pointer;
-//import com.sun.jna.ptr.IntByReference;
 import jdk.internal.org.jline.terminal.Cursor;
 import jdk.internal.org.jline.terminal.Size;
 import jdk.internal.org.jline.terminal.impl.AbstractWindowsTerminal;
+import jdk.internal.org.jline.terminal.spi.SystemStream;
 import jdk.internal.org.jline.terminal.spi.TerminalProvider;
+import jdk.internal.org.jline.utils.InfoCmp.Capability;
 import jdk.internal.org.jline.utils.InfoCmp;
 import jdk.internal.org.jline.utils.OSUtils;
 
-public class JnaWinSysTerminal extends AbstractWindowsTerminal {
+//import com.sun.jna.LastErrorException;
+//import com.sun.jna.Pointer;
+//import com.sun.jna.ptr.IntByReference;
+
+public class JnaWinSysTerminal extends AbstractWindowsTerminal {
 
     private static final Pointer consoleIn = Kernel32.INSTANCE.GetStdHandle(Kernel32.STD_INPUT_HANDLE);
     private static final Pointer consoleOut = Kernel32.INSTANCE.GetStdHandle(Kernel32.STD_OUTPUT_HANDLE);
     private static final Pointer consoleErr = Kernel32.INSTANCE.GetStdHandle(Kernel32.STD_ERROR_HANDLE);
 
-    public static JnaWinSysTerminal createTerminal(String name, String type, boolean ansiPassThrough, Charset encoding, boolean nativeSignals, SignalHandler signalHandler, boolean paused, TerminalProvider.Stream consoleStream, Function inputStreamWrapper) throws IOException {
+    public static JnaWinSysTerminal createTerminal(
+            TerminalProvider provider,
+            SystemStream systemStream,
+            String name,
+            String type,
+            boolean ansiPassThrough,
+            Charset encoding,
+            boolean nativeSignals,
+            SignalHandler signalHandler,
+            boolean paused,
+            Function inputStreamWrapper)
+            throws IOException {
+        // Get input console mode
+        IntByReference inMode = new IntByReference();
+        Kernel32.INSTANCE.GetConsoleMode(JnaWinSysTerminal.consoleIn, inMode);
+        // Get output console and mode
         Pointer console;
-        switch (consoleStream) {
+        switch (systemStream) {
             case Output:
                 console = JnaWinSysTerminal.consoleOut;
                 break;
@@ -42,38 +60,42 @@ public static JnaWinSysTerminal createTerminal(String name, String type, boolean
                 console = JnaWinSysTerminal.consoleErr;
                 break;
             default:
-                throw new IllegalArgumentException("Unsupport stream for console: " + consoleStream);
+                throw new IllegalArgumentException("Unsupported stream for console: " + systemStream);
         }
+        IntByReference outMode = new IntByReference();
+        Kernel32.INSTANCE.GetConsoleMode(console, outMode);
+        // Create writer
         Writer writer;
         if (ansiPassThrough) {
-            if (type == null) {
-                type = OSUtils.IS_CONEMU ? TYPE_WINDOWS_CONEMU : TYPE_WINDOWS;
-            }
+            type = type != null ? type : OSUtils.IS_CONEMU ? TYPE_WINDOWS_CONEMU : TYPE_WINDOWS;
             writer = new JnaWinConsoleWriter(console);
         } else {
-            IntByReference mode = new IntByReference();
-            Kernel32.INSTANCE.GetConsoleMode(console, mode);
-            try {
-                Kernel32.INSTANCE.SetConsoleMode(console, mode.getValue() | AbstractWindowsTerminal.ENABLE_VIRTUAL_TERMINAL_PROCESSING);
-                if (type == null) {
-                    type = TYPE_WINDOWS_VTP;
-                }
+            if (enableVtp(console, outMode.getValue())) {
+                type = type != null ? type : TYPE_WINDOWS_VTP;
                 writer = new JnaWinConsoleWriter(console);
-            } catch (LastErrorException e) {
-                if (OSUtils.IS_CONEMU) {
-                    if (type == null) {
-                        type = TYPE_WINDOWS_CONEMU;
-                    }
-                    writer = new JnaWinConsoleWriter(console);
-                } else {
-                    if (type == null) {
-                        type = TYPE_WINDOWS;
-                    }
-                    writer = new WindowsAnsiWriter(new BufferedWriter(new JnaWinConsoleWriter(console)), console);
-                }
+            } else if (OSUtils.IS_CONEMU) {
+                type = type != null ? type : TYPE_WINDOWS_CONEMU;
+                writer = new JnaWinConsoleWriter(console);
+            } else {
+                type = type != null ? type : TYPE_WINDOWS;
+                writer = new WindowsAnsiWriter(new BufferedWriter(new JnaWinConsoleWriter(console)), console);
             }
         }
-        JnaWinSysTerminal terminal = new JnaWinSysTerminal(writer, name, type, encoding, nativeSignals, signalHandler, inputStreamWrapper);
+        // Create terminal
+        JnaWinSysTerminal terminal = new JnaWinSysTerminal(
+                provider,
+                systemStream,
+                writer,
+                name,
+                type,
+                encoding,
+                nativeSignals,
+                signalHandler,
+                JnaWinSysTerminal.consoleIn,
+                inMode.getValue(),
+                console,
+                outMode.getValue(),
+                inputStreamWrapper);
         // Start input pump thread
         if (!paused) {
             terminal.resume();
@@ -81,15 +103,32 @@ public static JnaWinSysTerminal createTerminal(String name, String type, boolean
         return terminal;
     }
 
-    public static boolean isWindowsSystemStream(TerminalProvider.Stream stream) {
+    private static boolean enableVtp(Pointer console, int outMode) {
+        try {
+            Kernel32.INSTANCE.SetConsoleMode(
+                    console, outMode | AbstractWindowsTerminal.ENABLE_VIRTUAL_TERMINAL_PROCESSING);
+            return true;
+        } catch (LastErrorException e) {
+            return false;
+        }
+    }
+
+    public static boolean isWindowsSystemStream(SystemStream stream) {
         try {
             IntByReference mode = new IntByReference();
             Pointer console;
             switch (stream) {
-                case Input: console = consoleIn; break;
-                case Output: console = consoleOut; break;
-                case Error: console = consoleErr; break;
-                default: return false;
+                case Input:
+                    console = consoleIn;
+                    break;
+                case Output:
+                    console = consoleOut;
+                    break;
+                case Error:
+                    console = consoleErr;
+                    break;
+                default:
+                    return false;
             }
             Kernel32.INSTANCE.GetConsoleMode(console, mode);
             return true;
@@ -98,27 +137,53 @@ public static boolean isWindowsSystemStream(TerminalProvider.Stream stream) {
         }
     }
 
-    JnaWinSysTerminal(Writer writer, String name, String type, Charset encoding, boolean nativeSignals, SignalHandler signalHandler,
-            Function inputStreamWrapper) throws IOException {
-        super(writer, name, type, encoding, nativeSignals, signalHandler, inputStreamWrapper);
-        strings.put(InfoCmp.Capability.key_mouse, "\\E[M");
+    JnaWinSysTerminal(
+            TerminalProvider provider,
+            SystemStream systemStream,
+            Writer writer,
+            String name,
+            String type,
+            Charset encoding,
+            boolean nativeSignals,
+            SignalHandler signalHandler,
+            Pointer inConsole,
+            int inConsoleMode,
+            Pointer outConsole,
+            int outConsoleMode,
+            Function inputStreamWrapper)
+            throws IOException {
+        super(
+                provider,
+                systemStream,
+                writer,
+                name,
+                type,
+                encoding,
+                nativeSignals,
+                signalHandler,
+                inConsole,
+                inConsoleMode,
+                outConsole,
+                outConsoleMode,
+                inputStreamWrapper);
+        this.strings.put(Capability.key_mouse, "\\E[M");
     }
 
     @Override
-    protected int getConsoleMode() {
+    protected int getConsoleMode(Pointer console) {
         IntByReference mode = new IntByReference();
-        Kernel32.INSTANCE.GetConsoleMode(consoleIn, mode);
+        Kernel32.INSTANCE.GetConsoleMode(console, mode);
         return mode.getValue();
     }
 
     @Override
-    protected void setConsoleMode(int mode) {
-        Kernel32.INSTANCE.SetConsoleMode(consoleIn, mode);
+    protected void setConsoleMode(Pointer console, int mode) {
+        Kernel32.INSTANCE.SetConsoleMode(console, mode);
     }
 
     public Size getSize() {
         Kernel32.CONSOLE_SCREEN_BUFFER_INFO info = new Kernel32.CONSOLE_SCREEN_BUFFER_INFO();
-        Kernel32.INSTANCE.GetConsoleScreenBufferInfo(consoleOut, info);
+        Kernel32.INSTANCE.GetConsoleScreenBufferInfo(outConsole, info);
         return new Size(info.windowWidth(), info.windowHeight());
     }
 
@@ -154,10 +219,11 @@ protected boolean processConsoleInput() throws IOException {
     }
 
     private void processKeyEvent(Kernel32.KEY_EVENT_RECORD keyEvent) throws IOException {
-        processKeyEvent(keyEvent.bKeyDown, keyEvent.wVirtualKeyCode, keyEvent.uChar.UnicodeChar, keyEvent.dwControlKeyState);
+        processKeyEvent(
+                keyEvent.bKeyDown, keyEvent.wVirtualKeyCode, keyEvent.uChar.UnicodeChar, keyEvent.dwControlKeyState);
     }
 
-    private char[] focus = new char[] { '\033', '[', ' ' };
+    private char[] focus = new char[] {'\033', '[', ' '};
 
     private void processFocusEvent(boolean hasFocus) throws IOException {
         if (focusTracking) {
@@ -166,7 +232,7 @@ private void processFocusEvent(boolean hasFocus) throws IOException {
         }
     }
 
-    private char[] mouse = new char[] { '\033', '[', 'M', ' ', ' ', ' ' };
+    private char[] mouse = new char[] {'\033', '[', 'M', ' ', ' ', ' '};
 
     private void processMouseEvent(Kernel32.MOUSE_EVENT_RECORD mouseEvent) throws IOException {
         int dwEventFlags = mouseEvent.dwEventFlags;
@@ -177,7 +243,7 @@ private void processMouseEvent(Kernel32.MOUSE_EVENT_RECORD mouseEvent) throws IO
             return;
         }
         int cb = 0;
-        dwEventFlags &= ~ Kernel32.DOUBLE_CLICK; // Treat double-clicks as normal
+        dwEventFlags &= ~Kernel32.DOUBLE_CLICK; // Treat double-clicks as normal
         if (dwEventFlags == Kernel32.MOUSE_WHEELED) {
             cb |= 64;
             if ((dwButtonState >> 16) < 0) {
@@ -223,5 +289,4 @@ public Cursor getCursorPosition(IntConsumer discarded) {
         Kernel32.INSTANCE.GetConsoleScreenBufferInfo(consoleOut, info);
         return new Cursor(info.dwCursorPosition.X, info.dwCursorPosition.Y);
     }
-
 }
diff --git a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/Kernel32.java b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/Kernel32.java
index 6f350501ad4..d3e20364a8a 100644
--- a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/Kernel32.java
+++ b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/Kernel32.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2018, the original author or authors.
+ * Copyright (c) 2002-2018, the original author(s).
  *
  * This software is distributable under the BSD license. See the terms of the
  * BSD license in the documentation provided with this software.
@@ -30,46 +30,46 @@ interface Kernel32 {//extends StdCallLibrary {
 
 //    Pointer INVALID_HANDLE_VALUE = Pointer.createConstant(-1L);
 
-    int STD_INPUT_HANDLE =  -10;
+    int STD_INPUT_HANDLE = -10;
     int STD_OUTPUT_HANDLE = -11;
-    int STD_ERROR_HANDLE =  -12;
-
-    int ENABLE_PROCESSED_INPUT =    0x0001;
-    int ENABLE_LINE_INPUT =         0x0002;
-    int ENABLE_ECHO_INPUT =         0x0004;
-    int ENABLE_WINDOW_INPUT =       0x0008;
-    int ENABLE_MOUSE_INPUT =        0x0010;
-    int ENABLE_INSERT_MODE =        0x0020;
-    int ENABLE_QUICK_EDIT_MODE =    0x0040;
-    int ENABLE_EXTENDED_FLAGS =     0x0080;
-
-    int RIGHT_ALT_PRESSED =     0x0001;
-    int LEFT_ALT_PRESSED =      0x0002;
-    int RIGHT_CTRL_PRESSED =    0x0004;
-    int LEFT_CTRL_PRESSED =     0x0008;
-    int SHIFT_PRESSED =         0x0010;
-
-    int FOREGROUND_BLUE =       0x0001;
-    int FOREGROUND_GREEN =      0x0002;
-    int FOREGROUND_RED =        0x0004;
-    int FOREGROUND_INTENSITY =  0x0008;
-    int BACKGROUND_BLUE =       0x0010;
-    int BACKGROUND_GREEN =      0x0020;
-    int BACKGROUND_RED =        0x0040;
-    int BACKGROUND_INTENSITY =  0x0080;
+    int STD_ERROR_HANDLE = -12;
+
+    int ENABLE_PROCESSED_INPUT = 0x0001;
+    int ENABLE_LINE_INPUT = 0x0002;
+    int ENABLE_ECHO_INPUT = 0x0004;
+    int ENABLE_WINDOW_INPUT = 0x0008;
+    int ENABLE_MOUSE_INPUT = 0x0010;
+    int ENABLE_INSERT_MODE = 0x0020;
+    int ENABLE_QUICK_EDIT_MODE = 0x0040;
+    int ENABLE_EXTENDED_FLAGS = 0x0080;
+
+    int RIGHT_ALT_PRESSED = 0x0001;
+    int LEFT_ALT_PRESSED = 0x0002;
+    int RIGHT_CTRL_PRESSED = 0x0004;
+    int LEFT_CTRL_PRESSED = 0x0008;
+    int SHIFT_PRESSED = 0x0010;
+
+    int FOREGROUND_BLUE = 0x0001;
+    int FOREGROUND_GREEN = 0x0002;
+    int FOREGROUND_RED = 0x0004;
+    int FOREGROUND_INTENSITY = 0x0008;
+    int BACKGROUND_BLUE = 0x0010;
+    int BACKGROUND_GREEN = 0x0020;
+    int BACKGROUND_RED = 0x0040;
+    int BACKGROUND_INTENSITY = 0x0080;
 
     // Button state
     int FROM_LEFT_1ST_BUTTON_PRESSED = 0x0001;
-    int RIGHTMOST_BUTTON_PRESSED     = 0x0002;
+    int RIGHTMOST_BUTTON_PRESSED = 0x0002;
     int FROM_LEFT_2ND_BUTTON_PRESSED = 0x0004;
     int FROM_LEFT_3RD_BUTTON_PRESSED = 0x0008;
     int FROM_LEFT_4TH_BUTTON_PRESSED = 0x0010;
 
     // Event flags
-    int MOUSE_MOVED                  = 0x0001;
-    int DOUBLE_CLICK                 = 0x0002;
-    int MOUSE_WHEELED                = 0x0004;
-    int MOUSE_HWHEELED               = 0x0008;
+    int MOUSE_MOVED = 0x0001;
+    int DOUBLE_CLICK = 0x0002;
+    int MOUSE_WHEELED = 0x0004;
+    int MOUSE_HWHEELED = 0x0008;
 
     // DWORD WINAPI WaitForSingleObject(
     //  _In_ HANDLE hHandle,
@@ -94,18 +94,18 @@ interface Kernel32 {//extends StdCallLibrary {
 //    // UINT WINAPI GetConsoleCP(void)
 //    int GetConsoleCP();
 //
-    // UINT WINAPI GetConsoleOutputCP(void)
-    int GetConsoleOutputCP();
-
     // BOOL WINAPI FillConsoleOutputCharacter(
     // _In_ HANDLE hConsoleOutput,
     // _In_ TCHAR cCharacter,
     // _In_ DWORD nLength,
     // _In_ COORD dwWriteCoord,
     // _Out_ LPDWORD lpNumberOfCharsWritten);
-    void FillConsoleOutputCharacter(Pointer in_hConsoleOutput,
-                                    char in_cCharacter, int in_nLength, COORD in_dwWriteCoord,
-                                    IntByReference out_lpNumberOfCharsWritten)
+    void FillConsoleOutputCharacter(
+            Pointer in_hConsoleOutput,
+            char in_cCharacter,
+            int in_nLength,
+            COORD in_dwWriteCoord,
+            IntByReference out_lpNumberOfCharsWritten)
             throws LastErrorException;
 
     // BOOL WINAPI FillConsoleOutputAttribute(
@@ -114,56 +114,53 @@ void FillConsoleOutputCharacter(Pointer in_hConsoleOutput,
     // _In_ DWORD nLength,
     // _In_ COORD dwWriteCoord,
     // _Out_ LPDWORD lpNumberOfAttrsWritten);
-    void FillConsoleOutputAttribute(Pointer in_hConsoleOutput,
-                                    short in_wAttribute, int in_nLength, COORD in_dwWriteCoord,
-                                    IntByReference out_lpNumberOfAttrsWritten)
+    void FillConsoleOutputAttribute(
+            Pointer in_hConsoleOutput,
+            short in_wAttribute,
+            int in_nLength,
+            COORD in_dwWriteCoord,
+            IntByReference out_lpNumberOfAttrsWritten)
             throws LastErrorException;
-//
-////    // BOOL WINAPI GetConsoleCursorInfo(
-////    // _In_ HANDLE hConsoleOutput,
-////    // _Out_ PCONSOLE_CURSOR_INFO lpConsoleCursorInfo);
-////    void GetConsoleCursorInfo(Pointer in_hConsoleOutput,
-////                              CONSOLE_CURSOR_INFO.ByReference out_lpConsoleCursorInfo)
-////            throws LastErrorException;
-//
+
+//    // BOOL WINAPI GetConsoleCursorInfo(
+//    // _In_ HANDLE hConsoleOutput,
+//    // _Out_ PCONSOLE_CURSOR_INFO lpConsoleCursorInfo);
+//    void GetConsoleCursorInfo(Pointer in_hConsoleOutput, CONSOLE_CURSOR_INFO.ByReference out_lpConsoleCursorInfo)
+//            throws LastErrorException;
+
     // BOOL WINAPI GetConsoleMode(
     //   _In_   HANDLE hConsoleHandle,
     //   _Out_  LPDWORD lpMode);
-    void GetConsoleMode(
-            Pointer in_hConsoleOutput,
-            IntByReference out_lpMode)
-            throws LastErrorException;
+    void GetConsoleMode(Pointer in_hConsoleOutput, IntByReference out_lpMode) throws LastErrorException;
 
     // BOOL WINAPI GetConsoleScreenBufferInfo(
     // _In_   HANDLE hConsoleOutput,
     // _Out_  PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo);
-    void GetConsoleScreenBufferInfo(
-            Pointer in_hConsoleOutput,
-            CONSOLE_SCREEN_BUFFER_INFO out_lpConsoleScreenBufferInfo)
+    void GetConsoleScreenBufferInfo(Pointer in_hConsoleOutput, CONSOLE_SCREEN_BUFFER_INFO out_lpConsoleScreenBufferInfo)
             throws LastErrorException;
 //
 //    // BOOL WINAPI GetNumberOfConsoleInputEvents(
 //    // _In_ HANDLE hConsoleInput,
 //    // _Out_ LPDWORD lpcNumberOfEvents);
-//    void GetNumberOfConsoleInputEvents(Pointer in_hConsoleOutput,
-//                                       IntByReference out_lpcNumberOfEvents) throws LastErrorException;
+//    void GetNumberOfConsoleInputEvents(Pointer in_hConsoleOutput, IntByReference out_lpcNumberOfEvents)
+//            throws LastErrorException;
 //
     // BOOL WINAPI ReadConsoleInput(
     // _In_ HANDLE hConsoleInput,
     // _Out_ PINPUT_RECORD lpBuffer,
     // _In_ DWORD nLength,
     // _Out_ LPDWORD lpNumberOfEventsRead);
-    void ReadConsoleInput(Pointer in_hConsoleOutput,
-                          INPUT_RECORD[] out_lpBuffer, int in_nLength,
-                          IntByReference out_lpNumberOfEventsRead) throws LastErrorException;
+    void ReadConsoleInput(
+            Pointer in_hConsoleOutput,
+            INPUT_RECORD[] out_lpBuffer,
+            int in_nLength,
+            IntByReference out_lpNumberOfEventsRead)
+            throws LastErrorException;
 
 //    // BOOL WINAPI SetConsoleCtrlHandler(
 //    // _In_opt_  PHANDLER_ROUTINE HandlerRoutine,
 //    // _In_      BOOL Add);
-//    void SetConsoleCtrlHandler(
-//            Pointer in_opt_HandlerRoutine,
-//            boolean in_Add)
-//            throws LastErrorException;
+//    void SetConsoleCtrlHandler(Pointer in_opt_HandlerRoutine, boolean in_Add) throws LastErrorException;
 //
 //    // BOOL WINAPI ReadConsoleOutput(
 //    // _In_     HANDLE hConsoleOutput,
@@ -171,12 +168,21 @@ void ReadConsoleInput(Pointer in_hConsoleOutput,
 //    // _In_     COORD dwBufferSize,
 //    // _In_     COORD dwBufferCoord,
 //    // _Inout_  PSMALL_RECT lpReadRegion);
-////    void ReadConsoleOutput(Pointer in_hConsoleOutput, CHAR_INFO[] out_lpBuffer,
-////                           COORD in_dwBufferSize, COORD in_dwBufferCoord,
-////                           SMALL_RECT inout_lpReadRegion) throws LastErrorException;
-////    void ReadConsoleOutputA(Pointer in_hConsoleOutput, CHAR_INFO[] out_lpBuffer,
-////                            COORD in_dwBufferSize, COORD in_dwBufferCoord,
-////                            SMALL_RECT inout_lpReadRegion) throws LastErrorException;
+//    void ReadConsoleOutput(
+//            Pointer in_hConsoleOutput,
+//            CHAR_INFO[] out_lpBuffer,
+//            COORD in_dwBufferSize,
+//            COORD in_dwBufferCoord,
+//            SMALL_RECT inout_lpReadRegion)
+//            throws LastErrorException;
+//
+//    void ReadConsoleOutputA(
+//            Pointer in_hConsoleOutput,
+//            CHAR_INFO[] out_lpBuffer,
+//            COORD in_dwBufferSize,
+//            COORD in_dwBufferCoord,
+//            SMALL_RECT inout_lpReadRegion)
+//            throws LastErrorException;
 //
 //    // BOOL WINAPI ReadConsoleOutputCharacter(
 //    // _In_   HANDLE hConsoleOutput,
@@ -184,20 +190,26 @@ void ReadConsoleInput(Pointer in_hConsoleOutput,
 //    // _In_   DWORD nLength,
 //    // _In_   COORD dwReadCoord,
 //    // _Out_  LPDWORD lpNumberOfCharsRead);
-//    void ReadConsoleOutputCharacter(Pointer in_hConsoleOutput,
-//                                    char[] ouy_lpCharacter, int in_nLength, COORD in_dwReadCoord,
-//                                    IntByReference out_lpNumberOfCharsRead)
+//    void ReadConsoleOutputCharacter(
+//            Pointer in_hConsoleOutput,
+//            char[] ouy_lpCharacter,
+//            int in_nLength,
+//            COORD in_dwReadCoord,
+//            IntByReference out_lpNumberOfCharsRead)
 //            throws LastErrorException;
-//    void ReadConsoleOutputCharacterA(Pointer in_hConsoleOutput,
-//                                     byte[] ouy_lpCharacter, int in_nLength, COORD in_dwReadCoord,
-//                                     IntByReference out_lpNumberOfCharsRead)
+//
+//    void ReadConsoleOutputCharacterA(
+//            Pointer in_hConsoleOutput,
+//            byte[] ouy_lpCharacter,
+//            int in_nLength,
+//            COORD in_dwReadCoord,
+//            IntByReference out_lpNumberOfCharsRead)
 //            throws LastErrorException;
 //
 //    // BOOL WINAPI SetConsoleCursorInfo(
 //    // _In_ HANDLE hConsoleOutput,
 //    // _In_ const CONSOLE_CURSOR_INFO *lpConsoleCursorInfo);
-//    void SetConsoleCursorInfo(Pointer in_hConsoleOutput,
-//                              CONSOLE_CURSOR_INFO in_lpConsoleCursorInfo)
+//    void SetConsoleCursorInfo(Pointer in_hConsoleOutput, CONSOLE_CURSOR_INFO in_lpConsoleCursorInfo)
 //            throws LastErrorException;
 //
 //    // BOOL WINAPI SetConsoleCP(
@@ -207,47 +219,39 @@ void ReadConsoleInput(Pointer in_hConsoleOutput,
 //    // BOOL WINAPI SetConsoleOutputCP(
 //    // _In_ UINT wCodePageID);
 //    void SetConsoleOutputCP(int in_wCodePageID) throws LastErrorException;
-//
+
     // BOOL WINAPI SetConsoleCursorPosition(
     // _In_ HANDLE hConsoleOutput,
     // _In_ COORD dwCursorPosition);
-    void SetConsoleCursorPosition(Pointer in_hConsoleOutput,
-                                  COORD in_dwCursorPosition) throws LastErrorException;
+    void SetConsoleCursorPosition(Pointer in_hConsoleOutput, COORD in_dwCursorPosition) throws LastErrorException;
 
     // BOOL WINAPI SetConsoleMode(
     //   _In_  HANDLE hConsoleHandle,
     //   _In_  DWORD dwMode);
-    void SetConsoleMode(
-            Pointer in_hConsoleOutput,
-            int in_dwMode) throws LastErrorException;
+    void SetConsoleMode(Pointer in_hConsoleOutput, int in_dwMode) throws LastErrorException;
 
 //    // BOOL WINAPI SetConsoleScreenBufferSize(
 //    // __in HANDLE hConsoleOutput,
 //    // __in COORD dwSize
 //    // );
-//    void SetConsoleScreenBufferSize(Pointer in_hConsoleOutput,
-//                                    COORD in_dwSize) throws LastErrorException;
-//
+//    void SetConsoleScreenBufferSize(Pointer in_hConsoleOutput, COORD in_dwSize) throws LastErrorException;
+
     // BOOL WINAPI SetConsoleTextAttribute(
     // _In_ HANDLE hConsoleOutput,
     // _In_ WORD   wAttributes
     // );
-    void SetConsoleTextAttribute(Pointer in_hConsoleOutput,
-                                 short in_wAttributes)
-            throws LastErrorException;
+    void SetConsoleTextAttribute(Pointer in_hConsoleOutput, short in_wAttributes) throws LastErrorException;
 
     // BOOL WINAPI SetConsoleTitle(
     // _In_ LPCTSTR lpConsoleTitle
     // );
-    void SetConsoleTitle(String in_lpConsoleTitle)
-            throws LastErrorException;
+    void SetConsoleTitle(String in_lpConsoleTitle) throws LastErrorException;
 
 //    // BOOL WINAPI SetConsoleWindowInfo(
 //    // _In_ HANDLE hConsoleOutput,
 //    // _In_ BOOL bAbsolute,
 //    // _In_ const SMALL_RECT *lpConsoleWindow);
-//    void SetConsoleWindowInfo(Pointer in_hConsoleOutput,
-//                              boolean in_bAbsolute, SMALL_RECT in_lpConsoleWindow)
+//    void SetConsoleWindowInfo(Pointer in_hConsoleOutput, boolean in_bAbsolute, SMALL_RECT in_lpConsoleWindow)
 //            throws LastErrorException;
 
     // BOOL WINAPI WriteConsole(
@@ -257,8 +261,13 @@ void SetConsoleTitle(String in_lpConsoleTitle)
     //  _Out_            LPDWORD lpNumberOfCharsWritten,
     //  _Reserved_       LPVOID  lpReserved
     // );
-    void WriteConsoleW(Pointer in_hConsoleOutput, char[] in_lpBuffer, int in_nNumberOfCharsToWrite,
-                          IntByReference out_lpNumberOfCharsWritten, Pointer reserved_lpReserved) throws LastErrorException;
+    void WriteConsoleW(
+            Pointer in_hConsoleOutput,
+            char[] in_lpBuffer,
+            int in_nNumberOfCharsToWrite,
+            IntByReference out_lpNumberOfCharsWritten,
+            Pointer reserved_lpReserved)
+            throws LastErrorException;
 
 //    // BOOL WINAPI WriteConsoleOutput(
 //    // _In_ HANDLE hConsoleOutput,
@@ -266,12 +275,21 @@ void WriteConsoleW(Pointer in_hConsoleOutput, char[] in_lpBuffer, int in_nNumber
 //    // _In_ COORD dwBufferSize,
 //    // _In_ COORD dwBufferCoord,
 //    // _Inout_ PSMALL_RECT lpWriteRegion);
-////    void WriteConsoleOutput(Pointer in_hConsoleOutput, CHAR_INFO[] in_lpBuffer,
-////                            COORD in_dwBufferSize, COORD in_dwBufferCoord,
-////                            SMALL_RECT inout_lpWriteRegion) throws LastErrorException;
-////    void WriteConsoleOutputA(Pointer in_hConsoleOutput, CHAR_INFO[] in_lpBuffer,
-////                             COORD in_dwBufferSize, COORD in_dwBufferCoord,
-////                             SMALL_RECT inout_lpWriteRegion) throws LastErrorException;
+//    void WriteConsoleOutput(
+//            Pointer in_hConsoleOutput,
+//            CHAR_INFO[] in_lpBuffer,
+//            COORD in_dwBufferSize,
+//            COORD in_dwBufferCoord,
+//            SMALL_RECT inout_lpWriteRegion)
+//            throws LastErrorException;
+//
+//    void WriteConsoleOutputA(
+//            Pointer in_hConsoleOutput,
+//            CHAR_INFO[] in_lpBuffer,
+//            COORD in_dwBufferSize,
+//            COORD in_dwBufferCoord,
+//            SMALL_RECT inout_lpWriteRegion)
+//            throws LastErrorException;
 //
 //    // BOOL WINAPI WriteConsoleOutputCharacter(
 //    // _In_ HANDLE hConsoleOutput,
@@ -279,26 +297,34 @@ void WriteConsoleW(Pointer in_hConsoleOutput, char[] in_lpBuffer, int in_nNumber
 //    // _In_ DWORD nLength,
 //    // _In_ COORD dwWriteCoord,
 //    // _Out_ LPDWORD lpNumberOfCharsWritten);
-//    void WriteConsoleOutputCharacter(Pointer in_hConsoleOutput,
-//                                     char[] in_lpCharacter, int in_nLength, COORD in_dwWriteCoord,
-//                                     IntByReference out_lpNumberOfCharsWritten)
-//            throws LastErrorException;
-//    void WriteConsoleOutputCharacterA(Pointer in_hConsoleOutput,
-//                                      byte[] in_lpCharacter, int in_nLength, COORD in_dwWriteCoord,
-//                                      IntByReference out_lpNumberOfCharsWritten)
+//    void WriteConsoleOutputCharacter(
+//            Pointer in_hConsoleOutput,
+//            char[] in_lpCharacter,
+//            int in_nLength,
+//            COORD in_dwWriteCoord,
+//            IntByReference out_lpNumberOfCharsWritten)
 //            throws LastErrorException;
 //
+//    void WriteConsoleOutputCharacterA(
+//            Pointer in_hConsoleOutput,
+//            byte[] in_lpCharacter,
+//            int in_nLength,
+//            COORD in_dwWriteCoord,
+//            IntByReference out_lpNumberOfCharsWritten)
+//            throws LastErrorException;
+
     // BOOL WINAPI ScrollConsoleScreenBuffer(
     //     _In_           HANDLE     hConsoleOutput,
     //     _In_     const SMALL_RECT *lpScrollRectangle,
     //     _In_opt_ const SMALL_RECT *lpClipRectangle,
     //     _In_           COORD      dwDestinationOrigin,
     //     _In_     const CHAR_INFO  *lpFill);
-    void ScrollConsoleScreenBuffer(Pointer in_hConsoleOutput,
-                                   SMALL_RECT in_lpScrollRectangle,
-                                   SMALL_RECT in_lpClipRectangle,
-                                   COORD in_dwDestinationOrigin,
-                                   CHAR_INFO in_lpFill)
+    void ScrollConsoleScreenBuffer(
+            Pointer in_hConsoleOutput,
+            SMALL_RECT in_lpScrollRectangle,
+            SMALL_RECT in_lpClipRectangle,
+            COORD in_dwDestinationOrigin,
+            CHAR_INFO in_lpFill)
             throws LastErrorException;
 
     // typedef struct _CHAR_INFO {
@@ -309,8 +335,7 @@ void ScrollConsoleScreenBuffer(Pointer in_hConsoleOutput,
     //   WORD  Attributes;
     // } CHAR_INFO, *PCHAR_INFO;
     class CHAR_INFO {//extends Structure {
-        public CHAR_INFO() {
-        }
+        public CHAR_INFO() {}
 
         public CHAR_INFO(char c, short attr) {
             uChar = new UnionChar(c);
@@ -329,7 +354,7 @@ public CHAR_INFO(char c, short attr) {
 //            return (CHAR_INFO[]) new CHAR_INFO().toArray(size);
 //        }
 //
-//        private static String[] fieldOrder = { "uChar", "Attributes" };
+//        private static String[] fieldOrder = {"uChar", "Attributes"};
 //
 //        @Override
 //        protected java.util.List getFieldOrder() {
@@ -345,11 +370,9 @@ class CONSOLE_CURSOR_INFO {//extends Structure {
         public int dwSize;
         public boolean bVisible;
 
-//        public static class ByReference extends CONSOLE_CURSOR_INFO implements
-//                Structure.ByReference {
-//        }
+//        public static class ByReference extends CONSOLE_CURSOR_INFO implements Structure.ByReference {}
 //
-//        private static String[] fieldOrder = { "dwSize", "bVisible" };
+//        private static String[] fieldOrder = {"dwSize", "bVisible"};
 //
 //        @Override
 //        protected java.util.List getFieldOrder() {
@@ -365,13 +388,15 @@ class CONSOLE_CURSOR_INFO {//extends Structure {
     //   COORD      dwMaximumWindowSize;
     // } CONSOLE_SCREEN_BUFFER_INFO;
     class CONSOLE_SCREEN_BUFFER_INFO {//extends Structure {
-        public COORD      dwSize;
-        public COORD      dwCursorPosition;
-        public short      wAttributes;
+        public COORD dwSize;
+        public COORD dwCursorPosition;
+        public short wAttributes;
         public SMALL_RECT srWindow;
-        public COORD      dwMaximumWindowSize;
+        public COORD dwMaximumWindowSize;
 
-//        private static String[] fieldOrder = { "dwSize", "dwCursorPosition", "wAttributes", "srWindow", "dwMaximumWindowSize" };
+//        private static String[] fieldOrder = {
+//            "dwSize", "dwCursorPosition", "wAttributes", "srWindow", "dwMaximumWindowSize"
+//        };
 //
 //        @Override
 //        protected java.util.List getFieldOrder() {
@@ -392,8 +417,7 @@ public int windowHeight() {
     //    SHORT Y;
     //  } COORD, *PCOORD;
     class COORD {//extends Structure implements Structure.ByValue {
-        public COORD() {
-        }
+        public COORD() {}
 
         public COORD(short X, short Y) {
             this.X = X;
@@ -403,7 +427,7 @@ public COORD(short X, short Y) {
         public short X;
         public short Y;
 
-//        private static String[] fieldOrder = { "X", "Y" };
+//        private static String[] fieldOrder = {"X", "Y"};
 //
 //        @Override
 //        protected java.util.List getFieldOrder() {
@@ -489,7 +513,9 @@ class KEY_EVENT_RECORD {//extends Structure {
         public UnionChar uChar;
         public int dwControlKeyState;
 
-//        private static String[] fieldOrder = {"bKeyDown", "wRepeatCount", "wVirtualKeyCode", "wVirtualScanCode", "uChar", "dwControlKeyState"};
+//        private static String[] fieldOrder = {
+//            "bKeyDown", "wRepeatCount", "wVirtualKeyCode", "wVirtualScanCode", "uChar", "dwControlKeyState"
+//        };
 //
 //        @Override
 //        protected java.util.List getFieldOrder() {
@@ -509,7 +535,7 @@ class MOUSE_EVENT_RECORD {//extends Structure {
         public int dwControlKeyState;
         public int dwEventFlags;
 
-//        private static String[] fieldOrder = { "dwMousePosition", "dwButtonState", "dwControlKeyState", "dwEventFlags"};
+//        private static String[] fieldOrder = {"dwMousePosition", "dwButtonState", "dwControlKeyState", "dwEventFlags"};
 //
 //        @Override
 //        protected java.util.List getFieldOrder() {
@@ -548,7 +574,7 @@ class MENU_EVENT_RECORD {//extends Structure {
 
     // typedef struct _FOCUS_EVENT_RECORD {
     //  BOOL bSetFocus;
-    //} FOCUS_EVENT_RECORD;
+    // } FOCUS_EVENT_RECORD;
     class FOCUS_EVENT_RECORD {//extends Structure {
         public boolean bSetFocus;
 
@@ -567,8 +593,7 @@ class FOCUS_EVENT_RECORD {//extends Structure {
     //    SHORT Bottom;
     //  } SMALL_RECT;
     class SMALL_RECT {//extends Structure {
-        public SMALL_RECT() {
-        }
+        public SMALL_RECT() {}
 
         public SMALL_RECT(SMALL_RECT org) {
             this(org.Top, org.Left, org.Bottom, org.Right);
@@ -586,7 +611,7 @@ public SMALL_RECT(short Top, short Left, short Bottom, short Right) {
         public short Right;
         public short Bottom;
 
-//        private static String[] fieldOrder = { "Left", "Top", "Right", "Bottom" };
+//        private static String[] fieldOrder = {"Left", "Top", "Right", "Bottom"};
 //
 //        @Override
 //        protected java.util.List getFieldOrder() {
@@ -594,18 +619,16 @@ public SMALL_RECT(short Top, short Left, short Bottom, short Right) {
 //        }
 
         public short width() {
-            return (short)(this.Right - this.Left);
+            return (short) (this.Right - this.Left);
         }
 
         public short height() {
-            return (short)(this.Bottom - this.Top);
+            return (short) (this.Bottom - this.Top);
         }
-
     }
 
     class UnionChar {//extends Union {
-        public UnionChar() {
-        }
+        public UnionChar() {}
 
         public UnionChar(char c) {
 //            setType(char.class);
diff --git a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/Kernel32Impl.java b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/Kernel32Impl.java
index 2008bfacd18..90c19bd91a4 100644
--- a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/Kernel32Impl.java
+++ b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/Kernel32Impl.java
@@ -43,9 +43,6 @@ public class Kernel32Impl implements Kernel32 {
     @Override
     public native Pointer GetStdHandle(int nStdHandle);
 
-    @Override
-    public native int GetConsoleOutputCP();
-
     @Override
     public native void FillConsoleOutputCharacter(Pointer in_hConsoleOutput, char in_cCharacter, int in_nLength, COORD in_dwWriteCoord, IntByReference out_lpNumberOfCharsWritten) throws LastErrorException;
 
diff --git a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/WindowsAnsiWriter.java b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/WindowsAnsiWriter.java
index 7e1b82db805..6d3f217cbcd 100644
--- a/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/WindowsAnsiWriter.java
+++ b/src/jdk.internal.le/windows/classes/jdk/internal/org/jline/terminal/impl/jna/win/WindowsAnsiWriter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2016, the original author or authors.
+ * Copyright (c) 2002-2016, the original author(s).
  *
  * This software is distributable under the BSD license. See the terms of the
  * BSD license in the documentation provided with this software.
@@ -11,11 +11,12 @@
 import java.io.IOException;
 import java.io.Writer;
 
-//import com.sun.jna.Pointer;
-//import com.sun.jna.ptr.IntByReference;
 import jdk.internal.org.jline.utils.AnsiWriter;
 import jdk.internal.org.jline.utils.Colors;
 
+//import com.sun.jna.Pointer;
+//import com.sun.jna.ptr.IntByReference;
+
 import static jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.BACKGROUND_BLUE;
 import static jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.BACKGROUND_GREEN;
 import static jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.BACKGROUND_INTENSITY;
@@ -25,7 +26,6 @@
 import static jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.FOREGROUND_INTENSITY;
 import static jdk.internal.org.jline.terminal.impl.jna.win.Kernel32.FOREGROUND_RED;
 
-
 /**
  * A Windows ANSI escape processor, uses JNA to access native platform
  * API's to change the console attributes.
@@ -36,41 +36,41 @@
  */
 public final class WindowsAnsiWriter extends AnsiWriter {
 
-    private static final short FOREGROUND_BLACK   = 0;
-    private static final short FOREGROUND_YELLOW  = (short) (FOREGROUND_RED|FOREGROUND_GREEN);
-    private static final short FOREGROUND_MAGENTA = (short) (FOREGROUND_BLUE|FOREGROUND_RED);
-    private static final short FOREGROUND_CYAN    = (short) (FOREGROUND_BLUE|FOREGROUND_GREEN);
-    private static final short FOREGROUND_WHITE   = (short) (FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE);
+    private static final short FOREGROUND_BLACK = 0;
+    private static final short FOREGROUND_YELLOW = (short) (FOREGROUND_RED | FOREGROUND_GREEN);
+    private static final short FOREGROUND_MAGENTA = (short) (FOREGROUND_BLUE | FOREGROUND_RED);
+    private static final short FOREGROUND_CYAN = (short) (FOREGROUND_BLUE | FOREGROUND_GREEN);
+    private static final short FOREGROUND_WHITE = (short) (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
 
-    private static final short BACKGROUND_BLACK   = 0;
-    private static final short BACKGROUND_YELLOW  = (short) (BACKGROUND_RED|BACKGROUND_GREEN);
-    private static final short BACKGROUND_MAGENTA = (short) (BACKGROUND_BLUE|BACKGROUND_RED);
-    private static final short BACKGROUND_CYAN    = (short) (BACKGROUND_BLUE|BACKGROUND_GREEN);
-    private static final short BACKGROUND_WHITE   = (short) (BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE);
+    private static final short BACKGROUND_BLACK = 0;
+    private static final short BACKGROUND_YELLOW = (short) (BACKGROUND_RED | BACKGROUND_GREEN);
+    private static final short BACKGROUND_MAGENTA = (short) (BACKGROUND_BLUE | BACKGROUND_RED);
+    private static final short BACKGROUND_CYAN = (short) (BACKGROUND_BLUE | BACKGROUND_GREEN);
+    private static final short BACKGROUND_WHITE = (short) (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE);
 
     private static final short ANSI_FOREGROUND_COLOR_MAP[] = {
-            FOREGROUND_BLACK,
-            FOREGROUND_RED,
-            FOREGROUND_GREEN,
-            FOREGROUND_YELLOW,
-            FOREGROUND_BLUE,
-            FOREGROUND_MAGENTA,
-            FOREGROUND_CYAN,
-            FOREGROUND_WHITE,
+        FOREGROUND_BLACK,
+        FOREGROUND_RED,
+        FOREGROUND_GREEN,
+        FOREGROUND_YELLOW,
+        FOREGROUND_BLUE,
+        FOREGROUND_MAGENTA,
+        FOREGROUND_CYAN,
+        FOREGROUND_WHITE,
     };
 
     private static final short ANSI_BACKGROUND_COLOR_MAP[] = {
-            BACKGROUND_BLACK,
-            BACKGROUND_RED,
-            BACKGROUND_GREEN,
-            BACKGROUND_YELLOW,
-            BACKGROUND_BLUE,
-            BACKGROUND_MAGENTA,
-            BACKGROUND_CYAN,
-            BACKGROUND_WHITE,
+        BACKGROUND_BLACK,
+        BACKGROUND_RED,
+        BACKGROUND_GREEN,
+        BACKGROUND_YELLOW,
+        BACKGROUND_BLUE,
+        BACKGROUND_MAGENTA,
+        BACKGROUND_CYAN,
+        BACKGROUND_WHITE,
     };
 
-    private final static int MAX_ESCAPE_SEQUENCE_LENGTH = 100;
+    private static final int MAX_ESCAPE_SEQUENCE_LENGTH = 100;
 
     private final Pointer console;
 
@@ -134,7 +134,7 @@ private void applyCursorPosition() throws IOException {
     protected void processEraseScreen(int eraseOption) throws IOException {
         getConsoleInfo();
         IntByReference written = new IntByReference();
-        switch(eraseOption) {
+        switch (eraseOption) {
             case ERASE_SCREEN:
                 Kernel32.COORD topLeft = new Kernel32.COORD();
                 topLeft.X = 0;
@@ -147,36 +147,44 @@ protected void processEraseScreen(int eraseOption) throws IOException {
                 Kernel32.COORD topLeft2 = new Kernel32.COORD();
                 topLeft2.X = 0;
                 topLeft2.Y = info.srWindow.Top;
-                int lengthToCursor = (info.dwCursorPosition.Y - info.srWindow.Top) * info.dwSize.X + info.dwCursorPosition.X;
+                int lengthToCursor =
+                        (info.dwCursorPosition.Y - info.srWindow.Top) * info.dwSize.X + info.dwCursorPosition.X;
                 Kernel32.INSTANCE.FillConsoleOutputCharacter(console, ' ', lengthToCursor, topLeft2, written);
-                Kernel32.INSTANCE.FillConsoleOutputAttribute(console, info.wAttributes, lengthToCursor, topLeft2, written);
+                Kernel32.INSTANCE.FillConsoleOutputAttribute(
+                        console, info.wAttributes, lengthToCursor, topLeft2, written);
                 break;
             case ERASE_SCREEN_TO_END:
-                int lengthToEnd = (info.srWindow.Bottom - info.dwCursorPosition.Y) * info.dwSize.X +
-                        (info.dwSize.X - info.dwCursorPosition.X);
+                int lengthToEnd = (info.srWindow.Bottom - info.dwCursorPosition.Y) * info.dwSize.X
+                        + (info.dwSize.X - info.dwCursorPosition.X);
                 Kernel32.INSTANCE.FillConsoleOutputCharacter(console, ' ', lengthToEnd, info.dwCursorPosition, written);
-                Kernel32.INSTANCE.FillConsoleOutputAttribute(console, info.wAttributes, lengthToEnd, info.dwCursorPosition, written);
+                Kernel32.INSTANCE.FillConsoleOutputAttribute(
+                        console, info.wAttributes, lengthToEnd, info.dwCursorPosition, written);
         }
     }
 
     protected void processEraseLine(int eraseOption) throws IOException {
         getConsoleInfo();
         IntByReference written = new IntByReference();
-        switch(eraseOption) {
+        switch (eraseOption) {
             case ERASE_LINE:
                 Kernel32.COORD leftColCurrRow = new Kernel32.COORD((short) 0, info.dwCursorPosition.Y);
                 Kernel32.INSTANCE.FillConsoleOutputCharacter(console, ' ', info.dwSize.X, leftColCurrRow, written);
-                Kernel32.INSTANCE.FillConsoleOutputAttribute(console, info.wAttributes, info.dwSize.X, leftColCurrRow, written);
+                Kernel32.INSTANCE.FillConsoleOutputAttribute(
+                        console, info.wAttributes, info.dwSize.X, leftColCurrRow, written);
                 break;
             case ERASE_LINE_TO_BEGINING:
                 Kernel32.COORD leftColCurrRow2 = new Kernel32.COORD((short) 0, info.dwCursorPosition.Y);
-                Kernel32.INSTANCE.FillConsoleOutputCharacter(console, ' ', info.dwCursorPosition.X, leftColCurrRow2, written);
-                Kernel32.INSTANCE.FillConsoleOutputAttribute(console, info.wAttributes, info.dwCursorPosition.X, leftColCurrRow2, written);
+                Kernel32.INSTANCE.FillConsoleOutputCharacter(
+                        console, ' ', info.dwCursorPosition.X, leftColCurrRow2, written);
+                Kernel32.INSTANCE.FillConsoleOutputAttribute(
+                        console, info.wAttributes, info.dwCursorPosition.X, leftColCurrRow2, written);
                 break;
             case ERASE_LINE_TO_END:
                 int lengthToLastCol = info.dwSize.X - info.dwCursorPosition.X;
-                Kernel32.INSTANCE.FillConsoleOutputCharacter(console, ' ', lengthToLastCol, info.dwCursorPosition, written);
-                Kernel32.INSTANCE.FillConsoleOutputAttribute(console, info.wAttributes, lengthToLastCol, info.dwCursorPosition, written);
+                Kernel32.INSTANCE.FillConsoleOutputCharacter(
+                        console, ' ', lengthToLastCol, info.dwCursorPosition, written);
+                Kernel32.INSTANCE.FillConsoleOutputAttribute(
+                        console, info.wAttributes, lengthToLastCol, info.dwCursorPosition, written);
         }
     }
 
@@ -218,7 +226,7 @@ protected void processCursorDown(int count) throws IOException {
             scroll.Top = 0;
             Kernel32.COORD org = new Kernel32.COORD();
             org.X = 0;
-            org.Y = (short)(- nb);
+            org.Y = (short) (-nb);
             Kernel32.CHAR_INFO info = new Kernel32.CHAR_INFO(' ', originalColors);
             Kernel32.INSTANCE.ScrollConsoleScreenBuffer(console, scroll, scroll, org, info);
         }
@@ -247,29 +255,31 @@ protected void processCursorToColumn(int x) throws IOException {
     protected void processSetForegroundColorExt(int paletteIndex) throws IOException {
         int color = Colors.roundColor(paletteIndex, 16);
         info.wAttributes = (short) ((info.wAttributes & ~0x0007) | ANSI_FOREGROUND_COLOR_MAP[color & 0x07]);
-        info.wAttributes = (short) ((info.wAttributes & ~FOREGROUND_INTENSITY) | (color >= 8 ? FOREGROUND_INTENSITY : 0));
+        info.wAttributes =
+                (short) ((info.wAttributes & ~FOREGROUND_INTENSITY) | (color >= 8 ? FOREGROUND_INTENSITY : 0));
         applyAttribute();
     }
 
     protected void processSetBackgroundColorExt(int paletteIndex) throws IOException {
         int color = Colors.roundColor(paletteIndex, 16);
-        info.wAttributes = (short)((info.wAttributes & ~0x0070 ) | ANSI_BACKGROUND_COLOR_MAP[color & 0x07]);
-        info.wAttributes = (short) ((info.wAttributes & ~BACKGROUND_INTENSITY) | (color >= 8 ? BACKGROUND_INTENSITY : 0));
+        info.wAttributes = (short) ((info.wAttributes & ~0x0070) | ANSI_BACKGROUND_COLOR_MAP[color & 0x07]);
+        info.wAttributes =
+                (short) ((info.wAttributes & ~BACKGROUND_INTENSITY) | (color >= 8 ? BACKGROUND_INTENSITY : 0));
         applyAttribute();
     }
 
     protected void processDefaultTextColor() throws IOException {
-        info.wAttributes = (short)((info.wAttributes & ~0x000F ) | (originalColors & 0x000F));
+        info.wAttributes = (short) ((info.wAttributes & ~0x000F) | (originalColors & 0x000F));
         applyAttribute();
     }
 
     protected void processDefaultBackgroundColor() throws IOException {
-        info.wAttributes = (short)((info.wAttributes & ~0x00F0 ) | (originalColors & 0x00F0));
+        info.wAttributes = (short) ((info.wAttributes & ~0x00F0) | (originalColors & 0x00F0));
         applyAttribute();
     }
 
     protected void processAttributeRest() throws IOException {
-        info.wAttributes = (short)((info.wAttributes & ~0x00FF ) | originalColors);
+        info.wAttributes = (short) ((info.wAttributes & ~0x00FF) | originalColors);
         this.negative = false;
         this.bold = false;
         this.underline = false;
@@ -277,7 +287,7 @@ protected void processAttributeRest() throws IOException {
     }
 
     protected void processSetAttribute(int attribute) throws IOException {
-        switch(attribute) {
+        switch (attribute) {
             case ATTRIBUTE_INTENSITY_BOLD:
                 bold = true;
                 applyAttribute();
@@ -330,7 +340,7 @@ protected void processInsertLine(int optionInt) throws IOException {
         scroll.Top = info.dwCursorPosition.Y;
         Kernel32.COORD org = new Kernel32.COORD();
         org.X = 0;
-        org.Y = (short)(info.dwCursorPosition.Y + optionInt);
+        org.Y = (short) (info.dwCursorPosition.Y + optionInt);
         Kernel32.CHAR_INFO info = new Kernel32.CHAR_INFO(' ', originalColors);
         Kernel32.INSTANCE.ScrollConsoleScreenBuffer(console, scroll, scroll, org, info);
     }
@@ -342,7 +352,7 @@ protected void processDeleteLine(int optionInt) throws IOException {
         scroll.Top = info.dwCursorPosition.Y;
         Kernel32.COORD org = new Kernel32.COORD();
         org.X = 0;
-        org.Y = (short)(info.dwCursorPosition.Y - optionInt);
+        org.Y = (short) (info.dwCursorPosition.Y - optionInt);
         Kernel32.CHAR_INFO info = new Kernel32.CHAR_INFO(' ', originalColors);
         Kernel32.INSTANCE.ScrollConsoleScreenBuffer(console, scroll, scroll, org, info);
     }
diff --git a/src/jdk.internal.le/windows/native/lible/Kernel32.cpp b/src/jdk.internal.le/windows/native/lible/Kernel32.cpp
index 89fcc0acbda..e0a71f08559 100644
--- a/src/jdk.internal.le/windows/native/lible/Kernel32.cpp
+++ b/src/jdk.internal.le/windows/native/lible/Kernel32.cpp
@@ -327,16 +327,6 @@ JNIEXPORT jobject JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_win_Kern
                           nStdHandle);
 }
 
-/*
- * Class:     jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl
- * Method:    GetConsoleOutputCP
- * Signature: ()I
- */
-JNIEXPORT jint JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl_GetConsoleOutputCP
-  (JNIEnv *, jobject) {
-    return GetConsoleOutputCP();
-}
-
 /*
  * Class:     jdk_internal_org_jline_terminal_impl_jna_win_Kernel32Impl
  * Method:    FillConsoleOutputCharacter
diff --git a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/options/Options.java b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/options/Options.java
index 32f7fde60ab..2453ec16682 100644
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/options/Options.java
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/options/Options.java
@@ -416,16 +416,34 @@ public void displayHelp(final boolean extended) {
      * @param args arguments from command line
      */
     public void process(final String[] args) {
+        final LinkedList prepArgList = new LinkedList<>();
+        addSystemProperties(NASHORN_ARGS_PREPEND_PROPERTY, prepArgList);
+        final LinkedList postArgList = new LinkedList<>();
+        addSystemProperties(NASHORN_ARGS_PROPERTY, postArgList);
         final LinkedList argList = new LinkedList<>();
-        addSystemProperties(NASHORN_ARGS_PREPEND_PROPERTY, argList);
-        processArgList(argList);
-        assert argList.isEmpty();
-        Collections.addAll(argList, args);
-        processArgList(argList);
-        assert argList.isEmpty();
-        addSystemProperties(NASHORN_ARGS_PROPERTY, argList);
+        for (final String arg : args) {
+            if (arg.startsWith(definePropPrefix)) {
+                final String value = arg.substring(definePropPrefix.length());
+                final int eq = value.indexOf('=');
+                if (eq != -1) {
+                    String name = value.substring(0, eq);
+                    if (name.equals(NASHORN_ARGS_PREPEND_PROPERTY)) {
+                        addNashornProperties(value.substring(eq + 1), prepArgList, false);
+                        continue;
+                    } else if (name.equals(NASHORN_ARGS_PROPERTY)) {
+                        addNashornProperties(value.substring(eq + 1), postArgList, true);
+                        continue;
+                    }
+                }
+            }
+            argList.add(arg);
+        }
+        processArgList(prepArgList);
+        assert prepArgList.isEmpty();
         processArgList(argList);
         assert argList.isEmpty();
+        processArgList(postArgList);
+        assert postArgList.isEmpty();
     }
 
     private void processArgList(final LinkedList argList) {
@@ -529,6 +547,23 @@ private static void addSystemProperties(final String sysPropName, final List argList, boolean prepend) {
+        if (args != null) {
+            final StringTokenizer st = new StringTokenizer(args);
+            final LinkedList prepArgList = new LinkedList<>();
+            while (st.hasMoreTokens()) {
+                if (prepend) {
+                    prepArgList.add(st.nextToken());
+                } else {
+                    argList.add(st.nextToken());
+                }
+            }
+            if (prepend) {
+                argList.addAll(0,prepArgList);
+            }
+        }
+    }
+
     /**
      * Retrieves an option template identified by key.
      * @param shortKey the short (that is without the e.g. "nashorn.option." part) key
diff --git a/test/hotspot/gtest/gc/shared/test_collectorPolicy.cpp b/test/hotspot/gtest/gc/shared/test_collectorPolicy.cpp
index ce50b73a690..7f2cb854c55 100644
--- a/test/hotspot/gtest/gc/shared/test_collectorPolicy.cpp
+++ b/test/hotspot/gtest/gc/shared/test_collectorPolicy.cpp
@@ -78,7 +78,7 @@ class TestGenCollectorPolicy {
       FLAG_SET_ERGO(size_t, InitialHeapSize, 100 * M);
       FLAG_SET_ERGO(size_t, OldSize, 4 * M);
       FLAG_SET_ERGO(size_t, NewSize, 1 * M);
-      FLAG_SET_ERGO(size_t, MaxNewSize, 80 * M);
+      FLAG_SET_ERGO(size_t, MaxNewSize, 50 * M);
       Arguments::set_min_heap_size(40 * M);
 
       ASSERT_NO_FATAL_FAILURE(setter1->execute());
@@ -227,10 +227,16 @@ TEST_VM(CollectorPolicy, young_min_ergo) {
   TestGenCollectorPolicy::TestWrapper::test(&setter, &checker);
 }
 
+// Tests require at least 128M of MaxHeap
+// otherwise ergonomic is different and generation sizes might be changed.
+
 // If NewSize has been ergonomically set, the collector policy
 // should use it for min but calculate the initial young size
 // using NewRatio.
 TEST_VM(CollectorPolicy, young_scaled_initial_ergo) {
+  if (MaxHeapSize < 128 * M) {
+      return;
+  }
   TestGenCollectorPolicy::SetNewSizeErgo setter(20 * M);
   TestGenCollectorPolicy::CheckScaledYoungInitial checker;
 
@@ -243,6 +249,9 @@ TEST_VM(CollectorPolicy, young_scaled_initial_ergo) {
 // the rest of the VM lifetime. This is an irreversible change and
 // could impact other tests so we use TEST_OTHER_VM
 TEST_OTHER_VM(CollectorPolicy, young_cmd) {
+  if (MaxHeapSize < 128 * M) {
+    return;
+  }
   // If NewSize is set on the command line, it should be used
   // for both min and initial young size if less than min heap.
   TestGenCollectorPolicy::SetNewSizeCmd setter(20 * M);
@@ -255,8 +264,8 @@ TEST_OTHER_VM(CollectorPolicy, young_cmd) {
 
   // If NewSize is set on command line, but is larger than the min
   // heap size, it should only be used for initial young size.
-  TestGenCollectorPolicy::SetNewSizeCmd setter_large(80 * M);
-  TestGenCollectorPolicy::CheckYoungInitial checker_large(80 * M);
+  TestGenCollectorPolicy::SetNewSizeCmd setter_large(50 * M);
+  TestGenCollectorPolicy::CheckYoungInitial checker_large(50 * M);
   TestGenCollectorPolicy::TestWrapper::test(&setter_large, &checker_large);
 }
 
diff --git a/test/hotspot/jtreg/runtime/CheckUnhandledOops/TestVerifyOops.java b/test/hotspot/jtreg/runtime/CheckUnhandledOops/TestVerifyOops.java
new file mode 100644
index 00000000000..3326124d4d1
--- /dev/null
+++ b/test/hotspot/jtreg/runtime/CheckUnhandledOops/TestVerifyOops.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8231058
+ * @requires vm.debug & (os.arch != "sparc") & (os.arch != "sparcv9")
+ * @run main/othervm -XX:+VerifyOops TestVerifyOops
+ */
+
+public class TestVerifyOops {
+
+    public static void main(String[] args) {
+        System.out.println("Test passed");
+    }
+}
diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/Memory.java b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/Memory.java
index f5c70671e5e..244bcf423c5 100644
--- a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/Memory.java
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/Memory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -150,12 +150,9 @@ public static int getReferenceObjectSize() {
          *  @return length of array
          */
         public static int getArrayLength(long memory, long objectSize) {
-                int referenceSize = getReferenceSize();
                 int arrayExtraSize = getArrayExtraSize();
-                return (int) Math.min(
-                                (memory - arrayExtraSize) / (objectSize + referenceSize),
-                                Integer.MAX_VALUE
-                                );
+                return (int) Math.min((memory - arrayExtraSize) / objectSize,
+                        Integer.MAX_VALUE);
         }
 
         /**
@@ -166,7 +163,7 @@ public static int getArrayLength(long memory, long objectSize) {
          *  @return size of array
          */
         public static long getArraySize(int length, long objectSize) {
-                return getObjectExtraSize() + length * (objectSize + getReferenceSize());
+                return getArrayExtraSize() + length * objectSize;
         }
 
         /**
diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt
index 86f599fc5f9..7f97c49256f 100644
--- a/test/jdk/ProblemList.txt
+++ b/test/jdk/ProblemList.txt
@@ -604,7 +604,6 @@ com/sun/nio/sctp/SctpChannel/SocketOptionTests.java             8141694 linux-al
 
 # jdk_security
 
-sun/security/pkcs11/ec/TestKeyFactory.java                      8026976 generic-all
 sun/security/pkcs11/KeyStore/ClientAuth.sh                      8254806 solaris-all
 sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java            8161536 generic-all
 
diff --git a/test/jdk/java/net/httpclient/DigestEchoClient.java b/test/jdk/java/net/httpclient/DigestEchoClient.java
index a3321dc3b3c..53b945d70df 100644
--- a/test/jdk/java/net/httpclient/DigestEchoClient.java
+++ b/test/jdk/java/net/httpclient/DigestEchoClient.java
@@ -264,8 +264,9 @@ public static void main(String[] args) throws Exception {
         }
         try {
             for (DigestEchoServer.HttpAuthType authType : types) {
-                // The test server does not support PROXY305 properly
-                if (authType == DigestEchoServer.HttpAuthType.PROXY305) continue;
+                // The test server does not support PROXY305 or SERVER307 properly
+                if (authType == DigestEchoServer.HttpAuthType.PROXY305 ||
+                    authType == DigestEchoServer.HttpAuthType.SERVER307) continue;
                 EnumSet basics =
                         EnumSet.of(DigestEchoServer.HttpAuthSchemeType.BASICSERVER,
                                 DigestEchoServer.HttpAuthSchemeType.BASIC);
diff --git a/test/jdk/java/net/httpclient/HttpRedirectTest.java b/test/jdk/java/net/httpclient/HttpRedirectTest.java
new file mode 100644
index 00000000000..34ec95f7770
--- /dev/null
+++ b/test/jdk/java/net/httpclient/HttpRedirectTest.java
@@ -0,0 +1,457 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+import com.sun.net.httpserver.HttpServer;
+import com.sun.net.httpserver.HttpsConfigurator;
+import com.sun.net.httpserver.HttpsServer;
+import jdk.test.lib.net.SimpleSSLContext;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+import javax.net.ssl.SSLContext;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.net.ProxySelector;
+import java.net.SocketAddress;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * @test
+ * @bug 8232625
+ * @summary This test verifies that the HttpClient works correctly when redirecting a post request.
+ * @library /test/lib http2/server
+ * @build jdk.test.lib.net.SimpleSSLContext HttpServerAdapters DigestEchoServer HttpRedirectTest
+ * @modules java.net.http/jdk.internal.net.http.common
+ *          java.net.http/jdk.internal.net.http.frame
+ *          java.net.http/jdk.internal.net.http.hpack
+ *          java.logging
+ *          java.base/sun.net.www.http
+ *          java.base/sun.net.www
+ *          java.base/sun.net
+ * @run testng/othervm -Dtest.requiresHost=true
+ *                   -Djdk.httpclient.HttpClient.log=headers
+ *                   -Djdk.internal.httpclient.debug=false
+ *                   HttpRedirectTest
+ *
+ */
+public class HttpRedirectTest implements HttpServerAdapters {
+    static final String GET_RESPONSE_BODY = "Lorem ipsum dolor sit amet";
+    static final String REQUEST_BODY = "Here it goes";
+    static final SSLContext context;
+    static {
+        try {
+            context = new SimpleSSLContext().get();
+            SSLContext.setDefault(context);
+        } catch (Exception x) {
+            throw new ExceptionInInitializerError(x);
+        }
+    }
+
+    final AtomicLong requestCounter = new AtomicLong();
+    final AtomicLong responseCounter = new AtomicLong();
+    HttpTestServer http1Server;
+    HttpTestServer http2Server;
+    HttpTestServer https1Server;
+    HttpTestServer https2Server;
+    DigestEchoServer.TunnelingProxy proxy;
+
+    URI http1URI;
+    URI https1URI;
+    URI http2URI;
+    URI https2URI;
+    InetSocketAddress proxyAddress;
+    ProxySelector proxySelector;
+    HttpClient client;
+    List>  futures = new CopyOnWriteArrayList<>();
+    Set pending = new CopyOnWriteArraySet<>();
+
+    final ExecutorService executor = new ThreadPoolExecutor(12, 60, 10,
+            TimeUnit.SECONDS, new LinkedBlockingQueue<>()); // Shared by HTTP/1.1 servers
+    final ExecutorService clientexec = new ThreadPoolExecutor(6, 12, 1,
+            TimeUnit.SECONDS, new LinkedBlockingQueue<>()); // Used by the client
+
+    public HttpClient newHttpClient(ProxySelector ps) {
+        HttpClient.Builder builder = HttpClient
+                .newBuilder()
+                .sslContext(context)
+                .executor(clientexec)
+                .followRedirects(HttpClient.Redirect.ALWAYS)
+                .proxy(ps);
+        return builder.build();
+    }
+
+    @DataProvider(name="uris")
+    Object[][] testURIs() throws URISyntaxException {
+        List uris = List.of(
+                http1URI.resolve("direct/orig/"),
+                https1URI.resolve("direct/orig/"),
+                https1URI.resolve("proxy/orig/"),
+                http2URI.resolve("direct/orig/"),
+                https2URI.resolve("direct/orig/"),
+                https2URI.resolve("proxy/orig/"));
+        List> redirects = List.of(
+                Map.entry(301, "GET"),
+                Map.entry(308, "POST"),
+                Map.entry(302, "GET"),
+                Map.entry(303, "GET"),
+                Map.entry(307, "POST"),
+                Map.entry(300, "DO_NOT_FOLLOW"),
+                Map.entry(304, "DO_NOT_FOLLOW"),
+                Map.entry(305, "DO_NOT_FOLLOW"),
+                Map.entry(306, "DO_NOT_FOLLOW"),
+                Map.entry(309, "DO_NOT_FOLLOW"),
+                Map.entry(new Random().nextInt(90) + 310, "DO_NOT_FOLLOW")
+        );
+        Object[][] tests = new Object[redirects.size() * uris.size()][3];
+        int count = 0;
+        for (int i=0; i < uris.size(); i++) {
+            URI u = uris.get(i);
+            for (int j=0; j < redirects.size() ; j++) {
+                int code = redirects.get(j).getKey();
+                String m = redirects.get(j).getValue();
+                tests[count][0] = u.resolve(code +"/");
+                tests[count][1] = code;
+                tests[count][2] = m;
+                count++;
+            }
+        }
+        return tests;
+    }
+
+    @BeforeClass
+    public void setUp() throws Exception {
+        try {
+            InetSocketAddress sa = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0);
+
+            // HTTP/1.1
+            HttpServer server1 = HttpServer.create(sa, 0);
+            server1.setExecutor(executor);
+            http1Server = HttpTestServer.of(server1);
+            http1Server.addHandler(new HttpTestRedirectHandler("http", http1Server),
+                    "/HttpRedirectTest/http1/");
+            http1Server.start();
+            http1URI = new URI("http://" + http1Server.serverAuthority() + "/HttpRedirectTest/http1/");
+
+
+            // HTTPS/1.1
+            HttpsServer sserver1 = HttpsServer.create(sa, 100);
+            sserver1.setExecutor(executor);
+            sserver1.setHttpsConfigurator(new HttpsConfigurator(context));
+            https1Server = HttpTestServer.of(sserver1);
+            https1Server.addHandler(new HttpTestRedirectHandler("https", https1Server),
+                    "/HttpRedirectTest/https1/");
+            https1Server.start();
+            https1URI = new URI("https://" + https1Server.serverAuthority() + "/HttpRedirectTest/https1/");
+
+            // HTTP/2.0
+            http2Server = HttpTestServer.of(
+                    new Http2TestServer("localhost", false, 0));
+            http2Server.addHandler(new HttpTestRedirectHandler("http", http2Server),
+                    "/HttpRedirectTest/http2/");
+            http2Server.start();
+            http2URI = new URI("http://" + http2Server.serverAuthority() + "/HttpRedirectTest/http2/");
+
+            // HTTPS/2.0
+            https2Server = HttpTestServer.of(
+                    new Http2TestServer("localhost", true, 0));
+            https2Server.addHandler(new HttpTestRedirectHandler("https", https2Server),
+                    "/HttpRedirectTest/https2/");
+            https2Server.start();
+            https2URI = new URI("https://" + https2Server.serverAuthority() + "/HttpRedirectTest/https2/");
+
+            proxy = DigestEchoServer.createHttpsProxyTunnel(
+                    DigestEchoServer.HttpAuthSchemeType.NONE);
+            proxyAddress = proxy.getProxyAddress();
+            proxySelector = new HttpProxySelector(proxyAddress);
+            client = newHttpClient(proxySelector);
+            System.out.println("Setup: done");
+        } catch (Exception x) {
+            tearDown(); throw x;
+        } catch (Error e) {
+            tearDown(); throw e;
+        }
+    }
+
+    private void testNonIdempotent(URI u, HttpRequest request,
+                                   int code, String method) throws Exception {
+        System.out.println("Testing with " + u);
+        CompletableFuture> respCf =
+                client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
+        HttpResponse resp = respCf.join();
+        if (method.equals("DO_NOT_FOLLOW")) {
+            assertEquals(resp.statusCode(), code, u + ": status code");
+        } else {
+            assertEquals(resp.statusCode(), 200, u + ": status code");
+        }
+        if (method.equals("POST")) {
+            assertEquals(resp.body(), REQUEST_BODY, u + ": body");
+        } else if (code == 304) {
+            assertEquals(resp.body(), "", u + ": body");
+        } else if (method.equals("DO_NOT_FOLLOW")) {
+            assertNotEquals(resp.body(), GET_RESPONSE_BODY, u + ": body");
+            assertNotEquals(resp.body(), REQUEST_BODY, u + ": body");
+        } else {
+            assertEquals(resp.body(), GET_RESPONSE_BODY, u + ": body");
+        }
+    }
+
+    public void testIdempotent(URI u, HttpRequest request,
+                               int code, String method) throws Exception {
+        CompletableFuture> respCf =
+                client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
+        HttpResponse resp = respCf.join();
+        if (method.equals("DO_NOT_FOLLOW")) {
+            assertEquals(resp.statusCode(), code, u + ": status code");
+        } else {
+            assertEquals(resp.statusCode(), 200, u + ": status code");
+        }
+        if (method.equals("POST")) {
+            assertEquals(resp.body(), REQUEST_BODY, u + ": body");
+        } else if (code == 304) {
+            assertEquals(resp.body(), "", u + ": body");
+        } else if (method.equals("DO_NOT_FOLLOW")) {
+            assertNotEquals(resp.body(), GET_RESPONSE_BODY, u + ": body");
+            assertNotEquals(resp.body(), REQUEST_BODY, u + ": body");
+        } else if (code == 303) {
+            assertEquals(resp.body(), GET_RESPONSE_BODY, u + ": body");
+        } else {
+            assertEquals(resp.body(), REQUEST_BODY, u + ": body");
+        }
+    }
+
+    @Test(dataProvider = "uris")
+    public void testPOST(URI uri, int code, String method) throws Exception {
+        URI u = uri.resolve("foo?n=" + requestCounter.incrementAndGet());
+        HttpRequest request = HttpRequest.newBuilder(u)
+                .POST(HttpRequest.BodyPublishers.ofString(REQUEST_BODY)).build();
+        // POST is not considered idempotent.
+        testNonIdempotent(u, request, code, method);
+    }
+
+    @Test(dataProvider = "uris")
+    public void testPUT(URI uri, int code, String method) throws Exception {
+        URI u = uri.resolve("foo?n=" + requestCounter.incrementAndGet());
+        System.out.println("Testing with " + u);
+        HttpRequest request = HttpRequest.newBuilder(u)
+                .PUT(HttpRequest.BodyPublishers.ofString(REQUEST_BODY)).build();
+        // PUT is considered idempotent.
+        testIdempotent(u, request, code, method);
+    }
+
+    @Test(dataProvider = "uris")
+    public void testFoo(URI uri, int code, String method) throws Exception {
+        URI u = uri.resolve("foo?n=" + requestCounter.incrementAndGet());
+        System.out.println("Testing with " + u);
+        HttpRequest request = HttpRequest.newBuilder(u)
+                .method("FOO",
+                        HttpRequest.BodyPublishers.ofString(REQUEST_BODY)).build();
+        // FOO is considered idempotent.
+        testIdempotent(u, request, code, method);
+    }
+
+    @Test(dataProvider = "uris")
+    public void testGet(URI uri, int code, String method) throws Exception {
+        URI u = uri.resolve("foo?n=" + requestCounter.incrementAndGet());
+        System.out.println("Testing with " + u);
+        HttpRequest request = HttpRequest.newBuilder(u)
+                .method("GET",
+                        HttpRequest.BodyPublishers.ofString(REQUEST_BODY)).build();
+        CompletableFuture> respCf =
+                client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
+        HttpResponse resp = respCf.join();
+        // body will be preserved except for 304 and 303: this is a GET.
+        if (method.equals("DO_NOT_FOLLOW")) {
+            assertEquals(resp.statusCode(), code, u + ": status code");
+        } else {
+            assertEquals(resp.statusCode(), 200, u + ": status code");
+        }
+        if (code == 304) {
+            assertEquals(resp.body(), "", u + ": body");
+        } else if (method.equals("DO_NOT_FOLLOW")) {
+            assertNotEquals(resp.body(), GET_RESPONSE_BODY, u + ": body");
+            assertNotEquals(resp.body(), REQUEST_BODY, u + ": body");
+        } else if (code == 303) {
+            assertEquals(resp.body(), GET_RESPONSE_BODY, u + ": body");
+        } else {
+            assertEquals(resp.body(), REQUEST_BODY, u + ": body");
+        }
+    }
+
+    @AfterClass
+    public void tearDown() {
+        proxy = stop(proxy, DigestEchoServer.TunnelingProxy::stop);
+        http1Server = stop(http1Server, HttpTestServer::stop);
+        https1Server = stop(https1Server, HttpTestServer::stop);
+        http2Server = stop(http2Server, HttpTestServer::stop);
+        https2Server = stop(https2Server, HttpTestServer::stop);
+        client = null;
+        try {
+            executor.awaitTermination(2000, TimeUnit.MILLISECONDS);
+        } catch (Throwable x) {
+        } finally {
+            executor.shutdownNow();
+        }
+        try {
+            clientexec.awaitTermination(2000, TimeUnit.MILLISECONDS);
+        } catch (Throwable x) {
+        } finally {
+            clientexec.shutdownNow();
+        }
+        System.out.println("Teardown: done");
+    }
+
+    private interface Stoppable { public void stop(T service) throws Exception; }
+
+    static   T stop(T service, Stoppable stop) {
+        try { if (service != null) stop.stop(service); } catch (Throwable x) { };
+        return null;
+    }
+
+    static class HttpProxySelector extends ProxySelector {
+        private static final List NO_PROXY = List.of(Proxy.NO_PROXY);
+        private final List proxyList;
+        HttpProxySelector(InetSocketAddress proxyAddress) {
+            proxyList = List.of(new Proxy(Proxy.Type.HTTP, proxyAddress));
+        }
+
+        @Override
+        public List select(URI uri) {
+            // our proxy only supports tunneling
+            if (uri.getScheme().equalsIgnoreCase("https")) {
+                if (uri.getPath().contains("/proxy/")) {
+                    return proxyList;
+                }
+            }
+            return NO_PROXY;
+        }
+
+        @Override
+        public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
+            System.err.println("Connection to proxy failed: " + ioe);
+            System.err.println("Proxy: " + sa);
+            System.err.println("\tURI: " + uri);
+            ioe.printStackTrace();
+        }
+    }
+
+    public static class HttpTestRedirectHandler implements HttpTestHandler {
+        static final AtomicLong respCounter = new AtomicLong();
+        final String scheme;
+        final HttpTestServer server;
+        HttpTestRedirectHandler(String scheme, HttpTestServer server) {
+            this.scheme = scheme;
+            this.server = server;
+        }
+
+        @Override
+        public void handle(HttpTestExchange t) throws IOException {
+            try (InputStream is = t.getRequestBody()) {
+                byte[] bytes = is.readAllBytes();
+                URI u = t.getRequestURI();
+                long responseID = Long.parseLong(u.getQuery().substring(2));
+                String path = u.getPath();
+                int i = path.lastIndexOf('/');
+                String file = path.substring(i+1);
+                String parent =  path.substring(0, i);
+                int code = 200;
+                if (file.equals("foo")) {
+                    i = parent.lastIndexOf("/");
+                    code = Integer.parseInt(parent.substring(i+1));
+                }
+                String response;
+                if (code == 200) {
+                    if (t.getRequestMethod().equals("GET")) {
+                        if (bytes.length == 0) {
+                            response = GET_RESPONSE_BODY;
+                        } else {
+                            response = new String(bytes, StandardCharsets.UTF_8);
+                        }
+                    } else if (t.getRequestMethod().equals("POST")) {
+                        response = new String(bytes, StandardCharsets.UTF_8);
+                    } else {
+                        response = new String(bytes, StandardCharsets.UTF_8);
+                    }
+                } else if (code < 300 || code > 399) {
+                    response = "Unexpected code: " + code;
+                    code = 400;
+                } else {
+                    try {
+                        URI reloc = new URI(scheme, server.serverAuthority(), parent + "/bar", u.getQuery(), null);
+                        t.getResponseHeaders().addHeader("Location", reloc.toASCIIString());
+                        if (code != 304) {
+                            response = "Code: " + code;
+                        } else response = null;
+                    } catch (URISyntaxException x) {
+                        x.printStackTrace();
+                        x.printStackTrace(System.out);
+                        code = 400;
+                        response = x.toString();
+                    }
+                }
+
+                System.out.println("Server " + t.getRequestURI() + " sending response " + responseID);
+                System.out.println("code: " + code + " body: " + response);
+                t.sendResponseHeaders(code, code == 304 ? 0: -1);
+                if (code != 304) {
+                    try (OutputStream os = t.getResponseBody()) {
+                        bytes = response.getBytes(StandardCharsets.UTF_8);
+                        os.write(bytes);
+                        os.flush();
+                    }
+                } else {
+                    bytes = new byte[0];
+                }
+
+                System.out.println("\tresp:" + responseID + ": wrote " + bytes.length + " bytes");
+            } catch (Throwable e) {
+                e.printStackTrace();
+                e.printStackTrace(System.out);
+                throw e;
+            }
+        }
+    }
+
+}
diff --git a/test/jdk/java/net/httpclient/http2/RedirectTest.java b/test/jdk/java/net/httpclient/http2/RedirectTest.java
index bf886502954..b51c4df42ea 100644
--- a/test/jdk/java/net/httpclient/http2/RedirectTest.java
+++ b/test/jdk/java/net/httpclient/http2/RedirectTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -87,6 +87,11 @@ protected synchronized void examineExchange(Http2TestExchange ex) {
             }
         }
 
+        @Override
+        protected int redirectCode() {
+            return 308; // we need to use a code that preserves the body
+        }
+
         public synchronized boolean error() {
             return error;
         }
diff --git a/test/jdk/java/net/httpclient/http2/server/Http2RedirectHandler.java b/test/jdk/java/net/httpclient/http2/server/Http2RedirectHandler.java
index 42d269de81a..97ea94b7b91 100644
--- a/test/jdk/java/net/httpclient/http2/server/Http2RedirectHandler.java
+++ b/test/jdk/java/net/httpclient/http2/server/Http2RedirectHandler.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,11 +42,11 @@ public void handle(Http2TestExchange t) throws IOException {
             is.readAllBytes();
             String location = supplier.get();
             System.err.printf("RedirectHandler request to %s from %s\n",
-                t.getRequestURI().toString(), t.getRemoteAddress().toString());
+                    t.getRequestURI().toString(), t.getRemoteAddress().toString());
             System.err.println("Redirecting to: " + location);
             HttpHeadersBuilder headersBuilder = t.getResponseHeaders();
             headersBuilder.addHeader("Location", location);
-            t.sendResponseHeaders(301, 1024);
+            t.sendResponseHeaders(redirectCode(), 1024);
             byte[] bb = new byte[1024];
             OutputStream os = t.getResponseBody();
             os.write(bb);
@@ -55,6 +55,10 @@ public void handle(Http2TestExchange t) throws IOException {
         }
     }
 
+    protected int redirectCode() {
+        return 301;
+    }
+
     // override in sub-class to examine the exchange, but don't
     // alter transaction state by reading the request body etc.
     protected void examineExchange(Http2TestExchange t) {
diff --git a/test/jdk/java/util/Currency/ISO4217-list-one.txt b/test/jdk/java/util/Currency/ISO4217-list-one.txt
index 1912b5cc7db..aa8c2725899 100644
--- a/test/jdk/java/util/Currency/ISO4217-list-one.txt
+++ b/test/jdk/java/util/Currency/ISO4217-list-one.txt
@@ -1,12 +1,12 @@
 #
 #
-# Amendments up until ISO 4217 AMENDMENT NUMBER 177
-#   (As of 20 June 2024)
+# Amendments up until ISO 4217 AMENDMENT NUMBER 179
+#   (As of 02 May 2025)
 #
 
 # Version
 FILEVERSION=3
-DATAVERSION=177
+DATAVERSION=179
 
 # ISO 4217 currency data
 AF	AFN	971	2
diff --git a/test/jdk/java/util/Currency/ValidateISO4217.java b/test/jdk/java/util/Currency/ValidateISO4217.java
index 01c225e531c..90c7376abaa 100644
--- a/test/jdk/java/util/Currency/ValidateISO4217.java
+++ b/test/jdk/java/util/Currency/ValidateISO4217.java
@@ -26,6 +26,7 @@
  * @bug 4691089 4819436 4942982 5104960 6544471 6627549 7066203 7195759
  *      8039317 8074350 8074351 8145952 8187946 8193552 8202026 8204269
  *      8208746 8209775 8264792 8274658 8283277 8296239 8321480 8334653
+ *      8356096
  * @summary Validate ISO 4217 data for Currency class.
  * @modules java.base/java.util:open
  *          jdk.localedata
@@ -89,7 +90,7 @@ public class ValidateISO4217 {
             "ADP-AFA-ATS-AYM-AZM-BEF-BGL-BOV-BYB-BYR-CHE-CHW-CLF-COU-CUC-CYP-"
                     + "DEM-EEK-ESP-FIM-FRF-GHC-GRD-GWP-HRK-IEP-ITL-LTL-LUF-LVL-MGF-MRO-MTL-MXV-MZM-NLG-"
                     + "PTE-ROL-RUR-SDD-SIT-SLL-SKK-SRG-STD-TMM-TPE-TRL-VEF-UYI-USN-USS-VEB-VED-"
-                    + "XAG-XAU-XBA-XBB-XBC-XBD-XDR-XFO-XFU-XPD-XPT-XSU-XTS-XUA-XXX-"
+                    + "XAD-XAG-XAU-XBA-XBB-XBC-XBD-XDR-XFO-XFU-XPD-XPT-XSU-XTS-XUA-XXX-"
                     + "YUM-ZMK-ZWD-ZWL-ZWN-ZWR";
     private static final String[][] extraCodes = {
             /* Defined in ISO 4217 list, but don't have code and minor unit info. */
diff --git a/test/jdk/java/util/TimeZone/TimeZoneData/VERSION b/test/jdk/java/util/TimeZone/TimeZoneData/VERSION
index 5159b3786e3..750d9fae2b1 100644
--- a/test/jdk/java/util/TimeZone/TimeZoneData/VERSION
+++ b/test/jdk/java/util/TimeZone/TimeZoneData/VERSION
@@ -1 +1 @@
-tzdata2025a
+tzdata2025b
diff --git a/test/jdk/javax/accessibility/TestJMenuItemShortcutAccessibility.java b/test/jdk/javax/accessibility/TestJMenuItemShortcutAccessibility.java
new file mode 100644
index 00000000000..0eb3c0fc225
--- /dev/null
+++ b/test/jdk/javax/accessibility/TestJMenuItemShortcutAccessibility.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import javax.swing.JFrame;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.KeyStroke;
+
+/*
+ * @test
+ * @bug 8339728
+ * @summary Tests that JAWS announce the shortcuts for JMenuItems.
+ * @requires os.family == "windows"
+ * @library /java/awt/regtesthelpers
+ * @build PassFailJFrame
+ * @run main/manual TestJMenuItemShortcutAccessibility
+ */
+
+public class TestJMenuItemShortcutAccessibility {
+    public static void main(String[] args) throws Exception {
+        String INSTRUCTIONS = ""
+             + "1. Start the JAWS application\n"
+             + "2. Press Alt + M to open application Menu\n"
+             + "3. Navigate the Menu Items by using UP / DOWN arrow key\n"
+             + "4. Press Pass if you are able to hear correct JAWS announcements\n"
+             + "   (JAWS should read full shortcut text and not only the 1st\n"
+             + "   character of shortcut text for each menu item) else Fail\n";
+
+        PassFailJFrame.builder()
+                .title("TestJMenuItemShortcutAccessibility Instruction")
+                .instructions(INSTRUCTIONS)
+                .columns(35)
+                .testUI(TestJMenuItemShortcutAccessibility::createUI)
+                .build()
+                .awaitAndCheck();
+    }
+
+    private static JFrame createUI() {
+        JFrame frame = new JFrame("A Frame with Menu");
+
+        JMenuBar menuBar = new JMenuBar();
+        JMenu menu = new JMenu("Menu with shortcuts");
+        menu.setMnemonic(KeyEvent.VK_M);
+        menuBar.add(menu);
+
+        KeyStroke keyStroke1 = KeyStroke.getKeyStroke(KeyEvent.VK_F,
+                InputEvent.CTRL_DOWN_MASK);
+        KeyStroke keyStroke2 = KeyStroke.getKeyStroke(KeyEvent.VK_2,
+                InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK);
+        KeyStroke keyStroke3 = KeyStroke.getKeyStroke(KeyEvent.VK_F1,
+                InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK);
+        KeyStroke keyStroke4 = KeyStroke.getKeyStroke(KeyEvent.VK_COMMA,
+                InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK);
+        KeyStroke keyStroke5 = KeyStroke.getKeyStroke(KeyEvent.VK_PERIOD,
+                InputEvent.CTRL_DOWN_MASK | InputEvent.ALT_DOWN_MASK);
+        KeyStroke keyStroke6 = KeyStroke.getKeyStroke(KeyEvent.VK_TAB,
+                InputEvent.CTRL_DOWN_MASK);
+        KeyStroke keyStroke7 = KeyStroke.getKeyStroke(KeyEvent.VK_SPACE,
+                InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK);
+
+        JMenuItem menuItem1 = new JMenuItem("First Menu Item");
+        menuItem1.setAccelerator(keyStroke1);
+        JMenuItem menuItem2 = new JMenuItem("Second Menu Item");
+        menuItem2.setAccelerator(keyStroke2);
+        JMenuItem menuItem3 = new JMenuItem("Third Menu Item");
+        menuItem3.setAccelerator(keyStroke3);
+        JMenuItem menuItem4 = new JMenuItem("Fourth Menu Item");
+        menuItem4.setAccelerator(keyStroke4);
+        JMenuItem menuItem5 = new JMenuItem("Fifth Menu Item");
+        menuItem5.setAccelerator(keyStroke5);
+        JMenuItem menuItem6 = new JMenuItem("Sixth Menu Item");
+        menuItem6.setAccelerator(keyStroke6);
+        JMenuItem menuItem7 = new JMenuItem("Seventh Menu Item");
+        menuItem7.setAccelerator(keyStroke7);
+
+        menu.add(menuItem1);
+        menu.add(menuItem2);
+        menu.add(menuItem3);
+        menu.add(menuItem4);
+        menu.add(menuItem5);
+        menu.add(menuItem6);
+        menu.add(menuItem7);
+
+        frame.setJMenuBar(menuBar);
+        frame.setSize(300, 200);
+        return frame;
+    }
+}
diff --git a/test/jdk/jdk/internal/jline/AbstractWindowsTerminalTest.java b/test/jdk/jdk/internal/jline/AbstractWindowsTerminalTest.java
index d53c9b20309..3e401100851 100644
--- a/test/jdk/jdk/internal/jline/AbstractWindowsTerminalTest.java
+++ b/test/jdk/jdk/internal/jline/AbstractWindowsTerminalTest.java
@@ -27,6 +27,7 @@
  * @summary Verify the wrapper input stream is used when using Terminal.reader()
  * @modules jdk.internal.le/jdk.internal.org.jline.terminal
  *          jdk.internal.le/jdk.internal.org.jline.terminal.impl
+ *          jdk.internal.le/jdk.internal.org.jline.terminal.spi
  *          jdk.internal.le/jdk.internal.org.jline.utils
  */
 
@@ -39,6 +40,7 @@
 import jdk.internal.org.jline.terminal.Size;
 import jdk.internal.org.jline.terminal.Terminal.SignalHandler;
 import jdk.internal.org.jline.terminal.impl.AbstractWindowsTerminal;
+import jdk.internal.org.jline.terminal.spi.SystemStream;
 
 
 public class AbstractWindowsTerminalTest {
@@ -56,14 +58,17 @@ public int read() throws IOException {
                 return is.read();
             }
         };
-        var t = new AbstractWindowsTerminal(out, "test", "vt100", null, false, SignalHandler.SIG_DFL, isWrapper) {
+        var t = new AbstractWindowsTerminal(null, SystemStream.Output, out,
+                                                    "test", "vt100", null, false,
+                                                    SignalHandler.SIG_DFL, "", 0,
+                                                    "", 0, isWrapper) {
             @Override
-            protected int getConsoleMode() {
+            protected int getConsoleMode(String console) {
                 return -1;
             }
 
             @Override
-            protected void setConsoleMode(int mode) {
+            protected void setConsoleMode(String console, int mode) {
                 throw new UnsupportedOperationException("unexpected.");
             }
 
diff --git a/test/jdk/jdk/internal/jline/KeyConversionTest.java b/test/jdk/jdk/internal/jline/KeyConversionTest.java
index aed9a726715..ffd116dbbc2 100644
--- a/test/jdk/jdk/internal/jline/KeyConversionTest.java
+++ b/test/jdk/jdk/internal/jline/KeyConversionTest.java
@@ -27,6 +27,7 @@
  * @summary Verify the conversion from key events to escape sequences works properly.
  * @modules jdk.internal.le/jdk.internal.org.jline.terminal
  *          jdk.internal.le/jdk.internal.org.jline.terminal.impl
+ *          jdk.internal.le/jdk.internal.org.jline.terminal.spi
  */
 
 import java.io.IOException;
@@ -36,6 +37,7 @@
 import jdk.internal.org.jline.terminal.Size;
 import jdk.internal.org.jline.terminal.Terminal.SignalHandler;
 import jdk.internal.org.jline.terminal.impl.AbstractWindowsTerminal;
+import jdk.internal.org.jline.terminal.spi.SystemStream;
 
 public class KeyConversionTest {
     public static void main(String... args) throws Exception {
@@ -58,14 +60,17 @@ void run() throws Exception {
 
     void checkKeyConversion(KeyEvent event, String expected) throws IOException {
         StringBuilder result = new StringBuilder();
-        new AbstractWindowsTerminal(new StringWriter(), "", "windows", Charset.forName("UTF-8"),
-                                    true, SignalHandler.SIG_DFL, in -> in) {
+        new AbstractWindowsTerminal(null, SystemStream.Output,
+                                            new StringWriter(), "", "windows",
+                                            Charset.forName("UTF-8"), true,
+                                            SignalHandler.SIG_DFL, "", 0,
+                                            "", 0, in -> in) {
             @Override
-            protected int getConsoleMode() {
+            protected int getConsoleMode(String console) {
                 return 0;
             }
             @Override
-            protected void setConsoleMode(int mode) {
+            protected void setConsoleMode(String console, int mode) {
                 throw new UnsupportedOperationException("Not supported yet.");
             }
             @Override
diff --git a/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java b/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java
index 33f777d6490..3aac9375545 100644
--- a/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java
+++ b/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -505,6 +505,36 @@
  * @run main/othervm/manual -Djava.security.debug=certpath CAInterop ssltlsrootrsa2022 CRL
  */
 
+/*
+ * @test id=sectigotlsrootr46
+ * @bug 8359170
+ * @summary Interoperability tests with Sectigo Public Server Authentication
+ * Root R46
+ * @library /test/lib
+ * @build jtreg.SkippedException ValidatePathWithURL CAInterop
+ * @run main/othervm/manual -Djava.security.debug=certpath,ocsp CAInterop
+ * sectigotlsrootr46 OCSP
+ * @run main/othervm/manual -Djava.security.debug=certpath,ocsp
+ * -Dcom.sun.security.ocsp.useget=false CAInterop sectigotlsrootr46 OCSP
+ * @run main/othervm/manual -Djava.security.debug=certpath CAInterop
+ * sectigotlsrootr46 CRL
+ */
+
+/*
+ * @test id=sectigotlsroote46
+ * @bug 8359170
+ * @summary Interoperability tests with Sectigo Public Server Authentication
+ * Root E46
+ * @library /test/lib
+ * @build jtreg.SkippedException ValidatePathWithURL CAInterop
+ * @run main/othervm/manual -Djava.security.debug=certpath,ocsp CAInterop
+ * sectigotlsroote46 OCSP
+ * @run main/othervm/manual -Djava.security.debug=certpath,ocsp
+ * -Dcom.sun.security.ocsp.useget=false CAInterop sectigotlsroote46 OCSP
+ * @run main/othervm/manual -Djava.security.debug=certpath CAInterop
+ * sectigotlsroote46 CRL
+ */
+
 /**
  * Collection of certificate validation tests for interoperability with external CAs.
  * These tests are marked as manual as they depend on external infrastructure and may fail
@@ -690,6 +720,13 @@ private CATestURLs getTestURLs(String alias) {
                     return new CATestURLs("https://test-root-2022-rsa.ssl.com",
                             "https://revoked-root-2022-rsa.ssl.com");
 
+            case "sectigotlsrootr46":
+                    return new CATestURLs("https://sectigopublicserverauthenticationrootr46-ev.sectigo.com",
+                            "https://sectigopublicserverauthenticationrootr46-ev.sectigo.com:444");
+            case "sectigotlsroote46":
+                    return new CATestURLs("https://sectigopublicserverauthenticationroote46-ev.sectigo.com",
+                            "https://sectigopublicserverauthenticationroote46-ev.sectigo.com:444");
+
             default: throw new RuntimeException("No test setup found for: " + alias);
         }
     }
diff --git a/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/SectigoCSRootCAs.java b/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/SectigoCSRootCAs.java
new file mode 100644
index 00000000000..80cd1d41cbc
--- /dev/null
+++ b/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/SectigoCSRootCAs.java
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8359170
+ * @summary Interoperability tests with Sectigo Public Code Signing Root CAs
+ * @build ValidatePathWithParams
+ * @run main/othervm/manual -Djava.security.debug=ocsp,certpath SectigoCSRootCAs OCSP
+ * @run main/othervm/manual -Djava.security.debug=certpath SectigoCSRootCAs CRL
+ */
+
+public class SectigoCSRootCAs {
+
+    public static void main(String[] args) throws Exception {
+
+        ValidatePathWithParams pathValidator = new ValidatePathWithParams(null);
+
+        if (args.length >= 1 && "CRL".equalsIgnoreCase(args[0])) {
+            pathValidator.enableCRLCheck();
+        } else {
+            // OCSP check by default
+            pathValidator.enableOCSPCheck();
+        }
+
+        new SectigoCSRootCA_R46().runTest(pathValidator);
+        new SectigoCSRootCA_E46().runTest(pathValidator);
+    }
+}
+
+class SectigoCSRootCA_R46 {
+
+    // Owner: CN=Sectigo Public Code Signing CA R36, O=Sectigo Limited, C=GB
+    // Issuer: CN=Sectigo Public Code Signing Root R46, O=Sectigo Limited, C=GB
+    // Serial number: 621d6d0c52019e3b9079152089211c0a
+    // Valid from: Sun Mar 21 17:00:00 PDT 2021 until: Fri Mar 21 16:59:59
+    // PDT 2036
+    private static final String INT = "-----BEGIN CERTIFICATE-----\n" +
+            "MIIGGjCCBAKgAwIBAgIQYh1tDFIBnjuQeRUgiSEcCjANBgkqhkiG9w0BAQwFADBW\n" +
+            "MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQD\n" +
+            "EyRTZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBSNDYwHhcNMjEwMzIy\n" +
+            "MDAwMDAwWhcNMzYwMzIxMjM1OTU5WjBUMQswCQYDVQQGEwJHQjEYMBYGA1UEChMP\n" +
+            "U2VjdGlnbyBMaW1pdGVkMSswKQYDVQQDEyJTZWN0aWdvIFB1YmxpYyBDb2RlIFNp\n" +
+            "Z25pbmcgQ0EgUjM2MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAmyud\n" +
+            "U/o1P45gBkNqwM/1f/bIU1MYyM7TbH78WAeVF3llMwsRHgBGRmxDeEDIArCS2VCo\n" +
+            "Vk4Y/8j6stIkmYV5Gej4NgNjVQ4BYoDjGMwdjioXan1hlaGFt4Wk9vT0k2oWJMJj\n" +
+            "L9G//N523hAm4jF4UjrW2pvv9+hdPX8tbbAfI3v0VdJiJPFy/7XwiunD7mBxNtec\n" +
+            "M6ytIdUlh08T2z7mJEXZD9OWcJkZk5wDuf2q52PN43jc4T9OkoXZ0arWZVeffvMr\n" +
+            "/iiIROSCzKoDmWABDRzV/UiQ5vqsaeFaqQdzFf4ed8peNWh1OaZXnYvZQgWx/SXi\n" +
+            "JDRSAolRzZEZquE6cbcH747FHncs/Kzcn0Ccv2jrOW+LPmnOyB+tAfiWu01TPhCr\n" +
+            "9VrkxsHC5qFNxaThTG5j4/Kc+ODD2dX/fmBECELcvzUHf9shoFvrn35XGf2RPaNT\n" +
+            "O2uSZ6n9otv7jElspkfK9qEATHZcodp+R4q2OIypxR//YEb3fkDn3UayWW9bAgMB\n" +
+            "AAGjggFkMIIBYDAfBgNVHSMEGDAWgBQy65Ka/zWWSC8oQEJwIDaRXBeF5jAdBgNV\n" +
+            "HQ4EFgQUDyrLIIcouOxvSK4rVKYpqhekzQwwDgYDVR0PAQH/BAQDAgGGMBIGA1Ud\n" +
+            "EwEB/wQIMAYBAf8CAQAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwGwYDVR0gBBQwEjAG\n" +
+            "BgRVHSAAMAgGBmeBDAEEATBLBgNVHR8ERDBCMECgPqA8hjpodHRwOi8vY3JsLnNl\n" +
+            "Y3RpZ28uY29tL1NlY3RpZ29QdWJsaWNDb2RlU2lnbmluZ1Jvb3RSNDYuY3JsMHsG\n" +
+            "CCsGAQUFBwEBBG8wbTBGBggrBgEFBQcwAoY6aHR0cDovL2NydC5zZWN0aWdvLmNv\n" +
+            "bS9TZWN0aWdvUHVibGljQ29kZVNpZ25pbmdSb290UjQ2LnA3YzAjBggrBgEFBQcw\n" +
+            "AYYXaHR0cDovL29jc3Auc2VjdGlnby5jb20wDQYJKoZIhvcNAQEMBQADggIBAAb/\n" +
+            "guF3YzZue6EVIJsT/wT+mHVEYcNWlXHRkT+FoetAQLHI1uBy/YXKZDk8+Y1LoNqH\n" +
+            "rp22AKMGxQtgCivnDHFyAQ9GXTmlk7MjcgQbDCx6mn7yIawsppWkvfPkKaAQsiqa\n" +
+            "T9DnMWBHVNIabGqgQSGTrQWo43MOfsPynhbz2Hyxf5XWKZpRvr3dMapandPfYgoZ\n" +
+            "8iDL2OR3sYztgJrbG6VZ9DoTXFm1g0Rf97Aaen1l4c+w3DC+IkwFkvjFV3jS49ZS\n" +
+            "c4lShKK6BrPTJYs4NG1DGzmpToTnwoqZ8fAmi2XlZnuchC4NPSZaPATHvNIzt+z1\n" +
+            "PHo35D/f7j2pO1S8BCysQDHCbM5Mnomnq5aYcKCsdbh0czchOm8bkinLrYrKpii+\n" +
+            "Tk7pwL7TjRKLXkomm5D1Umds++pip8wH2cQpf93at3VDcOK4N7EwoIJB0kak6pSz\n" +
+            "Eu4I64U6gZs7tS/dGNSljf2OSSnRr7KWzq03zl8l75jy+hOds9TWSenLbjBQUGR9\n" +
+            "6cFr6lEUfAIEHVC1L68Y1GGxx4/eRI82ut83axHMViw1+sVpbPxg51Tbnio1lB93\n" +
+            "079WPFnYaOvfGAA0e0zcfF/M9gXr+korwQTh2Prqooq2bYNMvUoUKD85gnJ+t0sm\n" +
+            "rWrb8dee2CvYZXD5laGtaAxOfy/VKNmwuWuAh9kc\n" +
+            "-----END CERTIFICATE-----";
+
+    // Owner: CN=Sectigo Limited, O=Sectigo Limited, ST=West Yorkshire, C=GB
+    // Issuer: CN=Sectigo Public Code Signing CA R36, O=Sectigo Limited, C=GB
+    // Serial number: c1de046377578f1605414f3fa91bf5f6
+    // Valid from: Wed Jun 04 17:00:00 PDT 2025 until: Fri Jun 05 16:59:59
+    // PDT 2026
+    private static final String VALID = "-----BEGIN CERTIFICATE-----\n" +
+            "MIIGRDCCBKygAwIBAgIRAMHeBGN3V48WBUFPP6kb9fYwDQYJKoZIhvcNAQEMBQAw\n" +
+            "VDELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDErMCkGA1UE\n" +
+            "AxMiU2VjdGlnbyBQdWJsaWMgQ29kZSBTaWduaW5nIENBIFIzNjAeFw0yNTA2MDUw\n" +
+            "MDAwMDBaFw0yNjA2MDUyMzU5NTlaMFoxCzAJBgNVBAYTAkdCMRcwFQYDVQQIDA5X\n" +
+            "ZXN0IFlvcmtzaGlyZTEYMBYGA1UECgwPU2VjdGlnbyBMaW1pdGVkMRgwFgYDVQQD\n" +
+            "DA9TZWN0aWdvIExpbWl0ZWQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC\n" +
+            "AQDCYjakgsoYkqVpENW0MuN5hBZDdIM60WJgBXU7zTAXORntSu/Grn/SQywwTg4o\n" +
+            "ltRcKuCp0Cd5zLAIjtgpVDDACWHgxKUtxerjjBZeGp0+viR+biLL0mVNPXgZZ5bQ\n" +
+            "AnDYVKJaGnPsXQD8l+Bn/R2c4cw7mXjBYp2KrTuqOBkPzk4LmdgpKXjxiw1yYb+n\n" +
+            "WKZ+3BMLIU6/k+LB9+WB6Odrl4Lff1jB4C6XhQELGjZAbpkFB2+Qr0ajIA3ZFXqU\n" +
+            "IMh0j5oD5juuXxryOvCgSBkEwxPHnlXxZBNd3DmrZ9NGClBIGE2f9FOjzo5Rl7lV\n" +
+            "KlzFdFmcH8LaLtWjniF+iT+YZw3Ld1O9VMK7RaHePsS4JYfbjeapoCEgudecmIz4\n" +
+            "5Q2tTjCdR5s/SxiVbynfEw+cAGeiv4sRXNSg0uhZ2eGMHh6mPley2pUoRMR8Qx1U\n" +
+            "0Uzg2NtPsHAo0DIH3jKEWU2zP5UPwCfqKYGaZLNLeGh07NZHBCp3TGp9kPVen5Ib\n" +
+            "tnJssu+pab7fixvbpDM4/r9MkKU6C1IsE6lffyON0PA6LaywwecYTJGpieXqoz03\n" +
+            "5UmQXvAzkb9omIAcQ6yWMZNrqwwG9XRKQEhvG3v7sbFkck1KZOz4r/KHkLx9sIxm\n" +
+            "vngdD/qLFebxPIvPT0GKnvSzuGcdQXVTdkZBBBrunv+XpQIDAQABo4IBiTCCAYUw\n" +
+            "HwYDVR0jBBgwFoAUDyrLIIcouOxvSK4rVKYpqhekzQwwHQYDVR0OBBYEFGMpbbJO\n" +
+            "xiuD6t+HEyA3hjp4devXMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMBMG\n" +
+            "A1UdJQQMMAoGCCsGAQUFBwMDMEoGA1UdIARDMEEwNQYMKwYBBAGyMQECAQMCMCUw\n" +
+            "IwYIKwYBBQUHAgEWF2h0dHBzOi8vc2VjdGlnby5jb20vQ1BTMAgGBmeBDAEEATBJ\n" +
+            "BgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLnNlY3RpZ28uY29tL1NlY3RpZ29Q\n" +
+            "dWJsaWNDb2RlU2lnbmluZ0NBUjM2LmNybDB5BggrBgEFBQcBAQRtMGswRAYIKwYB\n" +
+            "BQUHMAKGOGh0dHA6Ly9jcnQuc2VjdGlnby5jb20vU2VjdGlnb1B1YmxpY0NvZGVT\n" +
+            "aWduaW5nQ0FSMzYuY3J0MCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5zZWN0aWdv\n" +
+            "LmNvbTANBgkqhkiG9w0BAQwFAAOCAYEAP2OCzJ+0hrg4XK3w+Ypoe0G5hKfzZ9RH\n" +
+            "nDcgY8BjgWYVOlN9ad2bU70RfgkZzylkaSt02KHOpkXmYpgfjZsovmyUchvlZ4fU\n" +
+            "RmivZleuO3G/ZvDFX373S40QFDd+lC1LYYUolRVz7/ZU2Vzql4FxsM1psRaW17xj\n" +
+            "jf9qaAvDlOH45eEEkfRUbIDdn1UYqDxdCN+90jtD1vRWkYINvE1T6mq3rHpEVoTS\n" +
+            "dIOgmcSL3MAKMB0LxWUPfoVdhnoUuoIxIAcV1SuR6zej4wHjClEaR8ReT/C23Jr3\n" +
+            "hQ4VDbfGu3gvlZG8/+lNmT+t4WaNPECxbFP0BgbD70FP594mSVH3fgptYiiRN7ez\n" +
+            "iUfOSBeCZpSMm7Z5P0KkxkagyFIR3vzgvqbJS/iaomvd9ZIkd9AwMEhugJpITeZj\n" +
+            "lKSXs+2q2UHQdLTPGVoOjmqyPhDGKAeVVF+jLIUWwtAaAoJm6ooXSp8sAeLA+e+K\n" +
+            "6RUFETVxhCefCjkbWq64OYLXriDb0l+W\n" +
+            "-----END CERTIFICATE-----";
+
+    // Owner: CN=Sectigo Limited, O=Sectigo Limited, ST=West Yorkshire, C=GB
+    // Issuer: CN=Sectigo Public Code Signing CA R36, O=Sectigo Limited, C=GB
+    // Serial number: 5ca6fb60da04db99dedbbc0c37131ec
+    // Valid from: Wed Jun 04 17:00:00 PDT 2025 until: Sun Jun 04 16:59:59
+    // PDT 2028
+    private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" +
+            "MIIGQzCCBKugAwIBAgIQBcpvtg2gTbmd7bvAw3Ex7DANBgkqhkiG9w0BAQwFADBU\n" +
+            "MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSswKQYDVQQD\n" +
+            "EyJTZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgQ0EgUjM2MB4XDTI1MDYwNTAw\n" +
+            "MDAwMFoXDTI4MDYwNDIzNTk1OVowWjELMAkGA1UEBhMCR0IxFzAVBgNVBAgMDldl\n" +
+            "c3QgWW9ya3NoaXJlMRgwFgYDVQQKDA9TZWN0aWdvIExpbWl0ZWQxGDAWBgNVBAMM\n" +
+            "D1NlY3RpZ28gTGltaXRlZDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB\n" +
+            "ALDjoFCMN16zlrcv/saieSYT7FXEhTVDPLNzGAbNdBEX09FoL5EIkiN3biVIbDki\n" +
+            "bIocCFpo/yTrjARG/zz82AjdWHyomdtDjL35CQmgiUX7V8tu64xUfUAgadqm+0PL\n" +
+            "by1LRddKE7chpdJu+EDEmeYDPqcRGM+u8suPgosFf6XfVNFy/FZJiD1c7q6JNZ8i\n" +
+            "5NrvTs0zA9HckKE3uvPO9rw56EyF3SfUz9+zHKHwSElv8nCYpREudUf4yCzPNisK\n" +
+            "MVovzeCo36nzJFEdWTnDOr4mtvfCEGvJOU3mgzpECK7QF+yFifr90SG4lvrwzkig\n" +
+            "wYQymukXmB2gxN1tGOvgLig3Q/b4vljBiEeRPEba/L8YQnaXpR/BnPze8yb2t39l\n" +
+            "bzmnghkWkGA0PAB2vrzpi7pq12fGOD0+ErtAzAl/TAD/UFWwXDQLWX9LXRRKi5E+\n" +
+            "ScTlqLl9U1q9HsWYfM6CvLbc32TByaQ8yBytvsSRB0C0blp7CtP5MAc8j9xJdwAs\n" +
+            "Mj2bvSOfA+NJ0Kdg/tqdHHU6hex2HnGzDiEhovm6u/oAfDp/i2bBKLgARglMfGaC\n" +
+            "hFWeHLL6GAyBezMv+AQNCDCTYDMlqAihVMRUAfYgoHcVCfvTSETTTGdRUDFzIdCA\n" +
+            "wNwSVfykpadsev43I2IF+F3aNgJYuXnpxSCLPngemcgxAgMBAAGjggGJMIIBhTAf\n" +
+            "BgNVHSMEGDAWgBQPKssghyi47G9IritUpimqF6TNDDAdBgNVHQ4EFgQUlff/C/GC\n" +
+            "faJ+Y7ua3hKsCsrW9y4wDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwEwYD\n" +
+            "VR0lBAwwCgYIKwYBBQUHAwMwSgYDVR0gBEMwQTA1BgwrBgEEAbIxAQIBAwIwJTAj\n" +
+            "BggrBgEFBQcCARYXaHR0cHM6Ly9zZWN0aWdvLmNvbS9DUFMwCAYGZ4EMAQQBMEkG\n" +
+            "A1UdHwRCMEAwPqA8oDqGOGh0dHA6Ly9jcmwuc2VjdGlnby5jb20vU2VjdGlnb1B1\n" +
+            "YmxpY0NvZGVTaWduaW5nQ0FSMzYuY3JsMHkGCCsGAQUFBwEBBG0wazBEBggrBgEF\n" +
+            "BQcwAoY4aHR0cDovL2NydC5zZWN0aWdvLmNvbS9TZWN0aWdvUHVibGljQ29kZVNp\n" +
+            "Z25pbmdDQVIzNi5jcnQwIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLnNlY3RpZ28u\n" +
+            "Y29tMA0GCSqGSIb3DQEBDAUAA4IBgQAfVq3mY7ggMcTJeWKKrGxs9RUiuAY0p4Xv\n" +
+            "CHNQViM/tHAn0t/nkPp+d2Ji3Zr6PefN+1F6zmsxsbZHse52JNHWYUwCb/Dx4Vw6\n" +
+            "3Wnc1zhXtZnvUTUfgrivuIsMjUG8yzTdEt/taMKEO0KqlKPsBPgFKveDVVaq9UZa\n" +
+            "FfxTWqgrnvkvP/Lag/YeKKj4cJG+a/MJZJm7kvyaBNKXVAamr/bumoxKDzpD67ds\n" +
+            "n9qwBi2Mv0rRXvZ2SHQXzsJ/zjNKWUhpPVrpypaER7EUxjNuSgC4L8AmfvHiO67v\n" +
+            "9EVIEud+beP3FtCXl/cSHhVeDxiC0KBXXBl9zLBaYvCH+8iABnZLStLgBDtfdkfk\n" +
+            "TZEAGbrNOXJDMnKRxr8y377Zq+KHwfiTnyizACHyMMTi+CCwg1ZFGcLOHa5shByc\n" +
+            "Ln9lYysM1/5vrEjt3ZUw11+pDqbPCGS++xgAwcftKfJ0TZrW/g6NZ9URg+11H9ad\n" +
+            "WalBv2VkhJAFJam9P2Y+pi9luk85sGo=\n" +
+            "-----END CERTIFICATE-----";
+
+    public void runTest(ValidatePathWithParams pathValidator) throws Exception {
+        // Validate valid
+        pathValidator.validate(new String[]{VALID, INT},
+                ValidatePathWithParams.Status.GOOD, null, System.out);
+
+        // Validate Revoked
+        pathValidator.validate(new String[]{REVOKED, INT},
+                ValidatePathWithParams.Status.REVOKED,
+                "Thu Jun 05 10:27:45 PDT 2025", System.out);
+    }
+}
+
+class SectigoCSRootCA_E46 {
+
+    // Owner: CN=Sectigo Public Code Signing CA EV E36, O=Sectigo Limited, C=GB
+    // Issuer: CN=Sectigo Public Code Signing Root E46, O=Sectigo Limited, C=GB
+    // Serial number: 3774434f9eb40e221f9236ca1f2f2717
+    // Valid from: Sun Mar 21 17:00:00 PDT 2021 until: Fri Mar 21 16:59:59
+    // PDT 2036
+    private static final String INT_VALID = "-----BEGIN CERTIFICATE-----\n" +
+            "MIIDMDCCAragAwIBAgIQN3RDT560DiIfkjbKHy8nFzAKBggqhkjOPQQDAzBWMQsw\n" +
+            "CQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQDEyRT\n" +
+            "ZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBFNDYwHhcNMjEwMzIyMDAw\n" +
+            "MDAwWhcNMzYwMzIxMjM1OTU5WjBXMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2Vj\n" +
+            "dGlnbyBMaW1pdGVkMS4wLAYDVQQDEyVTZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25p\n" +
+            "bmcgQ0EgRVYgRTM2MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE3mMV9nNViYoH\n" +
+            "4aSrPwFjpbbeXHw2pMbqezwDGb45uEZQr3qI9Hgt0k4R26o5upfXzJt03F8efu0r\n" +
+            "RNEs4yDDz6OCAWMwggFfMB8GA1UdIwQYMBaAFM99LKCQepgd3bZehcLg2hVx0uVe\n" +
+            "MB0GA1UdDgQWBBQadKQ417m2DrNb+txerj+28HM9iDAOBgNVHQ8BAf8EBAMCAYYw\n" +
+            "EgYDVR0TAQH/BAgwBgEB/wIBADATBgNVHSUEDDAKBggrBgEFBQcDAzAaBgNVHSAE\n" +
+            "EzARMAYGBFUdIAAwBwYFZ4EMAQMwSwYDVR0fBEQwQjBAoD6gPIY6aHR0cDovL2Ny\n" +
+            "bC5zZWN0aWdvLmNvbS9TZWN0aWdvUHVibGljQ29kZVNpZ25pbmdSb290RTQ2LmNy\n" +
+            "bDB7BggrBgEFBQcBAQRvMG0wRgYIKwYBBQUHMAKGOmh0dHA6Ly9jcnQuc2VjdGln\n" +
+            "by5jb20vU2VjdGlnb1B1YmxpY0NvZGVTaWduaW5nUm9vdEU0Ni5wN2MwIwYIKwYB\n" +
+            "BQUHMAGGF2h0dHA6Ly9vY3NwLnNlY3RpZ28uY29tMAoGCCqGSM49BAMDA2gAMGUC\n" +
+            "MQCger3L4CYx2W7HyHzvLaAnNee9QVqOwOrBYZyyqXERLtZg1DscsdoYZ2gszEW3\n" +
+            "zaUCMAaLtcwdoV35ADpru29wChS7kFgXt599Ex27wmL++uJCJth6xYr3nyF2b2YJ\n" +
+            "DAatOw==\n" +
+            "-----END CERTIFICATE-----";
+
+    // Owner: CN=Sectigo Public Code Signing CA E36, O=Sectigo Limited, C=GB
+    // Issuer: CN=Sectigo Public Code Signing Root E46, O=Sectigo Limited, C=GB
+    // Serial number: 3602617636e7034b9cc1fc5ffeac2d54
+    // Valid from: Sun Mar 21 17:00:00 PDT 2021 until: Fri Mar 21 16:59:59
+    // PDT 2036
+    private static final String INT_REVOKED = "-----BEGIN CERTIFICATE-----\n" +
+            "MIIDLjCCArSgAwIBAgIQNgJhdjbnA0ucwfxf/qwtVDAKBggqhkjOPQQDAzBWMQsw\n" +
+            "CQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQDEyRT\n" +
+            "ZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBFNDYwHhcNMjEwMzIyMDAw\n" +
+            "MDAwWhcNMzYwMzIxMjM1OTU5WjBUMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2Vj\n" +
+            "dGlnbyBMaW1pdGVkMSswKQYDVQQDEyJTZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25p\n" +
+            "bmcgQ0EgRTM2MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAElDe1m6jawDhrwMxJ\n" +
+            "yFPhKYf8EGu+lBw3bF5CzmfaH1I7Zi+WAmkeEwS3tiNxzPh8GbBBLtdaRuqGuyWc\n" +
+            "W6ERmaOCAWQwggFgMB8GA1UdIwQYMBaAFM99LKCQepgd3bZehcLg2hVx0uVeMB0G\n" +
+            "A1UdDgQWBBQlDZtt2Bh3t4rDOFFW5cfytf+DajAOBgNVHQ8BAf8EBAMCAYYwEgYD\n" +
+            "VR0TAQH/BAgwBgEB/wIBADATBgNVHSUEDDAKBggrBgEFBQcDAzAbBgNVHSAEFDAS\n" +
+            "MAYGBFUdIAAwCAYGZ4EMAQQBMEsGA1UdHwREMEIwQKA+oDyGOmh0dHA6Ly9jcmwu\n" +
+            "c2VjdGlnby5jb20vU2VjdGlnb1B1YmxpY0NvZGVTaWduaW5nUm9vdEU0Ni5jcmww\n" +
+            "ewYIKwYBBQUHAQEEbzBtMEYGCCsGAQUFBzAChjpodHRwOi8vY3J0LnNlY3RpZ28u\n" +
+            "Y29tL1NlY3RpZ29QdWJsaWNDb2RlU2lnbmluZ1Jvb3RFNDYucDdjMCMGCCsGAQUF\n" +
+            "BzABhhdodHRwOi8vb2NzcC5zZWN0aWdvLmNvbTAKBggqhkjOPQQDAwNoADBlAjBM\n" +
+            "ykNTSVvegC1m17yIi87qgx6QIGbw1Mw2bQ4gtOWBVb/C8ALByC1YK7yQJNLJFTkC\n" +
+            "MQCNBv3fe1eLrGELS5KQD0cEFbXGlzQ5r1mnOHePMqlK5d+rmMxff58/t6bo3QEb\n" +
+            "8SQ=\n" +
+            "-----END CERTIFICATE-----";
+
+    // Owner: CN=Sectigo Limited, O=Sectigo Limited, ST=West Yorkshire, C=GB,
+    // OID.2.5.4.15=Private Organization, OID.1.3.6.1.4.1.311.60.2.1.3=GB,
+    // SERIALNUMBER=04058690
+    // Issuer: CN=Sectigo Public Code Signing CA EV E36, O=Sectigo Limited, C=GB
+    // Serial number: fa2aa131f36b337717ac73f606a6ec49
+    // Valid from: Tue Feb 13 16:00:00 PST 2024 until: Sat Feb 13 15:59:59
+    // PST 2027
+    private static final String VALID = "-----BEGIN CERTIFICATE-----\n" +
+            "MIIDrjCCA1SgAwIBAgIRAPoqoTHzazN3F6xz9gam7EkwCgYIKoZIzj0EAwIwVzEL\n" +
+            "MAkGA1UEBhMCR0IxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDEuMCwGA1UEAxMl\n" +
+            "U2VjdGlnbyBQdWJsaWMgQ29kZSBTaWduaW5nIENBIEVWIEUzNjAeFw0yNDAyMTQw\n" +
+            "MDAwMDBaFw0yNzAyMTMyMzU5NTlaMIGhMREwDwYDVQQFEwgwNDA1ODY5MDETMBEG\n" +
+            "CysGAQQBgjc8AgEDEwJHQjEdMBsGA1UEDxMUUHJpdmF0ZSBPcmdhbml6YXRpb24x\n" +
+            "CzAJBgNVBAYTAkdCMRcwFQYDVQQIDA5XZXN0IFlvcmtzaGlyZTEYMBYGA1UECgwP\n" +
+            "U2VjdGlnbyBMaW1pdGVkMRgwFgYDVQQDDA9TZWN0aWdvIExpbWl0ZWQwWTATBgcq\n" +
+            "hkjOPQIBBggqhkjOPQMBBwNCAASwXGEU01WkW/hWNYza08ZT7i0ZeZ9M1s93JYEB\n" +
+            "rZ/f1Ho1YzxtToqgIK2o+32afablPFYWlE6wGyuL/TYggBpKo4IBtDCCAbAwHwYD\n" +
+            "VR0jBBgwFoAUGnSkONe5tg6zW/rcXq4/tvBzPYgwHQYDVR0OBBYEFHEcsJgcYuDO\n" +
+            "dv1raL6h83a6j9C/MA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMBMGA1Ud\n" +
+            "JQQMMAoGCCsGAQUFBwMDMEkGA1UdIARCMEAwNQYMKwYBBAGyMQECAQYBMCUwIwYI\n" +
+            "KwYBBQUHAgEWF2h0dHBzOi8vc2VjdGlnby5jb20vQ1BTMAcGBWeBDAEDMEsGA1Ud\n" +
+            "HwREMEIwQKA+oDyGOmh0dHA6Ly9jcmwuc2VjdGlnby5jb20vU2VjdGlnb1B1Ymxp\n" +
+            "Y0NvZGVTaWduaW5nQ0FFVkUzNi5jcmwwewYIKwYBBQUHAQEEbzBtMEYGCCsGAQUF\n" +
+            "BzAChjpodHRwOi8vY3J0LnNlY3RpZ28uY29tL1NlY3RpZ29QdWJsaWNDb2RlU2ln\n" +
+            "bmluZ0NBRVZFMzYuY3J0MCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5zZWN0aWdv\n" +
+            "LmNvbTAmBgNVHREEHzAdoBsGCCsGAQUFBwgDoA8wDQwLR0ItMDQwNTg2OTAwCgYI\n" +
+            "KoZIzj0EAwIDSAAwRQIgQVp7IIkEZNmC7GfmT1MSEhDebIjjzd75ZVEEbPP/4ocC\n" +
+            "IQDSyfPDKNMbKNOKrweDLwSE2GZV6nDWbiLz6ZmSZHob8w==\n" +
+            "-----END CERTIFICATE-----";
+
+    // Owner: CN=Sectigo Limited, O=Sectigo Limited, ST=West Yorkshire, C=GB
+    // Issuer: CN=Sectigo Public Code Signing CA E36, O=Sectigo Limited, C=GB
+    // Serial number: a1f601514271f24ca0a31c0d7b856705
+    // Valid from: Wed Jun 04 17:00:00 PDT 2025 until: Sun Jun 04 16:59:59
+    // PDT 2028
+    private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" +
+            "MIIDOTCCAt6gAwIBAgIRAKH2AVFCcfJMoKMcDXuFZwUwCgYIKoZIzj0EAwIwVDEL\n" +
+            "MAkGA1UEBhMCR0IxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDErMCkGA1UEAxMi\n" +
+            "U2VjdGlnbyBQdWJsaWMgQ29kZSBTaWduaW5nIENBIEUzNjAeFw0yNTA2MDUwMDAw\n" +
+            "MDBaFw0yODA2MDQyMzU5NTlaMFoxCzAJBgNVBAYTAkdCMRcwFQYDVQQIDA5XZXN0\n" +
+            "IFlvcmtzaGlyZTEYMBYGA1UECgwPU2VjdGlnbyBMaW1pdGVkMRgwFgYDVQQDDA9T\n" +
+            "ZWN0aWdvIExpbWl0ZWQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASwXGEU01Wk\n" +
+            "W/hWNYza08ZT7i0ZeZ9M1s93JYEBrZ/f1Ho1YzxtToqgIK2o+32afablPFYWlE6w\n" +
+            "GyuL/TYggBpKo4IBiTCCAYUwHwYDVR0jBBgwFoAUJQ2bbdgYd7eKwzhRVuXH8rX/\n" +
+            "g2owHQYDVR0OBBYEFHEcsJgcYuDOdv1raL6h83a6j9C/MA4GA1UdDwEB/wQEAwIH\n" +
+            "gDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMEoGA1UdIARDMEEw\n" +
+            "NQYMKwYBBAGyMQECAQMCMCUwIwYIKwYBBQUHAgEWF2h0dHBzOi8vc2VjdGlnby5j\n" +
+            "b20vQ1BTMAgGBmeBDAEEATBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLnNl\n" +
+            "Y3RpZ28uY29tL1NlY3RpZ29QdWJsaWNDb2RlU2lnbmluZ0NBRTM2LmNybDB5Bggr\n" +
+            "BgEFBQcBAQRtMGswRAYIKwYBBQUHMAKGOGh0dHA6Ly9jcnQuc2VjdGlnby5jb20v\n" +
+            "U2VjdGlnb1B1YmxpY0NvZGVTaWduaW5nQ0FFMzYuY3J0MCMGCCsGAQUFBzABhhdo\n" +
+            "dHRwOi8vb2NzcC5zZWN0aWdvLmNvbTAKBggqhkjOPQQDAgNJADBGAiEAlEkiISLz\n" +
+            "PdJsFmVzJ2VZ8hnnVsOBXKbqISFQvIdguJoCIQCH4T0vwxn6uVkJpMvtxiMG/rYg\n" +
+            "jRFhfbxDcVee6likOw==\n" +
+            "-----END CERTIFICATE-----";
+
+    public void runTest(ValidatePathWithParams pathValidator) throws Exception {
+        // Validate valid
+        pathValidator.validate(new String[]{VALID, INT_VALID},
+                ValidatePathWithParams.Status.GOOD, null, System.out);
+
+        // Validate Revoked
+        pathValidator.validate(new String[]{REVOKED, INT_REVOKED},
+                ValidatePathWithParams.Status.REVOKED,
+                "Thu Jun 05 10:27:19 PDT 2025", System.out);
+    }
+}
diff --git a/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java b/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java
index a0e02b32319..45bc5cd39e3 100644
--- a/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java
+++ b/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,7 @@
  *      8223499 8225392 8232019 8234245 8233223 8225068 8225069 8243321 8243320
  *      8243559 8225072 8258630 8259312 8256421 8225081 8225082 8225083 8245654
  *      8305975 8304760 8307134 8295894 8314960 8317373 8317374 8318759 8319187
- *      8321408 8316138 8341057
+ *      8321408 8316138 8341057 8303770 8350498 8359170
  * @summary Check root CA entries in cacerts file
  */
 import java.io.ByteArrayInputStream;
@@ -47,12 +47,12 @@ public class VerifyCACerts {
             + File.separator + "security" + File.separator + "cacerts";
 
     // The numbers of certs now.
-    private static final int COUNT = 112;
+    private static final int COUNT = 113;
 
     // SHA-256 of cacerts, can be generated with
     // shasum -a 256 cacerts | sed -e 's/../&:/g' | tr '[:lower:]' '[:upper:]' | cut -c1-95
     private static final String CHECKSUM
-            = "8F:E0:6F:7F:21:59:33:A6:43:F3:48:FD:A3:4A:8E:28:35:AA:DD:6E:A5:43:56:F1:28:34:48:DF:5C:D2:7C:72";
+            = "1E:63:88:DF:34:AD:7E:61:3F:06:BD:C4:DC:FE:05:52:9B:0D:86:6E:64:DA:E8:25:7C:C0:15:8F:31:C0:2C:78";
 
     // map of cert alias to SHA-256 fingerprint
     @SuppressWarnings("serial")
@@ -66,10 +66,6 @@ public class VerifyCACerts {
                     "ED:F7:EB:BC:A2:7A:2A:38:4D:38:7B:7D:40:10:C6:66:E2:ED:B4:84:3E:4C:29:B4:AE:1D:5B:93:32:E6:B2:4D");
             put("camerfirmachambersca [jdk]",
                     "06:3E:4A:FA:C4:91:DF:D3:32:F3:08:9B:85:42:E9:46:17:D8:93:D7:FE:94:4E:10:A7:93:7E:E2:9D:96:93:C0");
-            put("camerfirmachambersignca [jdk]",
-                    "13:63:35:43:93:34:A7:69:80:16:A0:D3:24:DE:72:28:4E:07:9D:7B:52:20:BB:8F:BD:74:78:16:EE:BE:BA:CA");
-            put("camerfirmachamberscommerceca [jdk]",
-                    "0C:25:8A:12:A5:67:4A:EF:25:F2:8B:A7:DC:FA:EC:EE:A3:48:E5:41:E6:F5:CC:4E:E6:3B:71:B3:61:60:6A:C3");
             put("certumca [jdk]",
                     "D8:E0:FE:BC:1D:B2:E3:8D:00:94:0F:37:D2:7D:41:34:4D:99:3E:73:4B:99:D5:65:6D:97:78:D4:D8:14:36:24");
             put("certumtrustednetworkca [jdk]",
@@ -92,8 +88,6 @@ public class VerifyCACerts {
                     "68:7F:A4:51:38:22:78:FF:F0:C8:B1:1F:8D:43:D5:76:67:1C:6E:B2:BC:EA:B4:13:FB:83:D9:65:D0:6D:2F:F2");
             put("addtrustqualifiedca [jdk]",
                     "80:95:21:08:05:DB:4B:BC:35:5E:44:28:D8:FD:6E:C2:CD:E3:AB:5F:B9:7A:99:42:98:8E:B8:F4:DC:D0:60:16");
-            put("baltimorecybertrustca [jdk]",
-                    "16:AF:57:A9:F6:76:B0:AB:12:60:95:AA:5E:BA:DE:F2:2A:B3:11:19:D6:44:AC:95:CD:4B:93:DB:F3:F2:6A:EB");
             put("digicertglobalrootca [jdk]",
                     "43:48:A0:E9:44:4C:78:CB:26:5E:05:8D:5E:89:44:B4:D8:4F:96:62:BD:26:DB:25:7F:89:34:A4:43:C7:01:61");
             put("digicertglobalrootg2 [jdk]",
@@ -282,6 +276,14 @@ public class VerifyCACerts {
                     "C3:2F:FD:9F:46:F9:36:D1:6C:36:73:99:09:59:43:4B:9A:D6:0A:AF:BB:9E:7C:F3:36:54:F1:44:CC:1B:A1:43");
             put("ssltlsrootrsa2022 [jdk]",
                     "8F:AF:7D:2E:2C:B4:70:9B:B8:E0:B3:36:66:BF:75:A5:DD:45:B5:DE:48:0F:8E:A8:D4:BF:E6:BE:BC:17:F2:ED");
+            put("sectigotlsrootr46 [jdk]",
+                    "7B:B6:47:A6:2A:EE:AC:88:BF:25:7A:A5:22:D0:1F:FE:A3:95:E0:AB:45:C7:3F:93:F6:56:54:EC:38:F2:5A:06");
+            put("sectigotlsroote46 [jdk]",
+                    "C9:0F:26:F0:FB:1B:40:18:B2:22:27:51:9B:5C:A2:B5:3E:2C:A5:B3:BE:5C:F1:8E:FE:1B:EF:47:38:0C:53:83");
+            put("sectigocodesignrootr46 [jdk]",
+                    "7E:76:26:0A:E6:9A:55:D3:F0:60:B0:FD:18:B2:A8:C0:14:43:C8:7B:60:79:10:30:C9:FA:0B:05:85:10:1A:38");
+            put("sectigocodesignroote46 [jdk]",
+                    "8F:63:71:D8:CC:5A:A7:CA:14:96:67:A9:8B:54:96:39:89:51:E4:31:9F:7A:FB:CC:6A:66:0D:67:3E:43:8D:0B");
         }
     };
 
diff --git a/test/jdk/sun/security/pkcs11/KeyStore/ClientAuthData/cert9.db b/test/jdk/sun/security/pkcs11/KeyStore/ClientAuthData/cert9.db
new file mode 100644
index 00000000000..f701c4fc2d4
Binary files /dev/null and b/test/jdk/sun/security/pkcs11/KeyStore/ClientAuthData/cert9.db differ
diff --git a/test/jdk/sun/security/pkcs11/KeyStore/ClientAuthData/key4.db b/test/jdk/sun/security/pkcs11/KeyStore/ClientAuthData/key4.db
new file mode 100644
index 00000000000..3c489989b0a
Binary files /dev/null and b/test/jdk/sun/security/pkcs11/KeyStore/ClientAuthData/key4.db differ
diff --git a/test/jdk/sun/security/pkcs11/PKCS11Test.java b/test/jdk/sun/security/pkcs11/PKCS11Test.java
index 1c0c8d6dcad..97e9ffe8153 100644
--- a/test/jdk/sun/security/pkcs11/PKCS11Test.java
+++ b/test/jdk/sun/security/pkcs11/PKCS11Test.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -56,9 +56,7 @@
 import java.util.ServiceConfigurationError;
 import java.util.ServiceLoader;
 import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import jdk.test.lib.Platform;
 import jdk.test.lib.artifacts.Artifact;
@@ -383,19 +381,13 @@ private static Path getNSSLibPath() throws Exception {
 
     static Path getNSSLibPath(String library) throws Exception {
         String osid = getOsId();
-        String nssLibDir = fetchNssLib(osid);
-        if (nssLibDir == null) {
+        Path libraryName = Path.of(System.mapLibraryName(library));
+        Path nssLibPath = fetchNssLib(osid, libraryName);
+        if (nssLibPath == null) {
             throw new SkippedException("Warning: unsupported OS: " + osid
                     + ", please initialize NSS library location, skipping test");
         }
-
-        String libraryName = System.mapLibraryName(library);
-        Path libPath = Paths.get(nssLibDir).resolve(libraryName);
-        if (!Files.exists(libPath)) {
-            throw new SkippedException("NSS library \"" + libraryName + "\" was not found in " + nssLibDir);
-        }
-
-        return libPath;
+        return nssLibPath;
     }
 
     private static String getOsId() {
@@ -834,42 +826,42 @@ static byte[] generateData(int length) {
         return data;
     }
 
-    private static String fetchNssLib(String osId) {
+    private static Path fetchNssLib(String osId, Path libraryName) {
         switch (osId) {
             case "Windows-amd64-64":
-                return fetchNssLib(WINDOWS_X64.class);
+                return fetchNssLib(WINDOWS_X64.class, libraryName);
 
             case "MacOSX-x86_64-64":
-                return fetchNssLib(MACOSX_X64.class);
+                return fetchNssLib(MACOSX_X64.class, libraryName);
 
             case "MacOSX-aarch64-64":
-                return fetchNssLib(MACOSX_AARCH64.class);
+                return fetchNssLib(MACOSX_AARCH64.class, libraryName);
 
             case "Linux-amd64-64":
                 if (Platform.isOracleLinux7()) {
                     throw new SkippedException("Skipping Oracle Linux prior to v8");
                 } else {
-                    return fetchNssLib(LINUX_X64.class);
+                    return fetchNssLib(LINUX_X64.class, libraryName);
                 }
 
             case "Linux-aarch64-64":
                 if (Platform.isOracleLinux7()) {
                     throw new SkippedException("Skipping Oracle Linux prior to v8");
                 } else {
-                    return fetchNssLib(LINUX_AARCH64.class);
+                    return fetchNssLib(LINUX_AARCH64.class, libraryName);
                 }
             default:
                 return null;
         }
     }
 
-    private static String fetchNssLib(Class clazz) {
-        String path = null;
+    private static Path fetchNssLib(Class clazz, Path libraryName) {
+        Path path = null;
         try {
-            path = ArtifactResolver.resolve(clazz).entrySet().stream()
-                    .findAny().get().getValue() + File.separator + "nss"
-                    + File.separator + "lib" + File.separator;
-        } catch (ArtifactResolverException e) {
+            Path p = ArtifactResolver.resolve(clazz).entrySet().stream()
+                    .findAny().get().getValue();
+            path = findNSSLibrary(p, libraryName);
+        } catch (ArtifactResolverException | IOException e) {
             Throwable cause = e.getCause();
             if (cause == null) {
                 System.out.println("Cannot resolve artifact, "
@@ -883,6 +875,16 @@ private static String fetchNssLib(Class clazz) {
         return path;
     }
 
+    private static Path findNSSLibrary(Path path, Path libraryName) throws IOException {
+        try(Stream files = Files.find(path, 10,
+                (tp, attr) -> tp.getFileName().equals(libraryName))) {
+
+            return files.findAny()
+                        .orElseThrow(() -> new SkippedException(
+                        "NSS library \"" + libraryName + "\" was not found in " + path));
+        }
+    }
+
     public abstract void main(Provider p) throws Exception;
 
     protected boolean skipTest(Provider p) {
@@ -949,14 +951,22 @@ protected void copyNssCertKeyToClassesDir() throws IOException {
 
     protected void copyNssCertKeyToClassesDir(Path dbPath) throws IOException {
         Path destinationPath = Path.of(TEST_CLASSES);
-        String keyDbFile = "key3.db";
-        String certDbFile = "cert8.db";
+        String keyDbFile3 = "key3.db";
+        String keyDbFile4 = "key4.db";
+        String certDbFile8 = "cert8.db";
+        String certDbFile9 = "cert9.db";
 
-        Files.copy(dbPath.resolve(certDbFile),
-                destinationPath.resolve(certDbFile),
+        Files.copy(dbPath.resolve(certDbFile8),
+                destinationPath.resolve(certDbFile8),
+                StandardCopyOption.REPLACE_EXISTING);
+        Files.copy(dbPath.resolve(certDbFile9),
+                destinationPath.resolve(certDbFile9),
+                StandardCopyOption.REPLACE_EXISTING);
+        Files.copy(dbPath.resolve(keyDbFile3),
+                destinationPath.resolve(keyDbFile3),
                 StandardCopyOption.REPLACE_EXISTING);
-        Files.copy(dbPath.resolve(keyDbFile),
-                destinationPath.resolve(keyDbFile),
+        Files.copy(dbPath.resolve(keyDbFile4),
+                destinationPath.resolve(keyDbFile4),
                 StandardCopyOption.REPLACE_EXISTING);
     }
 
diff --git a/test/jdk/sun/security/pkcs11/Provider/MultipleLogins.sh b/test/jdk/sun/security/pkcs11/Provider/MultipleLogins.sh
index c768834da7f..4a50e6782b9 100644
--- a/test/jdk/sun/security/pkcs11/Provider/MultipleLogins.sh
+++ b/test/jdk/sun/security/pkcs11/Provider/MultipleLogins.sh
@@ -99,6 +99,12 @@ esac
 
 # first make cert/key DBs writable
 
+${CP} ${TESTSRC}${FS}..${FS}nss${FS}db${FS}cert9.db ${TESTCLASSES}
+${CHMOD} +w ${TESTCLASSES}${FS}cert9.db
+
+${CP} ${TESTSRC}${FS}..${FS}nss${FS}db${FS}key4.db ${TESTCLASSES}
+${CHMOD} +w ${TESTCLASSES}${FS}key4.db
+
 ${CP} ${TESTSRC}${FS}..${FS}nss${FS}db${FS}cert8.db ${TESTCLASSES}
 ${CHMOD} +w ${TESTCLASSES}${FS}cert8.db
 
diff --git a/test/jdk/sun/security/pkcs11/Secmod/cert9.db b/test/jdk/sun/security/pkcs11/Secmod/cert9.db
index a202bea21e9..b823a79864f 100644
Binary files a/test/jdk/sun/security/pkcs11/Secmod/cert9.db and b/test/jdk/sun/security/pkcs11/Secmod/cert9.db differ
diff --git a/test/jdk/sun/security/pkcs11/Secmod/key4.db b/test/jdk/sun/security/pkcs11/Secmod/key4.db
index 222adb32286..8ddfc4c0fa6 100644
Binary files a/test/jdk/sun/security/pkcs11/Secmod/key4.db and b/test/jdk/sun/security/pkcs11/Secmod/key4.db differ
diff --git a/test/jdk/sun/security/pkcs11/Secmod/pkcs11.txt b/test/jdk/sun/security/pkcs11/Secmod/pkcs11.txt
index 60cc1c56553..d697da07670 100644
--- a/test/jdk/sun/security/pkcs11/Secmod/pkcs11.txt
+++ b/test/jdk/sun/security/pkcs11/Secmod/pkcs11.txt
@@ -1,4 +1,8 @@
 library=
 name=NSS Internal PKCS #11 Module
-parameters=configdir='sql:./tmpdb' certPrefix='' keyPrefix='' secmod='' flags= updatedir='' updateCertPrefix='' updateKeyPrefix='' updateid='' updateTokenDescription='' 
-NSS=Flags=internal,critical trustOrder=75 cipherOrder=100 slotParams=(1={slotFlags=[RSA,DSA,DH,RC2,RC4,DES,RANDOM,SHA1,MD5,MD2,SSL,TLS,AES,Camellia,SEED,SHA256,SHA512] askpw=any timeout=30})
+parameters=configdir='sql:./tmpdb' certPrefix='' keyPrefix='' secmod='secmod.db' flags= updatedir='' updateCertPrefix='' updateKeyPrefix='' updateid='' updateTokenDescription='' 
+NSS=trustOrder=75 cipherOrder=100 slotParams={0x00000001=[slotFlags=RSA,RC4,RC2,DES,DH,SHA1,MD5,MD2,SSL,TLS,AES,RANDOM askpw=any timeout=30 ] }  Flags=internal,critical
+
+library=libnssckbi.so
+name=Builtin Roots Module
+NSS=trustOrder=100    
diff --git a/test/jdk/sun/security/pkcs11/SecmodTest.java b/test/jdk/sun/security/pkcs11/SecmodTest.java
index c5a01b0a739..c1b5e4471ba 100644
--- a/test/jdk/sun/security/pkcs11/SecmodTest.java
+++ b/test/jdk/sun/security/pkcs11/SecmodTest.java
@@ -36,7 +36,7 @@ public class SecmodTest extends PKCS11Test {
     static String DBDIR;
     static char[] password = "test12".toCharArray();
     static String keyAlias = "mykey";
-    static boolean useSqlite = false;
+    static boolean useSqlite = true;
 
     static void useSqlite(boolean b) {
         useSqlite = b;
diff --git a/test/jdk/sun/security/pkcs11/fips/cert9.db b/test/jdk/sun/security/pkcs11/fips/cert9.db
new file mode 100644
index 00000000000..247bdad0abc
Binary files /dev/null and b/test/jdk/sun/security/pkcs11/fips/cert9.db differ
diff --git a/test/jdk/sun/security/pkcs11/fips/key4.db b/test/jdk/sun/security/pkcs11/fips/key4.db
new file mode 100644
index 00000000000..580dd2ebd6b
Binary files /dev/null and b/test/jdk/sun/security/pkcs11/fips/key4.db differ
diff --git a/test/jdk/sun/security/pkcs11/fips/pkcs11.txt b/test/jdk/sun/security/pkcs11/fips/pkcs11.txt
new file mode 100644
index 00000000000..ba339b25c76
--- /dev/null
+++ b/test/jdk/sun/security/pkcs11/fips/pkcs11.txt
@@ -0,0 +1,9 @@
+library=
+name=NSS Internal PKCS #11 Module
+parameters=configdir='sql:./tmpdb' certPrefix='' keyPrefix='' secmod='secmod.db' flags= updatedir='' updateCertPrefix='' updateKeyPrefix='' updateid='' updateTokenDescription='' 
+NSS=trustOrder=75 cipherOrder=100 slotParams={0x00000001=[slotFlags=RSA,RC4,RC2,DES,DH,SHA1,MD5,MD2,SSL,TLS,AES,RANDOM askpw=any timeout=30 ] }  Flags=internal,critical
+
+library=libnssckbi.so
+name=Builtin Roots Module
+NSS=trustOrder=100    
+
diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/Camerfirma.java b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/Camerfirma.java
index 50a723441a5..8d9dfe1ef18 100644
--- a/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/Camerfirma.java
+++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/Camerfirma.java
@@ -21,17 +21,19 @@
  * questions.
  */
 
+import javax.net.ssl.X509TrustManager;
 import java.io.File;
 import java.security.Security;
-import java.time.*;
-import java.util.*;
-import javax.net.ssl.*;
+import java.time.LocalDate;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.util.Date;
 
-/**
+/*
  * @test
- * @bug 8346587
+ * @bug 8346587 8350498
  * @summary Check that TLS Server certificates chaining back to distrusted
- *          Camerfirma roots are invalid
+ *          Camerfirma root are invalid
  * @library /test/lib
  * @modules java.base/sun.security.validator
  * @run main/othervm Camerfirma after policyOn invalid
@@ -42,13 +44,11 @@
 
 public class Camerfirma {
 
-    private static final String certPath = "chains" + File.separator + "camerfirma";
+    private static final String CERT_PATH = "chains" + File.separator + "camerfirma";
 
     // Each of the roots have a test certificate chain stored in a file
     // named "-chain.pem".
-    private static String[] rootsToTest = new String[] {
-            "camerfirmachamberscommerceca", "camerfirmachambersca",
-            "camerfirmachambersignca"};
+    private static final String ROOT_TO_TEST = "camerfirmachambersca";
 
     // Date after the restrictions take effect
     private static final ZonedDateTime DISTRUST_DATE =
@@ -56,7 +56,7 @@ public class Camerfirma {
 
     public static void main(String[] args) throws Exception {
 
-        // All of the test certificates are signed with SHA-1 so we need
+        // All the test certificates are signed with SHA-1, so we need
         // to remove the constraint that disallows SHA-1 certificates.
         String prop = Security.getProperty("jdk.certpath.disabledAlgorithms");
         String newProp = prop.replace(", SHA1 jdkCA & usage TLSServer", "");
@@ -70,6 +70,6 @@ public static void main(String[] args) throws Exception {
         };
 
         Date notBefore = distrust.getNotBefore(DISTRUST_DATE);
-        distrust.testCertificateChain(certPath, notBefore, tms, rootsToTest);
+        distrust.testCertificateChain(CERT_PATH, notBefore, tms, ROOT_TO_TEST);
     }
 }
diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/camerfirma/camerfirmachamberscommerceca-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/camerfirma/camerfirmachamberscommerceca-chain.pem
deleted file mode 100644
index b27d46c17c8..00000000000
--- a/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/camerfirma/camerfirmachamberscommerceca-chain.pem
+++ /dev/null
@@ -1,48 +0,0 @@
-Owner:   CN=AC Camerfirma Certificados Camerales,
-         O=AC Camerfirma SA, SERIALNUMBER=A82743287,
-         L=Madrid (see current address at www.camerfirma.com/address),
-         EMAILADDRESS=ac_camerfirma_cc@camerfirma.com, C=ES
-Issuer:  CN=Chambers of Commerce Root, OU=http://www.chambersign.org,
-         O=AC Camerfirma SA CIF A82743287, C=EU
-Serial number: 5
-Valid from: Mon Feb 09 07:42:47 PST 2004 until: Thu Feb 09 07:42:47 PST 2034
-Certificate fingerprints:
-         SHA1: 9F:36:B4:BE:9D:AF:1C:91:01:B2:D7:61:58:FB:95:CB:53:82:01:10
-         SHA256: C7:D8:43:81:E1:1F:7C:57:46:77:1A:F5:B0:50:DC:51:FC:6F:DA:D6:F6:F3:5B:B5:3A:3D:E9:13:82:2E:A0:9E
-Signature algorithm name: SHA1withRSA (weak)
-Subject Public Key Algorithm: 2048-bit RSA key
-Version: 3
-
------BEGIN CERTIFICATE-----
-MIIFwDCCBKigAwIBAgIBBTANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEn
-MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL
-ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMg
-b2YgQ29tbWVyY2UgUm9vdDAeFw0wNDAyMDkxNTQyNDdaFw0zNDAyMDkxNTQyNDda
-MIHgMQswCQYDVQQGEwJFUzEuMCwGCSqGSIb3DQEJARYfYWNfY2FtZXJmaXJtYV9j
-Y0BjYW1lcmZpcm1hLmNvbTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBh
-ZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ
-QTgyNzQzMjg3MRkwFwYDVQQKExBBQyBDYW1lcmZpcm1hIFNBMS0wKwYDVQQDEyRB
-QyBDYW1lcmZpcm1hIENlcnRpZmljYWRvcyBDYW1lcmFsZXMwggEgMA0GCSqGSIb3
-DQEBAQUAA4IBDQAwggEIAoIBAQCjxnvvj01f36lgGhihRYVf1fAPEXsTJKrY4aLQ
-cEUSh5szZE7VTtGiyMTMc2uCmnaXafjYHK8Lgmy6T9xxGEZ5OS4x6rgtuPyy13AP
-tu3X3Y2kPVLu7ZMw5HoQC64wBj6YcnxTnBwmVW05DjzRXp6OyBIEKEaAB9vv2qEl
-fh/Y234FG6Wd/ut1s0ScRZAo+6CSMNQxaY+ryXKD11uWkzWXJa9UZOasG7z4uPqc
-Gr4/Hz2/CTLDTgp0xkMJYuzOztpUvOACrxlkS2utKUwVlAikJnboNwf/en94RbHN
-zkKc5t0SAbzCf57ueawbzxSdPa+SAC25FNur64FKkfdq5PPjAgEDo4IB5TCCAeEw
-EgYDVR0TAQH/BAgwBgEB/wIBCzA8BgNVHR8ENTAzMDGgL6AthitodHRwOi8vY3Js
-LmNoYW1iZXJzaWduLm9yZy9jaGFtYmVyc3Jvb3QuY3JsMB0GA1UdDgQWBBS2H06d
-HGiRLjdyYOFGj1qlKjExuTCBqwYDVR0jBIGjMIGggBTjlPWxTenboSlbV4tNdgZ2
-4dGiiqGBhKSBgTB/MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJt
-YSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJz
-aWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdIIBADAO
-BgNVHQ8BAf8EBAMCAYYwKgYDVR0RBCMwIYEfYWNfY2FtZXJmaXJtYV9jY0BjYW1l
-cmZpcm1hLmNvbTAnBgNVHRIEIDAegRxjaGFtYmVyc3Jvb3RAY2hhbWJlcnNpZ24u
-b3JnMFsGA1UdIARUMFIwUAYLKwYBBAGBhy4KCQEwQTA/BggrBgEFBQcCARYzaHR0
-cDovL2Nwcy5jYW1lcmZpcm1hLmNvbS9jcHMvYWNfY2FtZXJmaXJtYV9jYy5odG1s
-MA0GCSqGSIb3DQEBBQUAA4IBAQBl8KoPBYL//EBonqQWS0N+hLfxImP1eQ6nac+v
-R5QfF/0w+VCTkShfKwHaa6V/W1dPlVwXSECuvXHkX6DYrtxFGGFB6qxuP1rkIpRs
-sTkAlpvOx3REiFjIkhsijKd/ijvqxjbMbuYU+EFACK/jQIRoj+LEEZ+haiqbALZB
-Iqq/26HTqX0itDosBj6M94YWcIpbTDefQNWCGsSnZcw2+k+az/wAOZT6xAxlnEim
-HpDDlgRsmaLrHpDPDoIRYOih0gbJTnn4mKex9Wgr0sZ+XFl03j+bvcXL1tiuQnwb
-9dMRDe/OdXABT35W4ZzLbpost65ZW3Tx+oi/bLbmu6pbKCgs
------END CERTIFICATE-----
diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/camerfirma/camerfirmachambersignca-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/camerfirma/camerfirmachambersignca-chain.pem
deleted file mode 100644
index 2ab3091439c..00000000000
--- a/test/jdk/sun/security/ssl/X509TrustManagerImpl/distrust/chains/camerfirma/camerfirmachambersignca-chain.pem
+++ /dev/null
@@ -1,62 +0,0 @@
-Owner:   CN=AC Camerfirma - 2009,
-         L=Madrid (see current address at https://www.camerfirma.com/address),
-         SERIALNUMBER=A82743287, O=AC Camerfirma S.A., C=ES
-Issuer:  CN=Global Chambersign Root - 2008,
-         O=AC Camerfirma S.A., SERIALNUMBER=A82743287,
-         L=Madrid (see current address at www.camerfirma.com/address), C=EU
-Serial number: 2
-Valid from: Mon Mar 16 10:16:25 PDT 2009 until: Sun Mar 11 10:16:25 PDT 2029
-Certificate fingerprints:
-         SHA1: BA:BA:69:CF:D5:CC:C9:4D:05:6B:5B:E7:80:5F:E2:03:CB:EB:5C:57
-         SHA256: B6:8D:5D:9B:4E:A6:35:95:7C:0C:32:15:C2:0D:35:B2:21:7B:69:E3:49:C7:A3:04:C4:F9:7F:20:C4:08:1F:88
-Signature algorithm name: SHA1withRSA (weak)
-Subject Public Key Algorithm: 4096-bit RSA key
-Version: 3
-
------BEGIN CERTIFICATE-----
-MIIIPzCCBiegAwIBAgIBAjANBgkqhkiG9w0BAQUFADCBrDELMAkGA1UEBhMCRVUx
-QzBBBgNVBAcTOk1hZHJpZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2Ft
-ZXJmaXJtYS5jb20vYWRkcmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UE
-ChMSQUMgQ2FtZXJmaXJtYSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNp
-Z24gUm9vdCAtIDIwMDgwHhcNMDkwMzE2MTcxNjI1WhcNMjkwMzExMTcxNjI1WjCB
-qjELMAkGA1UEBhMCRVMxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjESMBAG
-A1UEBRMJQTgyNzQzMjg3MUswSQYDVQQHE0JNYWRyaWQgKHNlZSBjdXJyZW50IGFk
-ZHJlc3MgYXQgaHR0cHM6Ly93d3cuY2FtZXJmaXJtYS5jb20vYWRkcmVzcykxHTAb
-BgNVBAMTFEFDIENhbWVyZmlybWEgLSAyMDA5MIICIjANBgkqhkiG9w0BAQEFAAOC
-Ag8AMIICCgKCAgEAmbHxFEYTJmMdPcYiPlWUGZu2+tQo4voohYi3dwCwoVuGdHSp
-kyoqs1B3YGx4u5KT4n0A7+Bb8YQ/QzbNy7UQ4JXAK+rT8JpNeKIvfN4lHnQJaChE
-4fdn0KpvHWymaNq2k+EbQClquZB6OsTLvsivwSuSnyLcUw5rbajj53wq77fwB12y
-phMjwz2AnD1BvHZd3vLOaH1jRQP3zzNmyjT/Oj6+jdux7SBKlJWgQEaKflwcvYyc
-DPFPhGM4KPwEGX61PCrS+l8Lw0Kdy6K4lE+GrfgJrXM5m1Ey1R0c9McYQQPAtYcm
-cOnHHgkJdEAFVDa76T9C+lcMP6DNckbJIyc/ENrmM2v4rq/JnsJKEEx0VLyLizQx
-cGU3gp4ckg0ImQ9hV3H/DLWEqfrPuD++zaV81gpstnc9+pLg0Jibvwg3qvIr7nS5
-acc//qqxH0iJGYoStHW5J5HoM9HcBvhACq5rjzjrNLPYSJqbPJwBHKcql/uUjQ6S
-SVWe3/CeJp6/vGuY1aRXAk9c/8oO0ZDrLKE8LsUgZesTLnWGd1LQcyQf6UMG1nb9
-5C3eZRkCVpKma6Hl/SUQNukerlbLOU9InFGNPdeEVq1Jo62XeEi8KMbTPdXou6Yl
-rpe99dFnOUjVOdY7gfBGSgIVJjORqf/V70jwsxcYz7j6PKl0XulJs06vpSECAwEA
-AaOCAmowggJmMBIGA1UdEwEB/wQIMAYBAf8CAQIwHQYDVR0OBBYEFMgAD/zGUvyf
-2ztkLjK5bi5x82V5MIHhBgNVHSMEgdkwgdaAFLkJypwe29NsOmuu7VTxW5MGNS5e
-oYGypIGvMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3Vy
-cmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAG
-A1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAl
-BgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwOIIJAMnN0+nVfSPO
-MH0GCCsGAQUFBwEBBHEwbzBFBggrBgEFBQcwAoY5aHR0cDovL3d3dy5jYW1lcmZp
-cm1hLmNvbS9jZXJ0cy9yb290X2NoYW1iZXJzaWduLTIwMDguY3J0MCYGCCsGAQUF
-BzABhhpodHRwOi8vb2NzcC5jYW1lcmZpcm1hLmNvbTAOBgNVHQ8BAf8EBAMCAQYw
-PgYDVR0gBDcwNTAzBgRVHSAAMCswKQYIKwYBBQUHAgEWHWh0dHBzOi8vcG9saWN5
-LmNhbWVyZmlybWEuY29tMH4GA1UdHwR3MHUwOKA2oDSGMmh0dHA6Ly9jcmwuY2Ft
-ZXJmaXJtYS5jb20vY2hhbWJlcnNpZ25yb290LTIwMDguY3JsMDmgN6A1hjNodHRw
-Oi8vY3JsMS5jYW1lcmZpcm1hLmNvbS9jaGFtYmVyc2lnbnJvb3QtMjAwOC5jcmww
-DQYJKoZIhvcNAQEFBQADggIBABNYG4jBwoI7e8pCuUyDc6rwpE9H6AgrUdL7O1xK
-TgTjDGBrMOBK+ZPS4Si8J3yZngvSrL694a1HmiiblJ+CmCdNGli2nBBM+OPK3tQB
-4TW6hgkIe3vSNg/9o9y6+MAJcm8Kn0nPCBkSRME87NwvpehtekuF1G2ng1KDVwAn
-F+eCXfNanEwY++vWbJAuPE69Z/0+rCgNyH1PzihiNu6vrUlSlLWKaG34O1DEttX+
-SsWTpEbpH9w5y9Vmw6WQ/B5nfhPM551HaMbiGgSxT9jHmf8APYQ3iT8EktcdTAdw
-m1miiyxfKG+WjPT7P/x8Np1spJZw+sNIDTLdZ0T1XQ6obVkBTFUDSULKW8949HDu
-VSwdl9Hu9lkDzzh9tyVYwwjEWVFZOiD/4TPVLfphf4ZEiyHt5YpNd9kZJIGGDxdc
-CdtzPm2dQODFpv72LnPQHbuBQPJ71zkoAmyeM/1Qj0DlrFsPcYnbRasck1VmYgDc
-Xc0+is0wcgCd7Gpx1zpEeVqwMD96am2xZPzd6nsbXvo+6TzsKLRMJo6nOERwrzuI
-F+/eq3WXxYMt2UenJsHqwSgPJRMdl3SFz0+SZN0viHeLuwb7qaHN74qC6GP8yHGp
-2xe6Z11mJDPLDSrQQ2dOceSJ1LurJgLP7amYmFlWwVnmM7LnfShhMWMV+MDrICnL
-2ksL
------END CERTIFICATE-----
diff --git a/test/jdk/sun/security/tools/jarsigner/TimestampCheck.java b/test/jdk/sun/security/tools/jarsigner/TimestampCheck.java
index eac97a94113..d206ba878f1 100644
--- a/test/jdk/sun/security/tools/jarsigner/TimestampCheck.java
+++ b/test/jdk/sun/security/tools/jarsigner/TimestampCheck.java
@@ -865,7 +865,7 @@ static void prepare() throws Exception {
         }
 
         gencert("tsold", "-ext eku:critical=ts -startdate -40d -validity 500");
-        gencert("tsbefore2019", "-ext eku:critical=ts -startdate 2018/01/01 -validity 3000");
+        gencert("tsbefore2019", "-ext eku:critical=ts -startdate 2018/01/01 -validity 5000");
 
         gencert("tsweak", "-ext eku:critical=ts");
         gencert("tsdisabled", "-ext eku:critical=ts");
diff --git a/test/jdk/sun/security/tools/jarsigner/TsacertOptionTest.java b/test/jdk/sun/security/tools/jarsigner/TsacertOptionTest.java
index bb528955322..3655c01b5b0 100644
--- a/test/jdk/sun/security/tools/jarsigner/TsacertOptionTest.java
+++ b/test/jdk/sun/security/tools/jarsigner/TsacertOptionTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -103,6 +103,7 @@ void start() throws Throwable {
                 "-alias", CA_KEY_ALIAS,
                 "-keystore", KEYSTORE,
                 "-storepass", PASSWORD,
+                "-startdate", "-1M",
                 "-keypass", PASSWORD,
                 "-validity", Integer.toString(VALIDITY),
                 "-infile", "certreq",
diff --git a/test/langtools/jdk/jshell/ExecPtyGetFlagsToSetTest.java b/test/langtools/jdk/jshell/ExecPtyGetFlagsToSetTest.java
index 36f96644961..efd1cd010cd 100644
--- a/test/langtools/jdk/jshell/ExecPtyGetFlagsToSetTest.java
+++ b/test/langtools/jdk/jshell/ExecPtyGetFlagsToSetTest.java
@@ -26,7 +26,7 @@
  * @bug 8224184
  * @summary Control Char  check for pty
  * @modules jdk.internal.le/jdk.internal.org.jline.terminal
- *          jdk.internal.le/jdk.internal.org.jline.terminal.impl
+ *          jdk.internal.le/jdk.internal.org.jline.terminal.impl.exec
  *          jdk.internal.le/jdk.internal.org.jline.terminal.spi
  * @requires (os.family == "linux") | (os.family == "aix")
  */
@@ -35,12 +35,13 @@
 import jdk.internal.org.jline.terminal.Attributes;
 import jdk.internal.org.jline.terminal.Attributes.ControlChar;
 import jdk.internal.org.jline.terminal.Attributes.LocalFlag;
-import jdk.internal.org.jline.terminal.impl.ExecPty;
+import jdk.internal.org.jline.terminal.impl.exec.ExecPty;
+import jdk.internal.org.jline.terminal.spi.SystemStream;
 import jdk.internal.org.jline.terminal.spi.TerminalProvider;
 
 public class ExecPtyGetFlagsToSetTest extends ExecPty {
-    public ExecPtyGetFlagsToSetTest(String name, TerminalProvider.Stream stream) {
-        super(name, stream);
+    public ExecPtyGetFlagsToSetTest(TerminalProvider provider, SystemStream stream, String name) {
+        super(provider, stream, name);
     }
 
     @Override
@@ -50,7 +51,7 @@ protected List getFlagsToSet(Attributes attr, Attributes current) {
 
     public static void main(String[] args) {
         ExecPtyGetFlagsToSetTest testPty =
-            new ExecPtyGetFlagsToSetTest("stty", TerminalProvider.Stream.Output);
+            new ExecPtyGetFlagsToSetTest(null, SystemStream.Output, "stty");
 
         Attributes attr = new Attributes();
         Attributes current = new Attributes();
diff --git a/test/langtools/jdk/jshell/FailOverDirectExecutionControlTest.java b/test/langtools/jdk/jshell/FailOverDirectExecutionControlTest.java
index a094ed4a86f..99457ea2ce6 100644
--- a/test/langtools/jdk/jshell/FailOverDirectExecutionControlTest.java
+++ b/test/langtools/jdk/jshell/FailOverDirectExecutionControlTest.java
@@ -62,6 +62,7 @@ public class FailOverDirectExecutionControlTest extends ExecutionControlTestBase
 
     ClassLoader ccl;
     ExecutionControlProvider provider;
+    Logger logger;
     LogTestHandler hndlr;
     Map> logged;
 
@@ -95,7 +96,7 @@ public void close() throws SecurityException {
     @BeforeMethod
     @Override
     public void setUp() {
-        Logger logger = Logger.getLogger("jdk.jshell.execution");
+        logger = Logger.getLogger("jdk.jshell.execution");
         logger.setLevel(Level.ALL);
         hndlr = new LogTestHandler();
         logger.addHandler(hndlr);
@@ -137,8 +138,8 @@ public void setUp() {
     @Override
     public void tearDown() {
         super.tearDown();
-        Logger logger = Logger.getLogger("jdk.jshell.execution");
         logger.removeHandler(hndlr);
+        logger = null;
         Thread.currentThread().setContextClassLoader(ccl);
     }
 
diff --git a/test/make/TestMakeBase.gmk b/test/make/TestMakeBase.gmk
index ccd0a89cd11..953bae328ea 100644
--- a/test/make/TestMakeBase.gmk
+++ b/test/make/TestMakeBase.gmk
@@ -158,6 +158,62 @@ ifneq ($(READ_WRITE_VALUE), $(READ_WRITE_RESULT))
   $(error Expected: >$(READ_WRITE_VALUE)< - Result: >$(READ_WRITE_RESULT)<)
 endif
 
+TEST_STRING_1 := 1234
+TEST_STRING_2 := 1234$(NEWLINE)
+TEST_STRING_3 := 1234$(NEWLINE)$(NEWLINE)
+
+# Writing a string ending in newline should not add a newline, but if it does
+# not, a newline should be added. We check this by verifying that the size of the
+# file is 5 characters for both test strings.
+TEST_FILE_1 := $(OUTPUT_DIR)/write-file-1
+TEST_FILE_2 := $(OUTPUT_DIR)/write-file-2
+TEST_FILE_3 := $(OUTPUT_DIR)/write-file-3
+
+$(call WriteFile, $(TEST_STRING_1), $(TEST_FILE_1))
+$(call WriteFile, $(TEST_STRING_2), $(TEST_FILE_2))
+$(call WriteFile, $(TEST_STRING_3), $(TEST_FILE_3))
+
+TEST_FILE_1_SIZE := $(strip $(shell $(WC) -c < $(TEST_FILE_1)))
+TEST_FILE_2_SIZE := $(strip $(shell $(WC) -c < $(TEST_FILE_2)))
+TEST_FILE_3_SIZE := $(strip $(shell $(WC) -c < $(TEST_FILE_3)))
+
+ifneq ($(TEST_FILE_1_SIZE), 5)
+  $(error Expected file size 5 for WriteFile 1, got $(TEST_FILE_1_SIZE))
+endif
+ifneq ($(TEST_FILE_2_SIZE), 5)
+  $(error Expected file size 5 for WriteFile 2, got $(TEST_FILE_2_SIZE))
+endif
+ifneq ($(TEST_FILE_3_SIZE), 5)
+  $(error Expected file size 5 for WriteFile 3, got $(TEST_FILE_3_SIZE))
+endif
+
+# Also test append (assumes WriteFile works as expected)
+$(call WriteFile, $(TEST_STRING_1), $(TEST_FILE_1))
+$(call AppendFile, $(TEST_STRING_1), $(TEST_FILE_1))
+$(call AppendFile, $(TEST_STRING_1), $(TEST_FILE_1))
+
+$(call WriteFile, $(TEST_STRING_2), $(TEST_FILE_2))
+$(call AppendFile, $(TEST_STRING_2), $(TEST_FILE_2))
+$(call AppendFile, $(TEST_STRING_2), $(TEST_FILE_2))
+
+$(call WriteFile, $(TEST_STRING_3), $(TEST_FILE_3))
+$(call AppendFile, $(TEST_STRING_3), $(TEST_FILE_3))
+$(call AppendFile, $(TEST_STRING_3), $(TEST_FILE_3))
+
+TEST_FILE_1_SIZE := $(strip $(shell $(WC) -c < $(TEST_FILE_1)))
+TEST_FILE_2_SIZE := $(strip $(shell $(WC) -c < $(TEST_FILE_2)))
+TEST_FILE_3_SIZE := $(strip $(shell $(WC) -c < $(TEST_FILE_3)))
+
+ifneq ($(TEST_FILE_1_SIZE), 15)
+  $(error Expected file size 15 for AppendFile 1, got $(TEST_FILE_1_SIZE))
+endif
+ifneq ($(TEST_FILE_2_SIZE), 15)
+  $(error Expected file size 15 for AppendFile 2, got $(TEST_FILE_2_SIZE))
+endif
+ifneq ($(TEST_FILE_3_SIZE), 15)
+  $(error Expected file size 15 for AppendFile 3, got $(TEST_FILE_3_SIZE))
+endif
+
 ################################################################################
 # Test creating dependencies on make variables