Merge branch 'master' of ssh://git.haiku-os.org/haiku
This commit is contained in:
+1
-1
@@ -199,7 +199,7 @@ rule ExtractArchive directory : entries : archiveFile : grist
|
||||
# <directory> and <archiveFile> combo.
|
||||
#
|
||||
# <directory> - The directory into which to extract the archive file. The
|
||||
# directory is created is by this rule and it is the target
|
||||
# directory is created by this rule and it is the target
|
||||
# that the extract action is associated with.
|
||||
# <entries> - The entries of the archive file one is interested in. The
|
||||
# rule always extracts the complete archive file, from the
|
||||
|
||||
@@ -239,7 +239,8 @@ AddFilesToHaikuImage system add-ons kernel busses usb
|
||||
AddFilesToHaikuImage system add-ons kernel console : vga_text ;
|
||||
AddFilesToHaikuImage system add-ons kernel debugger
|
||||
: <kdebug>demangle $(X86_ONLY)<kdebug>disasm <kdebug>hangman
|
||||
<kdebug>invalidate_on_exit <kdebug>usb_keyboard <kdebug>run_on_exit ;
|
||||
<kdebug>invalidate_on_exit <kdebug>usb_keyboard <kdebug>qrencode
|
||||
<kdebug>run_on_exit ;
|
||||
AddFilesToHaikuImage system add-ons kernel file_systems
|
||||
: $(SYSTEM_ADD_ONS_FILE_SYSTEMS) ;
|
||||
AddFilesToHaikuImage system add-ons kernel generic
|
||||
|
||||
@@ -12,9 +12,9 @@ if [ IsOptionalHaikuImagePackageAdded OpenSSL ] {
|
||||
}
|
||||
|
||||
if $(HAIKU_GCC_VERSION[1]) >= 4 {
|
||||
HAIKU_OPENSSL_PACKAGE = openssl-1.0.0e-x86-gcc4-2011-09-08.zip ;
|
||||
HAIKU_OPENSSL_PACKAGE = openssl-1.0.0j-x86-gcc4-2012-06-19.zip ;
|
||||
} else {
|
||||
HAIKU_OPENSSL_PACKAGE = openssl-1.0.0e-x86-gcc2-2011-09-09.zip ;
|
||||
HAIKU_OPENSSL_PACKAGE = openssl-1.0.0j-x86-gcc2-2012-06-19.zip ;
|
||||
}
|
||||
|
||||
local baseURL = http://haiku-files.org/files/optional-packages ;
|
||||
@@ -369,11 +369,11 @@ if $(TARGET_ARCH) = x86 {
|
||||
local freetypeBaseURL = http://haiku-files.org/files/optional-packages/lib ;
|
||||
if $(TARGET_ARCH) = ppc || $(TARGET_ARCH) = x86 {
|
||||
if $(TARGET_ARCH) = ppc {
|
||||
HAIKU_FREETYPE_FILE = freetype-2.4.6-ppc-gcc4-2012-03-17.zip ;
|
||||
HAIKU_FREETYPE_FILE = freetype-2.4.9-ppc-gcc4-2012-06-26.zip ;
|
||||
} else if $(HAIKU_GCC_VERSION[1]) >= 4 {
|
||||
HAIKU_FREETYPE_FILE = freetype-2.4.6-x86-gcc4-2012-03-15.zip ;
|
||||
HAIKU_FREETYPE_FILE = freetype-2.4.9-x86-gcc4-2012-06-15.zip ;
|
||||
} else {
|
||||
HAIKU_FREETYPE_FILE = freetype-2.4.6-x86-gcc2-2012-03-15.zip ;
|
||||
HAIKU_FREETYPE_FILE = freetype-2.4.9-x86-gcc2-2012-06-19.zip ;
|
||||
}
|
||||
|
||||
local freetypeZipFile = [ DownloadFile $(HAIKU_FREETYPE_FILE)
|
||||
@@ -393,7 +393,7 @@ if $(TARGET_ARCH) = ppc || $(TARGET_ARCH) = x86 {
|
||||
: extracted-freetype ] ;
|
||||
HAIKU_FREETYPE_CURRENT_LIB = [ ExtractArchive $(HAIKU_FREETYPE_DIR)
|
||||
:
|
||||
common/lib/libfreetype.so.6.7.1
|
||||
common/lib/libfreetype.so.6.8.1
|
||||
: $(freetypeZipFile)
|
||||
: extracted-freetype ] ;
|
||||
Depends $(HAIKU_FREETYPE_LIB) $(HAIKU_FREETYPE_CURRENT_LIB) : $(HAIKU_FREETYPE_HEADERS_DEPENDENCY) ;
|
||||
@@ -417,7 +417,7 @@ if [ IsOptionalHaikuImagePackageAdded TagLib ] {
|
||||
}
|
||||
|
||||
local baseURL = http://haiku-files.org/files/optional-packages ;
|
||||
HAIKU_TAGLIB_PACKAGE = taglib-1.6.3-r1a2-x86-gcc2-2010-04-25.zip ;
|
||||
HAIKU_TAGLIB_PACKAGE = taglib-1.6.3-r1a3-x86-gcc2-2011-05-20.zip ;
|
||||
HAIKU_TAGLIB_URL = $(baseURL)/$(HAIKU_TAGLIB_PACKAGE) ;
|
||||
|
||||
if $(HAIKU_BUILD_FEATURE_TAGLIB) {
|
||||
@@ -451,3 +451,36 @@ if $(HAIKU_BUILD_FEATURE_TAGLIB) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# WebKit
|
||||
local webkitBaseURL = http://haiku-files.org/files/optional-packages ;
|
||||
if $(TARGET_ARCH) = x86 {
|
||||
if $(HAIKU_GCC_VERSION[1]) < 4 {
|
||||
Echo "WebKit support not available on gcc $(HAIKU_GCC_VERSION[1])" ;
|
||||
} else {
|
||||
HAIKU_WEBKIT_FILE = webkit-0.1.1-x86-gcc4-2012-07-03.zip ;
|
||||
|
||||
local zipFile = [ DownloadFile $(HAIKU_WEBKIT_FILE)
|
||||
: $(webkitBaseURL)/$(HAIKU_WEBKIT_FILE) ] ;
|
||||
|
||||
HAIKU_WEBKIT_DIR = [ FDirName $(HAIKU_OPTIONAL_BUILD_PACKAGES_DIR)
|
||||
$(HAIKU_WEBKIT_FILE:B) ] ;
|
||||
|
||||
HAIKU_WEBKIT_HEADERS_DEPENDENCY = [ ExtractArchive $(HAIKU_WEBKIT_DIR)
|
||||
: include/ : $(zipFile) : extracted-webkit ] ;
|
||||
|
||||
HAIKU_WEBKIT_LIBS = [ ExtractArchive $(HAIKU_WEBKIT_DIR)
|
||||
:
|
||||
lib/libwtf.so
|
||||
lib/libjavascriptcore.so
|
||||
lib/libwebcore.so
|
||||
lib/libwebkit.so
|
||||
: $(zipFile)
|
||||
: extracted-webkit
|
||||
] ;
|
||||
|
||||
HAIKU_WEBKIT_HEADERS = [ FDirName $(HAIKU_WEBKIT_DIR) include ] ;
|
||||
}
|
||||
} else {
|
||||
Echo "WebKit support not available on $(TARGET_ARCH)" ;
|
||||
}
|
||||
|
||||
@@ -227,78 +227,78 @@ if [ IsOptionalHaikuImagePackageAdded SDLLibs ] {
|
||||
Echo "No optional package SDLLibs available for $(TARGET_ARCH)" ;
|
||||
} else if $(HAIKU_GCC_VERSION[1]) >= 4 {
|
||||
InstallOptionalHaikuImagePackage
|
||||
libsdl-1.2-hg-r1a3-x86-gcc4-2011-05-29.zip
|
||||
: $(baseURL)/lib/libsdl-1.2-hg-r1a3-x86-gcc4-2011-05-29.zip ;
|
||||
libsdl-1.2.15-x86-gcc4-2012-05-31.zip
|
||||
: $(baseURL)/lib/libsdl-1.2.15-x86-gcc4-2012-05-31.zip ;
|
||||
InstallOptionalHaikuImagePackage
|
||||
guilib-1.2.1-r1a3-x86-gcc4-2011-05-26.zip
|
||||
: $(baseURL)/lib/guilib-1.2.1-r1a3-x86-gcc4-2011-05-26.zip ;
|
||||
guilib-1.2.1-x86-gcc4-2012-05-31.zip
|
||||
: $(baseURL)/lib/guilib-1.2.1-x86-gcc4-2012-05-31.zip ;
|
||||
InstallOptionalHaikuImagePackage
|
||||
sdl-gfx-2.0.22-r1a3-x86-gcc4-2011-05-26.zip
|
||||
: $(baseURL)/lib/sdl-gfx-2.0.22-r1a3-x86-gcc4-2011-05-26.zip ;
|
||||
sdl-gfx-2.0.23-x86-gcc4-2011-05-31.zip
|
||||
: $(baseURL)/lib/sdl-gfx-2.0.23-x86-gcc4-2012-05-31.zip ;
|
||||
InstallOptionalHaikuImagePackage
|
||||
sdl-image-1.2.10-r1a3-x86-gcc4-2011-05-26.zip
|
||||
: $(baseURL)/lib/sdl-image-1.2.10-r1a3-x86-gcc4-2011-05-26.zip ;
|
||||
sdl-image-1.2.12-x86-gcc4-2012-05-31.zip
|
||||
: $(baseURL)/lib/sdl-image-1.2.12-x86-gcc4-2011-05-31.zip ;
|
||||
InstallOptionalHaikuImagePackage
|
||||
sdl-mixer-1.2.11-r1a3-x86-gcc4-2011-05-26.zip
|
||||
: $(baseURL)/lib/sdl-mixer-1.2.11-r1a3-x86-gcc4-2011-05-26.zip ;
|
||||
sdl-mixer-1.2.11-x86-gcc4-2012-05-31.zip
|
||||
: $(baseURL)/lib/sdl-mixer-1.2.11-x86-gcc4-2012-05-31.zip ;
|
||||
InstallOptionalHaikuImagePackage
|
||||
sdl-net-1.2.7-r1a3-x86-gcc4-2011-05-26.zip
|
||||
: $(baseURL)/lib/sdl-net-1.2.7-r1a3-x86-gcc4-2011-05-26.zip ;
|
||||
sdl-net-1.2.8-x86-gcc4-2012-05-31.zip
|
||||
: $(baseURL)/lib/sdl-net-1.2.8-x86-gcc4-2012-05-31.zip ;
|
||||
InstallOptionalHaikuImagePackage
|
||||
sdl-sound-1.0.3-r1a3-x86-gcc4-2011-05-26.zip
|
||||
: $(baseURL)/lib/sdl-sound-1.0.3-r1a3-x86-gcc4-2011-05-26.zip ;
|
||||
sdl-sound-1.0.3-x86-gcc4-2012-05-31.zip
|
||||
: $(baseURL)/lib/sdl-sound-1.0.3-x86-gcc4-2012-05-31.zip ;
|
||||
InstallOptionalHaikuImagePackage
|
||||
sdl-rtf-0.1.0-r1a3-x86-gcc4-2011-05-26.zip
|
||||
: $(baseURL)/lib/sdl-rtf-0.1.0-r1a3-x86-gcc4-2011-05-26.zip ;
|
||||
InstallOptionalHaikuImagePackage
|
||||
sdl-ttf-2.0.10-r1a3-x86-gcc4-2011-05-26.zip
|
||||
: $(baseURL)/lib/sdl-ttf-2.0.10-r1a3-x86-gcc4-2011-05-26.zip ;
|
||||
sdl-ttf-2.0.11-x86-gcc4-2012-05-31.zip
|
||||
: $(baseURL)/lib/sdl-ttf-2.0.11-x86-gcc4-2012-05-31.zip ;
|
||||
InstallOptionalHaikuImagePackage
|
||||
sge-030809-r1a3-x86-gcc4-2011-05-26.zip
|
||||
: $(baseURL)/lib/sge-030809-r1a3-x86-gcc4-2011-05-26.zip ;
|
||||
sge-030809-x86-gcc4-2012-05-31.zip
|
||||
: $(baseURL)/lib/sge-030809-x86-gcc4-2012-05-31.zip ;
|
||||
InstallOptionalHaikuImagePackage
|
||||
smjpeg-0.2.1-r1a3-x86-gcc4-2011-05-26.zip
|
||||
: $(baseURL)/lib/smjpeg-0.2.1-r1a3-x86-gcc4-2011-05-26.zip ;
|
||||
smjpeg-0.2.1-x86-gcc4-2012-05-31.zip
|
||||
: $(baseURL)/lib/smjpeg-0.2.1-x86-gcc4-2012-05-31.zip ;
|
||||
InstallOptionalHaikuImagePackage
|
||||
smpeg-0.4.5-r1a3-x86-gcc4-2011-05-26.zip
|
||||
: $(baseURL)/lib/smpeg-0.4.5-r1a3-x86-gcc4-2011-05-26.zip ;
|
||||
smpeg-0.4.5-x86-gcc4-2011-05-31.zip
|
||||
: $(baseURL)/lib/smpeg-0.4.5-x86-gcc4-2012-05-31.zip ;
|
||||
} else {
|
||||
InstallOptionalHaikuImagePackage
|
||||
libsdl-1.2-hg-r1a3-x86-gcc2-2011-05-29.zip
|
||||
: $(baseURL)/lib/libsdl-1.2-hg-r1a3-x86-gcc2-2011-05-29.zip ;
|
||||
libsdl-1.2.15-x86-gcc2-2012-06-24.zip
|
||||
: $(baseURL)/lib/libsdl-1.2.15-x86-gcc2-2012-06-24.zip ;
|
||||
InstallOptionalHaikuImagePackage
|
||||
guilib-1.2.1-r1a3-x86-gcc2-2011-05-19.zip
|
||||
: $(baseURL)/lib/guilib-1.2.1-r1a3-x86-gcc2-2011-05-19.zip ;
|
||||
guilib-1.2.1-x86-gcc2-2012-06-24.zip
|
||||
: $(baseURL)/lib/guilib-1.2.1-x86-gcc2-2012-06-24.zip ;
|
||||
InstallOptionalHaikuImagePackage
|
||||
sdl-gfx-2.0.22-r1a3-x86-gcc2-2011-05-19.zip
|
||||
: $(baseURL)/lib/sdl-gfx-2.0.22-r1a3-x86-gcc2-2011-05-19.zip ;
|
||||
sdl-gfx-2.0.23-x86-gcc2-2012-06-24.zip
|
||||
: $(baseURL)/lib/sdl-gfx-2.0.23-x86-gcc2-2012-06-24.zip ;
|
||||
InstallOptionalHaikuImagePackage
|
||||
sdl-image-1.2.10-x86-r1a3-x86-gcc2-2011-05-19.zip
|
||||
: $(baseURL)/lib/sdl-image-1.2.10-r1a3-x86-gcc2-2011-05-19.zip ;
|
||||
sdl-image-1.2.12-x86-x86-gcc2-2012-06-24.zip
|
||||
: $(baseURL)/lib/sdl-image-1.2.12-x86-gcc2-2012-06-24.zip ;
|
||||
InstallOptionalHaikuImagePackage
|
||||
sdl-mixer-1.2.11-r1a3-x86-gcc2-2011-05-19.zip
|
||||
: $(baseURL)/lib/sdl-mixer-1.2.11-r1a3-x86-gcc2-2011-05-19.zip ;
|
||||
sdl-mixer-1.2.11-x86-gcc2-2012-06-25.zip
|
||||
: $(baseURL)/lib/sdl-mixer-1.2.11-x86-gcc2-2012-06-25.zip ;
|
||||
InstallOptionalHaikuImagePackage
|
||||
sdl-net-1.2.7-r1a3-x86-gcc2-2011-05-19.zip
|
||||
: $(baseURL)/lib/sdl-net-1.2.7-r1a3-x86-gcc2-2011-05-19.zip ;
|
||||
sdl-net-1.2.8-x86-gcc2-2012-06-24.zip
|
||||
: $(baseURL)/lib/sdl-net-1.2.8-x86-gcc2-2012-06-24.zip ;
|
||||
InstallOptionalHaikuImagePackage
|
||||
sdl-sound-1.0.3-r1a3-x86-gcc2-2011-05-19.zip
|
||||
: $(baseURL)/lib/sdl-sound-1.0.3-r1a3-x86-gcc2-2011-05-19.zip ;
|
||||
sdl-sound-1.0.3-x86-gcc2-2012-06-24.zip
|
||||
: $(baseURL)/lib/sdl-sound-1.0.3-x86-gcc2-2012-06-24.zip ;
|
||||
InstallOptionalHaikuImagePackage
|
||||
sdl-rtf-0.1.0-r1a3-x86-gcc2-2011-05-20.zip
|
||||
: $(baseURL)/lib/sdl-rtf-0.1.0-r1a3-x86-gcc2-2011-05-20.zip ;
|
||||
InstallOptionalHaikuImagePackage
|
||||
sdl-ttf-2.0.10-r1a3-x86-gcc2-2011-05-19.zip
|
||||
: $(baseURL)/lib/sdl-ttf-2.0.10-r1a3-x86-gcc2-2011-05-19.zip ;
|
||||
sdl-ttf-2.0.11-x86-gcc2-2012-06-24.zip
|
||||
: $(baseURL)/lib/sdl-ttf-2.0.11-x86-gcc2-2012-06-24.zip ;
|
||||
InstallOptionalHaikuImagePackage
|
||||
sge-030809-r1a3-x86-gcc2-2011-05-19.zip
|
||||
: $(baseURL)/lib/sge-030809-r1a3-x86-gcc2-2011-05-19.zip ;
|
||||
sge-030809-x86-gcc2-2012-06-24.zip
|
||||
: $(baseURL)/lib/sge-030809-x86-gcc2-2012-06-24.zip ;
|
||||
InstallOptionalHaikuImagePackage
|
||||
smjpeg-0.2.1-r1a3-x86-gcc2-2011-05-19.zip
|
||||
: $(baseURL)/lib/smjpeg-0.2.1-r1a3-x86-gcc2-2011-05-19.zip ;
|
||||
smjpeg-0.2.1-x86-gcc2-2012-06-24.zip
|
||||
: $(baseURL)/lib/smjpeg-0.2.1-x86-gcc2-2012-06-24.zip ;
|
||||
InstallOptionalHaikuImagePackage
|
||||
smpeg-0.4.5-r1a3-x86-gcc2-2011-05-20.zip
|
||||
: $(baseURL)/lib/smpeg-0.4.5-r1a3-x86-gcc2-2011-05-20.zip ;
|
||||
smpeg-0.4.5-x86-gcc2-2012-06-24.zip
|
||||
: $(baseURL)/lib/smpeg-0.4.5-x86-gcc2-2012-06-24.zip ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ OptionalPackageDependencies Development : DevelopmentBase Perl ;
|
||||
OptionalPackageDependencies DevelopmentPowerPC : DevelopmentMin ;
|
||||
OptionalPackageDependencies GetText : LibIconv ;
|
||||
OptionalPackageDependencies Git : Expat Curl OpenSSL LibIconv ;
|
||||
OptionalPackageDependencies GitDoc : Man Git ;
|
||||
OptionalPackageDependencies ICU-devel : DevelopmentBase ;
|
||||
OptionalPackageDependencies LibLayout : DevelopmentBase ;
|
||||
OptionalPackageDependencies Man : Groff ;
|
||||
|
||||
+99
-78
@@ -50,6 +50,7 @@ if $(HAIKU_ADD_ALTERNATIVE_GCC_LIBS) = 1
|
||||
# friss - RSS/ATOM/... feeds reader
|
||||
# GetText - a framework to help produce multi-lingual messages.
|
||||
# Git - the distributed version control system
|
||||
# GitDoc - documentation for the distributed version control system
|
||||
# GPerf - the perfect hash function generator.
|
||||
# Groff - text formatter used for man pages
|
||||
# ICU-devel - the headers and lib-links for ICU (for development)
|
||||
@@ -122,13 +123,13 @@ if [ IsOptionalHaikuImagePackageAdded APR ] {
|
||||
Echo "No optional package APR available for $(TARGET_ARCH)" ;
|
||||
} else if $(HAIKU_GCC_VERSION[1]) >= 4 {
|
||||
InstallOptionalHaikuImagePackage
|
||||
apr-1.4.5-x86-gcc4-2011-08-03.zip
|
||||
: $(baseURL)/apr-1.4.5-x86-gcc4-2011-08-03.zip
|
||||
apr-1.4.6-x86-gcc4-2012-06-19.zip
|
||||
: $(baseURL)/apr-1.4.6-x86-gcc4-2012-06-19.zip
|
||||
: : true ;
|
||||
} else {
|
||||
InstallOptionalHaikuImagePackage
|
||||
apr-1.4.5-x86-gcc2-2011-08-02.zip
|
||||
: $(baseURL)/apr-1.4.5-x86-gcc2-2011-08-02.zip
|
||||
apr-1.4.6-x86-gcc2-2012-06-19.zip
|
||||
: $(baseURL)/apr-1.4.6-x86-gcc2-2012-06-19.zip
|
||||
: : true ;
|
||||
}
|
||||
}
|
||||
@@ -140,13 +141,13 @@ if [ IsOptionalHaikuImagePackageAdded APR-util ] {
|
||||
Echo "No optional package APR-util available for $(TARGET_ARCH)" ;
|
||||
} else if $(HAIKU_GCC_VERSION[1]) >= 4 {
|
||||
InstallOptionalHaikuImagePackage
|
||||
apr-util-1.3.12-x86-gcc4-2011-08-03.zip
|
||||
: $(baseURL)/apr-util-1.3.12-x86-gcc4-2011-08-03.zip
|
||||
apr-util-1.4.1-x86-gcc4-2012-06-19.zip
|
||||
: $(baseURL)/apr-util-1.4.1-x86-gcc4-2012-06-19.zip
|
||||
: : true ;
|
||||
} else {
|
||||
InstallOptionalHaikuImagePackage
|
||||
apr-util-1.3.12-x86-gcc2-2011-08-02.zip
|
||||
: $(baseURL)/apr-util-1.3.12-x86-gcc2-2011-08-02.zip
|
||||
apr-util-1.4.1-x86-gcc2-2012-06-19.zip
|
||||
: $(baseURL)/apr-util-1.4.1-x86-gcc2-2012-06-19.zip
|
||||
: : true ;
|
||||
}
|
||||
}
|
||||
@@ -173,11 +174,11 @@ if [ IsOptionalHaikuImagePackageAdded Bazaar ] {
|
||||
if $(TARGET_ARCH) != x86 {
|
||||
Echo "No optional package Bazaar available for $(TARGET_ARCH)" ;
|
||||
} else if $(HAIKU_GCC_VERSION[1]) >= 4 {
|
||||
InstallOptionalHaikuImagePackage bzr-2.6b1-x86-gcc4-2012-03-30.zip
|
||||
: $(baseURL)/bzr-2.6b1-x86-gcc4-2012-03-30.zip ;
|
||||
InstallOptionalHaikuImagePackage bzr-2.5.1-x86-gcc4-2012-06-22.zip
|
||||
: $(baseURL)/bzr-2.5.1-x86-gcc4-2012-06-22.zip ;
|
||||
} else {
|
||||
InstallOptionalHaikuImagePackage bzr-2.6b1-x86-gcc2-2012-03-31.zip
|
||||
: $(baseURL)/bzr-2.6b1-x86-gcc2-2012-03-31.zip ;
|
||||
InstallOptionalHaikuImagePackage bzr-2.5.1-x86-gcc2-2012-06-22.zip
|
||||
: $(baseURL)/bzr-2.5.1-x86-gcc2-2012-06-22.zip ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -358,8 +359,8 @@ if [ IsOptionalHaikuImagePackageAdded Bzip ] {
|
||||
|
||||
# CARootCertificates
|
||||
if [ IsOptionalHaikuImagePackageAdded CARootCertificates ] {
|
||||
InstallOptionalHaikuImagePackage cert-2012-05-02.zip
|
||||
: $(baseURL)/cert-2012-05-02.zip
|
||||
InstallOptionalHaikuImagePackage cert-2012-07-04.zip
|
||||
: $(baseURL)/cert-2012-07-04.zip
|
||||
: common data ssl ;
|
||||
}
|
||||
|
||||
@@ -408,12 +409,12 @@ if [ IsOptionalHaikuImagePackageAdded CDRecord ] {
|
||||
Echo "No optional package CDRecord available for $(TARGET_ARCH)" ;
|
||||
} else if $(HAIKU_GCC_VERSION[1]) >= 4 {
|
||||
InstallOptionalHaikuImagePackage
|
||||
cdrtools-3.01a01-r1a3-x86-gcc4-2011-05-23.zip
|
||||
: $(baseURL)/cdrtools-3.01a01-r1a3-x86-gcc4-2011-05-23.zip ;
|
||||
cdrtools-3.01a06-x86-gcc4-2012-06-19.zip
|
||||
: $(baseURL)/cdrtools-3.01a06-x86-gcc4-2012-06-19.zip ;
|
||||
} else {
|
||||
InstallOptionalHaikuImagePackage
|
||||
cdrtools-3.01a01-r1a3-x86-gcc2-2011-05-17.zip
|
||||
: $(baseURL)/cdrtools-3.01a01-r1a3-x86-gcc2-2011-05-17.zip ;
|
||||
cdrtools-3.01a06-x86-gcc2-2012-06-20.zip
|
||||
: $(baseURL)/cdrtools-3.01a06-x86-gcc2-2012-06-20.zip ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -532,11 +533,11 @@ if [ IsOptionalHaikuImagePackageAdded Curl ] {
|
||||
if $(TARGET_ARCH) != x86 {
|
||||
Echo "No optional package Curl available for $(TARGET_ARCH)" ;
|
||||
} else if $(HAIKU_GCC_VERSION[1]) >= 4 {
|
||||
InstallOptionalHaikuImagePackage curl-7.21.7-x86-gcc4-2012-02-18.zip
|
||||
: $(baseURL)/curl-7.21.7-x86-gcc4-2012-02-18.zip ;
|
||||
InstallOptionalHaikuImagePackage curl-7.26.0-x86-gcc4-2012-06-20.zip
|
||||
: $(baseURL)/curl-7.26.0-x86-gcc4-2012-06-20.zip ;
|
||||
} else {
|
||||
InstallOptionalHaikuImagePackage curl-7.21.7-x86-gcc2-2012-02-18.zip
|
||||
: $(baseURL)/curl-7.21.7-x86-gcc2-2012-02-18.zip ;
|
||||
InstallOptionalHaikuImagePackage curl-7.26.0-x86-gcc2-2012-06-21.zip
|
||||
: $(baseURL)/curl-7.26.0-x86-gcc2-2012-06-21.zip ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -548,13 +549,13 @@ if [ IsOptionalHaikuImagePackageAdded CVS ] {
|
||||
} else {
|
||||
if $(HAIKU_GCC_VERSION[1]) >= 4 {
|
||||
InstallOptionalHaikuImagePackage
|
||||
cvs-1.12.13.1-r1a3-x86-gcc4-2011-05-24.zip
|
||||
: $(baseURL)/cvs-1.12.13.1-r1a3-x86-gcc4-2011-05-24.zip
|
||||
cvs-1.12.13.1-x86-gcc4-2012-06-22.zip
|
||||
: $(baseURL)/cvs-1.12.13.1-x86-gcc4-2012-06-22.zip
|
||||
: : true ;
|
||||
} else {
|
||||
InstallOptionalHaikuImagePackage
|
||||
cvs-1.12.13.1-r1a3-x86-gcc2-2011-05-18.zip
|
||||
: $(baseURL)/cvs-1.12.13.1-r1a3-x86-gcc2-2011-05-18.zip
|
||||
cvs-1.12.13.1-x86-gcc2-2012-06-20.zip
|
||||
: $(baseURL)/cvs-1.12.13.1-x86-gcc2-2012-06-20.zip
|
||||
: : true ;
|
||||
}
|
||||
}
|
||||
@@ -912,8 +913,8 @@ if [ IsOptionalHaikuImagePackageAdded Expat ] {
|
||||
: : true ;
|
||||
} else {
|
||||
InstallOptionalHaikuImagePackage
|
||||
expat-2.0.1-r1a3-x86-gcc2-2011-05-20.zip
|
||||
: $(baseURL)/expat-2.0.1-r1a3-x86-gcc2-2011-05-20.zip
|
||||
expat-2.0.1-x86-gcc2-2012-06-20.zip
|
||||
: $(baseURL)/expat-2.0.1-x86-gcc2-2012-06-20.zip
|
||||
: : true ;
|
||||
}
|
||||
}
|
||||
@@ -983,13 +984,33 @@ if [ IsOptionalHaikuImagePackageAdded Git ] {
|
||||
} else {
|
||||
if $(HAIKU_GCC_VERSION[1]) >= 4 {
|
||||
InstallOptionalHaikuImagePackage
|
||||
git-1.7.7.2-x86-gcc4-2011-11-04.zip
|
||||
: $(baseURL)/git-1.7.7.2-x86-gcc4-2011-11-04.zip
|
||||
git-1.7.10.2-x86-gcc4-2012-06-19.zip
|
||||
: $(baseURL)/git-1.7.10.2-x86-gcc4-2012-06-19.zip
|
||||
: : true ;
|
||||
} else {
|
||||
InstallOptionalHaikuImagePackage
|
||||
git-1.7.7.2-x86-gcc2-2011-11-04.zip
|
||||
: $(baseURL)/git-1.7.7.2-x86-gcc2-2011-11-04.zip
|
||||
git-1.7.10.2-x86-gcc2-2012-06-20.zip
|
||||
: $(baseURL)/git-1.7.10.2-x86-gcc2-2012-06-20.zip
|
||||
: : true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# GitDoc
|
||||
if [ IsOptionalHaikuImagePackageAdded GitDoc ] {
|
||||
if $(TARGET_ARCH) != x86 {
|
||||
Echo "No optional package GitDoc available for $(TARGET_ARCH)" ;
|
||||
} else {
|
||||
if $(HAIKU_GCC_VERSION[1]) >= 4 {
|
||||
InstallOptionalHaikuImagePackage
|
||||
gitdoc-1.7.10.2-x86-gcc4-2012-06-20.zip
|
||||
: $(baseURL)/gitdoc-1.7.10.2-x86-gcc4-2012-06-20.zip
|
||||
: : true ;
|
||||
} else {
|
||||
InstallOptionalHaikuImagePackage
|
||||
gitdoc-1.7.10.2-x86-gcc2-2012-06-20.zip
|
||||
: $(baseURL)/gitdoc-1.7.10.2-x86-gcc2-2012-06-20.zip
|
||||
: : true ;
|
||||
}
|
||||
}
|
||||
@@ -1185,12 +1206,12 @@ if [ IsOptionalHaikuImagePackageAdded LibXML2 ] {
|
||||
} else {
|
||||
if $(HAIKU_GCC_VERSION[1]) >= 4 {
|
||||
InstallOptionalHaikuImagePackage
|
||||
libxml2-2.7.8-r1a3-x86-gcc4-2011-05-24.zip
|
||||
: $(baseURL)/libxml2-2.7.8-r1a3-x86-gcc4-2011-05-24.zip ;
|
||||
libxml2-2.8.0-x86-gcc4-2012-06-18.zip
|
||||
: $(baseURL)/libxml2-2.8.0-x86-gcc4-2012-06-18.zip ;
|
||||
} else {
|
||||
InstallOptionalHaikuImagePackage
|
||||
libxml2-2.7.8-r1a3-x86-gcc2-2011-05-18.zip
|
||||
: $(baseURL)/libxml2-2.7.8-r1a3-x86-gcc2-2011-05-18.zip ;
|
||||
libxml2-2.8.0-x86-gcc2-2012-06-21.zip
|
||||
: $(baseURL)/libxml2-2.8.0-x86-gcc2-2012-06-21.zip ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1254,12 +1275,12 @@ if [ IsOptionalHaikuImagePackageAdded Man ] {
|
||||
Echo "No optional package Man available for $(TARGET_ARCH)" ;
|
||||
} else if $(HAIKU_GCC_VERSION[1]) >= 4 {
|
||||
InstallOptionalHaikuImagePackage
|
||||
man-1.6f-r1a3-x86-gcc4-2011-05-24.zip
|
||||
: $(baseURL)/man-1.6f-r1a3-x86-gcc4-2011-05-24.zip ;
|
||||
man-1.6g-x86-gcc4-2012-06-19.zip
|
||||
: $(baseURL)/man-1.6g-x86-gcc4-2012-06-19.zip ;
|
||||
} else {
|
||||
InstallOptionalHaikuImagePackage
|
||||
man-1.6f-r1a3-x86-gcc2-2011-05-18.zip
|
||||
: $(baseURL)/man-1.6f-r1a3-x86-gcc2-2011-05-18.zip ;
|
||||
man-1.6g-x86-gcc2-2012-06-21.zip
|
||||
: $(baseURL)/man-1.6g-x86-gcc2-2012-06-21.zip ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1277,13 +1298,13 @@ if [ IsOptionalHaikuImagePackageAdded Mercurial ] {
|
||||
} else {
|
||||
if $(HAIKU_GCC_VERSION[1]) >= 4 {
|
||||
InstallOptionalHaikuImagePackage
|
||||
mercurial-1.8.3-r1a3-x86-gcc4-2011-05-24.zip
|
||||
: $(baseURL)/mercurial-1.8.3-r1a3-x86-gcc4-2011-05-24.zip
|
||||
mercurial-2.2.2-x86-gcc4-2012-06-19.zip
|
||||
: $(baseURL)/mercurial-2.2.2-x86-gcc4-2012-06-19.zip
|
||||
: : true ;
|
||||
} else {
|
||||
InstallOptionalHaikuImagePackage
|
||||
mercurial-1.8.3-r1a3-x86-gcc2-2011-05-17.zip
|
||||
: $(baseURL)/mercurial-1.8.3-r1a3-x86-gcc2-2011-05-17.zip
|
||||
mercurial-2.2.2-x86-gcc2-2012-06-20.zip
|
||||
: $(baseURL)/mercurial-2.2.2-x86-gcc2-2012-06-20.zip
|
||||
: : true ;
|
||||
}
|
||||
}
|
||||
@@ -1315,12 +1336,12 @@ if [ IsOptionalHaikuImagePackageAdded Neon ] {
|
||||
} else {
|
||||
if $(HAIKU_GCC_VERSION[1]) >= 4 {
|
||||
InstallOptionalHaikuImagePackage
|
||||
neon-0.29.6-r1a3-x86-gcc4-2011-05-24.zip
|
||||
: $(baseURL)/neon-0.29.6-r1a3-x86-gcc4-2011-05-24.zip ;
|
||||
neon-0.29.6-x86-gcc4-2012-06-19.zip
|
||||
: $(baseURL)/neon-0.29.6-x86-gcc4-2012-06-19.zip ;
|
||||
} else {
|
||||
InstallOptionalHaikuImagePackage
|
||||
neon-0.29.6-r1a3-x86-gcc2-2011-05-18.zip
|
||||
: $(baseURL)/neon-0.29.6-r1a3-x86-gcc2-2011-05-18.zip ;
|
||||
neon-0.29.6-x86-gcc2-2012-06-21.zip
|
||||
: $(baseURL)/neon-0.29.6-x86-gcc2-2012-06-21.zip ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1412,12 +1433,12 @@ if [ IsOptionalHaikuImagePackageAdded OpenSSH ] {
|
||||
|
||||
if $(HAIKU_GCC_VERSION[1]) >= 4 {
|
||||
InstallOptionalHaikuImagePackage
|
||||
openssh-5.9p1-x86-gcc4-2011-11-30.zip
|
||||
: $(baseURL)/openssh-5.9p1-x86-gcc4-2011-11-30.zip ;
|
||||
openssh-6.0p1-x86-gcc4-2012-06-20.zip
|
||||
: $(baseURL)/openssh-6.0p1-x86-gcc4-2012-06-20.zip ;
|
||||
} else {
|
||||
InstallOptionalHaikuImagePackage
|
||||
openssh-5.9p1-x86-gcc2-2011-11-30.zip
|
||||
: $(baseURL)/openssh-5.9p1-x86-gcc2-2011-11-30.zip ;
|
||||
openssh-6.0p1-x86-gcc2-2012-06-21.zip
|
||||
: $(baseURL)/openssh-6.0p1-x86-gcc2-2012-06-21.zip ;
|
||||
}
|
||||
|
||||
AddUserToHaikuImage sshd : 1001 : 100 : /var/empty : /bin/true
|
||||
@@ -1449,12 +1470,12 @@ if [ IsOptionalHaikuImagePackageAdded P7zip ] {
|
||||
} else {
|
||||
if $(HAIKU_GCC_VERSION[1]) >= 4 {
|
||||
InstallOptionalHaikuImagePackage
|
||||
p7zip-9.13-r1a3-x86-gcc4-2011-05-24.zip
|
||||
: $(baseURL)/p7zip-9.13-r1a3-x86-gcc4-2011-05-24.zip ;
|
||||
p7zip-9.20.1-x86-gcc4-2012-06-19.zip
|
||||
: $(baseURL)/p7zip-9.20.1-x86-gcc4-2012-06-19.zip ;
|
||||
} else {
|
||||
InstallOptionalHaikuImagePackage
|
||||
p7zip-9.13-r1a3-x86-gcc2-2011-05-18.zip
|
||||
: $(baseURL)/p7zip-9.13-r1a3-x86-gcc2-2011-05-18.zip ;
|
||||
p7zip-9.20.1-x86-gcc2-2012-06-21.zip
|
||||
: $(baseURL)/p7zip-9.20.1-x86-gcc2-2012-06-21.zip ;
|
||||
}
|
||||
AddExpanderRuleToHaikuImage "application/x-7z-compressed" : .7z
|
||||
: "7za l \\0045s"
|
||||
@@ -1627,12 +1648,12 @@ if [ IsOptionalHaikuImagePackageAdded SQLite ] {
|
||||
} else {
|
||||
if $(HAIKU_GCC_VERSION[1]) >= 4 {
|
||||
InstallOptionalHaikuImagePackage
|
||||
sqlite-3.7.7.1-x86-gcc4-2012-03-30.zip
|
||||
: $(baseURL)/sqlite-3.7.7.1-x86-gcc4-2012-03-30.zip ;
|
||||
sqlite-3.7.13-x86-gcc4-2012-06-19.zip
|
||||
: $(baseURL)/sqlite-3.7.13-x86-gcc4-2012-06-19.zip ;
|
||||
} else {
|
||||
InstallOptionalHaikuImagePackage
|
||||
sqlite-3.7.7.1-x86-gcc2-2012-03-31.zip
|
||||
: $(baseURL)/sqlite-3.7.7.1-x86-gcc2-2012-03-31.zip ;
|
||||
sqlite-3.7.13-x86-gcc2-2012-06-20.zip
|
||||
: $(baseURL)/sqlite-3.7.13-x86-gcc2-2012-06-20.zip ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1645,13 +1666,13 @@ if [ IsOptionalHaikuImagePackageAdded Subversion ] {
|
||||
} else {
|
||||
if $(HAIKU_GCC_VERSION[1]) >= 4 {
|
||||
InstallOptionalHaikuImagePackage
|
||||
subversion-1.6.17-x86-gcc4-2011-08-03.zip
|
||||
: $(baseURL)/subversion-1.6.17-x86-gcc4-2011-08-03.zip
|
||||
subversion-1.6.18-x86-gcc4-2012-06-19.zip
|
||||
: $(baseURL)/subversion-1.6.18-x86-gcc4-2012-06-19.zip
|
||||
: : true ;
|
||||
} else {
|
||||
InstallOptionalHaikuImagePackage
|
||||
subversion-1.6.17-x86-gcc2-2011-08-02.zip
|
||||
: $(baseURL)/subversion-1.6.17-x86-gcc2-2011-08-02.zip
|
||||
subversion-1.6.18-x86-gcc2-2012-06-21.zip
|
||||
: $(baseURL)/subversion-1.6.18-x86-gcc2-2012-06-21.zip
|
||||
: : true ;
|
||||
}
|
||||
}
|
||||
@@ -1681,12 +1702,12 @@ if [ IsOptionalHaikuImagePackageAdded Tar ] {
|
||||
} else {
|
||||
if $(HAIKU_GCC_VERSION[1]) >= 4 {
|
||||
InstallOptionalHaikuImagePackage
|
||||
tar-1.25-r1a3-x86-gcc4-2011-05-24.zip
|
||||
: $(baseURL)/tar-1.25-r1a3-x86-gcc4-2011-05-24.zip ;
|
||||
tar-1.26-x86-gcc4-2012-06-19.zip
|
||||
: $(baseURL)/tar-1.26-x86-gcc4-2012-06-19.zip ;
|
||||
} else {
|
||||
InstallOptionalHaikuImagePackage
|
||||
tar-1.25-r1a3-x86-gcc2-2011-05-20.zip
|
||||
: $(baseURL)/tar-1.25-r1a3-x86-gcc2-2011-05-20.zip ;
|
||||
tar-1.26-x86-gcc2-2012-06-21.zip
|
||||
: $(baseURL)/tar-1.26-x86-gcc2-2012-06-21.zip ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1869,7 +1890,7 @@ if [ IsOptionalHaikuImagePackageAdded WifiFirmwareScriptData ] {
|
||||
# firmware cutter
|
||||
local broadcomFWCutterArchive = b43-fwcutter-012.tar.bz2 ;
|
||||
local broadcomFWCutterURL =
|
||||
http://bu3sch.de/b43/fwcutter/$(broadcomFWCutterArchive) ;
|
||||
http://www.haiku-files.org/files/wifi-firmwares/b43/fwcutter/$(broadcomFWCutterArchive) ;
|
||||
local broadcomFWCutterFile = [ DownloadFile $(broadcomFWCutterArchive)
|
||||
: $(broadcomFWCutterURL) ] ;
|
||||
AddFilesToHaikuImage system data firmware broadcom43xx b43-fwcutter
|
||||
@@ -1889,16 +1910,16 @@ if [ IsOptionalHaikuImagePackageAdded WifiFirmwareScriptData ] {
|
||||
# file containing firmware
|
||||
local broadcom43xxFile ;
|
||||
broadcom43xxFile = [ DownloadFile wl_apsta-3.130.20.0.o
|
||||
: http://downloads.openwrt.org/sources/wl_apsta-3.130.20.0.o ] ;
|
||||
: http://www.haiku-files.org/files/wifi-firmwares/b43/wl_apsta-3.130.20.0.o ] ;
|
||||
AddFilesToHaikuImage system data firmware broadcom43xx
|
||||
: $(broadcom43xxFile) ;
|
||||
|
||||
# marvell88w8335
|
||||
local marvelArchive = malo-firmware-1.4.tgz ;
|
||||
local marvelURL = http://www.nazgul.ch/malo/$(marvelArchive) ;
|
||||
local marvelFile = [ DownloadFile $(marvelArchive) : $(marvelURL) ] ;
|
||||
local marvellArchive = malo-firmware-1.4.tgz ;
|
||||
local marvellURL = http://www.haiku-files.org/files/wifi-firmwares/marvell/$(marvellArchive) ;
|
||||
local marvellFile = [ DownloadFile $(marvellArchive) : $(marvellURL) ] ;
|
||||
AddFilesToHaikuImage system data firmware marvell88w8335
|
||||
: $(marvelFile) ;
|
||||
: $(marvellFile) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1973,11 +1994,11 @@ if [ IsOptionalHaikuImagePackageAdded Yasm ] {
|
||||
Echo "No optional package Yasm available for $(TARGET_ARCH)" ;
|
||||
} else if $(HAIKU_GCC_VERSION[1]) >= 4 {
|
||||
InstallOptionalHaikuImagePackage
|
||||
yasm-1.1.0-r1a3-x86-gcc4-2011-05-24.zip
|
||||
: $(baseURL)/yasm-1.1.0-r1a3-x86-gcc4-2011-05-24.zip ;
|
||||
yasm-1.2.0-x86-gcc4-2012-06-18.zip
|
||||
: $(baseURL)/yasm-1.2.0-x86-gcc4-2012-06-18.zip ;
|
||||
} else {
|
||||
InstallOptionalHaikuImagePackage
|
||||
yasm-1.1.0-r1a3-x86-gcc2-2011-05-17.zip
|
||||
: $(baseURL)/yasm-1.1.0-r1a3-x86-gcc2-2011-05-17.zip ;
|
||||
yasm-1.2.0-x86-gcc2-2012-06-19.zip
|
||||
: $(baseURL)/yasm-1.2.0-x86-gcc2-2012-06-19.zip ;
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -584,6 +584,8 @@ protected:
|
||||
|
||||
virtual void LayoutChanged();
|
||||
|
||||
void ScrollWithMouseWheelDelta(BScrollBar*, float);
|
||||
|
||||
private:
|
||||
void _Layout(bool force, BLayoutContext* context);
|
||||
void _LayoutLeft(BLayout* deleted);
|
||||
|
||||
@@ -19,6 +19,7 @@ extern "C" {
|
||||
debug_alloc_pool* create_debug_alloc_pool();
|
||||
void delete_debug_alloc_pool(debug_alloc_pool* pool);
|
||||
void* debug_malloc(size_t size);
|
||||
void* debug_calloc(size_t num, size_t size);
|
||||
void debug_free(void* address);
|
||||
void debug_heap_init();
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace AVLTreeMapStrategy {
|
||||
typename Node;
|
||||
inline Node* Allocate(const Key& key, const Value& value)
|
||||
inline void Free(Node* node)
|
||||
inline Key GetKey(Node* node) const
|
||||
inline const Key GetKey(const Node* node) const
|
||||
inline Value& GetValue(Node* node) const
|
||||
inline AVLTreeNode* GetAVLTreeNode(Node* node) const
|
||||
inline Node* GetNode(AVLTreeNode* node) const
|
||||
@@ -622,7 +622,7 @@ public:
|
||||
fAllocator.Deallocate(node);
|
||||
}
|
||||
|
||||
inline Key& GetKey(Node* node) const
|
||||
inline const Key& GetKey(const Node* node) const
|
||||
{
|
||||
return node->key;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2010 Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef STRING_FOR_RATE_H
|
||||
#define STRING_FOR_RATE_H
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
|
||||
namespace BPrivate {
|
||||
|
||||
|
||||
const char* string_for_rate(double rate, char* string, size_t stringSize,
|
||||
double base = 1000.0f);
|
||||
|
||||
|
||||
} // namespace BPrivate
|
||||
|
||||
|
||||
using BPrivate::string_for_rate;
|
||||
|
||||
|
||||
#endif // COLOR_QUANTIZER_H
|
||||
@@ -7,5 +7,6 @@ SubInclude HAIKU_TOP src add-ons kernel debugger disasm ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel debugger hangman ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel debugger invalidate_on_exit ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel debugger laplinkll ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel debugger qrencode ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel debugger run_on_exit ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel debugger usb_keyboard ;
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
SubDir HAIKU_TOP src add-ons kernel debugger qrencode ;
|
||||
|
||||
UsePrivateHeaders kernel ;
|
||||
|
||||
DEFINES += HAVE_CONFIG_H ;
|
||||
DEFINES += malloc=debug_malloc ;
|
||||
DEFINES += calloc=debug_calloc ;
|
||||
DEFINES += free=debug_free ;
|
||||
|
||||
KernelAddon <kdebug>qrencode :
|
||||
bitstream.c
|
||||
mask.c
|
||||
mmask.c
|
||||
mqrspec.c
|
||||
qrencode.c
|
||||
qrinput.c
|
||||
qrspec.c
|
||||
rscode.c
|
||||
split.c
|
||||
|
||||
module.cpp
|
||||
;
|
||||
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
* qrencode - QR Code encoder
|
||||
*
|
||||
* Binary sequence class.
|
||||
* Copyright (C) 2006-2011 Kentaro Fukuchi <[email protected]>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bitstream.h"
|
||||
|
||||
BitStream *BitStream_new(void)
|
||||
{
|
||||
BitStream *bstream;
|
||||
|
||||
bstream = (BitStream *)malloc(sizeof(BitStream));
|
||||
if(bstream == NULL) return NULL;
|
||||
|
||||
bstream->length = 0;
|
||||
bstream->data = NULL;
|
||||
|
||||
return bstream;
|
||||
}
|
||||
|
||||
static int BitStream_allocate(BitStream *bstream, int length)
|
||||
{
|
||||
unsigned char *data;
|
||||
|
||||
if(bstream == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
data = (unsigned char *)malloc(length);
|
||||
if(data == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(bstream->data) {
|
||||
free(bstream->data);
|
||||
}
|
||||
bstream->length = length;
|
||||
bstream->data = data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BitStream *BitStream_newFromNum(int bits, unsigned int num)
|
||||
{
|
||||
unsigned int mask;
|
||||
int i;
|
||||
unsigned char *p;
|
||||
BitStream *bstream;
|
||||
|
||||
bstream = BitStream_new();
|
||||
if(bstream == NULL) return NULL;
|
||||
|
||||
if(BitStream_allocate(bstream, bits)) {
|
||||
BitStream_free(bstream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p = bstream->data;
|
||||
mask = 1 << (bits - 1);
|
||||
for(i=0; i<bits; i++) {
|
||||
if(num & mask) {
|
||||
*p = 1;
|
||||
} else {
|
||||
*p = 0;
|
||||
}
|
||||
p++;
|
||||
mask = mask >> 1;
|
||||
}
|
||||
|
||||
return bstream;
|
||||
}
|
||||
|
||||
static BitStream *BitStream_newFromBytes(int size, unsigned char *data)
|
||||
{
|
||||
unsigned char mask;
|
||||
int i, j;
|
||||
unsigned char *p;
|
||||
BitStream *bstream;
|
||||
|
||||
bstream = BitStream_new();
|
||||
if(bstream == NULL) return NULL;
|
||||
|
||||
if(BitStream_allocate(bstream, size * 8)) {
|
||||
BitStream_free(bstream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p = bstream->data;
|
||||
for(i=0; i<size; i++) {
|
||||
mask = 0x80;
|
||||
for(j=0; j<8; j++) {
|
||||
if(data[i] & mask) {
|
||||
*p = 1;
|
||||
} else {
|
||||
*p = 0;
|
||||
}
|
||||
p++;
|
||||
mask = mask >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
return bstream;
|
||||
}
|
||||
|
||||
int BitStream_append(BitStream *bstream, BitStream *arg)
|
||||
{
|
||||
unsigned char *data;
|
||||
|
||||
if(arg == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if(arg->length == 0) {
|
||||
return 0;
|
||||
}
|
||||
if(bstream->length == 0) {
|
||||
if(BitStream_allocate(bstream, arg->length)) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(bstream->data, arg->data, arg->length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
data = (unsigned char *)malloc(bstream->length + arg->length);
|
||||
if(data == NULL) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(data, bstream->data, bstream->length);
|
||||
memcpy(data + bstream->length, arg->data, arg->length);
|
||||
|
||||
free(bstream->data);
|
||||
bstream->length += arg->length;
|
||||
bstream->data = data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BitStream_appendNum(BitStream *bstream, int bits, unsigned int num)
|
||||
{
|
||||
BitStream *b;
|
||||
int ret;
|
||||
|
||||
if(bits == 0) return 0;
|
||||
|
||||
b = BitStream_newFromNum(bits, num);
|
||||
if(b == NULL) return -1;
|
||||
|
||||
ret = BitStream_append(bstream, b);
|
||||
BitStream_free(b);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int BitStream_appendBytes(BitStream *bstream, int size, unsigned char *data)
|
||||
{
|
||||
BitStream *b;
|
||||
int ret;
|
||||
|
||||
if(size == 0) return 0;
|
||||
|
||||
b = BitStream_newFromBytes(size, data);
|
||||
if(b == NULL) return -1;
|
||||
|
||||
ret = BitStream_append(bstream, b);
|
||||
BitStream_free(b);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned char *BitStream_toByte(BitStream *bstream)
|
||||
{
|
||||
int i, j, size, bytes;
|
||||
unsigned char *data, v;
|
||||
unsigned char *p;
|
||||
|
||||
size = BitStream_size(bstream);
|
||||
if(size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
data = (unsigned char *)malloc((size + 7) / 8);
|
||||
if(data == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bytes = size / 8;
|
||||
|
||||
p = bstream->data;
|
||||
for(i=0; i<bytes; i++) {
|
||||
v = 0;
|
||||
for(j=0; j<8; j++) {
|
||||
v = v << 1;
|
||||
v |= *p;
|
||||
p++;
|
||||
}
|
||||
data[i] = v;
|
||||
}
|
||||
if(size & 7) {
|
||||
v = 0;
|
||||
for(j=0; j<(size & 7); j++) {
|
||||
v = v << 1;
|
||||
v |= *p;
|
||||
p++;
|
||||
}
|
||||
data[bytes] = v;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void BitStream_free(BitStream *bstream)
|
||||
{
|
||||
if(bstream != NULL) {
|
||||
free(bstream->data);
|
||||
free(bstream);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* qrencode - QR Code encoder
|
||||
*
|
||||
* Binary sequence class.
|
||||
* Copyright (C) 2006-2011 Kentaro Fukuchi <[email protected]>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __BITSTREAM_H__
|
||||
#define __BITSTREAM_H__
|
||||
|
||||
typedef struct {
|
||||
int length;
|
||||
unsigned char *data;
|
||||
} BitStream;
|
||||
|
||||
extern BitStream *BitStream_new(void);
|
||||
extern int BitStream_append(BitStream *bstream, BitStream *arg);
|
||||
extern int BitStream_appendNum(BitStream *bstream, int bits, unsigned int num);
|
||||
extern int BitStream_appendBytes(BitStream *bstream, int size, unsigned char *data);
|
||||
#define BitStream_size(__bstream__) (__bstream__->length)
|
||||
extern unsigned char *BitStream_toByte(BitStream *bstream);
|
||||
extern void BitStream_free(BitStream *bstream);
|
||||
|
||||
#endif /* __BITSTREAM_H__ */
|
||||
@@ -0,0 +1,5 @@
|
||||
#define MAJOR_VERSION 3
|
||||
#define MINOR_VERSION 3
|
||||
#define MICRO_VERSION 0
|
||||
#define VERSION "3.3.0"
|
||||
#define __STATIC static
|
||||
@@ -0,0 +1,330 @@
|
||||
/*
|
||||
* qrencode - QR Code encoder
|
||||
*
|
||||
* Masking.
|
||||
* Copyright (C) 2006-2011 Kentaro Fukuchi <[email protected]>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "qrencode.h"
|
||||
#include "qrspec.h"
|
||||
#include "mask.h"
|
||||
|
||||
__STATIC int Mask_writeFormatInformation(int width, unsigned char *frame, int mask, QRecLevel level)
|
||||
{
|
||||
unsigned int format;
|
||||
unsigned char v;
|
||||
int i;
|
||||
int blacks = 0;
|
||||
|
||||
format = QRspec_getFormatInfo(mask, level);
|
||||
|
||||
for(i=0; i<8; i++) {
|
||||
if(format & 1) {
|
||||
blacks += 2;
|
||||
v = 0x85;
|
||||
} else {
|
||||
v = 0x84;
|
||||
}
|
||||
frame[width * 8 + width - 1 - i] = v;
|
||||
if(i < 6) {
|
||||
frame[width * i + 8] = v;
|
||||
} else {
|
||||
frame[width * (i + 1) + 8] = v;
|
||||
}
|
||||
format= format >> 1;
|
||||
}
|
||||
for(i=0; i<7; i++) {
|
||||
if(format & 1) {
|
||||
blacks += 2;
|
||||
v = 0x85;
|
||||
} else {
|
||||
v = 0x84;
|
||||
}
|
||||
frame[width * (width - 7 + i) + 8] = v;
|
||||
if(i == 0) {
|
||||
frame[width * 8 + 7] = v;
|
||||
} else {
|
||||
frame[width * 8 + 6 - i] = v;
|
||||
}
|
||||
format= format >> 1;
|
||||
}
|
||||
|
||||
return blacks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Demerit coefficients.
|
||||
* See Section 8.8.2, pp.45, JIS X0510:2004.
|
||||
*/
|
||||
#define N1 (3)
|
||||
#define N2 (3)
|
||||
#define N3 (40)
|
||||
#define N4 (10)
|
||||
|
||||
#define MASKMAKER(__exp__) \
|
||||
int x, y;\
|
||||
int b = 0;\
|
||||
\
|
||||
for(y=0; y<width; y++) {\
|
||||
for(x=0; x<width; x++) {\
|
||||
if(*s & 0x80) {\
|
||||
*d = *s;\
|
||||
} else {\
|
||||
*d = *s ^ ((__exp__) == 0);\
|
||||
}\
|
||||
b += (int)(*d & 1);\
|
||||
s++; d++;\
|
||||
}\
|
||||
}\
|
||||
return b;
|
||||
|
||||
static int Mask_mask0(int width, const unsigned char *s, unsigned char *d)
|
||||
{
|
||||
MASKMAKER((x+y)&1)
|
||||
}
|
||||
|
||||
static int Mask_mask1(int width, const unsigned char *s, unsigned char *d)
|
||||
{
|
||||
MASKMAKER(y&1)
|
||||
}
|
||||
|
||||
static int Mask_mask2(int width, const unsigned char *s, unsigned char *d)
|
||||
{
|
||||
MASKMAKER(x%3)
|
||||
}
|
||||
|
||||
static int Mask_mask3(int width, const unsigned char *s, unsigned char *d)
|
||||
{
|
||||
MASKMAKER((x+y)%3)
|
||||
}
|
||||
|
||||
static int Mask_mask4(int width, const unsigned char *s, unsigned char *d)
|
||||
{
|
||||
MASKMAKER(((y/2)+(x/3))&1)
|
||||
}
|
||||
|
||||
static int Mask_mask5(int width, const unsigned char *s, unsigned char *d)
|
||||
{
|
||||
MASKMAKER(((x*y)&1)+(x*y)%3)
|
||||
}
|
||||
|
||||
static int Mask_mask6(int width, const unsigned char *s, unsigned char *d)
|
||||
{
|
||||
MASKMAKER((((x*y)&1)+(x*y)%3)&1)
|
||||
}
|
||||
|
||||
static int Mask_mask7(int width, const unsigned char *s, unsigned char *d)
|
||||
{
|
||||
MASKMAKER((((x*y)%3)+((x+y)&1))&1)
|
||||
}
|
||||
|
||||
#define maskNum (8)
|
||||
typedef int MaskMaker(int, const unsigned char *, unsigned char *);
|
||||
static MaskMaker *maskMakers[maskNum] = {
|
||||
Mask_mask0, Mask_mask1, Mask_mask2, Mask_mask3,
|
||||
Mask_mask4, Mask_mask5, Mask_mask6, Mask_mask7
|
||||
};
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
unsigned char *Mask_makeMaskedFrame(int width, unsigned char *frame, int mask)
|
||||
{
|
||||
unsigned char *masked;
|
||||
|
||||
masked = (unsigned char *)malloc(width * width);
|
||||
if(masked == NULL) return NULL;
|
||||
|
||||
maskMakers[mask](width, frame, masked);
|
||||
|
||||
return masked;
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned char *Mask_makeMask(int width, unsigned char *frame, int mask, QRecLevel level)
|
||||
{
|
||||
unsigned char *masked;
|
||||
|
||||
if(mask < 0 || mask >= maskNum) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
masked = (unsigned char *)malloc(width * width);
|
||||
if(masked == NULL) return NULL;
|
||||
|
||||
maskMakers[mask](width, frame, masked);
|
||||
Mask_writeFormatInformation(width, masked, mask, level);
|
||||
|
||||
return masked;
|
||||
}
|
||||
|
||||
|
||||
//static int n1;
|
||||
//static int n2;
|
||||
//static int n3;
|
||||
//static int n4;
|
||||
|
||||
__STATIC int Mask_calcN1N3(int length, int *runLength)
|
||||
{
|
||||
int i;
|
||||
int demerit = 0;
|
||||
int fact;
|
||||
|
||||
for(i=0; i<length; i++) {
|
||||
if(runLength[i] >= 5) {
|
||||
demerit += N1 + (runLength[i] - 5);
|
||||
//n1 += N1 + (runLength[i] - 5);
|
||||
}
|
||||
if((i & 1)) {
|
||||
if(i >= 3 && i < length-2 && (runLength[i] % 3) == 0) {
|
||||
fact = runLength[i] / 3;
|
||||
if(runLength[i-2] == fact &&
|
||||
runLength[i-1] == fact &&
|
||||
runLength[i+1] == fact &&
|
||||
runLength[i+2] == fact) {
|
||||
if(i == 3 || runLength[i-3] >= 4 * fact) {
|
||||
demerit += N3;
|
||||
//n3 += N3;
|
||||
} else if(i+4 >= length || runLength[i+3] >= 4 * fact) {
|
||||
demerit += N3;
|
||||
//n3 += N3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return demerit;
|
||||
}
|
||||
|
||||
__STATIC int Mask_calcN2(int width, unsigned char *frame)
|
||||
{
|
||||
int x, y;
|
||||
unsigned char *p;
|
||||
unsigned char b22, w22;
|
||||
int demerit = 0;
|
||||
|
||||
p = frame + width + 1;
|
||||
for(y=1; y<width; y++) {
|
||||
for(x=1; x<width; x++) {
|
||||
b22 = p[0] & p[-1] & p[-width] & p [-width-1];
|
||||
w22 = p[0] | p[-1] | p[-width] | p [-width-1];
|
||||
if((b22 | (w22 ^ 1))&1) {
|
||||
demerit += N2;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
return demerit;
|
||||
}
|
||||
|
||||
__STATIC int Mask_calcRunLength(int width, unsigned char *frame, int dir, int *runLength)
|
||||
{
|
||||
int head;
|
||||
int i;
|
||||
unsigned char *p;
|
||||
int pitch;
|
||||
|
||||
pitch = (dir==0)?1:width;
|
||||
if(frame[0] & 1) {
|
||||
runLength[0] = -1;
|
||||
head = 1;
|
||||
} else {
|
||||
head = 0;
|
||||
}
|
||||
runLength[head] = 1;
|
||||
p = frame + pitch;
|
||||
|
||||
for(i=1; i<width; i++) {
|
||||
if((p[0] ^ p[-pitch]) & 1) {
|
||||
head++;
|
||||
runLength[head] = 1;
|
||||
} else {
|
||||
runLength[head]++;
|
||||
}
|
||||
p += pitch;
|
||||
}
|
||||
|
||||
return head + 1;
|
||||
}
|
||||
|
||||
__STATIC int Mask_evaluateSymbol(int width, unsigned char *frame)
|
||||
{
|
||||
int x, y;
|
||||
int demerit = 0;
|
||||
int runLength[QRSPEC_WIDTH_MAX + 1];
|
||||
int length;
|
||||
|
||||
demerit += Mask_calcN2(width, frame);
|
||||
|
||||
for(y=0; y<width; y++) {
|
||||
length = Mask_calcRunLength(width, frame + y * width, 0, runLength);
|
||||
demerit += Mask_calcN1N3(length, runLength);
|
||||
}
|
||||
|
||||
for(x=0; x<width; x++) {
|
||||
length = Mask_calcRunLength(width, frame + x, 1, runLength);
|
||||
demerit += Mask_calcN1N3(length, runLength);
|
||||
}
|
||||
|
||||
return demerit;
|
||||
}
|
||||
|
||||
unsigned char *Mask_mask(int width, unsigned char *frame, QRecLevel level)
|
||||
{
|
||||
int i;
|
||||
unsigned char *mask, *bestMask;
|
||||
int minDemerit = INT_MAX;
|
||||
int blacks;
|
||||
int bratio;
|
||||
int demerit;
|
||||
int w2 = width * width;
|
||||
|
||||
mask = (unsigned char *)malloc(w2);
|
||||
if(mask == NULL) return NULL;
|
||||
bestMask = NULL;
|
||||
|
||||
for(i=0; i<maskNum; i++) {
|
||||
// n1 = n2 = n3 = n4 = 0;
|
||||
demerit = 0;
|
||||
blacks = maskMakers[i](width, frame, mask);
|
||||
blacks += Mask_writeFormatInformation(width, mask, i, level);
|
||||
bratio = (200 * blacks + w2) / w2 / 2; /* (int)(100*blacks/w2+0.5) */
|
||||
demerit = (abs(bratio - 50) / 5) * N4;
|
||||
// n4 = demerit;
|
||||
demerit += Mask_evaluateSymbol(width, mask);
|
||||
// printf("(%d,%d,%d,%d)=%d\n", n1, n2, n3 ,n4, demerit);
|
||||
if(demerit < minDemerit) {
|
||||
minDemerit = demerit;
|
||||
free(bestMask);
|
||||
bestMask = mask;
|
||||
mask = (unsigned char *)malloc(w2);
|
||||
if(mask == NULL) break;
|
||||
}
|
||||
}
|
||||
free(mask);
|
||||
return bestMask;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* qrencode - QR Code encoder
|
||||
*
|
||||
* Masking.
|
||||
* Copyright (C) 2006-2011 Kentaro Fukuchi <[email protected]>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __MASK_H__
|
||||
#define __MASK_H__
|
||||
|
||||
extern unsigned char *Mask_makeMask(int width, unsigned char *frame, int mask, QRecLevel level);
|
||||
extern unsigned char *Mask_mask(int width, unsigned char *frame, QRecLevel level);
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
extern int Mask_calcN2(int width, unsigned char *frame);
|
||||
extern int Mask_calcN1N3(int length, int *runLength);
|
||||
extern int Mask_calcRunLength(int width, unsigned char *frame, int dir, int *runLength);
|
||||
extern int Mask_evaluateSymbol(int width, unsigned char *frame);
|
||||
extern int Mask_writeFormatInformation(int width, unsigned char *frame, int mask, QRecLevel level);
|
||||
extern unsigned char *Mask_makeMaskedFrame(int width, unsigned char *frame, int mask);
|
||||
#endif
|
||||
|
||||
#endif /* __MASK_H__ */
|
||||
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* qrencode - QR Code encoder
|
||||
*
|
||||
* Masking for Micro QR Code.
|
||||
* Copyright (C) 2006-2011 Kentaro Fukuchi <[email protected]>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "qrencode.h"
|
||||
#include "mqrspec.h"
|
||||
#include "mmask.h"
|
||||
|
||||
__STATIC void MMask_writeFormatInformation(int version, int width, unsigned char *frame, int mask, QRecLevel level)
|
||||
{
|
||||
unsigned int format;
|
||||
unsigned char v;
|
||||
int i;
|
||||
|
||||
format = MQRspec_getFormatInfo(mask, version, level);
|
||||
|
||||
for(i=0; i<8; i++) {
|
||||
v = 0x84 | (format & 1);
|
||||
frame[width * (i + 1) + 8] = v;
|
||||
format = format >> 1;
|
||||
}
|
||||
for(i=0; i<7; i++) {
|
||||
v = 0x84 | (format & 1);
|
||||
frame[width * 8 + 7 - i] = v;
|
||||
format = format >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
#define MASKMAKER(__exp__) \
|
||||
int x, y;\
|
||||
\
|
||||
for(y=0; y<width; y++) {\
|
||||
for(x=0; x<width; x++) {\
|
||||
if(*s & 0x80) {\
|
||||
*d = *s;\
|
||||
} else {\
|
||||
*d = *s ^ ((__exp__) == 0);\
|
||||
}\
|
||||
s++; d++;\
|
||||
}\
|
||||
}
|
||||
|
||||
static void Mask_mask0(int width, const unsigned char *s, unsigned char *d)
|
||||
{
|
||||
MASKMAKER(y&1)
|
||||
}
|
||||
|
||||
static void Mask_mask1(int width, const unsigned char *s, unsigned char *d)
|
||||
{
|
||||
MASKMAKER(((y/2)+(x/3))&1)
|
||||
}
|
||||
|
||||
static void Mask_mask2(int width, const unsigned char *s, unsigned char *d)
|
||||
{
|
||||
MASKMAKER((((x*y)&1)+(x*y)%3)&1)
|
||||
}
|
||||
|
||||
static void Mask_mask3(int width, const unsigned char *s, unsigned char *d)
|
||||
{
|
||||
MASKMAKER((((x+y)&1)+((x*y)%3))&1)
|
||||
}
|
||||
|
||||
#define maskNum (4)
|
||||
typedef void MaskMaker(int, const unsigned char *, unsigned char *);
|
||||
static MaskMaker *maskMakers[maskNum] = {
|
||||
Mask_mask0, Mask_mask1, Mask_mask2, Mask_mask3
|
||||
};
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
unsigned char *MMask_makeMaskedFrame(int width, unsigned char *frame, int mask)
|
||||
{
|
||||
unsigned char *masked;
|
||||
|
||||
masked = (unsigned char *)malloc(width * width);
|
||||
if(masked == NULL) return NULL;
|
||||
|
||||
maskMakers[mask](width, frame, masked);
|
||||
|
||||
return masked;
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned char *MMask_makeMask(int version, unsigned char *frame, int mask, QRecLevel level)
|
||||
{
|
||||
unsigned char *masked;
|
||||
int width;
|
||||
|
||||
if(mask < 0 || mask >= maskNum) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
width = MQRspec_getWidth(version);
|
||||
masked = (unsigned char *)malloc(width * width);
|
||||
if(masked == NULL) return NULL;
|
||||
|
||||
maskMakers[mask](width, frame, masked);
|
||||
MMask_writeFormatInformation(version, width, masked, mask, level);
|
||||
|
||||
return masked;
|
||||
}
|
||||
|
||||
__STATIC int MMask_evaluateSymbol(int width, unsigned char *frame)
|
||||
{
|
||||
int x, y;
|
||||
unsigned char *p;
|
||||
int sum1 = 0, sum2 = 0;
|
||||
|
||||
p = frame + width * (width - 1);
|
||||
for(x=1; x<width; x++) {
|
||||
sum1 += (p[x] & 1);
|
||||
}
|
||||
|
||||
p = frame + width * 2 - 1;
|
||||
for(y=1; y<width; y++) {
|
||||
sum2 += (*p & 1);
|
||||
p += width;
|
||||
}
|
||||
|
||||
return (sum1 <= sum2)?(sum1 * 16 + sum2):(sum2 * 16 + sum1);
|
||||
}
|
||||
|
||||
unsigned char *MMask_mask(int version, unsigned char *frame, QRecLevel level)
|
||||
{
|
||||
int i;
|
||||
unsigned char *mask, *bestMask;
|
||||
int maxScore = 0;
|
||||
int score;
|
||||
int width;
|
||||
|
||||
width = MQRspec_getWidth(version);
|
||||
|
||||
mask = (unsigned char *)malloc(width * width);
|
||||
if(mask == NULL) return NULL;
|
||||
bestMask = NULL;
|
||||
|
||||
for(i=0; i<maskNum; i++) {
|
||||
score = 0;
|
||||
maskMakers[i](width, frame, mask);
|
||||
MMask_writeFormatInformation(version, width, mask, i, level);
|
||||
score = MMask_evaluateSymbol(width, mask);
|
||||
if(score > maxScore) {
|
||||
maxScore = score;
|
||||
free(bestMask);
|
||||
bestMask = mask;
|
||||
mask = (unsigned char *)malloc(width * width);
|
||||
if(mask == NULL) break;
|
||||
}
|
||||
}
|
||||
free(mask);
|
||||
return bestMask;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* qrencode - QR Code encoder
|
||||
*
|
||||
* Masking for Micro QR Code.
|
||||
* Copyright (C) 2006-2011 Kentaro Fukuchi <[email protected]>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __MMASK_H__
|
||||
#define __MMASK_H__
|
||||
|
||||
extern unsigned char *MMask_makeMask(int version, unsigned char *frame, int mask, QRecLevel level);
|
||||
extern unsigned char *MMask_mask(int version, unsigned char *frame, QRecLevel level);
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
extern int MMask_evaluateSymbol(int width, unsigned char *frame);
|
||||
extern void MMask_writeFormatInformation(int version, int width, unsigned char *frame, int mask, QRecLevel level);
|
||||
extern unsigned char *MMask_makeMaskedFrame(int width, unsigned char *frame, int mask);
|
||||
#endif
|
||||
|
||||
#endif /* __MMASK_H__ */
|
||||
@@ -0,0 +1,389 @@
|
||||
/*
|
||||
* Copyright 2012, Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <[email protected]>
|
||||
*/
|
||||
|
||||
|
||||
#include <debug.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
extern "C" {
|
||||
#include "qrencode.h"
|
||||
#include "qrspec.h"
|
||||
}
|
||||
|
||||
|
||||
extern "C" {
|
||||
extern void abort_debugger_command();
|
||||
}
|
||||
|
||||
|
||||
static const char* kWebPostBaseURL = "http://mlotz.ch/q";
|
||||
|
||||
static char sStringBuffer[16 * 1024];
|
||||
static char sEncodeBuffer[3 * 1024];
|
||||
static int sBufferPosition = 0;
|
||||
static int sQRCodeVersion = 19;
|
||||
static QRecLevel sQRCodeLevel = QR_ECLEVEL_L;
|
||||
static char sWebPostId[64];
|
||||
static int sWebPostCounter = 0;
|
||||
|
||||
|
||||
static bool
|
||||
qrcode_bit(QRcode* qrCode, int x, int y)
|
||||
{
|
||||
if (x >= qrCode->width || y >= qrCode->width)
|
||||
return false;
|
||||
|
||||
return (qrCode->data[y * qrCode->width + x] & 0x01) == 1;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
move_to_and_clear_line(int line)
|
||||
{
|
||||
kprintf(" \x1b[%dd\x1b[G\x1b[K", line + 1);
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
print_qrcode(QRcode* qrCode, bool waitForKey)
|
||||
{
|
||||
move_to_and_clear_line(0);
|
||||
for (int y = 0; y < qrCode->width; y += 2) {
|
||||
move_to_and_clear_line(y / 2 + 1);
|
||||
kputs(" ");
|
||||
|
||||
for (int x = 0; x < qrCode->width; x++) {
|
||||
bool upper = qrcode_bit(qrCode, x, y);
|
||||
bool lower = qrcode_bit(qrCode, x, y + 1);
|
||||
if (upper == lower)
|
||||
kputs(upper ? "\x11" : " ");
|
||||
else
|
||||
kputs(upper ? "\x12" : "\x13");
|
||||
}
|
||||
}
|
||||
|
||||
move_to_and_clear_line(qrCode->width / 2 + 2);
|
||||
move_to_and_clear_line(qrCode->width / 2 + 3);
|
||||
|
||||
if (waitForKey) {
|
||||
kputs("press q to abort or any other key to continue...\x1b[1B\x1b[G");
|
||||
if (kgetc() == 'q')
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
encode_url(const char* query, const char* data, int encodeLength,
|
||||
int inputLength)
|
||||
{
|
||||
sEncodeBuffer[0] = 0;
|
||||
strlcat(sEncodeBuffer, kWebPostBaseURL, encodeLength + 1);
|
||||
strlcat(sEncodeBuffer, "?i=", encodeLength + 1);
|
||||
strlcat(sEncodeBuffer, sWebPostId, encodeLength + 1);
|
||||
strlcat(sEncodeBuffer, "&", encodeLength + 1);
|
||||
strlcat(sEncodeBuffer, query, encodeLength + 1);
|
||||
int position = strlcat(sEncodeBuffer, "=", encodeLength + 1);
|
||||
if (position > encodeLength)
|
||||
return -1;
|
||||
|
||||
int copyCount = 0;
|
||||
while (inputLength > 0 && position < encodeLength) {
|
||||
char character = data[copyCount];
|
||||
if ((character >= 'a' && character <= 'z')
|
||||
|| (character >= 'A' && character <= 'Z')
|
||||
|| (character >= '0' && character <= '9')
|
||||
|| character == '.' || character == '-' || character == '_'
|
||||
|| character == '~'
|
||||
// These aren't strictly valid, but seem to work.
|
||||
|| character == '/' || character == '(' || character == ')'
|
||||
|| character == '=' || character == '^' || character == '?'
|
||||
|| character == '|' || character == '*' || character == '@'
|
||||
|| character == ';' || character == ':' || character == ','
|
||||
|| character == '{' || character == '}' || character == '['
|
||||
|| character == ']' || character == '<' || character == '>'
|
||||
|| character == '!' || character == '\\') {
|
||||
sEncodeBuffer[position++] = character;
|
||||
sEncodeBuffer[position] = 0;
|
||||
} else if (character == ' ') {
|
||||
// Encode spaces as '+' as that's shorter than %20.
|
||||
sEncodeBuffer[position++] = '+';
|
||||
sEncodeBuffer[position] = 0;
|
||||
} else {
|
||||
// Encode to a %xx escape.
|
||||
if (encodeLength - position < 3) {
|
||||
// Doesn't fit anymore, we're done.
|
||||
break;
|
||||
}
|
||||
|
||||
char escaped[4];
|
||||
sprintf(escaped, "%%%.2x", character);
|
||||
position = strlcat(sEncodeBuffer, escaped, encodeLength + 1);
|
||||
}
|
||||
|
||||
inputLength--;
|
||||
copyCount++;
|
||||
}
|
||||
|
||||
return copyCount;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
qrencode(int argc, char* argv[])
|
||||
{
|
||||
if (argc > 1 && strcmp(argv[1], "--help") == 0) {
|
||||
kprintf("%s [<string>]\n", argv[0]);
|
||||
kprintf("If an argument is given, encodes that string as a QR code.\n"
|
||||
"Otherwise the current QR buffer is encoded as QR codes.\n"
|
||||
"When encoding from the QR buffer, the buffer is left intact.\n"
|
||||
"use qrclear to clear the QR buffer or qrflush to encode/clear.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char* source = NULL;
|
||||
if (argc < 2) {
|
||||
sStringBuffer[sBufferPosition] = 0;
|
||||
source = sStringBuffer;
|
||||
} else
|
||||
source = argv[1];
|
||||
|
||||
int inputLength = strlen(source);
|
||||
int encodeLength = QRspec_getDataLength(sQRCodeVersion, sQRCodeLevel) - 3;
|
||||
while (inputLength > 0) {
|
||||
int copyCount = 0;
|
||||
if (sWebPostId[0] != 0) {
|
||||
copyCount = encode_url(sWebPostCounter++ == 0 ? "clear" : "d",
|
||||
source, encodeLength, inputLength);
|
||||
if (copyCount < 0) {
|
||||
kprintf("Failed to URL encode buffer.\n");
|
||||
QRcode_clearCache();
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
copyCount = inputLength < encodeLength ? inputLength : encodeLength;
|
||||
memcpy(sEncodeBuffer, source, copyCount);
|
||||
sEncodeBuffer[copyCount] = 0;
|
||||
}
|
||||
|
||||
QRcode* qrCode = QRcode_encodeString8bit(sEncodeBuffer, sQRCodeVersion,
|
||||
sQRCodeLevel);
|
||||
if (qrCode == NULL) {
|
||||
kprintf("Failed to encode buffer into qr code.\n");
|
||||
QRcode_clearCache();
|
||||
return 1;
|
||||
}
|
||||
|
||||
source += copyCount;
|
||||
inputLength -= copyCount;
|
||||
|
||||
bool doContinue = print_qrcode(qrCode, inputLength > 0);
|
||||
QRcode_free(qrCode);
|
||||
|
||||
if (!doContinue) {
|
||||
QRcode_clearCache();
|
||||
abort_debugger_command();
|
||||
// Does not return.
|
||||
}
|
||||
}
|
||||
|
||||
QRcode_clearCache();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
qrclear(int argc, char* argv[])
|
||||
{
|
||||
if (argc > 1 && strcmp(argv[1], "--help") == 0) {
|
||||
kprintf("Clears the current QR buffer.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
sBufferPosition = 0;
|
||||
sStringBuffer[0] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
qrflush(int argc, char* argv[])
|
||||
{
|
||||
if (argc > 1 && strcmp(argv[1], "--help") == 0) {
|
||||
kprintf("Flushes the current QR buffer by encoding QR codes from\n"
|
||||
"the data and then clears the QR buffer.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
qrencode(0, NULL);
|
||||
qrclear(0, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
qrappend(int argc, char* argv[])
|
||||
{
|
||||
if (argc < 2 || (argc > 1 && strcmp(argv[1], "--help") == 0)) {
|
||||
kprintf("%s <string>\n", argv[0]);
|
||||
kprintf("Appends the given string to the QR buffer. Can be used as\n"
|
||||
"the target of a pipe command to accumulate the output of other\n"
|
||||
"commands in the QR buffer.\n"
|
||||
"Note that this command will flush the QR buffer when it runs\n"
|
||||
"full to make room for the new string. This will cause QR codes\n"
|
||||
"to be generated while the append command still runs. As these\n"
|
||||
"implicit flushes only happen to make room in the buffer, the\n"
|
||||
"strings are afterwards appended aren't flushed, so make sure to\n"
|
||||
"execute the qrflush command to generate codes for these as\n"
|
||||
"well.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char* source = argv[1];
|
||||
int length = strlen(source) + 1;
|
||||
|
||||
while (length > 0) {
|
||||
int copyCount = sizeof(sStringBuffer) - sBufferPosition - 1;
|
||||
if (copyCount == 0) {
|
||||
// The buffer is full, we need to flush it.
|
||||
qrflush(0, NULL);
|
||||
}
|
||||
|
||||
if (length < copyCount)
|
||||
copyCount = length;
|
||||
|
||||
memcpy(sStringBuffer + sBufferPosition, source, copyCount);
|
||||
sBufferPosition += copyCount;
|
||||
source += copyCount;
|
||||
length -= copyCount;
|
||||
}
|
||||
|
||||
// Overwrite the 0 byte that was copied extra with a newline.
|
||||
if (sBufferPosition > 0)
|
||||
sStringBuffer[sBufferPosition - 1] = '\n';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
qrconfig(int argc, char* argv[])
|
||||
{
|
||||
if (argc < 2 || (argc > 1 && strcmp(argv[1], "--help") == 0)) {
|
||||
kprintf("%s <version>\n", argv[0]);
|
||||
kprintf("Sets the QR version to be used. Valid versions range from 1\n"
|
||||
"to 40 where each version determines the size of the QR code.\n"
|
||||
"Version 1 is 21x21 in size and each version increments that size\n"
|
||||
"by 4x4 up to 177x177 for version 40.\n"
|
||||
"Bigger QR codes can hold more data, so ideally you use a version\n"
|
||||
"that makes the QR code as big as possible while still fitting on\n"
|
||||
"your screen.\n"
|
||||
"You can test the new config by running qrencode\n"
|
||||
"with a test string.\n"
|
||||
"Note that due to memory constraints in the kernel debugger, some\n"
|
||||
"of the higher versions may actually not work. The kernel\n"
|
||||
"debugger heap size can be adjusted using the KDEBUG_HEAP define\n"
|
||||
"in the kernel_debug_config.h header\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int newVersion = atoi(argv[1]);
|
||||
if (newVersion <= 0 || newVersion > 40) {
|
||||
kprintf("Invalid QR code version supplied, "
|
||||
"must be between 1 and 40.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
sQRCodeVersion = newVersion;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
qrwebpost(int argc, char* argv[])
|
||||
{
|
||||
if (argc >= 3 && strcmp(argv[1], "start") == 0) {
|
||||
strlcpy(sWebPostId, argv[2], sizeof(sWebPostId));
|
||||
sWebPostCounter = 0;
|
||||
|
||||
// Generate the clear code.
|
||||
const char* args[2] = { "", "yes" };
|
||||
qrencode(2, (char**)args);
|
||||
} else if (argc >= 2 && strcmp(argv[1], "stop") == 0) {
|
||||
sWebPostId[0] = 0;
|
||||
} else {
|
||||
kprintf("%s start <id>\n", argv[0]);
|
||||
kprintf("%s stop\n", argv[0]);
|
||||
kprintf("Causes the QR codes to be rendered as URLs that resolve to\n"
|
||||
"a service that allows appending the data of multiple QR codes\n"
|
||||
"for easier handling.\n"
|
||||
"An initial QR code is generated that invokes a clear operation\n"
|
||||
"to prepare the output file on the server.\n"
|
||||
"Note that there is no logic behind the service, if you and\n"
|
||||
"someone else use the same id at the same time, they will\n"
|
||||
"overwrite eachother. Therefore use a reasonably unique name.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
std_ops(int32 op, ...)
|
||||
{
|
||||
switch (op) {
|
||||
case B_MODULE_INIT:
|
||||
add_debugger_command("qrencode", qrencode,
|
||||
"encodes a string / the current QR buffer");
|
||||
add_debugger_command("qrappend", qrappend,
|
||||
"appends a string to the QR buffer");
|
||||
add_debugger_command("qrclear", qrclear,
|
||||
"clears the current QR buffer");
|
||||
add_debugger_command("qrflush", qrflush,
|
||||
"encodes the current QR buffer and clears it");
|
||||
add_debugger_command("qrconfig", qrconfig,
|
||||
"sets the QR code version to be used");
|
||||
add_debugger_command("qrwebpost", qrwebpost,
|
||||
"sets up URL encoding for QR codes");
|
||||
return B_OK;
|
||||
case B_MODULE_UNINIT:
|
||||
remove_debugger_command("qrencode", qrencode);
|
||||
remove_debugger_command("qrappend", qrappend);
|
||||
remove_debugger_command("qrclear", qrclear);
|
||||
remove_debugger_command("qrflush", qrflush);
|
||||
remove_debugger_command("qrconfig", qrconfig);
|
||||
remove_debugger_command("qrwebpost", qrwebpost);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
|
||||
static struct debugger_module_info sModuleInfo = {
|
||||
{
|
||||
"debugger/qrencode/v1",
|
||||
0,
|
||||
&std_ops
|
||||
},
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
module_info *modules[] = {
|
||||
(module_info *)&sModuleInfo,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
* qrencode - QR Code encoder
|
||||
*
|
||||
* Micor QR Code specification in convenient format.
|
||||
* Copyright (C) 2006-2011 Kentaro Fukuchi <[email protected]>
|
||||
*
|
||||
* The following data / specifications are taken from
|
||||
* "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
|
||||
* or
|
||||
* "Automatic identification and data capture techniques --
|
||||
* QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include "mqrspec.h"
|
||||
|
||||
/******************************************************************************
|
||||
* Version and capacity
|
||||
*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
int width; //< Edge length of the symbol
|
||||
int ec[4]; //< Number of ECC code (bytes)
|
||||
} MQRspec_Capacity;
|
||||
|
||||
/**
|
||||
* Table of the capacity of symbols
|
||||
* See Table 1 (pp.106) and Table 8 (pp.113) of Appendix 1, JIS X0510:2004.
|
||||
*/
|
||||
static const MQRspec_Capacity mqrspecCapacity[MQRSPEC_VERSION_MAX + 1] = {
|
||||
{ 0, {0, 0, 0, 0}},
|
||||
{ 11, {2, 0, 0, 0}},
|
||||
{ 13, {5, 6, 0, 0}},
|
||||
{ 15, {6, 8, 0, 0}},
|
||||
{ 17, {8, 10, 14, 0}}
|
||||
};
|
||||
|
||||
int MQRspec_getDataLengthBit(int version, QRecLevel level)
|
||||
{
|
||||
int w;
|
||||
int ecc;
|
||||
|
||||
w = mqrspecCapacity[version].width - 1;
|
||||
ecc = mqrspecCapacity[version].ec[level];
|
||||
if(ecc == 0) return 0;
|
||||
return w * w - 64 - ecc * 8;
|
||||
}
|
||||
|
||||
int MQRspec_getDataLength(int version, QRecLevel level)
|
||||
{
|
||||
return (MQRspec_getDataLengthBit(version, level) + 4) / 8;
|
||||
}
|
||||
|
||||
int MQRspec_getECCLength(int version, QRecLevel level)
|
||||
{
|
||||
return mqrspecCapacity[version].ec[level];
|
||||
}
|
||||
|
||||
int MQRspec_getWidth(int version)
|
||||
{
|
||||
return mqrspecCapacity[version].width;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Length indicator
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* See Table 3 (pp.107) of Appendix 1, JIS X0510:2004.
|
||||
*/
|
||||
static const int lengthTableBits[4][4] = {
|
||||
{ 3, 4, 5, 6},
|
||||
{ 0, 3, 4, 5},
|
||||
{ 0, 0, 4, 5},
|
||||
{ 0, 0, 3, 4}
|
||||
};
|
||||
|
||||
int MQRspec_lengthIndicator(QRencodeMode mode, int version)
|
||||
{
|
||||
return lengthTableBits[mode][version - 1];
|
||||
}
|
||||
|
||||
int MQRspec_maximumWords(QRencodeMode mode, int version)
|
||||
{
|
||||
int bits;
|
||||
int words;
|
||||
|
||||
bits = lengthTableBits[mode][version - 1];
|
||||
words = (1 << bits) - 1;
|
||||
if(mode == QR_MODE_KANJI) {
|
||||
words *= 2; // the number of bytes is required
|
||||
}
|
||||
|
||||
return words;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Format information
|
||||
*****************************************************************************/
|
||||
|
||||
/* See calcFormatInfo in tests/test_mqrspec.c */
|
||||
static const unsigned int formatInfo[4][8] = {
|
||||
{0x4445, 0x55ae, 0x6793, 0x7678, 0x06de, 0x1735, 0x2508, 0x34e3},
|
||||
{0x4172, 0x5099, 0x62a4, 0x734f, 0x03e9, 0x1202, 0x203f, 0x31d4},
|
||||
{0x4e2b, 0x5fc0, 0x6dfd, 0x7c16, 0x0cb0, 0x1d5b, 0x2f66, 0x3e8d},
|
||||
{0x4b1c, 0x5af7, 0x68ca, 0x7921, 0x0987, 0x186c, 0x2a51, 0x3bba}
|
||||
};
|
||||
|
||||
/* See Table 10 of Appendix 1. (pp.115) */
|
||||
static const int typeTable[MQRSPEC_VERSION_MAX + 1][3] = {
|
||||
{-1, -1, -1},
|
||||
{ 0, -1, -1},
|
||||
{ 1, 2, -1},
|
||||
{ 3, 4, -1},
|
||||
{ 5, 6, 7}
|
||||
};
|
||||
|
||||
unsigned int MQRspec_getFormatInfo(int mask, int version, QRecLevel level)
|
||||
{
|
||||
int type;
|
||||
|
||||
if(mask < 0 || mask > 3) return 0;
|
||||
if(version <= 0 || version > MQRSPEC_VERSION_MAX) return 0;
|
||||
if(level == QR_ECLEVEL_H) return 0;
|
||||
type = typeTable[version][level];
|
||||
if(type < 0) return 0;
|
||||
|
||||
return formatInfo[mask][type];
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Frame
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Cache of initial frames.
|
||||
*/
|
||||
/* C99 says that static storage shall be initialized to a null pointer
|
||||
* by compiler. */
|
||||
static unsigned char *frames[MQRSPEC_VERSION_MAX + 1];
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
static pthread_mutex_t frames_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Put a finder pattern.
|
||||
* @param frame
|
||||
* @param width
|
||||
* @param ox,oy upper-left coordinate of the pattern
|
||||
*/
|
||||
static void putFinderPattern(unsigned char *frame, int width, int ox, int oy)
|
||||
{
|
||||
static const unsigned char finder[] = {
|
||||
0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1,
|
||||
0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1,
|
||||
0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
|
||||
0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
|
||||
0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
|
||||
0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1,
|
||||
0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1,
|
||||
};
|
||||
int x, y;
|
||||
const unsigned char *s;
|
||||
|
||||
frame += oy * width + ox;
|
||||
s = finder;
|
||||
for(y=0; y<7; y++) {
|
||||
for(x=0; x<7; x++) {
|
||||
frame[x] = s[x];
|
||||
}
|
||||
frame += width;
|
||||
s += 7;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned char *MQRspec_createFrame(int version)
|
||||
{
|
||||
unsigned char *frame, *p, *q;
|
||||
int width;
|
||||
int x, y;
|
||||
|
||||
width = mqrspecCapacity[version].width;
|
||||
frame = (unsigned char *)malloc(width * width);
|
||||
if(frame == NULL) return NULL;
|
||||
|
||||
memset(frame, 0, width * width);
|
||||
/* Finder pattern */
|
||||
putFinderPattern(frame, width, 0, 0);
|
||||
/* Separator */
|
||||
p = frame;
|
||||
for(y=0; y<7; y++) {
|
||||
p[7] = 0xc0;
|
||||
p += width;
|
||||
}
|
||||
memset(frame + width * 7, 0xc0, 8);
|
||||
/* Mask format information area */
|
||||
memset(frame + width * 8 + 1, 0x84, 8);
|
||||
p = frame + width + 8;
|
||||
for(y=0; y<7; y++) {
|
||||
*p = 0x84;
|
||||
p += width;
|
||||
}
|
||||
/* Timing pattern */
|
||||
p = frame + 8;
|
||||
q = frame + width * 8;
|
||||
for(x=1; x<width-7; x++) {
|
||||
*p = 0x90 | (x & 1);
|
||||
*q = 0x90 | (x & 1);
|
||||
p++;
|
||||
q += width;
|
||||
}
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
unsigned char *MQRspec_newFrame(int version)
|
||||
{
|
||||
unsigned char *frame;
|
||||
int width;
|
||||
|
||||
if(version < 1 || version > MQRSPEC_VERSION_MAX) return NULL;
|
||||
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_lock(&frames_mutex);
|
||||
#endif
|
||||
if(frames[version] == NULL) {
|
||||
frames[version] = MQRspec_createFrame(version);
|
||||
}
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_unlock(&frames_mutex);
|
||||
#endif
|
||||
if(frames[version] == NULL) return NULL;
|
||||
|
||||
width = mqrspecCapacity[version].width;
|
||||
frame = (unsigned char *)malloc(width * width);
|
||||
if(frame == NULL) return NULL;
|
||||
memcpy(frame, frames[version], width * width);
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
void MQRspec_clearCache(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_lock(&frames_mutex);
|
||||
#endif
|
||||
for(i=1; i<=MQRSPEC_VERSION_MAX; i++) {
|
||||
free(frames[i]);
|
||||
frames[i] = NULL;
|
||||
}
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_unlock(&frames_mutex);
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* qrencode - QR Code encoder
|
||||
*
|
||||
* Micro QR Code specification in convenient format.
|
||||
* Copyright (C) 2006-2011 Kentaro Fukuchi <[email protected]>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __MQRSPEC_H__
|
||||
#define __MQRSPEC_H__
|
||||
|
||||
#include "qrencode.h"
|
||||
|
||||
/******************************************************************************
|
||||
* Version and capacity
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Maximum width of a symbol
|
||||
*/
|
||||
#define MQRSPEC_WIDTH_MAX 17
|
||||
|
||||
/**
|
||||
* Return maximum data code length (bits) for the version.
|
||||
* @param version
|
||||
* @param level
|
||||
* @return maximum size (bits)
|
||||
*/
|
||||
extern int MQRspec_getDataLengthBit(int version, QRecLevel level);
|
||||
|
||||
/**
|
||||
* Return maximum data code length (bytes) for the version.
|
||||
* @param version
|
||||
* @param level
|
||||
* @return maximum size (bytes)
|
||||
*/
|
||||
extern int MQRspec_getDataLength(int version, QRecLevel level);
|
||||
|
||||
/**
|
||||
* Return maximum error correction code length (bytes) for the version.
|
||||
* @param version
|
||||
* @param level
|
||||
* @return ECC size (bytes)
|
||||
*/
|
||||
extern int MQRspec_getECCLength(int version, QRecLevel level);
|
||||
|
||||
/**
|
||||
* Return a version number that satisfies the input code length.
|
||||
* @param size input code length (byte)
|
||||
* @param level
|
||||
* @return version number
|
||||
*/
|
||||
extern int MQRspec_getMinimumVersion(int size, QRecLevel level);
|
||||
|
||||
/**
|
||||
* Return the width of the symbol for the version.
|
||||
* @param version
|
||||
* @return width
|
||||
*/
|
||||
extern int MQRspec_getWidth(int version);
|
||||
|
||||
/**
|
||||
* Return the numer of remainder bits.
|
||||
* @param version
|
||||
* @return number of remainder bits
|
||||
*/
|
||||
extern int MQRspec_getRemainder(int version);
|
||||
|
||||
/******************************************************************************
|
||||
* Length indicator
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Return the size of lenght indicator for the mode and version.
|
||||
* @param mode
|
||||
* @param version
|
||||
* @return the size of the appropriate length indicator (bits).
|
||||
*/
|
||||
extern int MQRspec_lengthIndicator(QRencodeMode mode, int version);
|
||||
|
||||
/**
|
||||
* Return the maximum length for the mode and version.
|
||||
* @param mode
|
||||
* @param version
|
||||
* @return the maximum length (bytes)
|
||||
*/
|
||||
extern int MQRspec_maximumWords(QRencodeMode mode, int version);
|
||||
|
||||
/******************************************************************************
|
||||
* Version information pattern
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Return BCH encoded version information pattern that is used for the symbol
|
||||
* of version 7 or greater. Use lower 18 bits.
|
||||
* @param version
|
||||
* @return BCH encoded version information pattern
|
||||
*/
|
||||
extern unsigned int MQRspec_getVersionPattern(int version);
|
||||
|
||||
/******************************************************************************
|
||||
* Format information
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Return BCH encoded format information pattern.
|
||||
* @param mask
|
||||
* @param version
|
||||
* @param level
|
||||
* @return BCH encoded format information pattern
|
||||
*/
|
||||
extern unsigned int MQRspec_getFormatInfo(int mask, int version, QRecLevel level);
|
||||
|
||||
/******************************************************************************
|
||||
* Frame
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Return a copy of initialized frame.
|
||||
* When the same version is requested twice or more, a copy of cached frame
|
||||
* is returned.
|
||||
* @param version
|
||||
* @return Array of unsigned char. You can free it by free().
|
||||
*/
|
||||
extern unsigned char *MQRspec_newFrame(int version);
|
||||
|
||||
/**
|
||||
* Clear the frame cache. Typically for debug.
|
||||
*/
|
||||
extern void MQRspec_clearCache(void);
|
||||
|
||||
/******************************************************************************
|
||||
* Mode indicator
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Mode indicator. See Table 2 in Appendix 1 of JIS X0510:2004, pp.107.
|
||||
*/
|
||||
#define MQRSPEC_MODEID_NUM 0
|
||||
#define MQRSPEC_MODEID_AN 1
|
||||
#define MQRSPEC_MODEID_8 2
|
||||
#define MQRSPEC_MODEID_KANJI 3
|
||||
|
||||
#endif /* __MQRSPEC_H__ */
|
||||
@@ -0,0 +1,929 @@
|
||||
/*
|
||||
* qrencode - QR Code encoder
|
||||
*
|
||||
* Copyright (C) 2006-2012 Kentaro Fukuchi <[email protected]>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "qrencode.h"
|
||||
#include "qrspec.h"
|
||||
#include "mqrspec.h"
|
||||
#include "bitstream.h"
|
||||
#include "qrinput.h"
|
||||
#include "rscode.h"
|
||||
#include "split.h"
|
||||
#include "mask.h"
|
||||
#include "mmask.h"
|
||||
|
||||
/******************************************************************************
|
||||
* Raw code
|
||||
*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
int dataLength;
|
||||
unsigned char *data;
|
||||
int eccLength;
|
||||
unsigned char *ecc;
|
||||
} RSblock;
|
||||
|
||||
typedef struct {
|
||||
int version;
|
||||
int dataLength;
|
||||
int eccLength;
|
||||
unsigned char *datacode;
|
||||
unsigned char *ecccode;
|
||||
int b1;
|
||||
int blocks;
|
||||
RSblock *rsblock;
|
||||
int count;
|
||||
} QRRawCode;
|
||||
|
||||
static void RSblock_initBlock(RSblock *block, int dl, unsigned char *data, int el, unsigned char *ecc, RS *rs)
|
||||
{
|
||||
block->dataLength = dl;
|
||||
block->data = data;
|
||||
block->eccLength = el;
|
||||
block->ecc = ecc;
|
||||
|
||||
encode_rs_char(rs, data, ecc);
|
||||
}
|
||||
|
||||
static int RSblock_init(RSblock *blocks, int spec[5], unsigned char *data, unsigned char *ecc)
|
||||
{
|
||||
int i;
|
||||
RSblock *block;
|
||||
unsigned char *dp, *ep;
|
||||
RS *rs;
|
||||
int el, dl;
|
||||
|
||||
dl = QRspec_rsDataCodes1(spec);
|
||||
el = QRspec_rsEccCodes1(spec);
|
||||
rs = init_rs(8, 0x11d, 0, 1, el, 255 - dl - el);
|
||||
if(rs == NULL) return -1;
|
||||
|
||||
block = blocks;
|
||||
dp = data;
|
||||
ep = ecc;
|
||||
for(i=0; i<QRspec_rsBlockNum1(spec); i++) {
|
||||
RSblock_initBlock(block, dl, dp, el, ep, rs);
|
||||
dp += dl;
|
||||
ep += el;
|
||||
block++;
|
||||
}
|
||||
|
||||
if(QRspec_rsBlockNum2(spec) == 0) return 0;
|
||||
|
||||
dl = QRspec_rsDataCodes2(spec);
|
||||
el = QRspec_rsEccCodes2(spec);
|
||||
rs = init_rs(8, 0x11d, 0, 1, el, 255 - dl - el);
|
||||
if(rs == NULL) return -1;
|
||||
for(i=0; i<QRspec_rsBlockNum2(spec); i++) {
|
||||
RSblock_initBlock(block, dl, dp, el, ep, rs);
|
||||
dp += dl;
|
||||
ep += el;
|
||||
block++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__STATIC void QRraw_free(QRRawCode *raw);
|
||||
__STATIC QRRawCode *QRraw_new(QRinput *input)
|
||||
{
|
||||
QRRawCode *raw;
|
||||
int spec[5], ret;
|
||||
|
||||
raw = (QRRawCode *)malloc(sizeof(QRRawCode));
|
||||
if(raw == NULL) return NULL;
|
||||
|
||||
raw->datacode = QRinput_getByteStream(input);
|
||||
if(raw->datacode == NULL) {
|
||||
free(raw);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
QRspec_getEccSpec(input->version, input->level, spec);
|
||||
|
||||
raw->version = input->version;
|
||||
raw->b1 = QRspec_rsBlockNum1(spec);
|
||||
raw->dataLength = QRspec_rsDataLength(spec);
|
||||
raw->eccLength = QRspec_rsEccLength(spec);
|
||||
raw->ecccode = (unsigned char *)malloc(raw->eccLength);
|
||||
if(raw->ecccode == NULL) {
|
||||
free(raw->datacode);
|
||||
free(raw);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
raw->blocks = QRspec_rsBlockNum(spec);
|
||||
raw->rsblock = (RSblock *)calloc(sizeof(RSblock), raw->blocks);
|
||||
if(raw->rsblock == NULL) {
|
||||
QRraw_free(raw);
|
||||
return NULL;
|
||||
}
|
||||
ret = RSblock_init(raw->rsblock, spec, raw->datacode, raw->ecccode);
|
||||
if(ret < 0) {
|
||||
QRraw_free(raw);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
raw->count = 0;
|
||||
|
||||
return raw;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a code (byte).
|
||||
* This function can be called iteratively.
|
||||
* @param raw raw code.
|
||||
* @return code
|
||||
*/
|
||||
__STATIC unsigned char QRraw_getCode(QRRawCode *raw)
|
||||
{
|
||||
int col, row;
|
||||
unsigned char ret;
|
||||
|
||||
if(raw->count < raw->dataLength) {
|
||||
row = raw->count % raw->blocks;
|
||||
col = raw->count / raw->blocks;
|
||||
if(col >= raw->rsblock[0].dataLength) {
|
||||
row += raw->b1;
|
||||
}
|
||||
ret = raw->rsblock[row].data[col];
|
||||
} else if(raw->count < raw->dataLength + raw->eccLength) {
|
||||
row = (raw->count - raw->dataLength) % raw->blocks;
|
||||
col = (raw->count - raw->dataLength) / raw->blocks;
|
||||
ret = raw->rsblock[row].ecc[col];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
raw->count++;
|
||||
return ret;
|
||||
}
|
||||
|
||||
__STATIC void QRraw_free(QRRawCode *raw)
|
||||
{
|
||||
if(raw != NULL) {
|
||||
free(raw->datacode);
|
||||
free(raw->ecccode);
|
||||
free(raw->rsblock);
|
||||
free(raw);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Raw code for Micro QR Code
|
||||
*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
int version;
|
||||
int dataLength;
|
||||
int eccLength;
|
||||
unsigned char *datacode;
|
||||
unsigned char *ecccode;
|
||||
RSblock *rsblock;
|
||||
int oddbits;
|
||||
int count;
|
||||
} MQRRawCode;
|
||||
|
||||
__STATIC void MQRraw_free(MQRRawCode *raw);
|
||||
__STATIC MQRRawCode *MQRraw_new(QRinput *input)
|
||||
{
|
||||
MQRRawCode *raw;
|
||||
RS *rs;
|
||||
|
||||
raw = (MQRRawCode *)malloc(sizeof(MQRRawCode));
|
||||
if(raw == NULL) return NULL;
|
||||
|
||||
raw->version = input->version;
|
||||
raw->dataLength = MQRspec_getDataLength(input->version, input->level);
|
||||
raw->eccLength = MQRspec_getECCLength(input->version, input->level);
|
||||
raw->oddbits = raw->dataLength * 8 - MQRspec_getDataLengthBit(input->version, input->level);
|
||||
raw->datacode = QRinput_getByteStream(input);
|
||||
if(raw->datacode == NULL) {
|
||||
free(raw);
|
||||
return NULL;
|
||||
}
|
||||
raw->ecccode = (unsigned char *)malloc(raw->eccLength);
|
||||
if(raw->ecccode == NULL) {
|
||||
free(raw->datacode);
|
||||
free(raw);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
raw->rsblock = (RSblock *)calloc(sizeof(RSblock), 1);
|
||||
if(raw->rsblock == NULL) {
|
||||
MQRraw_free(raw);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rs = init_rs(8, 0x11d, 0, 1, raw->eccLength, 255 - raw->dataLength - raw->eccLength);
|
||||
if(rs == NULL) {
|
||||
MQRraw_free(raw);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RSblock_initBlock(raw->rsblock, raw->dataLength, raw->datacode, raw->eccLength, raw->ecccode, rs);
|
||||
|
||||
raw->count = 0;
|
||||
|
||||
return raw;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a code (byte).
|
||||
* This function can be called iteratively.
|
||||
* @param raw raw code.
|
||||
* @return code
|
||||
*/
|
||||
__STATIC unsigned char MQRraw_getCode(MQRRawCode *raw)
|
||||
{
|
||||
unsigned char ret;
|
||||
|
||||
if(raw->count < raw->dataLength) {
|
||||
ret = raw->datacode[raw->count];
|
||||
} else if(raw->count < raw->dataLength + raw->eccLength) {
|
||||
ret = raw->ecccode[raw->count - raw->dataLength];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
raw->count++;
|
||||
return ret;
|
||||
}
|
||||
|
||||
__STATIC void MQRraw_free(MQRRawCode *raw)
|
||||
{
|
||||
if(raw != NULL) {
|
||||
free(raw->datacode);
|
||||
free(raw->ecccode);
|
||||
free(raw->rsblock);
|
||||
free(raw);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Frame filling
|
||||
*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
int width;
|
||||
unsigned char *frame;
|
||||
int x, y;
|
||||
int dir;
|
||||
int bit;
|
||||
int mqr;
|
||||
} FrameFiller;
|
||||
|
||||
static FrameFiller *FrameFiller_new(int width, unsigned char *frame, int mqr)
|
||||
{
|
||||
FrameFiller *filler;
|
||||
|
||||
filler = (FrameFiller *)malloc(sizeof(FrameFiller));
|
||||
if(filler == NULL) return NULL;
|
||||
filler->width = width;
|
||||
filler->frame = frame;
|
||||
filler->x = width - 1;
|
||||
filler->y = width - 1;
|
||||
filler->dir = -1;
|
||||
filler->bit = -1;
|
||||
filler->mqr = mqr;
|
||||
|
||||
return filler;
|
||||
}
|
||||
|
||||
static unsigned char *FrameFiller_next(FrameFiller *filler)
|
||||
{
|
||||
unsigned char *p;
|
||||
int x, y, w;
|
||||
|
||||
if(filler->bit == -1) {
|
||||
filler->bit = 0;
|
||||
return filler->frame + filler->y * filler->width + filler->x;
|
||||
}
|
||||
|
||||
x = filler->x;
|
||||
y = filler->y;
|
||||
p = filler->frame;
|
||||
w = filler->width;
|
||||
|
||||
if(filler->bit == 0) {
|
||||
x--;
|
||||
filler->bit++;
|
||||
} else {
|
||||
x++;
|
||||
y += filler->dir;
|
||||
filler->bit--;
|
||||
}
|
||||
|
||||
if(filler->dir < 0) {
|
||||
if(y < 0) {
|
||||
y = 0;
|
||||
x -= 2;
|
||||
filler->dir = 1;
|
||||
if(!filler->mqr && x == 6) {
|
||||
x--;
|
||||
y = 9;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(y == w) {
|
||||
y = w - 1;
|
||||
x -= 2;
|
||||
filler->dir = -1;
|
||||
if(!filler->mqr && x == 6) {
|
||||
x--;
|
||||
y -= 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(x < 0 || y < 0) return NULL;
|
||||
|
||||
filler->x = x;
|
||||
filler->y = y;
|
||||
|
||||
if(p[y * w + x] & 0x80) {
|
||||
// This tail recursion could be optimized.
|
||||
return FrameFiller_next(filler);
|
||||
}
|
||||
return &p[y * w + x];
|
||||
}
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
extern unsigned char *FrameFiller_test(int version)
|
||||
{
|
||||
int width;
|
||||
unsigned char *frame, *p;
|
||||
FrameFiller *filler;
|
||||
int i, length;
|
||||
|
||||
width = QRspec_getWidth(version);
|
||||
frame = QRspec_newFrame(version);
|
||||
if(frame == NULL) return NULL;
|
||||
filler = FrameFiller_new(width, frame, 0);
|
||||
if(filler == NULL) {
|
||||
free(frame);
|
||||
return NULL;
|
||||
}
|
||||
length = QRspec_getDataLength(version, QR_ECLEVEL_L) * 8
|
||||
+ QRspec_getECCLength(version, QR_ECLEVEL_L) * 8
|
||||
+ QRspec_getRemainder(version);
|
||||
for(i=0; i<length; i++) {
|
||||
p = FrameFiller_next(filler);
|
||||
if(p == NULL) {
|
||||
free(filler);
|
||||
free(frame);
|
||||
return NULL;
|
||||
}
|
||||
*p = (unsigned char)(i & 0x7f) | 0x80;
|
||||
}
|
||||
free(filler);
|
||||
return frame;
|
||||
}
|
||||
|
||||
extern unsigned char *FrameFiller_testMQR(int version)
|
||||
{
|
||||
int width;
|
||||
unsigned char *frame, *p;
|
||||
FrameFiller *filler;
|
||||
int i, length;
|
||||
|
||||
width = MQRspec_getWidth(version);
|
||||
frame = MQRspec_newFrame(version);
|
||||
if(frame == NULL) return NULL;
|
||||
filler = FrameFiller_new(width, frame, 1);
|
||||
if(filler == NULL) {
|
||||
free(frame);
|
||||
return NULL;
|
||||
}
|
||||
length = MQRspec_getDataLengthBit(version, QR_ECLEVEL_L)
|
||||
+ MQRspec_getECCLength(version, QR_ECLEVEL_L) * 8;
|
||||
for(i=0; i<length; i++) {
|
||||
p = FrameFiller_next(filler);
|
||||
if(p == NULL) {
|
||||
fprintf(stderr, "Frame filler run over the frame!\n");
|
||||
free(filler);
|
||||
return frame;
|
||||
}
|
||||
*p = (unsigned char)(i & 0x7f) | 0x80;
|
||||
}
|
||||
free(filler);
|
||||
return frame;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* QR-code encoding
|
||||
*****************************************************************************/
|
||||
|
||||
__STATIC QRcode *QRcode_new(int version, int width, unsigned char *data)
|
||||
{
|
||||
QRcode *qrcode;
|
||||
|
||||
qrcode = (QRcode *)malloc(sizeof(QRcode));
|
||||
if(qrcode == NULL) return NULL;
|
||||
|
||||
qrcode->version = version;
|
||||
qrcode->width = width;
|
||||
qrcode->data = data;
|
||||
|
||||
return qrcode;
|
||||
}
|
||||
|
||||
void QRcode_free(QRcode *qrcode)
|
||||
{
|
||||
if(qrcode != NULL) {
|
||||
free(qrcode->data);
|
||||
free(qrcode);
|
||||
}
|
||||
}
|
||||
|
||||
__STATIC QRcode *QRcode_encodeMask(QRinput *input, int mask)
|
||||
{
|
||||
int width, version;
|
||||
QRRawCode *raw;
|
||||
unsigned char *frame, *masked, *p, code, bit;
|
||||
FrameFiller *filler;
|
||||
int i, j;
|
||||
QRcode *qrcode = NULL;
|
||||
|
||||
if(input->mqr) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
if(input->version < 0 || input->version > QRSPEC_VERSION_MAX) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
if(input->level > QR_ECLEVEL_H) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
raw = QRraw_new(input);
|
||||
if(raw == NULL) return NULL;
|
||||
|
||||
version = raw->version;
|
||||
width = QRspec_getWidth(version);
|
||||
frame = QRspec_newFrame(version);
|
||||
if(frame == NULL) {
|
||||
QRraw_free(raw);
|
||||
return NULL;
|
||||
}
|
||||
filler = FrameFiller_new(width, frame, 0);
|
||||
if(filler == NULL) {
|
||||
QRraw_free(raw);
|
||||
free(frame);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* inteleaved data and ecc codes */
|
||||
for(i=0; i<raw->dataLength + raw->eccLength; i++) {
|
||||
code = QRraw_getCode(raw);
|
||||
bit = 0x80;
|
||||
for(j=0; j<8; j++) {
|
||||
p = FrameFiller_next(filler);
|
||||
if(p == NULL) goto EXIT;
|
||||
*p = 0x02 | ((bit & code) != 0);
|
||||
bit = bit >> 1;
|
||||
}
|
||||
}
|
||||
QRraw_free(raw);
|
||||
raw = NULL;
|
||||
/* remainder bits */
|
||||
j = QRspec_getRemainder(version);
|
||||
for(i=0; i<j; i++) {
|
||||
p = FrameFiller_next(filler);
|
||||
if(p == NULL) goto EXIT;
|
||||
*p = 0x02;
|
||||
}
|
||||
|
||||
/* masking */
|
||||
if(mask == -2) { // just for debug purpose
|
||||
masked = (unsigned char *)malloc(width * width);
|
||||
memcpy(masked, frame, width * width);
|
||||
} else if(mask < 0) {
|
||||
masked = Mask_mask(width, frame, input->level);
|
||||
} else {
|
||||
masked = Mask_makeMask(width, frame, mask, input->level);
|
||||
}
|
||||
if(masked == NULL) {
|
||||
goto EXIT;
|
||||
}
|
||||
qrcode = QRcode_new(version, width, masked);
|
||||
|
||||
EXIT:
|
||||
QRraw_free(raw);
|
||||
free(filler);
|
||||
free(frame);
|
||||
return qrcode;
|
||||
}
|
||||
|
||||
__STATIC QRcode *QRcode_encodeMaskMQR(QRinput *input, int mask)
|
||||
{
|
||||
int width, version;
|
||||
MQRRawCode *raw;
|
||||
unsigned char *frame, *masked, *p, code, bit;
|
||||
FrameFiller *filler;
|
||||
int i, j;
|
||||
QRcode *qrcode = NULL;
|
||||
|
||||
if(!input->mqr) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
if(input->version <= 0 || input->version > MQRSPEC_VERSION_MAX) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
if(input->level > QR_ECLEVEL_Q) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
raw = MQRraw_new(input);
|
||||
if(raw == NULL) return NULL;
|
||||
|
||||
version = raw->version;
|
||||
width = MQRspec_getWidth(version);
|
||||
frame = MQRspec_newFrame(version);
|
||||
if(frame == NULL) {
|
||||
MQRraw_free(raw);
|
||||
return NULL;
|
||||
}
|
||||
filler = FrameFiller_new(width, frame, 1);
|
||||
if(filler == NULL) {
|
||||
MQRraw_free(raw);
|
||||
free(frame);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* inteleaved data and ecc codes */
|
||||
for(i=0; i<raw->dataLength + raw->eccLength; i++) {
|
||||
code = MQRraw_getCode(raw);
|
||||
if(raw->oddbits && i == raw->dataLength - 1) {
|
||||
bit = 1 << raw->oddbits;
|
||||
for(j=0; j<raw->oddbits; j++) {
|
||||
p = FrameFiller_next(filler);
|
||||
if(p == NULL) goto EXIT;
|
||||
*p = 0x02 | ((bit & code) != 0);
|
||||
bit = bit >> 1;
|
||||
}
|
||||
} else {
|
||||
bit = 0x80;
|
||||
for(j=0; j<8; j++) {
|
||||
p = FrameFiller_next(filler);
|
||||
if(p == NULL) goto EXIT;
|
||||
*p = 0x02 | ((bit & code) != 0);
|
||||
bit = bit >> 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
MQRraw_free(raw);
|
||||
raw = NULL;
|
||||
|
||||
/* masking */
|
||||
if(mask < 0) {
|
||||
masked = MMask_mask(version, frame, input->level);
|
||||
} else {
|
||||
masked = MMask_makeMask(version, frame, mask, input->level);
|
||||
}
|
||||
if(masked == NULL) {
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
qrcode = QRcode_new(version, width, masked);
|
||||
|
||||
EXIT:
|
||||
MQRraw_free(raw);
|
||||
free(filler);
|
||||
free(frame);
|
||||
return qrcode;
|
||||
}
|
||||
|
||||
QRcode *QRcode_encodeInput(QRinput *input)
|
||||
{
|
||||
if(input->mqr) {
|
||||
return QRcode_encodeMaskMQR(input, -1);
|
||||
} else {
|
||||
return QRcode_encodeMask(input, -1);
|
||||
}
|
||||
}
|
||||
|
||||
static QRcode *QRcode_encodeStringReal(const char *string, int version, QRecLevel level, int mqr, QRencodeMode hint, int casesensitive)
|
||||
{
|
||||
QRinput *input;
|
||||
QRcode *code;
|
||||
int ret;
|
||||
|
||||
if(string == NULL) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
if(hint != QR_MODE_8 && hint != QR_MODE_KANJI) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(mqr) {
|
||||
input = QRinput_newMQR(version, level);
|
||||
} else {
|
||||
input = QRinput_new2(version, level);
|
||||
}
|
||||
if(input == NULL) return NULL;
|
||||
|
||||
ret = Split_splitStringToQRinput(string, input, hint, casesensitive);
|
||||
if(ret < 0) {
|
||||
QRinput_free(input);
|
||||
return NULL;
|
||||
}
|
||||
code = QRcode_encodeInput(input);
|
||||
QRinput_free(input);
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
QRcode *QRcode_encodeString(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive)
|
||||
{
|
||||
return QRcode_encodeStringReal(string, version, level, 0, hint, casesensitive);
|
||||
}
|
||||
|
||||
QRcode *QRcode_encodeStringMQR(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive)
|
||||
{
|
||||
return QRcode_encodeStringReal(string, version, level, 1, hint, casesensitive);
|
||||
}
|
||||
|
||||
static QRcode *QRcode_encodeDataReal(const unsigned char *data, int length, int version, QRecLevel level, int mqr)
|
||||
{
|
||||
QRinput *input;
|
||||
QRcode *code;
|
||||
int ret;
|
||||
|
||||
if(data == NULL || length == 0) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(mqr) {
|
||||
input = QRinput_newMQR(version, level);
|
||||
} else {
|
||||
input = QRinput_new2(version, level);
|
||||
}
|
||||
if(input == NULL) return NULL;
|
||||
|
||||
ret = QRinput_append(input, QR_MODE_8, length, data);
|
||||
if(ret < 0) {
|
||||
QRinput_free(input);
|
||||
return NULL;
|
||||
}
|
||||
code = QRcode_encodeInput(input);
|
||||
QRinput_free(input);
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
QRcode *QRcode_encodeData(int size, const unsigned char *data, int version, QRecLevel level)
|
||||
{
|
||||
return QRcode_encodeDataReal(data, size, version, level, 0);
|
||||
}
|
||||
|
||||
QRcode *QRcode_encodeString8bit(const char *string, int version, QRecLevel level)
|
||||
{
|
||||
if(string == NULL) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
return QRcode_encodeDataReal((unsigned char *)string, strlen(string), version, level, 0);
|
||||
}
|
||||
|
||||
QRcode *QRcode_encodeDataMQR(int size, const unsigned char *data, int version, QRecLevel level)
|
||||
{
|
||||
return QRcode_encodeDataReal(data, size, version, level, 1);
|
||||
}
|
||||
|
||||
QRcode *QRcode_encodeString8bitMQR(const char *string, int version, QRecLevel level)
|
||||
{
|
||||
if(string == NULL) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
return QRcode_encodeDataReal((unsigned char *)string, strlen(string), version, level, 1);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Structured QR-code encoding
|
||||
*****************************************************************************/
|
||||
|
||||
static QRcode_List *QRcode_List_newEntry(void)
|
||||
{
|
||||
QRcode_List *entry;
|
||||
|
||||
entry = (QRcode_List *)malloc(sizeof(QRcode_List));
|
||||
if(entry == NULL) return NULL;
|
||||
|
||||
entry->next = NULL;
|
||||
entry->code = NULL;
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
static void QRcode_List_freeEntry(QRcode_List *entry)
|
||||
{
|
||||
if(entry != NULL) {
|
||||
QRcode_free(entry->code);
|
||||
free(entry);
|
||||
}
|
||||
}
|
||||
|
||||
void QRcode_List_free(QRcode_List *qrlist)
|
||||
{
|
||||
QRcode_List *list = qrlist, *next;
|
||||
|
||||
while(list != NULL) {
|
||||
next = list->next;
|
||||
QRcode_List_freeEntry(list);
|
||||
list = next;
|
||||
}
|
||||
}
|
||||
|
||||
int QRcode_List_size(QRcode_List *qrlist)
|
||||
{
|
||||
QRcode_List *list = qrlist;
|
||||
int size = 0;
|
||||
|
||||
while(list != NULL) {
|
||||
size++;
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static unsigned char QRcode_parity(const char *str, int size)
|
||||
{
|
||||
unsigned char parity = 0;
|
||||
int i;
|
||||
|
||||
for(i=0; i<size; i++) {
|
||||
parity ^= str[i];
|
||||
}
|
||||
|
||||
return parity;
|
||||
}
|
||||
#endif
|
||||
|
||||
QRcode_List *QRcode_encodeInputStructured(QRinput_Struct *s)
|
||||
{
|
||||
QRcode_List *head = NULL;
|
||||
QRcode_List *tail = NULL;
|
||||
QRcode_List *entry;
|
||||
QRinput_InputList *list = s->head;
|
||||
|
||||
while(list != NULL) {
|
||||
if(head == NULL) {
|
||||
entry = QRcode_List_newEntry();
|
||||
if(entry == NULL) goto ABORT;
|
||||
head = entry;
|
||||
tail = head;
|
||||
} else {
|
||||
entry = QRcode_List_newEntry();
|
||||
if(entry == NULL) goto ABORT;
|
||||
tail->next = entry;
|
||||
tail = tail->next;
|
||||
}
|
||||
tail->code = QRcode_encodeInput(list->input);
|
||||
if(tail->code == NULL) {
|
||||
goto ABORT;
|
||||
}
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
return head;
|
||||
ABORT:
|
||||
QRcode_List_free(head);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static QRcode_List *QRcode_encodeInputToStructured(QRinput *input)
|
||||
{
|
||||
QRinput_Struct *s;
|
||||
QRcode_List *codes;
|
||||
|
||||
s = QRinput_splitQRinputToStruct(input);
|
||||
if(s == NULL) return NULL;
|
||||
|
||||
codes = QRcode_encodeInputStructured(s);
|
||||
QRinput_Struct_free(s);
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
static QRcode_List *QRcode_encodeDataStructuredReal(
|
||||
int size, const unsigned char *data,
|
||||
int version, QRecLevel level,
|
||||
int eightbit, QRencodeMode hint, int casesensitive)
|
||||
{
|
||||
QRinput *input;
|
||||
QRcode_List *codes;
|
||||
int ret;
|
||||
|
||||
if(version <= 0) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
if(!eightbit && (hint != QR_MODE_8 && hint != QR_MODE_KANJI)) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
input = QRinput_new2(version, level);
|
||||
if(input == NULL) return NULL;
|
||||
|
||||
if(eightbit) {
|
||||
ret = QRinput_append(input, QR_MODE_8, size, data);
|
||||
} else {
|
||||
ret = Split_splitStringToQRinput((char *)data, input, hint, casesensitive);
|
||||
}
|
||||
if(ret < 0) {
|
||||
QRinput_free(input);
|
||||
return NULL;
|
||||
}
|
||||
codes = QRcode_encodeInputToStructured(input);
|
||||
QRinput_free(input);
|
||||
|
||||
return codes;
|
||||
}
|
||||
|
||||
QRcode_List *QRcode_encodeDataStructured(int size, const unsigned char *data, int version, QRecLevel level) {
|
||||
return QRcode_encodeDataStructuredReal(size, data, version, level, 1, QR_MODE_NUL, 0);
|
||||
}
|
||||
|
||||
QRcode_List *QRcode_encodeString8bitStructured(const char *string, int version, QRecLevel level) {
|
||||
if(string == NULL) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
return QRcode_encodeDataStructured(strlen(string), (unsigned char *)string, version, level);
|
||||
}
|
||||
|
||||
QRcode_List *QRcode_encodeStringStructured(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive)
|
||||
{
|
||||
if(string == NULL) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
return QRcode_encodeDataStructuredReal(strlen(string), (unsigned char *)string, version, level, 0, hint, casesensitive);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* System utilities
|
||||
*****************************************************************************/
|
||||
|
||||
void QRcode_APIVersion(int *major_version, int *minor_version, int *micro_version)
|
||||
{
|
||||
if(major_version != NULL) {
|
||||
*major_version = MAJOR_VERSION;
|
||||
}
|
||||
if(minor_version != NULL) {
|
||||
*minor_version = MINOR_VERSION;
|
||||
}
|
||||
if(micro_version != NULL) {
|
||||
*micro_version = MICRO_VERSION;
|
||||
}
|
||||
}
|
||||
|
||||
char *QRcode_APIVersionString(void)
|
||||
{
|
||||
return VERSION;
|
||||
}
|
||||
|
||||
void QRcode_clearCache(void)
|
||||
{
|
||||
QRspec_clearCache();
|
||||
MQRspec_clearCache();
|
||||
free_rs_cache();
|
||||
}
|
||||
@@ -0,0 +1,565 @@
|
||||
/**
|
||||
* qrencode - QR Code encoder
|
||||
*
|
||||
* Copyright (C) 2006-2011 Kentaro Fukuchi <[email protected]>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/** \mainpage
|
||||
* Libqrencode is a library for encoding data in a QR Code symbol, a kind of 2D
|
||||
* symbology.
|
||||
*
|
||||
* \section encoding Encoding
|
||||
*
|
||||
* There are two ways to encode data: <b>encoding a string</b> or
|
||||
* <b>encoding a structured data</b>.
|
||||
*
|
||||
* \subsection encoding-string Encoding a string
|
||||
* You can encode a string by calling QRcode_encodeString().
|
||||
* The given string is parsed automatically and encoded. If you want to encode
|
||||
* data that can be represented as a C string style (NUL terminated), you can
|
||||
* simply use this way.
|
||||
*
|
||||
* If the input data contains Kanji (Shift-JIS) characters and you want to
|
||||
* encode them as Kanji in QR Code, you should give QR_MODE_KANJI as a hint.
|
||||
* Otherwise, all of non-alphanumeric characters are encoded as 8 bit data.
|
||||
* If you want to encode a whole string in 8 bit mode, use
|
||||
* QRcode_encodeString8bit() instead.
|
||||
*
|
||||
* Please note that a C string can not contain NUL character. If your data
|
||||
* contains NUL, you should chose the second way.
|
||||
*
|
||||
* \subsection encoding-input Encoding a structured data
|
||||
* You can construct a structured input data manually. If the structure of the
|
||||
* input data is known, you can use this way.
|
||||
* At first, create a ::QRinput object by QRinput_new(). Then add input data
|
||||
* to the QRinput object by QRinput_append(). Finally call QRcode_encodeInput()
|
||||
* to encode the QRinput data.
|
||||
* You can reuse the QRinput data again to encode it in other symbols with
|
||||
* different parameters.
|
||||
*
|
||||
* \section result Result
|
||||
* The encoded symbol is resulted as a ::QRcode object. It will contain
|
||||
* its version number, width of the symbol and an array represents the symbol.
|
||||
* See ::QRcode for the details. You can free the object by QRcode_free().
|
||||
*
|
||||
* Please note that the version of the result may be larger than specified.
|
||||
* In such cases, the input data would be too large to be encoded in a
|
||||
* symbol of the specified version.
|
||||
*
|
||||
* \section structured Structured append
|
||||
* Libqrencode can generate "Structured-appended" symbols that enables to split
|
||||
* a large data set into mulitple QR codes. A QR code reader concatenates
|
||||
* multiple QR code symbols into a string.
|
||||
* Just like QRcode_encodeString(), you can use QRcode_encodeStringStructured()
|
||||
* to generate structured-appended symbols. This functions returns an instance
|
||||
* of ::QRcode_List. The returned list is a singly-linked list of QRcode: you
|
||||
* can retrieve each QR code in this way:
|
||||
*
|
||||
* \code
|
||||
* QRcode_List *qrcodes;
|
||||
* QRcode_List *entry;
|
||||
* QRcode *qrcode;
|
||||
*
|
||||
* qrcodes = QRcode_encodeStringStructured(...);
|
||||
* entry = qrcodes;
|
||||
* while(entry != NULL) {
|
||||
* qrcode = entry->code;
|
||||
* // do something
|
||||
* entry = entry->next;
|
||||
* }
|
||||
* QRcode_List_free(entry);
|
||||
* \endcode
|
||||
*
|
||||
* Instead of using auto-parsing functions, you can construct your own
|
||||
* structured input. At first, instantiate an object of ::QRinput_Struct
|
||||
* by calling QRinput_Struct_new(). This object can hold multiple ::QRinput,
|
||||
* and one QR code is generated for a ::QRinput.
|
||||
* QRinput_Struct_appendInput() appends a ::QRinput to a ::QRinput_Struct
|
||||
* object. In order to generate structured-appended symbols, it is required to
|
||||
* embed headers to each symbol. You can use
|
||||
* QRinput_Struct_insertStructuredAppendHeaders() to insert appropriate
|
||||
* headers to each symbol. You should call this function just once before
|
||||
* encoding symbols.
|
||||
*/
|
||||
|
||||
#ifndef __QRENCODE_H__
|
||||
#define __QRENCODE_H__
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Encoding mode.
|
||||
*/
|
||||
typedef enum {
|
||||
QR_MODE_NUL = -1, ///< Terminator (NUL character). Internal use only
|
||||
QR_MODE_NUM = 0, ///< Numeric mode
|
||||
QR_MODE_AN, ///< Alphabet-numeric mode
|
||||
QR_MODE_8, ///< 8-bit data mode
|
||||
QR_MODE_KANJI, ///< Kanji (shift-jis) mode
|
||||
QR_MODE_STRUCTURE, ///< Internal use only
|
||||
QR_MODE_ECI, ///< ECI mode
|
||||
QR_MODE_FNC1FIRST, ///< FNC1, first position
|
||||
QR_MODE_FNC1SECOND, ///< FNC1, second position
|
||||
} QRencodeMode;
|
||||
|
||||
/**
|
||||
* Level of error correction.
|
||||
*/
|
||||
typedef enum {
|
||||
QR_ECLEVEL_L = 0, ///< lowest
|
||||
QR_ECLEVEL_M,
|
||||
QR_ECLEVEL_Q,
|
||||
QR_ECLEVEL_H ///< highest
|
||||
} QRecLevel;
|
||||
|
||||
/**
|
||||
* Maximum version (size) of QR-code symbol.
|
||||
*/
|
||||
#define QRSPEC_VERSION_MAX 40
|
||||
|
||||
/**
|
||||
* Maximum version (size) of QR-code symbol.
|
||||
*/
|
||||
#define MQRSPEC_VERSION_MAX 4
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Input data (qrinput.c)
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Singly linked list to contain input strings. An instance of this class
|
||||
* contains its version and error correction level too. It is required to
|
||||
* set them by QRinput_setVersion() and QRinput_setErrorCorrectionLevel(),
|
||||
* or use QRinput_new2() to instantiate an object.
|
||||
*/
|
||||
typedef struct _QRinput QRinput;
|
||||
|
||||
/**
|
||||
* Instantiate an input data object. The version is set to 0 (auto-select)
|
||||
* and the error correction level is set to QR_ECLEVEL_L.
|
||||
* @return an input object (initialized). On error, NULL is returned and errno
|
||||
* is set to indicate the error.
|
||||
* @throw ENOMEM unable to allocate memory.
|
||||
*/
|
||||
extern QRinput *QRinput_new(void);
|
||||
|
||||
/**
|
||||
* Instantiate an input data object.
|
||||
* @param version version number.
|
||||
* @param level Error correction level.
|
||||
* @return an input object (initialized). On error, NULL is returned and errno
|
||||
* is set to indicate the error.
|
||||
* @throw ENOMEM unable to allocate memory for input objects.
|
||||
* @throw EINVAL invalid arguments.
|
||||
*/
|
||||
extern QRinput *QRinput_new2(int version, QRecLevel level);
|
||||
|
||||
/**
|
||||
* Instantiate an input data object. Object's Micro QR Code flag is set.
|
||||
* Unlike with full-sized QR Code, version number must be specified (>0).
|
||||
* @param version version number (1--4).
|
||||
* @param level Error correction level.
|
||||
* @return an input object (initialized). On error, NULL is returned and errno
|
||||
* is set to indicate the error.
|
||||
* @throw ENOMEM unable to allocate memory for input objects.
|
||||
* @throw EINVAL invalid arguments.
|
||||
*/
|
||||
extern QRinput *QRinput_newMQR(int version, QRecLevel level);
|
||||
|
||||
/**
|
||||
* Append data to an input object.
|
||||
* The data is copied and appended to the input object.
|
||||
* @param input input object.
|
||||
* @param mode encoding mode.
|
||||
* @param size size of data (byte).
|
||||
* @param data a pointer to the memory area of the input data.
|
||||
* @retval 0 success.
|
||||
* @retval -1 an error occurred and errno is set to indeicate the error.
|
||||
* See Execptions for the details.
|
||||
* @throw ENOMEM unable to allocate memory.
|
||||
* @throw EINVAL input data is invalid.
|
||||
*
|
||||
*/
|
||||
extern int QRinput_append(QRinput *input, QRencodeMode mode, int size, const unsigned char *data);
|
||||
|
||||
/**
|
||||
* Append ECI header.
|
||||
* @param input input object.
|
||||
* @param ecinum ECI indicator number (0 - 999999)
|
||||
* @retval 0 success.
|
||||
* @retval -1 an error occurred and errno is set to indeicate the error.
|
||||
* See Execptions for the details.
|
||||
* @throw ENOMEM unable to allocate memory.
|
||||
* @throw EINVAL input data is invalid.
|
||||
*
|
||||
*/
|
||||
extern int QRinput_appendECIheader(QRinput *input, unsigned int ecinum);
|
||||
|
||||
/**
|
||||
* Get current version.
|
||||
* @param input input object.
|
||||
* @return current version.
|
||||
*/
|
||||
extern int QRinput_getVersion(QRinput *input);
|
||||
|
||||
/**
|
||||
* Set version of the QR code that is to be encoded.
|
||||
* This function cannot be applied to Micro QR Code.
|
||||
* @param input input object.
|
||||
* @param version version number (0 = auto)
|
||||
* @retval 0 success.
|
||||
* @retval -1 invalid argument.
|
||||
*/
|
||||
extern int QRinput_setVersion(QRinput *input, int version);
|
||||
|
||||
/**
|
||||
* Get current error correction level.
|
||||
* @param input input object.
|
||||
* @return Current error correcntion level.
|
||||
*/
|
||||
extern QRecLevel QRinput_getErrorCorrectionLevel(QRinput *input);
|
||||
|
||||
/**
|
||||
* Set error correction level of the QR code that is to be encoded.
|
||||
* This function cannot be applied to Micro QR Code.
|
||||
* @param input input object.
|
||||
* @param level Error correction level.
|
||||
* @retval 0 success.
|
||||
* @retval -1 invalid argument.
|
||||
*/
|
||||
extern int QRinput_setErrorCorrectionLevel(QRinput *input, QRecLevel level);
|
||||
|
||||
/**
|
||||
* Set version and error correction level of the QR code at once.
|
||||
* This function is recommened for Micro QR Code.
|
||||
* @param input input object.
|
||||
* @param version version number (0 = auto)
|
||||
* @param level Error correction level.
|
||||
* @retval 0 success.
|
||||
* @retval -1 invalid argument.
|
||||
*/
|
||||
extern int QRinput_setVersionAndErrorCorrectionLevel(QRinput *input, int version, QRecLevel level);
|
||||
|
||||
/**
|
||||
* Free the input object.
|
||||
* All of data chunks in the input object are freed too.
|
||||
* @param input input object.
|
||||
*/
|
||||
extern void QRinput_free(QRinput *input);
|
||||
|
||||
/**
|
||||
* Validate the input data.
|
||||
* @param mode encoding mode.
|
||||
* @param size size of data (byte).
|
||||
* @param data a pointer to the memory area of the input data.
|
||||
* @retval 0 success.
|
||||
* @retval -1 invalid arguments.
|
||||
*/
|
||||
extern int QRinput_check(QRencodeMode mode, int size, const unsigned char *data);
|
||||
|
||||
/**
|
||||
* Set of QRinput for structured symbols.
|
||||
*/
|
||||
typedef struct _QRinput_Struct QRinput_Struct;
|
||||
|
||||
/**
|
||||
* Instantiate a set of input data object.
|
||||
* @return an instance of QRinput_Struct. On error, NULL is returned and errno
|
||||
* is set to indicate the error.
|
||||
* @throw ENOMEM unable to allocate memory.
|
||||
*/
|
||||
extern QRinput_Struct *QRinput_Struct_new(void);
|
||||
|
||||
/**
|
||||
* Set parity of structured symbols.
|
||||
* @param s structured input object.
|
||||
* @param parity parity of s.
|
||||
*/
|
||||
extern void QRinput_Struct_setParity(QRinput_Struct *s, unsigned char parity);
|
||||
|
||||
/**
|
||||
* Append a QRinput object to the set. QRinput created by QRinput_newMQR()
|
||||
* will be rejected.
|
||||
* @warning never append the same QRinput object twice or more.
|
||||
* @param s structured input object.
|
||||
* @param input an input object.
|
||||
* @retval >0 number of input objects in the structure.
|
||||
* @retval -1 an error occurred. See Exceptions for the details.
|
||||
* @throw ENOMEM unable to allocate memory.
|
||||
* @throw EINVAL invalid arguments.
|
||||
*/
|
||||
extern int QRinput_Struct_appendInput(QRinput_Struct *s, QRinput *input);
|
||||
|
||||
/**
|
||||
* Free all of QRinput in the set.
|
||||
* @param s a structured input object.
|
||||
*/
|
||||
extern void QRinput_Struct_free(QRinput_Struct *s);
|
||||
|
||||
/**
|
||||
* Split a QRinput to QRinput_Struct. It calculates a parity, set it, then
|
||||
* insert structured-append headers. QRinput created by QRinput_newMQR() will
|
||||
* be rejected.
|
||||
* @param input input object. Version number and error correction level must be
|
||||
* set.
|
||||
* @return a set of input data. On error, NULL is returned, and errno is set
|
||||
* to indicate the error. See Exceptions for the details.
|
||||
* @throw ERANGE input data is too large.
|
||||
* @throw EINVAL invalid input data.
|
||||
* @throw ENOMEM unable to allocate memory.
|
||||
*/
|
||||
extern QRinput_Struct *QRinput_splitQRinputToStruct(QRinput *input);
|
||||
|
||||
/**
|
||||
* Insert structured-append headers to the input structure. It calculates
|
||||
* a parity and set it if the parity is not set yet.
|
||||
* @param s input structure
|
||||
* @retval 0 success.
|
||||
* @retval -1 an error occurred and errno is set to indeicate the error.
|
||||
* See Execptions for the details.
|
||||
* @throw EINVAL invalid input object.
|
||||
* @throw ENOMEM unable to allocate memory.
|
||||
*/
|
||||
extern int QRinput_Struct_insertStructuredAppendHeaders(QRinput_Struct *s);
|
||||
|
||||
/**
|
||||
* Set FNC1-1st position flag.
|
||||
*/
|
||||
extern int QRinput_setFNC1First(QRinput *input);
|
||||
|
||||
/**
|
||||
* Set FNC1-2nd position flag and application identifier.
|
||||
*/
|
||||
extern int QRinput_setFNC1Second(QRinput *input, unsigned char appid);
|
||||
|
||||
/******************************************************************************
|
||||
* QRcode output (qrencode.c)
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* QRcode class.
|
||||
* Symbol data is represented as an array contains width*width uchars.
|
||||
* Each uchar represents a module (dot). If the less significant bit of
|
||||
* the uchar is 1, the corresponding module is black. The other bits are
|
||||
* meaningless for usual applications, but here its specification is described.
|
||||
*
|
||||
* <pre>
|
||||
* MSB 76543210 LSB
|
||||
* |||||||`- 1=black/0=white
|
||||
* ||||||`-- data and ecc code area
|
||||
* |||||`--- format information
|
||||
* ||||`---- version information
|
||||
* |||`----- timing pattern
|
||||
* ||`------ alignment pattern
|
||||
* |`------- finder pattern and separator
|
||||
* `-------- non-data modules (format, timing, etc.)
|
||||
* </pre>
|
||||
*/
|
||||
typedef struct {
|
||||
int version; ///< version of the symbol
|
||||
int width; ///< width of the symbol
|
||||
unsigned char *data; ///< symbol data
|
||||
} QRcode;
|
||||
|
||||
/**
|
||||
* Singly-linked list of QRcode. Used to represent a structured symbols.
|
||||
* A list is terminated with NULL.
|
||||
*/
|
||||
typedef struct _QRcode_List QRcode_List;
|
||||
|
||||
struct _QRcode_List {
|
||||
QRcode *code;
|
||||
QRcode_List *next;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a symbol from the input data.
|
||||
* @warning This function is THREAD UNSAFE when pthread is disabled.
|
||||
* @param input input data.
|
||||
* @return an instance of QRcode class. The version of the result QRcode may
|
||||
* be larger than the designated version. On error, NULL is returned,
|
||||
* and errno is set to indicate the error. See Exceptions for the
|
||||
* details.
|
||||
* @throw EINVAL invalid input object.
|
||||
* @throw ENOMEM unable to allocate memory for input objects.
|
||||
*/
|
||||
extern QRcode *QRcode_encodeInput(QRinput *input);
|
||||
|
||||
/**
|
||||
* Create a symbol from the string. The library automatically parses the input
|
||||
* string and encodes in a QR Code symbol.
|
||||
* @warning This function is THREAD UNSAFE when pthread is disabled.
|
||||
* @param string input string. It must be NUL terminated.
|
||||
* @param version version of the symbol. If 0, the library chooses the minimum
|
||||
* version for the given input data.
|
||||
* @param level error correction level.
|
||||
* @param hint tell the library how non-alphanumerical characters should be
|
||||
* encoded. If QR_MODE_KANJI is given, kanji characters will be
|
||||
* encoded as Shif-JIS characters. If QR_MODE_8 is given, all of
|
||||
* non-alphanumerical characters will be encoded as is. If you want
|
||||
* to embed UTF-8 string, choose this.
|
||||
* @param casesensitive case-sensitive(1) or not(0).
|
||||
* @return an instance of QRcode class. The version of the result QRcode may
|
||||
* be larger than the designated version. On error, NULL is returned,
|
||||
* and errno is set to indicate the error. See Exceptions for the
|
||||
* details.
|
||||
* @throw EINVAL invalid input object.
|
||||
* @throw ENOMEM unable to allocate memory for input objects.
|
||||
* @throw ERANGE input data is too large.
|
||||
*/
|
||||
extern QRcode *QRcode_encodeString(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive);
|
||||
|
||||
/**
|
||||
* Same to QRcode_encodeString(), but encode whole data in 8-bit mode.
|
||||
* @warning This function is THREAD UNSAFE when pthread is disabled.
|
||||
*/
|
||||
extern QRcode *QRcode_encodeString8bit(const char *string, int version, QRecLevel level);
|
||||
|
||||
/**
|
||||
* Micro QR Code version of QRcode_encodeString().
|
||||
* @warning This function is THREAD UNSAFE when pthread is disabled.
|
||||
*/
|
||||
extern QRcode *QRcode_encodeStringMQR(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive);
|
||||
|
||||
/**
|
||||
* Micro QR Code version of QRcode_encodeString8bit().
|
||||
* @warning This function is THREAD UNSAFE when pthread is disabled.
|
||||
*/
|
||||
extern QRcode *QRcode_encodeString8bitMQR(const char *string, int version, QRecLevel level);
|
||||
|
||||
/**
|
||||
* Encode byte stream (may include '\0') in 8-bit mode.
|
||||
* @warning This function is THREAD UNSAFE when pthread is disabled.
|
||||
* @param size size of the input data.
|
||||
* @param data input data.
|
||||
* @param version version of the symbol. If 0, the library chooses the minimum
|
||||
* version for the given input data.
|
||||
* @param level error correction level.
|
||||
* @throw EINVAL invalid input object.
|
||||
* @throw ENOMEM unable to allocate memory for input objects.
|
||||
* @throw ERANGE input data is too large.
|
||||
*/
|
||||
extern QRcode *QRcode_encodeData(int size, const unsigned char *data, int version, QRecLevel level);
|
||||
|
||||
/**
|
||||
* Micro QR Code version of QRcode_encodeData().
|
||||
* @warning This function is THREAD UNSAFE when pthread is disabled.
|
||||
*/
|
||||
extern QRcode *QRcode_encodeDataMQR(int size, const unsigned char *data, int version, QRecLevel level);
|
||||
|
||||
/**
|
||||
* Free the instance of QRcode class.
|
||||
* @param qrcode an instance of QRcode class.
|
||||
*/
|
||||
extern void QRcode_free(QRcode *qrcode);
|
||||
|
||||
/**
|
||||
* Create structured symbols from the input data.
|
||||
* @warning This function is THREAD UNSAFE when pthread is disabled.
|
||||
* @param s
|
||||
* @return a singly-linked list of QRcode.
|
||||
*/
|
||||
extern QRcode_List *QRcode_encodeInputStructured(QRinput_Struct *s);
|
||||
|
||||
/**
|
||||
* Create structured symbols from the string. The library automatically parses
|
||||
* the input string and encodes in a QR Code symbol.
|
||||
* @warning This function is THREAD UNSAFE when pthread is disabled.
|
||||
* @param string input string. It must be NUL terminated.
|
||||
* @param version version of the symbol.
|
||||
* @param level error correction level.
|
||||
* @param hint tell the library how non-alphanumerical characters should be
|
||||
* encoded. If QR_MODE_KANJI is given, kanji characters will be
|
||||
* encoded as Shif-JIS characters. If QR_MODE_8 is given, all of
|
||||
* non-alphanumerical characters will be encoded as is. If you want
|
||||
* to embed UTF-8 string, choose this.
|
||||
* @param casesensitive case-sensitive(1) or not(0).
|
||||
* @return a singly-linked list of QRcode. On error, NULL is returned, and
|
||||
* errno is set to indicate the error. See Exceptions for the details.
|
||||
* @throw EINVAL invalid input object.
|
||||
* @throw ENOMEM unable to allocate memory for input objects.
|
||||
*/
|
||||
extern QRcode_List *QRcode_encodeStringStructured(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive);
|
||||
|
||||
/**
|
||||
* Same to QRcode_encodeStringStructured(), but encode whole data in 8-bit mode.
|
||||
* @warning This function is THREAD UNSAFE when pthread is disabled.
|
||||
*/
|
||||
extern QRcode_List *QRcode_encodeString8bitStructured(const char *string, int version, QRecLevel level);
|
||||
|
||||
/**
|
||||
* Create structured symbols from byte stream (may include '\0'). Wholde data
|
||||
* are encoded in 8-bit mode.
|
||||
* @warning This function is THREAD UNSAFE when pthread is disabled.
|
||||
* @param size size of the input data.
|
||||
* @param data input dat.
|
||||
* @param version version of the symbol.
|
||||
* @param level error correction level.
|
||||
* @return a singly-linked list of QRcode. On error, NULL is returned, and
|
||||
* errno is set to indicate the error. See Exceptions for the details.
|
||||
* @throw EINVAL invalid input object.
|
||||
* @throw ENOMEM unable to allocate memory for input objects.
|
||||
*/
|
||||
extern QRcode_List *QRcode_encodeDataStructured(int size, const unsigned char *data, int version, QRecLevel level);
|
||||
|
||||
/**
|
||||
* Return the number of symbols included in a QRcode_List.
|
||||
* @param qrlist a head entry of a QRcode_List.
|
||||
* @return number of symbols in the list.
|
||||
*/
|
||||
extern int QRcode_List_size(QRcode_List *qrlist);
|
||||
|
||||
/**
|
||||
* Free the QRcode_List.
|
||||
* @param qrlist a head entry of a QRcode_List.
|
||||
*/
|
||||
extern void QRcode_List_free(QRcode_List *qrlist);
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* System utilities
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Return a string that identifies the library version.
|
||||
* @param major_version
|
||||
* @param minor_version
|
||||
* @param micro_version
|
||||
*/
|
||||
extern void QRcode_APIVersion(int *major_version, int *minor_version, int *micro_version);
|
||||
|
||||
/**
|
||||
* Return a string that identifies the library version.
|
||||
* @return a string identifies the library version. The string is held by the
|
||||
* library. Do NOT free it.
|
||||
*/
|
||||
extern char *QRcode_APIVersionString(void);
|
||||
|
||||
/**
|
||||
* Clear all caches. This is only for debug purpose. If you are attacking a
|
||||
* complicated memory leak bug, try this to reduce the reachable blocks record.
|
||||
*/
|
||||
extern void QRcode_clearCache(void);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __QRENCODE_H__ */
|
||||
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* qrencode - QR Code encoder
|
||||
*
|
||||
* Header for test use
|
||||
* Copyright (C) 2006-2011 Kentaro Fukuchi <[email protected]>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __QRENCODE_INNER_H__
|
||||
#define __QRENCODE_INNER_H__
|
||||
|
||||
/**
|
||||
* This header file includes definitions for test use.
|
||||
*/
|
||||
|
||||
/******************************************************************************
|
||||
* Raw code
|
||||
*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
int dataLength;
|
||||
unsigned char *data;
|
||||
int eccLength;
|
||||
unsigned char *ecc;
|
||||
} RSblock;
|
||||
|
||||
typedef struct {
|
||||
int version;
|
||||
int dataLength;
|
||||
int eccLength;
|
||||
unsigned char *datacode;
|
||||
unsigned char *ecccode;
|
||||
int b1;
|
||||
int blocks;
|
||||
RSblock *rsblock;
|
||||
int count;
|
||||
} QRRawCode;
|
||||
|
||||
extern QRRawCode *QRraw_new(QRinput *input);
|
||||
extern unsigned char QRraw_getCode(QRRawCode *raw);
|
||||
extern void QRraw_free(QRRawCode *raw);
|
||||
|
||||
/******************************************************************************
|
||||
* Raw code for Micro QR Code
|
||||
*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
int version;
|
||||
int dataLength;
|
||||
int eccLength;
|
||||
unsigned char *datacode;
|
||||
unsigned char *ecccode;
|
||||
RSblock *rsblock;
|
||||
int oddbits;
|
||||
int count;
|
||||
} MQRRawCode;
|
||||
|
||||
extern MQRRawCode *MQRraw_new(QRinput *input);
|
||||
extern unsigned char MQRraw_getCode(MQRRawCode *raw);
|
||||
extern void MQRraw_free(MQRRawCode *raw);
|
||||
|
||||
/******************************************************************************
|
||||
* Frame filling
|
||||
*****************************************************************************/
|
||||
extern unsigned char *FrameFiller_test(int version);
|
||||
extern unsigned char *FrameFiller_testMQR(int version);
|
||||
|
||||
/******************************************************************************
|
||||
* QR-code encoding
|
||||
*****************************************************************************/
|
||||
extern QRcode *QRcode_encodeMask(QRinput *input, int mask);
|
||||
extern QRcode *QRcode_encodeMaskMQR(QRinput *input, int mask);
|
||||
extern QRcode *QRcode_new(int version, int width, unsigned char *data);
|
||||
|
||||
#endif /* __QRENCODE_INNER_H__ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* qrencode - QR Code encoder
|
||||
*
|
||||
* Input data chunk class
|
||||
* Copyright (C) 2006-2011 Kentaro Fukuchi <[email protected]>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __QRINPUT_H__
|
||||
#define __QRINPUT_H__
|
||||
|
||||
#include "qrencode.h"
|
||||
#include "bitstream.h"
|
||||
|
||||
int QRinput_isSplittableMode(QRencodeMode mode);
|
||||
|
||||
/******************************************************************************
|
||||
* Entry of input data
|
||||
*****************************************************************************/
|
||||
typedef struct _QRinput_List QRinput_List;
|
||||
|
||||
struct _QRinput_List {
|
||||
QRencodeMode mode;
|
||||
int size; ///< Size of data chunk (byte).
|
||||
unsigned char *data; ///< Data chunk.
|
||||
BitStream *bstream;
|
||||
QRinput_List *next;
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* Input Data
|
||||
*****************************************************************************/
|
||||
struct _QRinput {
|
||||
int version;
|
||||
QRecLevel level;
|
||||
QRinput_List *head;
|
||||
QRinput_List *tail;
|
||||
int mqr;
|
||||
int fnc1;
|
||||
unsigned char appid;
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
* Structured append input data
|
||||
*****************************************************************************/
|
||||
typedef struct _QRinput_InputList QRinput_InputList;
|
||||
|
||||
struct _QRinput_InputList {
|
||||
QRinput *input;
|
||||
QRinput_InputList *next;
|
||||
};
|
||||
|
||||
struct _QRinput_Struct {
|
||||
int size; ///< number of structured symbols
|
||||
int parity;
|
||||
QRinput_InputList *head;
|
||||
QRinput_InputList *tail;
|
||||
};
|
||||
|
||||
/**
|
||||
* Pack all bit streams padding bits into a byte array.
|
||||
* @param input input data.
|
||||
* @return padded merged byte stream
|
||||
*/
|
||||
extern unsigned char *QRinput_getByteStream(QRinput *input);
|
||||
|
||||
|
||||
extern int QRinput_estimateBitsModeNum(int size);
|
||||
extern int QRinput_estimateBitsModeAn(int size);
|
||||
extern int QRinput_estimateBitsMode8(int size);
|
||||
extern int QRinput_estimateBitsModeKanji(int size);
|
||||
|
||||
extern QRinput *QRinput_dup(QRinput *input);
|
||||
|
||||
extern const signed char QRinput_anTable[128];
|
||||
|
||||
/**
|
||||
* Look up the alphabet-numeric convesion table (see JIS X0510:2004, pp.19).
|
||||
* @param __c__ character
|
||||
* @return value
|
||||
*/
|
||||
#define QRinput_lookAnTable(__c__) \
|
||||
((__c__ & 0x80)?-1:QRinput_anTable[(int)__c__])
|
||||
|
||||
/**
|
||||
* Length of a standard mode indicator in bits.
|
||||
*/
|
||||
|
||||
#define MODE_INDICATOR_SIZE 4
|
||||
|
||||
/**
|
||||
* Length of a segment of structured-append header.
|
||||
*/
|
||||
#define STRUCTURE_HEADER_SIZE 20
|
||||
|
||||
/**
|
||||
* Maximum number of symbols in a set of structured-appended symbols.
|
||||
*/
|
||||
#define MAX_STRUCTURED_SYMBOLS 16
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
extern BitStream *QRinput_mergeBitStream(QRinput *input);
|
||||
extern BitStream *QRinput_getBitStream(QRinput *input);
|
||||
extern int QRinput_estimateBitStreamSize(QRinput *input, int version);
|
||||
extern int QRinput_splitEntry(QRinput_List *entry, int bytes);
|
||||
extern int QRinput_lengthOfCode(QRencodeMode mode, int version, int bits);
|
||||
extern int QRinput_insertStructuredAppendHeader(QRinput *input, int size, int index, unsigned char parity);
|
||||
#endif
|
||||
|
||||
#endif /* __QRINPUT_H__ */
|
||||
@@ -0,0 +1,562 @@
|
||||
/*
|
||||
* qrencode - QR Code encoder
|
||||
*
|
||||
* QR Code specification in convenient format.
|
||||
* Copyright (C) 2006-2011 Kentaro Fukuchi <[email protected]>
|
||||
*
|
||||
* The following data / specifications are taken from
|
||||
* "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
|
||||
* or
|
||||
* "Automatic identification and data capture techniques --
|
||||
* QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include "qrspec.h"
|
||||
#include "qrinput.h"
|
||||
|
||||
/******************************************************************************
|
||||
* Version and capacity
|
||||
*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
int width; //< Edge length of the symbol
|
||||
int words; //< Data capacity (bytes)
|
||||
int remainder; //< Remainder bit (bits)
|
||||
int ec[4]; //< Number of ECC code (bytes)
|
||||
} QRspec_Capacity;
|
||||
|
||||
/**
|
||||
* Table of the capacity of symbols
|
||||
* See Table 1 (pp.13) and Table 12-16 (pp.30-36), JIS X0510:2004.
|
||||
*/
|
||||
static const QRspec_Capacity qrspecCapacity[QRSPEC_VERSION_MAX + 1] = {
|
||||
{ 0, 0, 0, { 0, 0, 0, 0}},
|
||||
{ 21, 26, 0, { 7, 10, 13, 17}}, // 1
|
||||
{ 25, 44, 7, { 10, 16, 22, 28}},
|
||||
{ 29, 70, 7, { 15, 26, 36, 44}},
|
||||
{ 33, 100, 7, { 20, 36, 52, 64}},
|
||||
{ 37, 134, 7, { 26, 48, 72, 88}}, // 5
|
||||
{ 41, 172, 7, { 36, 64, 96, 112}},
|
||||
{ 45, 196, 0, { 40, 72, 108, 130}},
|
||||
{ 49, 242, 0, { 48, 88, 132, 156}},
|
||||
{ 53, 292, 0, { 60, 110, 160, 192}},
|
||||
{ 57, 346, 0, { 72, 130, 192, 224}}, //10
|
||||
{ 61, 404, 0, { 80, 150, 224, 264}},
|
||||
{ 65, 466, 0, { 96, 176, 260, 308}},
|
||||
{ 69, 532, 0, { 104, 198, 288, 352}},
|
||||
{ 73, 581, 3, { 120, 216, 320, 384}},
|
||||
{ 77, 655, 3, { 132, 240, 360, 432}}, //15
|
||||
{ 81, 733, 3, { 144, 280, 408, 480}},
|
||||
{ 85, 815, 3, { 168, 308, 448, 532}},
|
||||
{ 89, 901, 3, { 180, 338, 504, 588}},
|
||||
{ 93, 991, 3, { 196, 364, 546, 650}},
|
||||
{ 97, 1085, 3, { 224, 416, 600, 700}}, //20
|
||||
{101, 1156, 4, { 224, 442, 644, 750}},
|
||||
{105, 1258, 4, { 252, 476, 690, 816}},
|
||||
{109, 1364, 4, { 270, 504, 750, 900}},
|
||||
{113, 1474, 4, { 300, 560, 810, 960}},
|
||||
{117, 1588, 4, { 312, 588, 870, 1050}}, //25
|
||||
{121, 1706, 4, { 336, 644, 952, 1110}},
|
||||
{125, 1828, 4, { 360, 700, 1020, 1200}},
|
||||
{129, 1921, 3, { 390, 728, 1050, 1260}},
|
||||
{133, 2051, 3, { 420, 784, 1140, 1350}},
|
||||
{137, 2185, 3, { 450, 812, 1200, 1440}}, //30
|
||||
{141, 2323, 3, { 480, 868, 1290, 1530}},
|
||||
{145, 2465, 3, { 510, 924, 1350, 1620}},
|
||||
{149, 2611, 3, { 540, 980, 1440, 1710}},
|
||||
{153, 2761, 3, { 570, 1036, 1530, 1800}},
|
||||
{157, 2876, 0, { 570, 1064, 1590, 1890}}, //35
|
||||
{161, 3034, 0, { 600, 1120, 1680, 1980}},
|
||||
{165, 3196, 0, { 630, 1204, 1770, 2100}},
|
||||
{169, 3362, 0, { 660, 1260, 1860, 2220}},
|
||||
{173, 3532, 0, { 720, 1316, 1950, 2310}},
|
||||
{177, 3706, 0, { 750, 1372, 2040, 2430}} //40
|
||||
};
|
||||
|
||||
int QRspec_getDataLength(int version, QRecLevel level)
|
||||
{
|
||||
return qrspecCapacity[version].words - qrspecCapacity[version].ec[level];
|
||||
}
|
||||
|
||||
int QRspec_getECCLength(int version, QRecLevel level)
|
||||
{
|
||||
return qrspecCapacity[version].ec[level];
|
||||
}
|
||||
|
||||
int QRspec_getMinimumVersion(int size, QRecLevel level)
|
||||
{
|
||||
int i;
|
||||
int words;
|
||||
|
||||
for(i=1; i<= QRSPEC_VERSION_MAX; i++) {
|
||||
words = qrspecCapacity[i].words - qrspecCapacity[i].ec[level];
|
||||
if(words >= size) return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int QRspec_getWidth(int version)
|
||||
{
|
||||
return qrspecCapacity[version].width;
|
||||
}
|
||||
|
||||
int QRspec_getRemainder(int version)
|
||||
{
|
||||
return qrspecCapacity[version].remainder;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Length indicator
|
||||
*****************************************************************************/
|
||||
|
||||
static const int lengthTableBits[4][3] = {
|
||||
{10, 12, 14},
|
||||
{ 9, 11, 13},
|
||||
{ 8, 16, 16},
|
||||
{ 8, 10, 12}
|
||||
};
|
||||
|
||||
int QRspec_lengthIndicator(QRencodeMode mode, int version)
|
||||
{
|
||||
int l;
|
||||
|
||||
if(!QRinput_isSplittableMode(mode)) return 0;
|
||||
if(version <= 9) {
|
||||
l = 0;
|
||||
} else if(version <= 26) {
|
||||
l = 1;
|
||||
} else {
|
||||
l = 2;
|
||||
}
|
||||
|
||||
return lengthTableBits[mode][l];
|
||||
}
|
||||
|
||||
int QRspec_maximumWords(QRencodeMode mode, int version)
|
||||
{
|
||||
int l;
|
||||
int bits;
|
||||
int words;
|
||||
|
||||
if(!QRinput_isSplittableMode(mode)) return 0;
|
||||
if(version <= 9) {
|
||||
l = 0;
|
||||
} else if(version <= 26) {
|
||||
l = 1;
|
||||
} else {
|
||||
l = 2;
|
||||
}
|
||||
|
||||
bits = lengthTableBits[mode][l];
|
||||
words = (1 << bits) - 1;
|
||||
if(mode == QR_MODE_KANJI) {
|
||||
words *= 2; // the number of bytes is required
|
||||
}
|
||||
|
||||
return words;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Error correction code
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Table of the error correction code (Reed-Solomon block)
|
||||
* See Table 12-16 (pp.30-36), JIS X0510:2004.
|
||||
*/
|
||||
static const int eccTable[QRSPEC_VERSION_MAX+1][4][2] = {
|
||||
{{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}},
|
||||
{{ 1, 0}, { 1, 0}, { 1, 0}, { 1, 0}}, // 1
|
||||
{{ 1, 0}, { 1, 0}, { 1, 0}, { 1, 0}},
|
||||
{{ 1, 0}, { 1, 0}, { 2, 0}, { 2, 0}},
|
||||
{{ 1, 0}, { 2, 0}, { 2, 0}, { 4, 0}},
|
||||
{{ 1, 0}, { 2, 0}, { 2, 2}, { 2, 2}}, // 5
|
||||
{{ 2, 0}, { 4, 0}, { 4, 0}, { 4, 0}},
|
||||
{{ 2, 0}, { 4, 0}, { 2, 4}, { 4, 1}},
|
||||
{{ 2, 0}, { 2, 2}, { 4, 2}, { 4, 2}},
|
||||
{{ 2, 0}, { 3, 2}, { 4, 4}, { 4, 4}},
|
||||
{{ 2, 2}, { 4, 1}, { 6, 2}, { 6, 2}}, //10
|
||||
{{ 4, 0}, { 1, 4}, { 4, 4}, { 3, 8}},
|
||||
{{ 2, 2}, { 6, 2}, { 4, 6}, { 7, 4}},
|
||||
{{ 4, 0}, { 8, 1}, { 8, 4}, {12, 4}},
|
||||
{{ 3, 1}, { 4, 5}, {11, 5}, {11, 5}},
|
||||
{{ 5, 1}, { 5, 5}, { 5, 7}, {11, 7}}, //15
|
||||
{{ 5, 1}, { 7, 3}, {15, 2}, { 3, 13}},
|
||||
{{ 1, 5}, {10, 1}, { 1, 15}, { 2, 17}},
|
||||
{{ 5, 1}, { 9, 4}, {17, 1}, { 2, 19}},
|
||||
{{ 3, 4}, { 3, 11}, {17, 4}, { 9, 16}},
|
||||
{{ 3, 5}, { 3, 13}, {15, 5}, {15, 10}}, //20
|
||||
{{ 4, 4}, {17, 0}, {17, 6}, {19, 6}},
|
||||
{{ 2, 7}, {17, 0}, { 7, 16}, {34, 0}},
|
||||
{{ 4, 5}, { 4, 14}, {11, 14}, {16, 14}},
|
||||
{{ 6, 4}, { 6, 14}, {11, 16}, {30, 2}},
|
||||
{{ 8, 4}, { 8, 13}, { 7, 22}, {22, 13}}, //25
|
||||
{{10, 2}, {19, 4}, {28, 6}, {33, 4}},
|
||||
{{ 8, 4}, {22, 3}, { 8, 26}, {12, 28}},
|
||||
{{ 3, 10}, { 3, 23}, { 4, 31}, {11, 31}},
|
||||
{{ 7, 7}, {21, 7}, { 1, 37}, {19, 26}},
|
||||
{{ 5, 10}, {19, 10}, {15, 25}, {23, 25}}, //30
|
||||
{{13, 3}, { 2, 29}, {42, 1}, {23, 28}},
|
||||
{{17, 0}, {10, 23}, {10, 35}, {19, 35}},
|
||||
{{17, 1}, {14, 21}, {29, 19}, {11, 46}},
|
||||
{{13, 6}, {14, 23}, {44, 7}, {59, 1}},
|
||||
{{12, 7}, {12, 26}, {39, 14}, {22, 41}}, //35
|
||||
{{ 6, 14}, { 6, 34}, {46, 10}, { 2, 64}},
|
||||
{{17, 4}, {29, 14}, {49, 10}, {24, 46}},
|
||||
{{ 4, 18}, {13, 32}, {48, 14}, {42, 32}},
|
||||
{{20, 4}, {40, 7}, {43, 22}, {10, 67}},
|
||||
{{19, 6}, {18, 31}, {34, 34}, {20, 61}},//40
|
||||
};
|
||||
|
||||
void QRspec_getEccSpec(int version, QRecLevel level, int spec[5])
|
||||
{
|
||||
int b1, b2;
|
||||
int data, ecc;
|
||||
|
||||
b1 = eccTable[version][level][0];
|
||||
b2 = eccTable[version][level][1];
|
||||
data = QRspec_getDataLength(version, level);
|
||||
ecc = QRspec_getECCLength(version, level);
|
||||
|
||||
if(b2 == 0) {
|
||||
spec[0] = b1;
|
||||
spec[1] = data / b1;
|
||||
spec[2] = ecc / b1;
|
||||
spec[3] = spec[4] = 0;
|
||||
} else {
|
||||
spec[0] = b1;
|
||||
spec[1] = data / (b1 + b2);
|
||||
spec[2] = ecc / (b1 + b2);
|
||||
spec[3] = b2;
|
||||
spec[4] = spec[1] + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Alignment pattern
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Positions of alignment patterns.
|
||||
* This array includes only the second and the third position of the alignment
|
||||
* patterns. Rest of them can be calculated from the distance between them.
|
||||
*
|
||||
* See Table 1 in Appendix E (pp.71) of JIS X0510:2004.
|
||||
*/
|
||||
static const int alignmentPattern[QRSPEC_VERSION_MAX+1][2] = {
|
||||
{ 0, 0},
|
||||
{ 0, 0}, {18, 0}, {22, 0}, {26, 0}, {30, 0}, // 1- 5
|
||||
{34, 0}, {22, 38}, {24, 42}, {26, 46}, {28, 50}, // 6-10
|
||||
{30, 54}, {32, 58}, {34, 62}, {26, 46}, {26, 48}, //11-15
|
||||
{26, 50}, {30, 54}, {30, 56}, {30, 58}, {34, 62}, //16-20
|
||||
{28, 50}, {26, 50}, {30, 54}, {28, 54}, {32, 58}, //21-25
|
||||
{30, 58}, {34, 62}, {26, 50}, {30, 54}, {26, 52}, //26-30
|
||||
{30, 56}, {34, 60}, {30, 58}, {34, 62}, {30, 54}, //31-35
|
||||
{24, 50}, {28, 54}, {32, 58}, {26, 54}, {30, 58}, //35-40
|
||||
};
|
||||
|
||||
/**
|
||||
* Put an alignment marker.
|
||||
* @param frame
|
||||
* @param width
|
||||
* @param ox,oy center coordinate of the pattern
|
||||
*/
|
||||
static void QRspec_putAlignmentMarker(unsigned char *frame, int width, int ox, int oy)
|
||||
{
|
||||
static const unsigned char finder[] = {
|
||||
0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
|
||||
0xa1, 0xa0, 0xa0, 0xa0, 0xa1,
|
||||
0xa1, 0xa0, 0xa1, 0xa0, 0xa1,
|
||||
0xa1, 0xa0, 0xa0, 0xa0, 0xa1,
|
||||
0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
|
||||
};
|
||||
int x, y;
|
||||
const unsigned char *s;
|
||||
|
||||
frame += (oy - 2) * width + ox - 2;
|
||||
s = finder;
|
||||
for(y=0; y<5; y++) {
|
||||
for(x=0; x<5; x++) {
|
||||
frame[x] = s[x];
|
||||
}
|
||||
frame += width;
|
||||
s += 5;
|
||||
}
|
||||
}
|
||||
|
||||
static void QRspec_putAlignmentPattern(int version, unsigned char *frame, int width)
|
||||
{
|
||||
int d, w, x, y, cx, cy;
|
||||
|
||||
if(version < 2) return;
|
||||
|
||||
d = alignmentPattern[version][1] - alignmentPattern[version][0];
|
||||
if(d < 0) {
|
||||
w = 2;
|
||||
} else {
|
||||
w = (width - alignmentPattern[version][0]) / d + 2;
|
||||
}
|
||||
|
||||
if(w * w - 3 == 1) {
|
||||
x = alignmentPattern[version][0];
|
||||
y = alignmentPattern[version][0];
|
||||
QRspec_putAlignmentMarker(frame, width, x, y);
|
||||
return;
|
||||
}
|
||||
|
||||
cx = alignmentPattern[version][0];
|
||||
for(x=1; x<w - 1; x++) {
|
||||
QRspec_putAlignmentMarker(frame, width, 6, cx);
|
||||
QRspec_putAlignmentMarker(frame, width, cx, 6);
|
||||
cx += d;
|
||||
}
|
||||
|
||||
cy = alignmentPattern[version][0];
|
||||
for(y=0; y<w-1; y++) {
|
||||
cx = alignmentPattern[version][0];
|
||||
for(x=0; x<w-1; x++) {
|
||||
QRspec_putAlignmentMarker(frame, width, cx, cy);
|
||||
cx += d;
|
||||
}
|
||||
cy += d;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Version information pattern
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Version information pattern (BCH coded).
|
||||
* See Table 1 in Appendix D (pp.68) of JIS X0510:2004.
|
||||
*/
|
||||
static const unsigned int versionPattern[QRSPEC_VERSION_MAX - 6] = {
|
||||
0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d,
|
||||
0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9,
|
||||
0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75,
|
||||
0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64,
|
||||
0x27541, 0x28c69
|
||||
};
|
||||
|
||||
unsigned int QRspec_getVersionPattern(int version)
|
||||
{
|
||||
if(version < 7 || version > QRSPEC_VERSION_MAX) return 0;
|
||||
|
||||
return versionPattern[version - 7];
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Format information
|
||||
*****************************************************************************/
|
||||
|
||||
/* See calcFormatInfo in tests/test_qrspec.c */
|
||||
static const unsigned int formatInfo[4][8] = {
|
||||
{0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976},
|
||||
{0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0},
|
||||
{0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed},
|
||||
{0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b}
|
||||
};
|
||||
|
||||
unsigned int QRspec_getFormatInfo(int mask, QRecLevel level)
|
||||
{
|
||||
if(mask < 0 || mask > 7) return 0;
|
||||
|
||||
return formatInfo[level][mask];
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Frame
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Cache of initial frames.
|
||||
*/
|
||||
/* C99 says that static storage shall be initialized to a null pointer
|
||||
* by compiler. */
|
||||
static unsigned char *frames[QRSPEC_VERSION_MAX + 1];
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
static pthread_mutex_t frames_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Put a finder pattern.
|
||||
* @param frame
|
||||
* @param width
|
||||
* @param ox,oy upper-left coordinate of the pattern
|
||||
*/
|
||||
static void putFinderPattern(unsigned char *frame, int width, int ox, int oy)
|
||||
{
|
||||
static const unsigned char finder[] = {
|
||||
0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1,
|
||||
0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1,
|
||||
0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
|
||||
0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
|
||||
0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
|
||||
0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1,
|
||||
0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1,
|
||||
};
|
||||
int x, y;
|
||||
const unsigned char *s;
|
||||
|
||||
frame += oy * width + ox;
|
||||
s = finder;
|
||||
for(y=0; y<7; y++) {
|
||||
for(x=0; x<7; x++) {
|
||||
frame[x] = s[x];
|
||||
}
|
||||
frame += width;
|
||||
s += 7;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static unsigned char *QRspec_createFrame(int version)
|
||||
{
|
||||
unsigned char *frame, *p, *q;
|
||||
int width;
|
||||
int x, y;
|
||||
unsigned int verinfo, v;
|
||||
|
||||
width = qrspecCapacity[version].width;
|
||||
frame = (unsigned char *)malloc(width * width);
|
||||
if(frame == NULL) return NULL;
|
||||
|
||||
memset(frame, 0, width * width);
|
||||
/* Finder pattern */
|
||||
putFinderPattern(frame, width, 0, 0);
|
||||
putFinderPattern(frame, width, width - 7, 0);
|
||||
putFinderPattern(frame, width, 0, width - 7);
|
||||
/* Separator */
|
||||
p = frame;
|
||||
q = frame + width * (width - 7);
|
||||
for(y=0; y<7; y++) {
|
||||
p[7] = 0xc0;
|
||||
p[width - 8] = 0xc0;
|
||||
q[7] = 0xc0;
|
||||
p += width;
|
||||
q += width;
|
||||
}
|
||||
memset(frame + width * 7, 0xc0, 8);
|
||||
memset(frame + width * 8 - 8, 0xc0, 8);
|
||||
memset(frame + width * (width - 8), 0xc0, 8);
|
||||
/* Mask format information area */
|
||||
memset(frame + width * 8, 0x84, 9);
|
||||
memset(frame + width * 9 - 8, 0x84, 8);
|
||||
p = frame + 8;
|
||||
for(y=0; y<8; y++) {
|
||||
*p = 0x84;
|
||||
p += width;
|
||||
}
|
||||
p = frame + width * (width - 7) + 8;
|
||||
for(y=0; y<7; y++) {
|
||||
*p = 0x84;
|
||||
p += width;
|
||||
}
|
||||
/* Timing pattern */
|
||||
p = frame + width * 6 + 8;
|
||||
q = frame + width * 8 + 6;
|
||||
for(x=1; x<width-15; x++) {
|
||||
*p = 0x90 | (x & 1);
|
||||
*q = 0x90 | (x & 1);
|
||||
p++;
|
||||
q += width;
|
||||
}
|
||||
/* Alignment pattern */
|
||||
QRspec_putAlignmentPattern(version, frame, width);
|
||||
|
||||
/* Version information */
|
||||
if(version >= 7) {
|
||||
verinfo = QRspec_getVersionPattern(version);
|
||||
|
||||
p = frame + width * (width - 11);
|
||||
v = verinfo;
|
||||
for(x=0; x<6; x++) {
|
||||
for(y=0; y<3; y++) {
|
||||
p[width * y + x] = 0x88 | (v & 1);
|
||||
v = v >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
p = frame + width - 11;
|
||||
v = verinfo;
|
||||
for(y=0; y<6; y++) {
|
||||
for(x=0; x<3; x++) {
|
||||
p[x] = 0x88 | (v & 1);
|
||||
v = v >> 1;
|
||||
}
|
||||
p += width;
|
||||
}
|
||||
}
|
||||
/* and a little bit... */
|
||||
frame[width * (width - 8) + 8] = 0x81;
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
unsigned char *QRspec_newFrame(int version)
|
||||
{
|
||||
unsigned char *frame;
|
||||
int width;
|
||||
|
||||
if(version < 1 || version > QRSPEC_VERSION_MAX) return NULL;
|
||||
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_lock(&frames_mutex);
|
||||
#endif
|
||||
if(frames[version] == NULL) {
|
||||
frames[version] = QRspec_createFrame(version);
|
||||
}
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_unlock(&frames_mutex);
|
||||
#endif
|
||||
if(frames[version] == NULL) return NULL;
|
||||
|
||||
width = qrspecCapacity[version].width;
|
||||
frame = (unsigned char *)malloc(width * width);
|
||||
if(frame == NULL) return NULL;
|
||||
memcpy(frame, frames[version], width * width);
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
void QRspec_clearCache(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_lock(&frames_mutex);
|
||||
#endif
|
||||
for(i=1; i<=QRSPEC_VERSION_MAX; i++) {
|
||||
free(frames[i]);
|
||||
frames[i] = NULL;
|
||||
}
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_unlock(&frames_mutex);
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* qrencode - QR Code encoder
|
||||
*
|
||||
* QR Code specification in convenient format.
|
||||
* Copyright (C) 2006-2011 Kentaro Fukuchi <kentaro@fukuchi.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __QRSPEC_H__
|
||||
#define __QRSPEC_H__
|
||||
|
||||
#include "qrencode.h"
|
||||
|
||||
/******************************************************************************
|
||||
* Version and capacity
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Maximum width of a symbol
|
||||
*/
|
||||
#define QRSPEC_WIDTH_MAX 177
|
||||
|
||||
/**
|
||||
* Return maximum data code length (bytes) for the version.
|
||||
* @param version
|
||||
* @param level
|
||||
* @return maximum size (bytes)
|
||||
*/
|
||||
extern int QRspec_getDataLength(int version, QRecLevel level);
|
||||
|
||||
/**
|
||||
* Return maximum error correction code length (bytes) for the version.
|
||||
* @param version
|
||||
* @param level
|
||||
* @return ECC size (bytes)
|
||||
*/
|
||||
extern int QRspec_getECCLength(int version, QRecLevel level);
|
||||
|
||||
/**
|
||||
* Return a version number that satisfies the input code length.
|
||||
* @param size input code length (byte)
|
||||
* @param level
|
||||
* @return version number
|
||||
*/
|
||||
extern int QRspec_getMinimumVersion(int size, QRecLevel level);
|
||||
|
||||
/**
|
||||
* Return the width of the symbol for the version.
|
||||
* @param version
|
||||
* @return width
|
||||
*/
|
||||
extern int QRspec_getWidth(int version);
|
||||
|
||||
/**
|
||||
* Return the numer of remainder bits.
|
||||
* @param version
|
||||
* @return number of remainder bits
|
||||
*/
|
||||
extern int QRspec_getRemainder(int version);
|
||||
|
||||
/******************************************************************************
|
||||
* Length indicator
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Return the size of lenght indicator for the mode and version.
|
||||
* @param mode
|
||||
* @param version
|
||||
* @return the size of the appropriate length indicator (bits).
|
||||
*/
|
||||
extern int QRspec_lengthIndicator(QRencodeMode mode, int version);
|
||||
|
||||
/**
|
||||
* Return the maximum length for the mode and version.
|
||||
* @param mode
|
||||
* @param version
|
||||
* @return the maximum length (bytes)
|
||||
*/
|
||||
extern int QRspec_maximumWords(QRencodeMode mode, int version);
|
||||
|
||||
/******************************************************************************
|
||||
* Error correction code
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Return an array of ECC specification.
|
||||
* @param version
|
||||
* @param level
|
||||
* @param spec an array of ECC specification contains as following:
|
||||
* {# of type1 blocks, # of data code, # of ecc code,
|
||||
* # of type2 blocks, # of data code}
|
||||
*/
|
||||
void QRspec_getEccSpec(int version, QRecLevel level, int spec[5]);
|
||||
|
||||
#define QRspec_rsBlockNum(__spec__) (__spec__[0] + __spec__[3])
|
||||
#define QRspec_rsBlockNum1(__spec__) (__spec__[0])
|
||||
#define QRspec_rsDataCodes1(__spec__) (__spec__[1])
|
||||
#define QRspec_rsEccCodes1(__spec__) (__spec__[2])
|
||||
#define QRspec_rsBlockNum2(__spec__) (__spec__[3])
|
||||
#define QRspec_rsDataCodes2(__spec__) (__spec__[4])
|
||||
#define QRspec_rsEccCodes2(__spec__) (__spec__[2])
|
||||
|
||||
#define QRspec_rsDataLength(__spec__) \
|
||||
((QRspec_rsBlockNum1(__spec__) * QRspec_rsDataCodes1(__spec__)) + \
|
||||
(QRspec_rsBlockNum2(__spec__) * QRspec_rsDataCodes2(__spec__)))
|
||||
#define QRspec_rsEccLength(__spec__) \
|
||||
(QRspec_rsBlockNum(__spec__) * QRspec_rsEccCodes1(__spec__))
|
||||
|
||||
/******************************************************************************
|
||||
* Version information pattern
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Return BCH encoded version information pattern that is used for the symbol
|
||||
* of version 7 or greater. Use lower 18 bits.
|
||||
* @param version
|
||||
* @return BCH encoded version information pattern
|
||||
*/
|
||||
extern unsigned int QRspec_getVersionPattern(int version);
|
||||
|
||||
/******************************************************************************
|
||||
* Format information
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Return BCH encoded format information pattern.
|
||||
* @param mask
|
||||
* @param level
|
||||
* @return BCH encoded format information pattern
|
||||
*/
|
||||
extern unsigned int QRspec_getFormatInfo(int mask, QRecLevel level);
|
||||
|
||||
/******************************************************************************
|
||||
* Frame
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Return a copy of initialized frame.
|
||||
* When the same version is requested twice or more, a copy of cached frame
|
||||
* is returned.
|
||||
* @param version
|
||||
* @return Array of unsigned char. You can free it by free().
|
||||
*/
|
||||
extern unsigned char *QRspec_newFrame(int version);
|
||||
|
||||
/**
|
||||
* Clear the frame cache. Typically for debug.
|
||||
*/
|
||||
extern void QRspec_clearCache(void);
|
||||
|
||||
/******************************************************************************
|
||||
* Mode indicator
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* Mode indicator. See Table 2 of JIS X0510:2004, pp.16.
|
||||
*/
|
||||
#define QRSPEC_MODEID_ECI 7
|
||||
#define QRSPEC_MODEID_NUM 1
|
||||
#define QRSPEC_MODEID_AN 2
|
||||
#define QRSPEC_MODEID_8 4
|
||||
#define QRSPEC_MODEID_KANJI 8
|
||||
#define QRSPEC_MODEID_FNC1FIRST 5
|
||||
#define QRSPEC_MODEID_FNC1SECOND 9
|
||||
#define QRSPEC_MODEID_STRUCTURE 3
|
||||
#define QRSPEC_MODEID_TERMINATOR 0
|
||||
|
||||
#endif /* __QRSPEC_H__ */
|
||||
@@ -0,0 +1,327 @@
|
||||
/*
|
||||
* qrencode - QR Code encoder
|
||||
*
|
||||
* Reed solomon encoder. This code is taken from Phil Karn's libfec then
|
||||
* editted and packed into a pair of .c and .h files.
|
||||
*
|
||||
* Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q
|
||||
* (libfec is released under the GNU Lesser General Public License.)
|
||||
*
|
||||
* Copyright (C) 2006-2011 Kentaro Fukuchi <kentaro@fukuchi.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include "rscode.h"
|
||||
|
||||
/* Stuff specific to the 8-bit symbol version of the general purpose RS codecs
|
||||
*
|
||||
*/
|
||||
typedef unsigned char data_t;
|
||||
|
||||
|
||||
/**
|
||||
* Reed-Solomon codec control block
|
||||
*/
|
||||
struct _RS {
|
||||
int mm; /* Bits per symbol */
|
||||
int nn; /* Symbols per block (= (1<<mm)-1) */
|
||||
data_t *alpha_to; /* log lookup table */
|
||||
data_t *index_of; /* Antilog lookup table */
|
||||
data_t *genpoly; /* Generator polynomial */
|
||||
int nroots; /* Number of generator roots = number of parity symbols */
|
||||
int fcr; /* First consecutive root, index form */
|
||||
int prim; /* Primitive element, index form */
|
||||
int iprim; /* prim-th root of 1, index form */
|
||||
int pad; /* Padding bytes in shortened block */
|
||||
int gfpoly;
|
||||
struct _RS *next;
|
||||
};
|
||||
|
||||
static RS *rslist = NULL;
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
static pthread_mutex_t rslist_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
#endif
|
||||
|
||||
static inline int modnn(RS *rs, int x){
|
||||
while (x >= rs->nn) {
|
||||
x -= rs->nn;
|
||||
x = (x >> rs->mm) + (x & rs->nn);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
#define MODNN(x) modnn(rs,x)
|
||||
|
||||
#define MM (rs->mm)
|
||||
#define NN (rs->nn)
|
||||
#define ALPHA_TO (rs->alpha_to)
|
||||
#define INDEX_OF (rs->index_of)
|
||||
#define GENPOLY (rs->genpoly)
|
||||
#define NROOTS (rs->nroots)
|
||||
#define FCR (rs->fcr)
|
||||
#define PRIM (rs->prim)
|
||||
#define IPRIM (rs->iprim)
|
||||
#define PAD (rs->pad)
|
||||
#define A0 (NN)
|
||||
|
||||
|
||||
/* Initialize a Reed-Solomon codec
|
||||
* symsize = symbol size, bits
|
||||
* gfpoly = Field generator polynomial coefficients
|
||||
* fcr = first root of RS code generator polynomial, index form
|
||||
* prim = primitive element to generate polynomial roots
|
||||
* nroots = RS code generator polynomial degree (number of roots)
|
||||
* pad = padding bytes at front of shortened block
|
||||
*/
|
||||
static RS *init_rs_char(int symsize, int gfpoly, int fcr, int prim, int nroots, int pad)
|
||||
{
|
||||
RS *rs;
|
||||
|
||||
|
||||
/* Common code for intializing a Reed-Solomon control block (char or int symbols)
|
||||
* Copyright 2004 Phil Karn, KA9Q
|
||||
* May be used under the terms of the GNU Lesser General Public License (LGPL)
|
||||
*/
|
||||
//#undef NULL
|
||||
//#define NULL ((void *)0)
|
||||
|
||||
int i, j, sr,root,iprim;
|
||||
|
||||
rs = NULL;
|
||||
/* Check parameter ranges */
|
||||
if(symsize < 0 || symsize > (int)(8*sizeof(data_t))){
|
||||
goto done;
|
||||
}
|
||||
|
||||
if(fcr < 0 || fcr >= (1<<symsize))
|
||||
goto done;
|
||||
if(prim <= 0 || prim >= (1<<symsize))
|
||||
goto done;
|
||||
if(nroots < 0 || nroots >= (1<<symsize))
|
||||
goto done; /* Can't have more roots than symbol values! */
|
||||
if(pad < 0 || pad >= ((1<<symsize) -1 - nroots))
|
||||
goto done; /* Too much padding */
|
||||
|
||||
rs = (RS *)calloc(1,sizeof(RS));
|
||||
if(rs == NULL)
|
||||
goto done;
|
||||
|
||||
rs->mm = symsize;
|
||||
rs->nn = (1<<symsize)-1;
|
||||
rs->pad = pad;
|
||||
|
||||
rs->alpha_to = (data_t *)malloc(sizeof(data_t)*(rs->nn+1));
|
||||
if(rs->alpha_to == NULL){
|
||||
free(rs);
|
||||
rs = NULL;
|
||||
goto done;
|
||||
}
|
||||
rs->index_of = (data_t *)malloc(sizeof(data_t)*(rs->nn+1));
|
||||
if(rs->index_of == NULL){
|
||||
free(rs->alpha_to);
|
||||
free(rs);
|
||||
rs = NULL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Generate Galois field lookup tables */
|
||||
rs->index_of[0] = A0; /* log(zero) = -inf */
|
||||
rs->alpha_to[A0] = 0; /* alpha**-inf = 0 */
|
||||
sr = 1;
|
||||
for(i=0;i<rs->nn;i++){
|
||||
rs->index_of[sr] = i;
|
||||
rs->alpha_to[i] = sr;
|
||||
sr <<= 1;
|
||||
if(sr & (1<<symsize))
|
||||
sr ^= gfpoly;
|
||||
sr &= rs->nn;
|
||||
}
|
||||
if(sr != 1){
|
||||
/* field generator polynomial is not primitive! */
|
||||
free(rs->alpha_to);
|
||||
free(rs->index_of);
|
||||
free(rs);
|
||||
rs = NULL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Form RS code generator polynomial from its roots */
|
||||
rs->genpoly = (data_t *)malloc(sizeof(data_t)*(nroots+1));
|
||||
if(rs->genpoly == NULL){
|
||||
free(rs->alpha_to);
|
||||
free(rs->index_of);
|
||||
free(rs);
|
||||
rs = NULL;
|
||||
goto done;
|
||||
}
|
||||
rs->fcr = fcr;
|
||||
rs->prim = prim;
|
||||
rs->nroots = nroots;
|
||||
rs->gfpoly = gfpoly;
|
||||
|
||||
/* Find prim-th root of 1, used in decoding */
|
||||
for(iprim=1;(iprim % prim) != 0;iprim += rs->nn)
|
||||
;
|
||||
rs->iprim = iprim / prim;
|
||||
|
||||
rs->genpoly[0] = 1;
|
||||
for (i = 0,root=fcr*prim; i < nroots; i++,root += prim) {
|
||||
rs->genpoly[i+1] = 1;
|
||||
|
||||
/* Multiply rs->genpoly[] by @**(root + x) */
|
||||
for (j = i; j > 0; j--){
|
||||
if (rs->genpoly[j] != 0)
|
||||
rs->genpoly[j] = rs->genpoly[j-1] ^ rs->alpha_to[modnn(rs,rs->index_of[rs->genpoly[j]] + root)];
|
||||
else
|
||||
rs->genpoly[j] = rs->genpoly[j-1];
|
||||
}
|
||||
/* rs->genpoly[0] can never be zero */
|
||||
rs->genpoly[0] = rs->alpha_to[modnn(rs,rs->index_of[rs->genpoly[0]] + root)];
|
||||
}
|
||||
/* convert rs->genpoly[] to index form for quicker encoding */
|
||||
for (i = 0; i <= nroots; i++)
|
||||
rs->genpoly[i] = rs->index_of[rs->genpoly[i]];
|
||||
done:;
|
||||
|
||||
return rs;
|
||||
}
|
||||
|
||||
RS *init_rs(int symsize, int gfpoly, int fcr, int prim, int nroots, int pad)
|
||||
{
|
||||
RS *rs;
|
||||
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_lock(&rslist_mutex);
|
||||
#endif
|
||||
for(rs = rslist; rs != NULL; rs = rs->next) {
|
||||
if(rs->pad != pad) continue;
|
||||
if(rs->nroots != nroots) continue;
|
||||
if(rs->mm != symsize) continue;
|
||||
if(rs->gfpoly != gfpoly) continue;
|
||||
if(rs->fcr != fcr) continue;
|
||||
if(rs->prim != prim) continue;
|
||||
|
||||
goto DONE;
|
||||
}
|
||||
|
||||
rs = init_rs_char(symsize, gfpoly, fcr, prim, nroots, pad);
|
||||
if(rs == NULL) goto DONE;
|
||||
rs->next = rslist;
|
||||
rslist = rs;
|
||||
|
||||
DONE:
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_unlock(&rslist_mutex);
|
||||
#endif
|
||||
return rs;
|
||||
}
|
||||
|
||||
|
||||
void free_rs_char(RS *rs)
|
||||
{
|
||||
free(rs->alpha_to);
|
||||
free(rs->index_of);
|
||||
free(rs->genpoly);
|
||||
free(rs);
|
||||
}
|
||||
|
||||
void free_rs_cache(void)
|
||||
{
|
||||
RS *rs, *next;
|
||||
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_lock(&rslist_mutex);
|
||||
#endif
|
||||
rs = rslist;
|
||||
while(rs != NULL) {
|
||||
next = rs->next;
|
||||
free_rs_char(rs);
|
||||
rs = next;
|
||||
}
|
||||
rslist = NULL;
|
||||
#ifdef HAVE_LIBPTHREAD
|
||||
pthread_mutex_unlock(&rslist_mutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* The guts of the Reed-Solomon encoder, meant to be #included
|
||||
* into a function body with the following typedefs, macros and variables supplied
|
||||
* according to the code parameters:
|
||||
|
||||
* data_t - a typedef for the data symbol
|
||||
* data_t data[] - array of NN-NROOTS-PAD and type data_t to be encoded
|
||||
* data_t parity[] - an array of NROOTS and type data_t to be written with parity symbols
|
||||
* NROOTS - the number of roots in the RS code generator polynomial,
|
||||
* which is the same as the number of parity symbols in a block.
|
||||
Integer variable or literal.
|
||||
*
|
||||
* NN - the total number of symbols in a RS block. Integer variable or literal.
|
||||
* PAD - the number of pad symbols in a block. Integer variable or literal.
|
||||
* ALPHA_TO - The address of an array of NN elements to convert Galois field
|
||||
* elements in index (log) form to polynomial form. Read only.
|
||||
* INDEX_OF - The address of an array of NN elements to convert Galois field
|
||||
* elements in polynomial form to index (log) form. Read only.
|
||||
* MODNN - a function to reduce its argument modulo NN. May be inline or a macro.
|
||||
* GENPOLY - an array of NROOTS+1 elements containing the generator polynomial in index form
|
||||
|
||||
* The memset() and memmove() functions are used. The appropriate header
|
||||
* file declaring these functions (usually <string.h>) must be included by the calling
|
||||
* program.
|
||||
|
||||
* Copyright 2004, Phil Karn, KA9Q
|
||||
* May be used under the terms of the GNU Lesser General Public License (LGPL)
|
||||
*/
|
||||
|
||||
#undef A0
|
||||
#define A0 (NN) /* Special reserved value encoding zero in index form */
|
||||
|
||||
void encode_rs_char(RS *rs, const data_t *data, data_t *parity)
|
||||
{
|
||||
int i, j;
|
||||
data_t feedback;
|
||||
|
||||
memset(parity,0,NROOTS*sizeof(data_t));
|
||||
|
||||
for(i=0;i<NN-NROOTS-PAD;i++){
|
||||
feedback = INDEX_OF[data[i] ^ parity[0]];
|
||||
if(feedback != A0){ /* feedback term is non-zero */
|
||||
#ifdef UNNORMALIZED
|
||||
/* This line is unnecessary when GENPOLY[NROOTS] is unity, as it must
|
||||
* always be for the polynomials constructed by init_rs()
|
||||
*/
|
||||
feedback = MODNN(NN - GENPOLY[NROOTS] + feedback);
|
||||
#endif
|
||||
for(j=1;j<NROOTS;j++)
|
||||
parity[j] ^= ALPHA_TO[MODNN(feedback + GENPOLY[NROOTS-j])];
|
||||
}
|
||||
/* Shift */
|
||||
memmove(&parity[0],&parity[1],sizeof(data_t)*(NROOTS-1));
|
||||
if(feedback != A0)
|
||||
parity[NROOTS-1] = ALPHA_TO[MODNN(feedback + GENPOLY[0])];
|
||||
else
|
||||
parity[NROOTS-1] = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* qrencode - QR Code encoder
|
||||
*
|
||||
* Reed solomon encoder. This code is taken from Phil Karn's libfec then
|
||||
* editted and packed into a pair of .c and .h files.
|
||||
*
|
||||
* Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q
|
||||
* (libfec is released under the GNU Lesser General Public License.)
|
||||
*
|
||||
* Copyright (C) 2006-2011 Kentaro Fukuchi <kentaro@fukuchi.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __RSCODE_H__
|
||||
#define __RSCODE_H__
|
||||
|
||||
/*
|
||||
* General purpose RS codec, 8-bit symbols.
|
||||
*/
|
||||
|
||||
typedef struct _RS RS;
|
||||
|
||||
extern RS *init_rs(int symsize, int gfpoly, int fcr, int prim, int nroots, int pad);
|
||||
extern void encode_rs_char(RS *rs, const unsigned char *data, unsigned char *parity);
|
||||
extern void free_rs_char(RS *rs);
|
||||
extern void free_rs_cache(void);
|
||||
|
||||
#endif /* __RSCODE_H__ */
|
||||
@@ -0,0 +1,311 @@
|
||||
/*
|
||||
* qrencode - QR Code encoder
|
||||
*
|
||||
* Input data splitter.
|
||||
* Copyright (C) 2006-2011 Kentaro Fukuchi <kentaro@fukuchi.org>
|
||||
*
|
||||
* The following data / specifications are taken from
|
||||
* "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
|
||||
* or
|
||||
* "Automatic identification and data capture techniques --
|
||||
* QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "qrencode.h"
|
||||
#include "qrinput.h"
|
||||
#include "qrspec.h"
|
||||
#include "split.h"
|
||||
|
||||
#define isdigit(__c__) ((unsigned char)((signed char)(__c__) - '0') < 10)
|
||||
#define isalnum(__c__) (QRinput_lookAnTable(__c__) >= 0)
|
||||
|
||||
#if !HAVE_STRDUP
|
||||
#undef strdup
|
||||
char *strdup_internal(const char *s)
|
||||
{
|
||||
size_t len = strlen(s) + 1;
|
||||
void *new = malloc(len);
|
||||
if(new == NULL) return NULL;
|
||||
return (char *)memcpy(new, s, len);
|
||||
}
|
||||
#endif
|
||||
|
||||
static QRencodeMode Split_identifyMode(const char *string, QRencodeMode hint)
|
||||
{
|
||||
unsigned char c, d;
|
||||
unsigned int word;
|
||||
|
||||
c = string[0];
|
||||
|
||||
if(c == '\0') return QR_MODE_NUL;
|
||||
if(isdigit(c)) {
|
||||
return QR_MODE_NUM;
|
||||
} else if(isalnum(c)) {
|
||||
return QR_MODE_AN;
|
||||
} else if(hint == QR_MODE_KANJI) {
|
||||
d = string[1];
|
||||
if(d != '\0') {
|
||||
word = ((unsigned int)c << 8) | d;
|
||||
if((word >= 0x8140 && word <= 0x9ffc) || (word >= 0xe040 && word <= 0xebbf)) {
|
||||
return QR_MODE_KANJI;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return QR_MODE_8;
|
||||
}
|
||||
|
||||
static int Split_eatNum(const char *string, QRinput *input, QRencodeMode hint);
|
||||
static int Split_eatAn(const char *string, QRinput *input, QRencodeMode hint);
|
||||
static int Split_eat8(const char *string, QRinput *input, QRencodeMode hint);
|
||||
static int Split_eatKanji(const char *string, QRinput *input, QRencodeMode hint);
|
||||
|
||||
static int Split_eatNum(const char *string, QRinput *input,QRencodeMode hint)
|
||||
{
|
||||
const char *p;
|
||||
int ret;
|
||||
int run;
|
||||
int dif;
|
||||
int ln;
|
||||
QRencodeMode mode;
|
||||
|
||||
ln = QRspec_lengthIndicator(QR_MODE_NUM, input->version);
|
||||
|
||||
p = string;
|
||||
while(isdigit(*p)) {
|
||||
p++;
|
||||
}
|
||||
run = p - string;
|
||||
mode = Split_identifyMode(p, hint);
|
||||
if(mode == QR_MODE_8) {
|
||||
dif = QRinput_estimateBitsModeNum(run) + 4 + ln
|
||||
+ QRinput_estimateBitsMode8(1) /* + 4 + l8 */
|
||||
- QRinput_estimateBitsMode8(run + 1) /* - 4 - l8 */;
|
||||
if(dif > 0) {
|
||||
return Split_eat8(string, input, hint);
|
||||
}
|
||||
}
|
||||
if(mode == QR_MODE_AN) {
|
||||
dif = QRinput_estimateBitsModeNum(run) + 4 + ln
|
||||
+ QRinput_estimateBitsModeAn(1) /* + 4 + la */
|
||||
- QRinput_estimateBitsModeAn(run + 1) /* - 4 - la */;
|
||||
if(dif > 0) {
|
||||
return Split_eatAn(string, input, hint);
|
||||
}
|
||||
}
|
||||
|
||||
ret = QRinput_append(input, QR_MODE_NUM, run, (unsigned char *)string);
|
||||
if(ret < 0) return -1;
|
||||
|
||||
return run;
|
||||
}
|
||||
|
||||
static int Split_eatAn(const char *string, QRinput *input, QRencodeMode hint)
|
||||
{
|
||||
const char *p, *q;
|
||||
int ret;
|
||||
int run;
|
||||
int dif;
|
||||
int la, ln;
|
||||
|
||||
la = QRspec_lengthIndicator(QR_MODE_AN, input->version);
|
||||
ln = QRspec_lengthIndicator(QR_MODE_NUM, input->version);
|
||||
|
||||
p = string;
|
||||
while(isalnum(*p)) {
|
||||
if(isdigit(*p)) {
|
||||
q = p;
|
||||
while(isdigit(*q)) {
|
||||
q++;
|
||||
}
|
||||
dif = QRinput_estimateBitsModeAn(p - string) /* + 4 + la */
|
||||
+ QRinput_estimateBitsModeNum(q - p) + 4 + ln
|
||||
- QRinput_estimateBitsModeAn(q - string) /* - 4 - la */;
|
||||
if(dif < 0) {
|
||||
break;
|
||||
} else {
|
||||
p = q;
|
||||
}
|
||||
} else {
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
run = p - string;
|
||||
|
||||
if(*p && !isalnum(*p)) {
|
||||
dif = QRinput_estimateBitsModeAn(run) + 4 + la
|
||||
+ QRinput_estimateBitsMode8(1) /* + 4 + l8 */
|
||||
- QRinput_estimateBitsMode8(run + 1) /* - 4 - l8 */;
|
||||
if(dif > 0) {
|
||||
return Split_eat8(string, input, hint);
|
||||
}
|
||||
}
|
||||
|
||||
ret = QRinput_append(input, QR_MODE_AN, run, (unsigned char *)string);
|
||||
if(ret < 0) return -1;
|
||||
|
||||
return run;
|
||||
}
|
||||
|
||||
static int Split_eatKanji(const char *string, QRinput *input, QRencodeMode hint)
|
||||
{
|
||||
const char *p;
|
||||
int ret;
|
||||
int run;
|
||||
|
||||
p = string;
|
||||
while(Split_identifyMode(p, hint) == QR_MODE_KANJI) {
|
||||
p += 2;
|
||||
}
|
||||
run = p - string;
|
||||
ret = QRinput_append(input, QR_MODE_KANJI, run, (unsigned char *)string);
|
||||
if(ret < 0) return -1;
|
||||
|
||||
return run;
|
||||
}
|
||||
|
||||
static int Split_eat8(const char *string, QRinput *input, QRencodeMode hint)
|
||||
{
|
||||
const char *p, *q;
|
||||
QRencodeMode mode;
|
||||
int ret;
|
||||
int run;
|
||||
int dif;
|
||||
int la, ln;
|
||||
|
||||
la = QRspec_lengthIndicator(QR_MODE_AN, input->version);
|
||||
ln = QRspec_lengthIndicator(QR_MODE_NUM, input->version);
|
||||
|
||||
p = string + 1;
|
||||
while(*p != '\0') {
|
||||
mode = Split_identifyMode(p, hint);
|
||||
if(mode == QR_MODE_KANJI) {
|
||||
break;
|
||||
}
|
||||
if(mode == QR_MODE_NUM) {
|
||||
q = p;
|
||||
while(isdigit(*q)) {
|
||||
q++;
|
||||
}
|
||||
dif = QRinput_estimateBitsMode8(p - string) /* + 4 + l8 */
|
||||
+ QRinput_estimateBitsModeNum(q - p) + 4 + ln
|
||||
- QRinput_estimateBitsMode8(q - string) /* - 4 - l8 */;
|
||||
if(dif < 0) {
|
||||
break;
|
||||
} else {
|
||||
p = q;
|
||||
}
|
||||
} else if(mode == QR_MODE_AN) {
|
||||
q = p;
|
||||
while(isalnum(*q)) {
|
||||
q++;
|
||||
}
|
||||
dif = QRinput_estimateBitsMode8(p - string) /* + 4 + l8 */
|
||||
+ QRinput_estimateBitsModeAn(q - p) + 4 + la
|
||||
- QRinput_estimateBitsMode8(q - string) /* - 4 - l8 */;
|
||||
if(dif < 0) {
|
||||
break;
|
||||
} else {
|
||||
p = q;
|
||||
}
|
||||
} else {
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
run = p - string;
|
||||
ret = QRinput_append(input, QR_MODE_8, run, (unsigned char *)string);
|
||||
if(ret < 0) return -1;
|
||||
|
||||
return run;
|
||||
}
|
||||
|
||||
static int Split_splitString(const char *string, QRinput *input,
|
||||
QRencodeMode hint)
|
||||
{
|
||||
int length;
|
||||
QRencodeMode mode;
|
||||
|
||||
if(*string == '\0') return 0;
|
||||
|
||||
mode = Split_identifyMode(string, hint);
|
||||
if(mode == QR_MODE_NUM) {
|
||||
length = Split_eatNum(string, input, hint);
|
||||
} else if(mode == QR_MODE_AN) {
|
||||
length = Split_eatAn(string, input, hint);
|
||||
} else if(mode == QR_MODE_KANJI && hint == QR_MODE_KANJI) {
|
||||
length = Split_eatKanji(string, input, hint);
|
||||
} else {
|
||||
length = Split_eat8(string, input, hint);
|
||||
}
|
||||
if(length == 0) return 0;
|
||||
if(length < 0) return -1;
|
||||
return Split_splitString(&string[length], input, hint);
|
||||
}
|
||||
|
||||
static char *dupAndToUpper(const char *str, QRencodeMode hint)
|
||||
{
|
||||
char *newstr, *p;
|
||||
QRencodeMode mode;
|
||||
|
||||
newstr = strdup_internal(str);
|
||||
if(newstr == NULL) return NULL;
|
||||
|
||||
p = newstr;
|
||||
while(*p != '\0') {
|
||||
mode = Split_identifyMode(p, hint);
|
||||
if(mode == QR_MODE_KANJI) {
|
||||
p += 2;
|
||||
} else {
|
||||
if (*p >= 'a' && *p <= 'z') {
|
||||
*p = (char)((int)*p - 32);
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
return newstr;
|
||||
}
|
||||
|
||||
int Split_splitStringToQRinput(const char *string, QRinput *input,
|
||||
QRencodeMode hint, int casesensitive)
|
||||
{
|
||||
char *newstr;
|
||||
int ret;
|
||||
|
||||
if(string == NULL || *string == '\0') {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if(!casesensitive) {
|
||||
newstr = dupAndToUpper(string, hint);
|
||||
if(newstr == NULL) return -1;
|
||||
ret = Split_splitString(newstr, input, hint);
|
||||
free(newstr);
|
||||
} else {
|
||||
ret = Split_splitString(string, input, hint);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* qrencode - QR Code encoder
|
||||
*
|
||||
* Input data splitter.
|
||||
* Copyright (C) 2006-2011 Kentaro Fukuchi <kentaro@fukuchi.org>
|
||||
*
|
||||
* The following data / specifications are taken from
|
||||
* "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
|
||||
* or
|
||||
* "Automatic identification and data capture techniques --
|
||||
* QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __SPLIT_H__
|
||||
#define __SPLIT_H__
|
||||
|
||||
#include "qrencode.h"
|
||||
|
||||
/**
|
||||
* Split the input string (null terminated) into QRinput.
|
||||
* @param string input string
|
||||
* @param hint give QR_MODE_KANJI if the input string contains Kanji character encoded in Shift-JIS. If not, give QR_MODE_8.
|
||||
* @param casesensitive 0 for case-insensitive encoding (all alphabet characters are replaced to UPPER-CASE CHARACTERS.
|
||||
* @retval 0 success.
|
||||
* @retval -1 an error occurred. errno is set to indicate the error. See
|
||||
* Exceptions for the details.
|
||||
* @throw EINVAL invalid input object.
|
||||
* @throw ENOMEM unable to allocate memory for input objects.
|
||||
*/
|
||||
extern int Split_splitStringToQRinput(const char *string, QRinput *input,
|
||||
QRencodeMode hint, int casesensitive);
|
||||
|
||||
#endif /* __SPLIT_H__ */
|
||||
@@ -1450,6 +1450,7 @@ AVFormatReader::Stream::Seek(uint32 flags, int64* frame, bigtime_t* time)
|
||||
|
||||
AVFormatReader::AVFormatReader()
|
||||
:
|
||||
fCopyright(""),
|
||||
fStreams(NULL),
|
||||
fSourceLock("source I/O lock")
|
||||
{
|
||||
@@ -1478,12 +1479,12 @@ AVFormatReader::~AVFormatReader()
|
||||
const char*
|
||||
AVFormatReader::Copyright()
|
||||
{
|
||||
// TODO: Could not find the equivalent in libavformat >= version 53.
|
||||
// Use metadata API instead!
|
||||
// if (fStreams != NULL && fStreams[0] != NULL)
|
||||
// return fStreams[0]->Context()->copyright;
|
||||
// TODO: Return copyright of the file instead!
|
||||
return "Copyright 2009, Stephan Aßmus";
|
||||
if (fCopyright.Length() <= 0) {
|
||||
BMessage message;
|
||||
if (GetMetaData(&message) == B_OK)
|
||||
message.FindString("copyright", &fCopyright);
|
||||
}
|
||||
return fCopyright.String();
|
||||
}
|
||||
|
||||
|
||||
@@ -1638,9 +1639,9 @@ AVFormatReader::GetMetaData(BMessage* _data)
|
||||
|
||||
// Add program info
|
||||
for (unsigned i = 0; i < context->nb_programs; i++) {
|
||||
BMessage progamData;
|
||||
avdictionary_to_message(context->programs[i]->metadata, &progamData);
|
||||
_data->AddMessage("be:program", &progamData);
|
||||
BMessage programData;
|
||||
avdictionary_to_message(context->programs[i]->metadata, &programData);
|
||||
_data->AddMessage("be:program", &programData);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
|
||||
#include <Locker.h>
|
||||
#include <String.h>
|
||||
|
||||
#include "ReaderPlugin.h"
|
||||
|
||||
@@ -48,6 +49,7 @@ public:
|
||||
private:
|
||||
class Stream;
|
||||
|
||||
BString fCopyright;
|
||||
Stream** fStreams;
|
||||
BLocker fSourceLock;
|
||||
};
|
||||
|
||||
@@ -59,5 +59,6 @@ HaikuSubInclude terminal ;
|
||||
HaikuSubInclude text_search ;
|
||||
HaikuSubInclude tracker ;
|
||||
HaikuSubInclude tv ;
|
||||
HaikuSubInclude webpositive ;
|
||||
HaikuSubInclude webwatch ;
|
||||
HaikuSubInclude workspaces ;
|
||||
|
||||
@@ -1694,6 +1694,12 @@ AboutView::_CreateCreditsView()
|
||||
.SetLicense(B_TRANSLATE("BSD (3-clause)"))
|
||||
.SetURL("http://gtf.sourceforge.net/"));
|
||||
|
||||
// libqrencode
|
||||
_AddPackageCredit(PackageCredit("libqrencode")
|
||||
.SetCopyright(B_TRANSLATE(COPYRIGHT_STRING "2006-2012 Kentaro Fukuchi"))
|
||||
.SetLicense(B_TRANSLATE("GNU LGPL v2.1"))
|
||||
.SetURL("http://fukuchi.org/works/qrencode/"));
|
||||
|
||||
_AddCopyrightsFromAttribute();
|
||||
_AddPackageCreditEntries();
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <Menu.h>
|
||||
#include <MenuBar.h>
|
||||
#include <MenuItem.h>
|
||||
#include <Path.h>
|
||||
#include <PopUpMenu.h>
|
||||
#include <scheduler.h>
|
||||
#include <TabView.h>
|
||||
@@ -22,6 +23,7 @@
|
||||
#include <TimeSource.h>
|
||||
#include <TranslationKit.h>
|
||||
|
||||
#include <storage/FindDirectory.h>
|
||||
|
||||
#undef B_TRANSLATION_CONTEXT
|
||||
#define B_TRANSLATION_CONTEXT "CodyCam"
|
||||
@@ -169,7 +171,11 @@ CodyCam::CodyCam()
|
||||
kUploadClients[index++] = B_TRANSLATE("SFTP");
|
||||
kUploadClients[index++] = B_TRANSLATE("Local");
|
||||
|
||||
chdir("/boot/home");
|
||||
BPath homeDir;
|
||||
if (find_directory(B_USER_DIRECTORY, &homeDir) != B_OK)
|
||||
homeDir.SetTo("/boot/home");
|
||||
|
||||
chdir(homeDir.Path());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -20,6 +20,11 @@ resource app_version {
|
||||
|
||||
resource app_flags B_SINGLE_LAUNCH;
|
||||
|
||||
resource file_types message {
|
||||
"types" = "application/x-vnd.Haiku-icon",
|
||||
"types" = "image/svg+xml"
|
||||
};
|
||||
|
||||
resource vector_icon {
|
||||
$"6E6369660E050102000603399E0F3D9C0ABF82B23B84A94B88504910C900A5B1"
|
||||
$"FFBCEAF1FFFFB3B8FF020106023E49240000000000003CAAAA4940004A8000FF"
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
#include <Locale.h>
|
||||
#include <Message.h>
|
||||
#include <Mime.h>
|
||||
#include <Path.h>
|
||||
#include <storage/FindDirectory.h>
|
||||
|
||||
#include "support_settings.h"
|
||||
|
||||
@@ -329,8 +331,14 @@ IconEditorApp::_LastFilePath(path_kind which)
|
||||
path = fLastOpenPath.String();
|
||||
break;
|
||||
}
|
||||
if (!path)
|
||||
if (!path) {
|
||||
|
||||
BPath homePath;
|
||||
if (find_directory(B_USER_DIRECTORY, &homePath) == B_OK)
|
||||
path = homePath.Path();
|
||||
else
|
||||
path = "/boot/home";
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
#include <StringView.h>
|
||||
#include <TextControl.h>
|
||||
|
||||
#include <storage/FindDirectory.h>
|
||||
|
||||
#include "MediaFileInfoView.h"
|
||||
#include "MediaFileListView.h"
|
||||
#include "MessageConstants.h"
|
||||
@@ -122,8 +124,10 @@ MediaConverterWindow::MediaConverterWindow(BRect frame)
|
||||
fConverting(false),
|
||||
fCancelling(false)
|
||||
{
|
||||
const char* defaultDirectory = "/boot/home";
|
||||
fOutputDir.SetTo(defaultDirectory);
|
||||
BPath outputDir;
|
||||
if (find_directory(B_USER_DIRECTORY, &outputDir) != B_OK)
|
||||
outputDir.SetTo("/boot/home");
|
||||
fOutputDir.SetTo(outputDir.Path());
|
||||
|
||||
fMenuBar = new BMenuBar("menubar");
|
||||
_CreateMenu();
|
||||
@@ -165,7 +169,7 @@ MediaConverterWindow::MediaConverterWindow(BRect frame)
|
||||
fDestButton = new BButton(B_TRANSLATE("Output folder"),
|
||||
new BMessage(OUTPUT_FOLDER_MESSAGE));
|
||||
BAlignment labelAlignment(be_control_look->DefaultLabelAlignment());
|
||||
fOutputFolder = new BStringView(NULL, defaultDirectory);
|
||||
fOutputFolder = new BStringView(NULL, outputDir.Path());
|
||||
fOutputFolder->SetExplicitAlignment(labelAlignment);
|
||||
|
||||
// start/end duration
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <Mime.h>
|
||||
#include <NodeInfo.h>
|
||||
#include <String.h>
|
||||
#include <StringForRate.h>
|
||||
#include <StringView.h>
|
||||
#include <TextView.h>
|
||||
|
||||
@@ -405,6 +406,12 @@ printf("InfoWin::Update(0x%08lx)\n", which);
|
||||
rateString.ReplaceFirst("%d", "??");
|
||||
s << rateString;
|
||||
}
|
||||
if (format.type == B_MEDIA_ENCODED_AUDIO) {
|
||||
float br = format.u.encoded_audio.bit_rate;
|
||||
char string[20] = "";
|
||||
if (br > 0.0)
|
||||
s << ", " << string_for_rate(br, string, sizeof(string));
|
||||
}
|
||||
s << "\n\n";
|
||||
fContentsView->Insert(s.String());
|
||||
}
|
||||
@@ -430,6 +437,8 @@ printf("InfoWin::Update(0x%08lx)\n", which);
|
||||
d = d % (60 * 1000);
|
||||
s << v << ":";
|
||||
v = d / 1000;
|
||||
if (v < 10)
|
||||
s << '0';
|
||||
s << v;
|
||||
if (hours)
|
||||
s << " " << B_TRANSLATE_COMMENT("h", "Hours");
|
||||
|
||||
@@ -243,9 +243,12 @@ void
|
||||
NetworkStatusView::AttachedToWindow()
|
||||
{
|
||||
BView::AttachedToWindow();
|
||||
if (Parent())
|
||||
SetViewColor(Parent()->ViewColor());
|
||||
if (Parent() != NULL) {
|
||||
if ((Parent()->Flags() & B_DRAW_ON_CHILDREN) != 0)
|
||||
SetViewColor(B_TRANSPARENT_COLOR);
|
||||
else
|
||||
SetViewColor(Parent()->ViewColor());
|
||||
} else
|
||||
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||
|
||||
SetLowColor(ViewColor());
|
||||
|
||||
+136
-84
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright 2003-2006, Haiku.
|
||||
* Copyright 2004-2005 yellowTAB GmbH. All Rights Reserverd.
|
||||
* Copyright 2003-2006, Haiku, Inc. All rights reserved.
|
||||
* Copyright 2004-2005 yellowTAB GmbH. All Rights Reserved.
|
||||
* Copyright 2006 Bernd Korz. All Rights Reserved
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
@@ -21,29 +21,33 @@
|
||||
|
||||
|
||||
// Implementation of FilterThread
|
||||
FilterThread::FilterThread(Filter* filter, int32 i, int32 n, bool runInCurrentThread)
|
||||
: fFilter(filter)
|
||||
, fI(i)
|
||||
, fN(n)
|
||||
FilterThread::FilterThread(Filter* filter, int32 i, int32 n,
|
||||
bool runInCurrentThread)
|
||||
:
|
||||
fFilter(filter),
|
||||
fI(i),
|
||||
fN(n)
|
||||
{
|
||||
if (runInCurrentThread) {
|
||||
if (runInCurrentThread)
|
||||
Run();
|
||||
} else {
|
||||
else {
|
||||
thread_id tid;
|
||||
tid = spawn_thread(worker_thread, "filter", suggest_thread_priority(B_STATUS_RENDERING), this);
|
||||
if (tid >= 0) {
|
||||
tid = spawn_thread(worker_thread, "filter",
|
||||
suggest_thread_priority(B_STATUS_RENDERING), this);
|
||||
if (tid >= 0)
|
||||
resume_thread(tid);
|
||||
} else {
|
||||
else
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FilterThread::~FilterThread()
|
||||
{
|
||||
fFilter->FilterThreadDone();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
FilterThread::worker_thread(void* data)
|
||||
{
|
||||
@@ -51,6 +55,7 @@ FilterThread::worker_thread(void* data)
|
||||
return thread->Run();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
FilterThread::Run()
|
||||
{
|
||||
@@ -67,24 +72,25 @@ FilterThread::Run()
|
||||
new FilterThread(fFilter, i, fN);
|
||||
}
|
||||
}
|
||||
if (fFilter->GetBitmap()) {
|
||||
if (fFilter->GetBitmap())
|
||||
fFilter->Run(fI, fN);
|
||||
}
|
||||
|
||||
delete this;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// Implementation of Filter
|
||||
Filter::Filter(BBitmap* image, BMessenger listener, uint32 what)
|
||||
: fListener(listener)
|
||||
, fWhat(what)
|
||||
, fStarted(false)
|
||||
, fN(0)
|
||||
, fNumberOfThreads(0)
|
||||
, fIsRunning(false)
|
||||
, fSrcImage(image)
|
||||
, fDestImageInitialized(false)
|
||||
, fDestImage(NULL)
|
||||
:
|
||||
fListener(listener),
|
||||
fWhat(what),
|
||||
fStarted(false),
|
||||
fN(0),
|
||||
fNumberOfThreads(0),
|
||||
fIsRunning(false),
|
||||
fSrcImage(image),
|
||||
fDestImageInitialized(false),
|
||||
fDestImage(NULL)
|
||||
{
|
||||
fCPUCount = NumberOfActiveCPUs();
|
||||
|
||||
@@ -95,12 +101,14 @@ Filter::Filter(BBitmap* image, BMessenger listener, uint32 what)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
Filter::~Filter()
|
||||
{
|
||||
delete fDestImage;
|
||||
delete_sem(fWaitForThreads);
|
||||
}
|
||||
|
||||
|
||||
BBitmap*
|
||||
Filter::GetBitmap()
|
||||
{
|
||||
@@ -111,6 +119,7 @@ Filter::GetBitmap()
|
||||
return fDestImage;
|
||||
}
|
||||
|
||||
|
||||
BBitmap*
|
||||
Filter::DetachBitmap()
|
||||
{
|
||||
@@ -119,6 +128,7 @@ Filter::DetachBitmap()
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Filter::Start(bool async)
|
||||
{
|
||||
@@ -136,10 +146,10 @@ Filter::Start(bool async)
|
||||
// start first filter thread
|
||||
new FilterThread(this, 0, fN, !async);
|
||||
|
||||
if (!async) {
|
||||
if (!async)
|
||||
Wait();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Filter::Wait()
|
||||
@@ -152,6 +162,7 @@ Filter::Wait()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Filter::Stop()
|
||||
{
|
||||
@@ -160,17 +171,20 @@ Filter::Stop()
|
||||
Wait();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Filter::IsRunning() const
|
||||
{
|
||||
return fIsRunning;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Filter::Completed()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Filter::FilterThreadDone()
|
||||
{
|
||||
@@ -179,14 +193,15 @@ Filter::FilterThreadDone()
|
||||
delete fStopWatch; fStopWatch = NULL;
|
||||
#endif
|
||||
Completed();
|
||||
if (fIsRunning) {
|
||||
if (fIsRunning)
|
||||
fListener.SendMessage(fWhat);
|
||||
}
|
||||
|
||||
fIsRunning = false;
|
||||
}
|
||||
release_sem(fWaitForThreads);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Filter::FilterThreadInitFailed()
|
||||
{
|
||||
@@ -197,38 +212,43 @@ Filter::FilterThreadInitFailed()
|
||||
release_sem_etc(fWaitForThreads, fN, 0);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Filter::IsBitmapValid(BBitmap* bitmap) const
|
||||
{
|
||||
return bitmap != NULL && bitmap->InitCheck() == B_OK && bitmap->IsValid();
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
Filter::NumberOfThreads()
|
||||
{
|
||||
const int32 units = GetNumberOfUnits();
|
||||
int32 n;
|
||||
n = units / 32; // at least 32 units per CPU
|
||||
if (n > CPUCount()) {
|
||||
if (n > CPUCount())
|
||||
n = CPUCount();
|
||||
} else if (n <= 0) {
|
||||
else if (n <= 0)
|
||||
n = 1; // at least one thread!
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
BBitmap*
|
||||
Filter::GetSrcImage()
|
||||
{
|
||||
return fSrcImage;
|
||||
}
|
||||
|
||||
|
||||
BBitmap*
|
||||
Filter::GetDestImage()
|
||||
{
|
||||
return fDestImage;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
Filter::NumberOfActiveCPUs() const
|
||||
{
|
||||
@@ -247,15 +267,19 @@ Filter::NumberOfActiveCPUs() const
|
||||
return cpuCount;
|
||||
}
|
||||
|
||||
|
||||
// Implementation of (bilinear) Scaler
|
||||
Scaler::Scaler(BBitmap* image, BRect rect, BMessenger listener, uint32 what, bool dither)
|
||||
: Filter(image, listener, what)
|
||||
, fScaledImage(NULL)
|
||||
, fRect(rect)
|
||||
, fDither(dither)
|
||||
Scaler::Scaler(BBitmap* image, BRect rect, BMessenger listener, uint32 what,
|
||||
bool dither)
|
||||
:
|
||||
Filter(image, listener, what),
|
||||
fScaledImage(NULL),
|
||||
fRect(rect),
|
||||
fDither(dither)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Scaler::~Scaler()
|
||||
{
|
||||
if (GetDestImage() != fScaledImage) {
|
||||
@@ -264,13 +288,17 @@ Scaler::~Scaler()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BBitmap*
|
||||
Scaler::CreateDestImage(BBitmap* srcImage)
|
||||
{
|
||||
if (srcImage == NULL || (srcImage->ColorSpace() != B_RGB32 && srcImage->ColorSpace() != B_RGBA32)) return NULL;
|
||||
if (srcImage == NULL || (srcImage->ColorSpace() != B_RGB32
|
||||
&& srcImage->ColorSpace() != B_RGBA32))
|
||||
return NULL;
|
||||
|
||||
BRect dest(0, 0, fRect.IntegerWidth(), fRect.IntegerHeight());
|
||||
BBitmap* destImage = new BBitmap(dest, fDither ? B_CMAP8 : srcImage->ColorSpace());
|
||||
BBitmap* destImage = new BBitmap(dest,
|
||||
fDither ? B_CMAP8 : srcImage->ColorSpace());
|
||||
|
||||
if (!IsBitmapValid(destImage)) {
|
||||
delete destImage;
|
||||
@@ -287,19 +315,19 @@ Scaler::CreateDestImage(BBitmap* srcImage)
|
||||
fScaledImage = NULL;
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
} else
|
||||
fScaledImage = destImage;
|
||||
}
|
||||
|
||||
return destImage;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Scaler::Matches(BRect rect, bool dither) const
|
||||
{
|
||||
return fRect.IntegerWidth() == rect.IntegerWidth() &&
|
||||
fRect.IntegerHeight() == rect.IntegerHeight() &&
|
||||
fDither == dither;
|
||||
return fRect.IntegerWidth() == rect.IntegerWidth()
|
||||
&& fRect.IntegerHeight() == rect.IntegerHeight()
|
||||
&& fDither == dither;
|
||||
}
|
||||
|
||||
|
||||
@@ -310,6 +338,7 @@ typedef struct {
|
||||
float alpha1;
|
||||
} ColumnData;
|
||||
|
||||
|
||||
void
|
||||
Scaler::ScaleBilinear(intType fromRow, int32 toRow)
|
||||
{
|
||||
@@ -357,11 +386,11 @@ Scaler::ScaleBilinear(intType fromRow, int32 toRow)
|
||||
intType srcRow;
|
||||
float alpha0, alpha1;
|
||||
|
||||
if (destH == 0) {
|
||||
if (destH == 0)
|
||||
row = 0;
|
||||
} else {
|
||||
else
|
||||
row = (float)y * (float)srcH / (float)destH;
|
||||
}
|
||||
|
||||
srcRow = (intType)row;
|
||||
alpha1 = row - srcRow;
|
||||
alpha0 = 1.0 - alpha1;
|
||||
@@ -434,6 +463,7 @@ Scaler::ScaleBilinear(intType fromRow, int32 toRow)
|
||||
delete[] columnData;
|
||||
}
|
||||
|
||||
|
||||
// Scale bilinear using fixed point calculations
|
||||
// Is already more than two times faster than floating point version
|
||||
// on AMD Athlon 1 GHz and Dual Intel Pentium III 866 MHz.
|
||||
@@ -444,6 +474,7 @@ typedef struct {
|
||||
fixed_point alpha1;
|
||||
} ColumnDataFP;
|
||||
|
||||
|
||||
void
|
||||
Scaler::ScaleBilinearFP(intType fromRow, int32 toRow)
|
||||
{
|
||||
@@ -483,7 +514,8 @@ Scaler::ScaleBilinearFP(intType fromRow, int32 toRow)
|
||||
columnData = new ColumnDataFP[destW];
|
||||
cd = columnData;
|
||||
for (i = 0; i < destW; i++, cd++) {
|
||||
fixed_point column = to_fixed_point(i) * (long_fixed_point)fpSrcW / fpDestW;
|
||||
fixed_point column = to_fixed_point(i) * (long_fixed_point)fpSrcW
|
||||
/ fpDestW;
|
||||
cd->srcColumn = from_fixed_point(column);
|
||||
cd->alpha1 = tail_value(column); // weigth for left pixel value
|
||||
cd->alpha0 = kFPOne - cd->alpha1; // weigth for right pixel value
|
||||
@@ -496,11 +528,11 @@ Scaler::ScaleBilinearFP(intType fromRow, int32 toRow)
|
||||
intType srcRow;
|
||||
fixed_point alpha0, alpha1;
|
||||
|
||||
if (fpDestH == 0) {
|
||||
if (fpDestH == 0)
|
||||
row = 0;
|
||||
} else {
|
||||
else
|
||||
row = to_fixed_point(y) * (long_fixed_point)fpSrcH / fpDestH;
|
||||
}
|
||||
|
||||
srcRow = from_fixed_point(row);
|
||||
alpha1 = tail_value(row); // weight for row y + 1
|
||||
alpha0 = kFPOne - alpha1; // weight for row y
|
||||
@@ -566,14 +598,15 @@ Scaler::ScaleBilinearFP(intType fromRow, int32 toRow)
|
||||
destData[2] = a[2];
|
||||
destData[3] = a[3];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
delete[] columnData;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Scaler::RowValues(float* sum, const uchar* src, intType srcW, intType fromX, intType toX, const float a0X, const float a1X, const int32 kBPP)
|
||||
Scaler::RowValues(float* sum, const uchar* src, intType srcW, intType fromX,
|
||||
intType toX, const float a0X, const float a1X, const int32 kBPP)
|
||||
{
|
||||
sum[0] = a0X * src[0];
|
||||
sum[1] = a0X * src[1];
|
||||
@@ -594,6 +627,7 @@ Scaler::RowValues(float* sum, const uchar* src, intType srcW, intType fromX, int
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
int32 from;
|
||||
int32 to;
|
||||
@@ -601,6 +635,7 @@ typedef struct {
|
||||
float alpha1;
|
||||
} DownScaleColumnData;
|
||||
|
||||
|
||||
void
|
||||
Scaler::DownScaleBilinear(intType fromRow, int32 toRow)
|
||||
{
|
||||
@@ -706,6 +741,7 @@ Scaler::DownScaleBilinear(intType fromRow, int32 toRow)
|
||||
delete[] columnData;
|
||||
}
|
||||
|
||||
|
||||
// Flyod-Steinberg Dithering
|
||||
// Filter (distribution of error to adjacent pixels, X is current pixel):
|
||||
// 0 X 7
|
||||
@@ -715,6 +751,7 @@ typedef struct {
|
||||
intType error[3];
|
||||
} DitheringColumnData;
|
||||
|
||||
|
||||
uchar
|
||||
Scaler::Limit(intType value)
|
||||
{
|
||||
@@ -726,6 +763,7 @@ Scaler::Limit(intType value)
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Scaler::Dither(int32 fromRow, int32 toRow)
|
||||
{
|
||||
@@ -778,7 +816,8 @@ Scaler::Dither(int32 fromRow, int32 toRow)
|
||||
|
||||
srcDataRow = srcBits + fromRow * srcBPR;
|
||||
destDataRow = destBits + fromRow * destBPR;
|
||||
for (y = fromRow; IsRunning() && y <= toRow; y ++, srcDataRow += srcBPR, destDataRow += destBPR) {
|
||||
for (y = fromRow; IsRunning() && y <= toRow; y++, srcDataRow += srcBPR,
|
||||
destDataRow += destBPR) {
|
||||
// left to right
|
||||
error[0] = error[1] = error[2] = 0;
|
||||
srcData = srcDataRow;
|
||||
@@ -879,12 +918,14 @@ Scaler::Dither(int32 fromRow, int32 toRow)
|
||||
delete[] columnData0;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
Scaler::GetNumberOfUnits()
|
||||
{
|
||||
return fRect.IntegerHeight() + 1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Scaler::Run(int32 i, int32 n)
|
||||
{
|
||||
@@ -892,43 +933,47 @@ Scaler::Run(int32 i, int32 n)
|
||||
imageHeight = GetDestImage()->Bounds().IntegerHeight() + 1;
|
||||
height = imageHeight / n;
|
||||
from = i * height;
|
||||
if (i+1 == n) {
|
||||
if (i + 1 == n)
|
||||
to = imageHeight - 1;
|
||||
} else {
|
||||
else
|
||||
to = from + height - 1;
|
||||
}
|
||||
if (GetDestImage()->Bounds().Width() >= GetSrcImage()->Bounds().Width()) {
|
||||
|
||||
if (GetDestImage()->Bounds().Width() >= GetSrcImage()->Bounds().Width())
|
||||
ScaleBilinearFP(from, to);
|
||||
} else {
|
||||
else
|
||||
DownScaleBilinear(from, to);
|
||||
}
|
||||
if (fDither) {
|
||||
|
||||
if (fDither)
|
||||
Dither(from, to);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Scaler::Completed()
|
||||
{
|
||||
if (GetDestImage() != fScaledImage) {
|
||||
if (GetDestImage() != fScaledImage)
|
||||
delete fScaledImage;
|
||||
}
|
||||
|
||||
fScaledImage = NULL;
|
||||
}
|
||||
|
||||
// Implementation of ImageProcessor
|
||||
ImageProcessor::ImageProcessor(enum operation op, BBitmap* image, BMessenger listener, uint32 what)
|
||||
: Filter(image, listener, what)
|
||||
, fOp(op)
|
||||
, fBPP(0)
|
||||
, fWidth(0)
|
||||
, fHeight(0)
|
||||
, fSrcBPR(0)
|
||||
, fDestBPR(0)
|
||||
|
||||
// Implementation of ImageProcessor
|
||||
ImageProcessor::ImageProcessor(enum operation op, BBitmap* image,
|
||||
BMessenger listener, uint32 what)
|
||||
:
|
||||
Filter(image, listener, what),
|
||||
fOp(op),
|
||||
fBPP(0),
|
||||
fWidth(0),
|
||||
fHeight(0),
|
||||
fSrcBPR(0),
|
||||
fDestBPR(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BBitmap*
|
||||
ImageProcessor::CreateDestImage(BBitmap* /* srcImage */)
|
||||
{
|
||||
@@ -936,20 +981,21 @@ ImageProcessor::CreateDestImage(BBitmap* /* srcImage */)
|
||||
BBitmap* bm;
|
||||
BRect rect;
|
||||
|
||||
if (GetSrcImage() == NULL) return NULL;
|
||||
if (GetSrcImage() == NULL)
|
||||
return NULL;
|
||||
|
||||
cs = GetSrcImage()->ColorSpace();
|
||||
fBPP = BytesPerPixel(cs);
|
||||
if (fBPP < 1) return NULL;
|
||||
if (fBPP < 1)
|
||||
return NULL;
|
||||
|
||||
fWidth = GetSrcImage()->Bounds().IntegerWidth();
|
||||
fHeight = GetSrcImage()->Bounds().IntegerHeight();
|
||||
|
||||
if (fOp == kRotateClockwise || fOp == kRotateCounterClockwise) {
|
||||
if (fOp == kRotateClockwise || fOp == kRotateCounterClockwise)
|
||||
rect.Set(0, 0, fHeight, fWidth);
|
||||
} else {
|
||||
else
|
||||
rect.Set(0, 0, fWidth, fHeight);
|
||||
}
|
||||
|
||||
bm = new BBitmap(rect, cs);
|
||||
if (!IsBitmapValid(bm)) {
|
||||
@@ -963,12 +1009,14 @@ ImageProcessor::CreateDestImage(BBitmap* /* srcImage */)
|
||||
return bm;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
ImageProcessor::GetNumberOfUnits()
|
||||
{
|
||||
return GetSrcImage()->Bounds().IntegerHeight() + 1;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
ImageProcessor::BytesPerPixel(color_space cs) const
|
||||
{
|
||||
@@ -995,11 +1043,14 @@ ImageProcessor::BytesPerPixel(color_space cs) const
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ImageProcessor::CopyPixel(uchar* dest, int32 destX, int32 destY, const uchar* src, int32 x, int32 y)
|
||||
ImageProcessor::CopyPixel(uchar* dest, int32 destX, int32 destY,
|
||||
const uchar* src, int32 x, int32 y)
|
||||
{
|
||||
// Note: On my systems (Dual Intel P3 866MHz and AMD Athlon 1GHz), replacing
|
||||
// the multiplications below with pointer arithmethics showed no speedup at all!
|
||||
// Note: On my systems (Dual Intel P3 866MHz and AMD Athlon 1GHz),
|
||||
// replacing the multiplications below with pointer arithmethics showed
|
||||
// no speedup at all!
|
||||
dest += fDestBPR * destY + destX * fBPP;
|
||||
src += fSrcBPR * y + x * fBPP;
|
||||
// Replacing memcpy with this switch statement is slightly faster
|
||||
@@ -1016,6 +1067,7 @@ ImageProcessor::CopyPixel(uchar* dest, int32 destX, int32 destY, const uchar* sr
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Note: For B_CMAP8 InvertPixel inverts the color index not the color value!
|
||||
void
|
||||
ImageProcessor::InvertPixel(int32 x, int32 y, uchar* dest, const uchar* src)
|
||||
@@ -1035,18 +1087,19 @@ ImageProcessor::InvertPixel(int32 x, int32 y, uchar* dest, const uchar* src)
|
||||
}
|
||||
}
|
||||
|
||||
// Note: On my systems, the operation kInvert shows a speedup on multiple CPUs only!
|
||||
|
||||
// Note: On my systems, the operation kInvert shows a speedup on
|
||||
// multiple CPUs only!
|
||||
void
|
||||
ImageProcessor::Run(int32 i, int32 n)
|
||||
{
|
||||
int32 from, to;
|
||||
int32 height = (fHeight + 1) / n;
|
||||
from = i * height;
|
||||
if (i+1 == n) {
|
||||
if (i + 1 == n)
|
||||
to = fHeight;
|
||||
} else {
|
||||
else
|
||||
to = from + height - 1;
|
||||
}
|
||||
|
||||
int32 x, y, destX, destY;
|
||||
const uchar* src = (uchar*)GetSrcImage()->Bits();
|
||||
@@ -1097,5 +1150,4 @@ ImageProcessor::Run(int32 i, int32 n)
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -63,7 +63,8 @@ const int32 kFPOne = to_fixed_point(1);
|
||||
// Used by class Filter
|
||||
class FilterThread {
|
||||
public:
|
||||
FilterThread(Filter* filter, int32 i, int32 n, bool runInCurrentThread = false);
|
||||
FilterThread(Filter* filter, int32 i, int32 n,
|
||||
bool runInCurrentThread = false);
|
||||
~FilterThread();
|
||||
|
||||
private:
|
||||
@@ -161,7 +162,8 @@ private:
|
||||
// Scales and optionally dithers an image
|
||||
class Scaler : public Filter {
|
||||
public:
|
||||
Scaler(BBitmap* image, BRect rect, BMessenger listener, uint32 what, bool dither);
|
||||
Scaler(BBitmap* image, BRect rect, BMessenger listener, uint32 what,
|
||||
bool dither);
|
||||
~Scaler();
|
||||
|
||||
BBitmap* CreateDestImage(BBitmap* srcImage);
|
||||
@@ -173,7 +175,9 @@ public:
|
||||
private:
|
||||
void ScaleBilinear(int32 fromRow, int32 toRow);
|
||||
void ScaleBilinearFP(int32 fromRow, int32 toRow);
|
||||
inline void RowValues(float* sum, const uchar* srcData, intType srcW, intType fromX, intType toX, const float a0X, const float a1X, const int32 kBPP);
|
||||
inline void RowValues(float* sum, const uchar* srcData, intType srcW,
|
||||
intType fromX, intType toX, const float a0X,
|
||||
const float a1X, const int32 kBPP);
|
||||
void DownScaleBilinear(int32 fromRow, int32 toRow);
|
||||
static inline uchar Limit(intType value);
|
||||
void Dither(int32 fromRow, int32 toRow);
|
||||
@@ -195,14 +199,16 @@ public:
|
||||
kNumberOfAffineTransformations = 4
|
||||
};
|
||||
|
||||
ImageProcessor(enum operation op, BBitmap* image, BMessenger listener, uint32 what);
|
||||
ImageProcessor(enum operation op, BBitmap* image, BMessenger listener,
|
||||
uint32 what);
|
||||
BBitmap* CreateDestImage(BBitmap* srcImage);
|
||||
int32 GetNumberOfUnits();
|
||||
void Run(int32 i, int32 n);
|
||||
|
||||
private:
|
||||
int32 BytesPerPixel(color_space cs) const;
|
||||
inline void CopyPixel(uchar* dest, int32 destX, int32 destY, const uchar* src, int32 x, int32 y);
|
||||
inline void CopyPixel(uchar* dest, int32 destX, int32 destY,
|
||||
const uchar* src, int32 x, int32 y);
|
||||
inline void InvertPixel(int32 x, int32 y, uchar* dest, const uchar* src);
|
||||
|
||||
enum operation fOp;
|
||||
|
||||
@@ -374,14 +374,16 @@ AutoAdjustingNavigator::~AutoAdjustingNavigator()
|
||||
|
||||
|
||||
bool
|
||||
AutoAdjustingNavigator::FindNextImage(const entry_ref& currentRef, entry_ref& nextRef,
|
||||
bool next, bool rewind)
|
||||
AutoAdjustingNavigator::FindNextImage(const entry_ref& currentRef,
|
||||
entry_ref& nextRef, bool next, bool rewind)
|
||||
{
|
||||
if (_CheckForTracker(currentRef))
|
||||
return fTrackerNavigator->FindNextImage(currentRef, nextRef, next, rewind);
|
||||
return fTrackerNavigator->FindNextImage(currentRef, nextRef, next,
|
||||
rewind);
|
||||
|
||||
if (fFolderNavigator != NULL)
|
||||
return fFolderNavigator->FindNextImage(currentRef, nextRef, next, rewind);
|
||||
return fFolderNavigator->FindNextImage(currentRef, nextRef, next,
|
||||
rewind);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
#include <Button.h>
|
||||
#include <Catalog.h>
|
||||
#include <ControlLook.h>
|
||||
#include <GroupLayoutBuilder.h>
|
||||
#include <GridLayoutBuilder.h>
|
||||
#include <Locale.h>
|
||||
#include <GroupLayoutBuilder.h>
|
||||
#include <LayoutBuilder.h>
|
||||
#include <Locale.h>
|
||||
#include <String.h>
|
||||
|
||||
#include "ShowImageConstants.h"
|
||||
|
||||
@@ -129,19 +129,18 @@ compose_checker_background(const BBitmap* bitmap)
|
||||
p[3] = 255;
|
||||
alpha = 255 - alpha;
|
||||
if (x % 10 >= 5) {
|
||||
if (i % 10 >= 5) {
|
||||
if (i % 10 >= 5)
|
||||
blend_colors(p, kAlphaLow.red, kAlphaLow.green, kAlphaLow.blue, alpha);
|
||||
} else {
|
||||
else
|
||||
blend_colors(p, kAlphaHigh.red, kAlphaHigh.green, kAlphaHigh.blue, alpha);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (i % 10 >= 5) {
|
||||
if (i % 10 >= 5)
|
||||
blend_colors(p, kAlphaHigh.red, kAlphaHigh.green, kAlphaHigh.blue, alpha);
|
||||
} else {
|
||||
else
|
||||
blend_colors(p, kAlphaLow.red, kAlphaLow.green, kAlphaLow.blue, alpha);
|
||||
}
|
||||
}
|
||||
}
|
||||
p += 4;
|
||||
}
|
||||
bits += bpr;
|
||||
@@ -249,9 +248,8 @@ ShowImageView::Pulse()
|
||||
BPoint mousePos;
|
||||
uint32 buttons;
|
||||
GetMouse(&mousePos, &buttons, false);
|
||||
if (Bounds().Contains(mousePos)) {
|
||||
if (Bounds().Contains(mousePos))
|
||||
be_app->ObscureCursor();
|
||||
}
|
||||
} else
|
||||
fHideCursorCountDown--;
|
||||
}
|
||||
@@ -812,9 +810,9 @@ ShowImageView::_AddSupportedTypes(BMessage* msg, BBitmap* bitmap)
|
||||
int32 count;
|
||||
roster->GetOutputFormats(info[i].translator, &formats, &count);
|
||||
for (int32 j = 0; j < count; j++) {
|
||||
if (fMimeType == formats[j].MIME) {
|
||||
if (fMimeType == formats[j].MIME)
|
||||
foundCurrent = true;
|
||||
} else if (strcmp(formats[j].MIME, "image/x-be-bitmap") != 0) {
|
||||
else if (strcmp(formats[j].MIME, "image/x-be-bitmap") != 0) {
|
||||
foundOther = true;
|
||||
// needed to send data in message
|
||||
msg->AddString("be:types", formats[j].MIME);
|
||||
@@ -965,14 +963,16 @@ ShowImageView::SaveToFile(BDirectory* dir, const char* name, BBitmap* bitmap,
|
||||
|
||||
|
||||
void
|
||||
ShowImageView::_SendInMessage(BMessage* msg, BBitmap* bitmap, translation_format* format)
|
||||
ShowImageView::_SendInMessage(BMessage* msg, BBitmap* bitmap,
|
||||
translation_format* format)
|
||||
{
|
||||
BMessage reply(B_MIME_DATA);
|
||||
BBitmapStream stream(bitmap); // destructor deletes bitmap
|
||||
BTranslatorRoster* roster = BTranslatorRoster::Default();
|
||||
BMallocIO memStream;
|
||||
if (roster->Translate(&stream, NULL, NULL, &memStream, format->type) == B_OK) {
|
||||
reply.AddData(format->MIME, B_MIME_TYPE, memStream.Buffer(), memStream.BufferLength());
|
||||
reply.AddData(format->MIME, B_MIME_TYPE, memStream.Buffer(),
|
||||
memStream.BufferLength());
|
||||
msg->SendReply(&reply);
|
||||
}
|
||||
}
|
||||
@@ -1172,7 +1172,7 @@ ShowImageView::MouseMoved(BPoint point, uint32 state, const BMessage* message)
|
||||
fHideCursorCountDown = HIDE_CURSOR_DELAY_TIME;
|
||||
if (fHideCursor) {
|
||||
// Show toolbar when mouse hits top 15 pixels, hide otherwise
|
||||
_ShowToolBarIfEnabled(point.y <= 15);
|
||||
_ShowToolBarIfEnabled(ConvertToScreen(point).y <= 15);
|
||||
}
|
||||
if (fCreatingSelection)
|
||||
_UpdateSelectionRect(point, false);
|
||||
@@ -1435,13 +1435,13 @@ ShowImageView::FixupScrollBar(orientation o, float bitmapLength,
|
||||
psb = ScrollBar(o);
|
||||
if (psb) {
|
||||
range = bitmapLength - viewLength;
|
||||
if (range < 0.0) {
|
||||
if (range < 0.0)
|
||||
range = 0.0;
|
||||
}
|
||||
|
||||
prop = viewLength / bitmapLength;
|
||||
if (prop > 1.0) {
|
||||
if (prop > 1.0)
|
||||
prop = 1.0;
|
||||
}
|
||||
|
||||
psb->SetRange(0, range);
|
||||
psb->SetProportion(prop);
|
||||
psb->SetSteps(10, 100);
|
||||
@@ -1496,7 +1496,8 @@ ShowImageView::Undo()
|
||||
BBitmap* undoSelection;
|
||||
undoSelection = fUndo.GetSelectionBitmap();
|
||||
// NOTE: ShowImageView is responsible for deleting this bitmap
|
||||
// (Which it will, as it would with a fSelectionBitmap that it allocated itself)
|
||||
// (Which it will, as it would with a fSelectionBitmap that it
|
||||
// allocated itself)
|
||||
if (!undoSelection)
|
||||
_SetHasSelection(false);
|
||||
else {
|
||||
@@ -1683,10 +1684,14 @@ ShowImageView::_DoImageOperation(ImageProcessor::operation op, bool quiet)
|
||||
// update orientation state
|
||||
if (op != ImageProcessor::kInvert) {
|
||||
// Note: If one of these fails, check its definition in class ImageProcessor.
|
||||
// ASSERT(ImageProcessor::kRotateClockwise < ImageProcessor::kNumberOfAffineTransformations);
|
||||
// ASSERT(ImageProcessor::kRotateCounterClockwise < ImageProcessor::kNumberOfAffineTransformations);
|
||||
// ASSERT(ImageProcessor::kFlipLeftToRight < ImageProcessor::kNumberOfAffineTransformations);
|
||||
// ASSERT(ImageProcessor::kFlipTopToBottom < ImageProcessor::kNumberOfAffineTransformations);
|
||||
// ASSERT(ImageProcessor::kRotateClockwise <
|
||||
// ImageProcessor::kNumberOfAffineTransformations);
|
||||
// ASSERT(ImageProcessor::kRotateCounterClockwise <
|
||||
// ImageProcessor::kNumberOfAffineTransformations);
|
||||
// ASSERT(ImageProcessor::kFlipLeftToRight <
|
||||
// ImageProcessor::kNumberOfAffineTransformations);
|
||||
// ASSERT(ImageProcessor::kFlipTopToBottom <
|
||||
// ImageProcessor::kNumberOfAffineTransformations);
|
||||
fImageOrientation = fTransformation[op][fImageOrientation];
|
||||
}
|
||||
|
||||
@@ -1697,10 +1702,9 @@ ShowImageView::_DoImageOperation(ImageProcessor::operation op, bool quiet)
|
||||
if (orientation != k0) {
|
||||
node.WriteAttr(SHOW_IMAGE_ORIENTATION_ATTRIBUTE, B_INT32_TYPE, 0,
|
||||
&orientation, sizeof(orientation));
|
||||
} else {
|
||||
} else
|
||||
node.RemoveAttr(SHOW_IMAGE_ORIENTATION_ATTRIBUTE);
|
||||
}
|
||||
}
|
||||
|
||||
// set new bitmap
|
||||
_DeleteBitmap();
|
||||
|
||||
@@ -990,7 +990,8 @@ ShowImageWindow::MessageReceived(BMessage* message)
|
||||
backgroundsMessage.AddRef("refs", fImageView->Image());
|
||||
// This is used in the Backgrounds code for scaled placement
|
||||
backgroundsMessage.AddInt32("placement", 'scpl');
|
||||
be_roster->Launch("application/x-vnd.haiku-backgrounds", &backgroundsMessage);
|
||||
be_roster->Launch("application/x-vnd.haiku-backgrounds",
|
||||
&backgroundsMessage);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1050,15 +1051,15 @@ ShowImageWindow::MessageReceived(BMessage* message)
|
||||
if (message->FindFloat("offset", &offset) == B_OK
|
||||
&& message->FindBool("show", &show) == B_OK) {
|
||||
// Compensate rounding errors with the final placement
|
||||
if (show) {
|
||||
if (show)
|
||||
fToolBarView->MoveTo(fToolBarView->Frame().left, 0);
|
||||
} else {
|
||||
else {
|
||||
fToolBarView->MoveTo(fToolBarView->Frame().left, offset);
|
||||
fToolBarView->Hide();
|
||||
}
|
||||
BRect frame = fToolBarView->Parent()->Bounds();
|
||||
frame.top = fToolBarView->Frame().bottom + 1;
|
||||
fScrollView->MoveTo(0, frame.top);
|
||||
fScrollView->MoveTo(fScrollView->Frame().left, frame.top);
|
||||
fScrollView->ResizeTo(fScrollView->Bounds().Width(),
|
||||
frame.Height() - B_H_SCROLL_BAR_HEIGHT + 1);
|
||||
fVerticalScrollBar->MoveTo(
|
||||
@@ -1174,7 +1175,8 @@ ShowImageWindow::_SaveToFile(BMessage* message)
|
||||
|
||||
int32 i;
|
||||
for (i = 0; i < outCount; i++) {
|
||||
if (outFormat[i].group == B_TRANSLATOR_BITMAP && outFormat[i].type == outType)
|
||||
if (outFormat[i].group == B_TRANSLATOR_BITMAP && outFormat[i].type
|
||||
== outType)
|
||||
break;
|
||||
}
|
||||
if (i == outCount)
|
||||
|
||||
@@ -51,8 +51,8 @@ ToolBarView::AddAction(uint32 command, BHandler* target, const BBitmap* icon,
|
||||
|
||||
|
||||
void
|
||||
ToolBarView::AddAction(BMessage* message, BHandler* target, const BBitmap* icon,
|
||||
const char* toolTipText)
|
||||
ToolBarView::AddAction(BMessage* message, BHandler* target,
|
||||
const BBitmap* icon, const char* toolTipText)
|
||||
{
|
||||
BIconButton* button = new BIconButton(NULL, NULL, message, target);
|
||||
button->SetIcon(icon);
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
|
||||
// default window positioning
|
||||
static const float MIN_WIDTH = 400.0f;
|
||||
static const float MIN_HEIGHT = 336.0f;
|
||||
static const float MIN_HEIGHT = 175.0f;
|
||||
static const float XPOS = 100.0f;
|
||||
static const float YPOS = 200.0f;
|
||||
|
||||
@@ -364,7 +364,7 @@ RecorderWindow::InitWindow()
|
||||
fSoundList = new SoundListView(r, B_TRANSLATE("Sound List"),
|
||||
B_FOLLOW_ALL);
|
||||
fSoundList->SetSelectionMessage(new BMessage(SOUND_SELECTED));
|
||||
fSoundList->SetViewColor(216, 216, 216);
|
||||
fSoundList->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||
BScrollView *scroller = new BScrollView("scroller", fSoundList,
|
||||
B_FOLLOW_ALL, 0, false, true, B_FANCY_BORDER);
|
||||
fBottomBox->AddChild(scroller);
|
||||
@@ -374,43 +374,75 @@ RecorderWindow::InitWindow()
|
||||
r.bottom -= 25;
|
||||
r.InsetBy(10, 8);
|
||||
r.top -= 1;
|
||||
fFileInfoBox = new BBox(r, "fileinfo", B_FOLLOW_LEFT | B_FOLLOW_BOTTOM);
|
||||
fFileInfoBox = new BBox(r, "fileinfo", B_FOLLOW_LEFT);
|
||||
fFileInfoBox->SetLabel(B_TRANSLATE("File info"));
|
||||
|
||||
fFileInfoBox->SetHighColor(ui_color(B_PANEL_TEXT_COLOR));
|
||||
|
||||
BFont font = be_plain_font;
|
||||
font.SetSize(font.Size() * 0.92f);
|
||||
font_height height;
|
||||
font.GetHeight(&height);
|
||||
float fontHeight = height.ascent + height.leading + height.descent;
|
||||
|
||||
r = fFileInfoBox->Bounds();
|
||||
r.left = 8;
|
||||
r.top = 13;
|
||||
r.bottom = r.top + 15;
|
||||
r.top = fontHeight + 6;
|
||||
r.bottom = r.top + fontHeight + 3;
|
||||
r.right -= 10;
|
||||
fFilename = new BStringView(r, "filename", B_TRANSLATE("File name:"));
|
||||
fFileInfoBox->AddChild(fFilename);
|
||||
r.top += 13;
|
||||
r.bottom = r.top + 15;
|
||||
fFilename->SetFont(&font, B_FONT_SIZE);
|
||||
fFilename->SetHighColor(ui_color(B_PANEL_TEXT_COLOR));
|
||||
|
||||
r.top += fontHeight;
|
||||
r.bottom = r.top + fontHeight + 3;
|
||||
fFormat = new BStringView(r, "format", B_TRANSLATE("Format:"));
|
||||
fFileInfoBox->AddChild(fFormat);
|
||||
r.top += 13;
|
||||
r.bottom = r.top + 15;
|
||||
fFormat->SetFont(&font, B_FONT_SIZE);
|
||||
fFormat->SetHighColor(ui_color(B_PANEL_TEXT_COLOR));
|
||||
|
||||
r.top += fontHeight;
|
||||
r.bottom = r.top + fontHeight + 3;
|
||||
fCompression = new BStringView(r, "compression",
|
||||
B_TRANSLATE("Compression:"));
|
||||
fFileInfoBox->AddChild(fCompression);
|
||||
r.top += 13;
|
||||
r.bottom = r.top + 15;
|
||||
fCompression->SetFont(&font, B_FONT_SIZE);
|
||||
fCompression->SetHighColor(ui_color(B_PANEL_TEXT_COLOR));
|
||||
|
||||
r.top += fontHeight;
|
||||
r.bottom = r.top + fontHeight + 3;
|
||||
fChannels = new BStringView(r, "channels", B_TRANSLATE("Channels:"));
|
||||
fFileInfoBox->AddChild(fChannels);
|
||||
r.top += 13;
|
||||
r.bottom = r.top + 15;
|
||||
fChannels->SetFont(&font, B_FONT_SIZE);
|
||||
fChannels->SetHighColor(ui_color(B_PANEL_TEXT_COLOR));
|
||||
|
||||
r.top += fontHeight;
|
||||
r.bottom = r.top + fontHeight + 3;
|
||||
fSampleSize = new BStringView(r, "samplesize",
|
||||
B_TRANSLATE("Sample size:"));
|
||||
fFileInfoBox->AddChild(fSampleSize);
|
||||
r.top += 13;
|
||||
r.bottom = r.top + 15;
|
||||
fSampleSize->SetFont(&font, B_FONT_SIZE);
|
||||
fSampleSize->SetHighColor(ui_color(B_PANEL_TEXT_COLOR));
|
||||
|
||||
r.top += fontHeight;
|
||||
r.bottom = r.top + fontHeight + 3;
|
||||
fSampleRate = new BStringView(r, "samplerate",
|
||||
B_TRANSLATE("Sample rate:"));
|
||||
fFileInfoBox->AddChild(fSampleRate);
|
||||
r.top += 13;
|
||||
r.bottom = r.top + 15;
|
||||
fSampleRate->SetFont(&font, B_FONT_SIZE);
|
||||
fSampleRate->SetHighColor(ui_color(B_PANEL_TEXT_COLOR));
|
||||
|
||||
r.top += fontHeight;
|
||||
r.bottom = r.top + fontHeight + 3;
|
||||
fDuration = new BStringView(r, "duration", B_TRANSLATE("Duration:"));
|
||||
fFileInfoBox->AddChild(fDuration);
|
||||
fDuration->SetFont(&font, B_FONT_SIZE);
|
||||
fDuration->SetHighColor(ui_color(B_PANEL_TEXT_COLOR));
|
||||
|
||||
fFileInfoBox->ResizeTo(fFileInfoBox->Frame().Width(),
|
||||
r.bottom + fontHeight / 2.0f);
|
||||
fDeployedHeight = MIN_HEIGHT + fFileInfoBox->Bounds().Height() + 40.0f;
|
||||
|
||||
// Input selection lists all available physical inputs that produce
|
||||
// buffers with B_MEDIA_RAW_AUDIO format data.
|
||||
@@ -451,12 +483,10 @@ RecorderWindow::InitWindow()
|
||||
}
|
||||
|
||||
// Create the actual widget
|
||||
BRect frame(fBottomBox->Bounds());
|
||||
r = frame;
|
||||
r.left = 42;
|
||||
r.right = (r.left + r.right) / 2;
|
||||
r = fFileInfoBox->Bounds();
|
||||
r.top = r.bottom + 2;
|
||||
r.bottom = r.top + 18;
|
||||
r.InsetBy(10, 10);
|
||||
r.top = r.bottom - 18;
|
||||
fInputField = new BMenuField(r, "Input", B_TRANSLATE("Input:"), popup);
|
||||
fInputField->SetDivider(fInputField->StringWidth(B_TRANSLATE("Input:"))
|
||||
+ 4.0f);
|
||||
@@ -465,9 +495,8 @@ RecorderWindow::InitWindow()
|
||||
fBottomBox->AddChild(fFileInfoBox);
|
||||
|
||||
fBottomBox->Hide();
|
||||
CalcSizes(Frame().Width(), MIN_HEIGHT-161);
|
||||
ResizeTo(Frame().Width(), MIN_HEIGHT-161);
|
||||
|
||||
CalcSizes(MIN_WIDTH, MIN_HEIGHT);
|
||||
ResizeTo(Frame().Width(), MIN_HEIGHT);
|
||||
|
||||
popup->Superitem()->SetLabel(selected_name);
|
||||
|
||||
@@ -551,12 +580,12 @@ RecorderWindow::MessageReceived(BMessage * message)
|
||||
case VIEW_LIST:
|
||||
if (fUpDownButton->Value() == B_CONTROL_ON) {
|
||||
fBottomBox->Show();
|
||||
CalcSizes(Frame().Width(), MIN_HEIGHT);
|
||||
ResizeTo(Frame().Width(), MIN_HEIGHT);
|
||||
CalcSizes(MIN_WIDTH, fDeployedHeight);
|
||||
ResizeTo(Frame().Width(), fDeployedHeight);
|
||||
} else {
|
||||
fBottomBox->Hide();
|
||||
CalcSizes(Frame().Width(), MIN_HEIGHT-161);
|
||||
ResizeTo(Frame().Width(), MIN_HEIGHT-161);
|
||||
CalcSizes(MIN_WIDTH, MIN_HEIGHT);
|
||||
ResizeTo(Frame().Width(), MIN_HEIGHT);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -94,6 +94,8 @@ private:
|
||||
BDirectory fTempDir;
|
||||
int fTempCount;
|
||||
|
||||
float fDeployedHeight;
|
||||
|
||||
BBox * fBottomBox;
|
||||
BBox * fFileInfoBox;
|
||||
BStringView *fFilename;
|
||||
|
||||
@@ -34,12 +34,11 @@ void
|
||||
SoundListView::Draw(BRect updateRect)
|
||||
{
|
||||
if (IsEmpty()) {
|
||||
SetHighColor(235,235,235);
|
||||
FillRect(Bounds());
|
||||
SetLowColor(ViewColor());
|
||||
FillRect(Bounds(), B_SOLID_LOW);
|
||||
|
||||
SetHighColor(0,0,0);
|
||||
SetHighColor(ui_color(B_PANEL_TEXT_COLOR));
|
||||
BFont font(be_bold_font);
|
||||
font.SetSize(12.0);
|
||||
SetFont(&font);
|
||||
font_height height;
|
||||
font.GetHeight(&height);
|
||||
@@ -58,7 +57,8 @@ void
|
||||
SoundListView::AttachedToWindow()
|
||||
{
|
||||
BListView::AttachedToWindow();
|
||||
SetViewColor(255,255,255);
|
||||
SetViewColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR),
|
||||
B_LIGHTEN_1_TINT));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -890,7 +890,7 @@ SudokuView::MouseDown(BPoint where)
|
||||
}
|
||||
|
||||
if (value + 1 != fValueHintValue)
|
||||
_SetValueHintValue(~0UL);
|
||||
_SetValueHintValue(value + 1);
|
||||
|
||||
if (wasCompleted != fField->IsValueCompleted(value + 1))
|
||||
_InvalidateValue(value + 1, false, x, y);
|
||||
|
||||
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "AuthenticationPanel.h"
|
||||
|
||||
#include <Button.h>
|
||||
#include <CheckBox.h>
|
||||
#include <ControlLook.h>
|
||||
#include <GridLayoutBuilder.h>
|
||||
#include <GroupLayoutBuilder.h>
|
||||
#include <Message.h>
|
||||
#include <Screen.h>
|
||||
#include <SeparatorView.h>
|
||||
#include <SpaceLayoutItem.h>
|
||||
#include <StringView.h>
|
||||
#include <TextControl.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static const uint32 kMsgPanelOK = 'pnok';
|
||||
static const uint32 kMsgJitter = 'jitr';
|
||||
static const uint32 kHidePassword = 'hdpw';
|
||||
|
||||
AuthenticationPanel::AuthenticationPanel(BRect parentFrame)
|
||||
: BWindow(BRect(-1000, -1000, -900, -900), "Authentication Required",
|
||||
B_TITLED_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL,
|
||||
B_ASYNCHRONOUS_CONTROLS | B_NOT_RESIZABLE | B_NOT_ZOOMABLE
|
||||
| B_CLOSE_ON_ESCAPE | B_AUTO_UPDATE_SIZE_LIMITS)
|
||||
, m_parentWindowFrame(parentFrame)
|
||||
, m_usernameTextControl(new BTextControl("user", "Username:", "", NULL))
|
||||
, m_passwordTextControl(new BTextControl("pass", "Password:", "", NULL))
|
||||
, m_hidePasswordCheckBox(new BCheckBox("hide", "Hide password text", new BMessage(kHidePassword)))
|
||||
, m_rememberCredentialsCheckBox(new BCheckBox("remember", "Remember username and password for this site", NULL))
|
||||
, m_okButton(new BButton("ok", "OK", new BMessage(kMsgPanelOK)))
|
||||
, m_cancelButton(new BButton("cancel", "Cancel", new BMessage(B_QUIT_REQUESTED)))
|
||||
, m_cancelled(false)
|
||||
, m_exitSemaphore(create_sem(0, "Authentication Panel"))
|
||||
{
|
||||
}
|
||||
|
||||
AuthenticationPanel::~AuthenticationPanel()
|
||||
{
|
||||
delete_sem(m_exitSemaphore);
|
||||
}
|
||||
|
||||
bool
|
||||
AuthenticationPanel::QuitRequested()
|
||||
{
|
||||
m_cancelled = true;
|
||||
release_sem(m_exitSemaphore);
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
AuthenticationPanel::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch (message->what) {
|
||||
case kMsgPanelOK:
|
||||
release_sem(m_exitSemaphore);
|
||||
break;
|
||||
case kHidePassword: {
|
||||
// TODO: Toggling this is broken in BTextView. Workaround is to
|
||||
// set the text and selection again.
|
||||
BString text = m_passwordTextControl->Text();
|
||||
int32 selectionStart;
|
||||
int32 selectionEnd;
|
||||
m_passwordTextControl->TextView()->GetSelection(&selectionStart, &selectionEnd);
|
||||
m_passwordTextControl->TextView()->HideTyping(
|
||||
m_hidePasswordCheckBox->Value() == B_CONTROL_ON);
|
||||
m_passwordTextControl->SetText(text.String());
|
||||
m_passwordTextControl->TextView()->Select(selectionStart, selectionEnd);
|
||||
break;
|
||||
}
|
||||
case kMsgJitter: {
|
||||
UpdateIfNeeded();
|
||||
BPoint leftTop = Frame().LeftTop();
|
||||
const float jitterOffsets[] = { -10, 0, 10, 0 };
|
||||
const int32 jitterOffsetCount = sizeof(jitterOffsets) / sizeof(float);
|
||||
for (int32 i = 0; i < 20; i++) {
|
||||
float offset = jitterOffsets[i % jitterOffsetCount];
|
||||
MoveTo(leftTop.x + offset, leftTop.y);
|
||||
snooze(15000);
|
||||
}
|
||||
MoveTo(leftTop);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
BWindow::MessageReceived(message);
|
||||
}
|
||||
}
|
||||
|
||||
bool AuthenticationPanel::getAuthentication(const BString& text,
|
||||
const BString& previousUser, const BString& previousPass,
|
||||
bool previousRememberCredentials, bool badPassword,
|
||||
BString& user, BString& pass, bool* rememberCredentials)
|
||||
{
|
||||
// Configure panel and layout controls.
|
||||
rgb_color infoColor = ui_color(B_PANEL_TEXT_COLOR);
|
||||
BRect textBounds(0, 0, 250, 200);
|
||||
BTextView* textView = new BTextView(textBounds, "text", textBounds,
|
||||
be_plain_font, &infoColor, B_FOLLOW_NONE, B_WILL_DRAW | B_SUPPORTS_LAYOUT);
|
||||
textView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||
textView->SetText(text.String());
|
||||
textView->MakeEditable(false);
|
||||
textView->MakeSelectable(false);
|
||||
|
||||
m_usernameTextControl->SetText(previousUser.String());
|
||||
m_passwordTextControl->TextView()->HideTyping(true);
|
||||
// Ignore the previous password, if it didn't work.
|
||||
if (!badPassword)
|
||||
m_passwordTextControl->SetText(previousPass.String());
|
||||
m_hidePasswordCheckBox->SetValue(B_CONTROL_ON);
|
||||
m_rememberCredentialsCheckBox->SetValue(previousRememberCredentials);
|
||||
|
||||
// create layout
|
||||
SetLayout(new BGroupLayout(B_VERTICAL, 0.0));
|
||||
float spacing = be_control_look->DefaultItemSpacing();
|
||||
AddChild(BGroupLayoutBuilder(B_VERTICAL, 0.0)
|
||||
.Add(BGridLayoutBuilder(0, spacing)
|
||||
.Add(textView, 0, 0, 2)
|
||||
.Add(m_usernameTextControl->CreateLabelLayoutItem(), 0, 1)
|
||||
.Add(m_usernameTextControl->CreateTextViewLayoutItem(), 1, 1)
|
||||
.Add(m_passwordTextControl->CreateLabelLayoutItem(), 0, 2)
|
||||
.Add(m_passwordTextControl->CreateTextViewLayoutItem(), 1, 2)
|
||||
.Add(BSpaceLayoutItem::CreateGlue(), 0, 3)
|
||||
.Add(m_hidePasswordCheckBox, 1, 3)
|
||||
.Add(m_rememberCredentialsCheckBox, 0, 4, 2)
|
||||
.SetInsets(spacing, spacing, spacing, spacing)
|
||||
)
|
||||
.Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER))
|
||||
.Add(BGroupLayoutBuilder(B_HORIZONTAL, spacing)
|
||||
.AddGlue()
|
||||
.Add(m_cancelButton)
|
||||
.Add(m_okButton)
|
||||
.SetInsets(spacing, spacing, spacing, spacing)
|
||||
)
|
||||
);
|
||||
|
||||
float textHeight = textView->LineHeight(0) * textView->CountLines();
|
||||
textView->SetExplicitMinSize(BSize(B_SIZE_UNSET, textHeight));
|
||||
|
||||
SetDefaultButton(m_okButton);
|
||||
if (badPassword && previousUser.Length())
|
||||
m_passwordTextControl->MakeFocus(true);
|
||||
else
|
||||
m_usernameTextControl->MakeFocus(true);
|
||||
|
||||
if (m_parentWindowFrame.IsValid())
|
||||
CenterIn(m_parentWindowFrame);
|
||||
else
|
||||
CenterOnScreen();
|
||||
|
||||
// Start AuthenticationPanel window thread
|
||||
Show();
|
||||
|
||||
// Let the window jitter, if the previous password was invalid
|
||||
if (badPassword)
|
||||
PostMessage(kMsgJitter);
|
||||
|
||||
// Block calling thread
|
||||
// Get the originating window, if it exists, to let it redraw itself.
|
||||
BWindow* window = dynamic_cast<BWindow*>(BLooper::LooperForThread(find_thread(NULL)));
|
||||
if (window) {
|
||||
status_t err;
|
||||
for (;;) {
|
||||
do {
|
||||
err = acquire_sem_etc(m_exitSemaphore, 1, B_RELATIVE_TIMEOUT, 10000);
|
||||
// We've (probably) had our time slice taken away from us
|
||||
} while (err == B_INTERRUPTED);
|
||||
|
||||
if (err != B_TIMED_OUT) {
|
||||
// Semaphore was finally released or nuked.
|
||||
break;
|
||||
}
|
||||
window->UpdateIfNeeded();
|
||||
}
|
||||
} else {
|
||||
// No window to update, so just hang out until we're done.
|
||||
while (acquire_sem(m_exitSemaphore) == B_INTERRUPTED) {
|
||||
}
|
||||
}
|
||||
|
||||
// AuthenticationPanel wants to quit.
|
||||
Lock();
|
||||
|
||||
user = m_usernameTextControl->Text();
|
||||
pass = m_passwordTextControl->Text();
|
||||
if (rememberCredentials)
|
||||
*rememberCredentials = m_rememberCredentialsCheckBox->Value() == B_CONTROL_ON;
|
||||
|
||||
bool canceled = m_cancelled;
|
||||
Quit();
|
||||
// AuthenticationPanel object is TOAST here.
|
||||
return !canceled;
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef AuthenticationPanel_h
|
||||
#define AuthenticationPanel_h
|
||||
|
||||
#include <String.h>
|
||||
#include <Window.h>
|
||||
|
||||
class BCheckBox;
|
||||
class BTextControl;
|
||||
|
||||
class AuthenticationPanel : public BWindow {
|
||||
public:
|
||||
AuthenticationPanel(BRect parentFrame = BRect());
|
||||
virtual ~AuthenticationPanel();
|
||||
|
||||
virtual bool QuitRequested();
|
||||
|
||||
virtual void MessageReceived(BMessage *message);
|
||||
|
||||
bool getAuthentication(const BString& text, const BString& previousUser,
|
||||
const BString& previousPass, bool previousRememberCredentials,
|
||||
bool badPassword, BString& user, BString& pass,
|
||||
bool* rememberCredentials);
|
||||
|
||||
private:
|
||||
BRect m_parentWindowFrame;
|
||||
BTextControl* m_usernameTextControl;
|
||||
BTextControl* m_passwordTextControl;
|
||||
BCheckBox* m_hidePasswordCheckBox;
|
||||
BCheckBox* m_rememberCredentialsCheckBox;
|
||||
BButton* m_okButton;
|
||||
BButton* m_cancelButton;
|
||||
|
||||
bool m_cancelled;
|
||||
|
||||
sem_id m_exitSemaphore;
|
||||
};
|
||||
|
||||
#endif // AuthenticationPanel_h
|
||||
@@ -0,0 +1,449 @@
|
||||
/*
|
||||
* Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
|
||||
* Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "BrowserApp.h"
|
||||
|
||||
#include "BrowserWindow.h"
|
||||
#include "BrowsingHistory.h"
|
||||
#include "DownloadWindow.h"
|
||||
#include "SettingsMessage.h"
|
||||
#include "SettingsWindow.h"
|
||||
#include "svn_revision.h"
|
||||
#include "NetworkCookieJar.h"
|
||||
#include "WebPage.h"
|
||||
#include "WebSettings.h"
|
||||
#include "WebView.h"
|
||||
#include <Alert.h>
|
||||
#include <Autolock.h>
|
||||
#include <Directory.h>
|
||||
#include <Entry.h>
|
||||
#include <FindDirectory.h>
|
||||
#include <Locale.h>
|
||||
#include <Path.h>
|
||||
#include <Screen.h>
|
||||
#include <debugger.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
const char* kApplicationSignature = "application/x-vnd.Haiku-WebPositive";
|
||||
const char* kApplicationName = "WebPositive";
|
||||
static const uint32 PRELOAD_BROWSING_HISTORY = 'plbh';
|
||||
|
||||
#define ENABLE_NATIVE_COOKIES 0
|
||||
|
||||
|
||||
BrowserApp::BrowserApp()
|
||||
:
|
||||
BApplication(kApplicationSignature),
|
||||
fWindowCount(0),
|
||||
fLastWindowFrame(50, 50, 950, 750),
|
||||
fLaunchRefsMessage(0),
|
||||
fInitialized(false),
|
||||
fSettings(NULL),
|
||||
fCookies(NULL),
|
||||
fCookieJar(NULL),
|
||||
fDownloadWindow(NULL),
|
||||
fSettingsWindow(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BrowserApp::~BrowserApp()
|
||||
{
|
||||
delete fLaunchRefsMessage;
|
||||
delete fSettings;
|
||||
delete fCookies;
|
||||
delete fCookieJar;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BrowserApp::AboutRequested()
|
||||
{
|
||||
BString aboutText("WebPositive\n\nby Ryan Leavengood, Andrea Anzani, "
|
||||
"Maxime Simon, Michael Lotz, Rene Gollent and Stephan Aßmus");
|
||||
aboutText << "\n\nSVN revision: " << kSVNRevision;
|
||||
|
||||
BAlert* alert = new BAlert("About WebPositive", aboutText.String(),
|
||||
"Sweet!");
|
||||
alert->Go(NULL);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BrowserApp::ArgvReceived(int32 argc, char** argv)
|
||||
{
|
||||
BMessage message(B_REFS_RECEIVED);
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (strcmp("-f", argv[i]) == 0
|
||||
|| strcmp("--fullscreen", argv[i]) == 0) {
|
||||
message.AddBool("fullscreen", true);
|
||||
continue;
|
||||
}
|
||||
const char* url = argv[i];
|
||||
BEntry entry(argv[i], true);
|
||||
BPath path;
|
||||
if (entry.Exists() && entry.GetPath(&path) == B_OK)
|
||||
url = path.Path();
|
||||
message.AddString("url", url);
|
||||
}
|
||||
// Upon program launch, it will buffer a copy of the message, since
|
||||
// ArgReceived() is called before ReadyToRun().
|
||||
RefsReceived(&message);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BrowserApp::ReadyToRun()
|
||||
{
|
||||
// Since we will essentially run the GUI...
|
||||
set_thread_priority(Thread(), B_DISPLAY_PRIORITY);
|
||||
|
||||
BWebPage::InitializeOnce();
|
||||
BWebPage::SetCacheModel(B_WEBKIT_CACHE_MODEL_WEB_BROWSER);
|
||||
|
||||
BPath path;
|
||||
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK
|
||||
&& path.Append(kApplicationName) == B_OK
|
||||
&& create_directory(path.Path(), 0777) == B_OK) {
|
||||
|
||||
BWebSettings::SetPersistentStoragePath(path.Path());
|
||||
}
|
||||
|
||||
BString mainSettingsPath(kApplicationName);
|
||||
mainSettingsPath << "/Application";
|
||||
fSettings = new SettingsMessage(B_USER_SETTINGS_DIRECTORY,
|
||||
mainSettingsPath.String());
|
||||
#if ENABLE_NATIVE_COOKIES
|
||||
mainSettingsPath = kApplicationName;
|
||||
mainSettingsPath << "/Cookies";
|
||||
fCookies = new SettingsMessage(B_USER_SETTINGS_DIRECTORY,
|
||||
mainSettingsPath.String());
|
||||
BMessage cookieArchive;
|
||||
cookieArchive = fCookies->GetValue("cookies", cookieArchive);
|
||||
fCookieJar = new BNetworkCookieJar(cookieArchive);
|
||||
BWebPage::SetCookieJar(fCookieJar);
|
||||
#endif
|
||||
|
||||
fLastWindowFrame = fSettings->GetValue("window frame", fLastWindowFrame);
|
||||
BRect defaultDownloadWindowFrame(-10, -10, 365, 265);
|
||||
BRect downloadWindowFrame = fSettings->GetValue("downloads window frame",
|
||||
defaultDownloadWindowFrame);
|
||||
BRect settingsWindowFrame = fSettings->GetValue("settings window frame",
|
||||
BRect());
|
||||
bool showDownloads = fSettings->GetValue("show downloads", false);
|
||||
|
||||
fDownloadWindow = new DownloadWindow(downloadWindowFrame, showDownloads,
|
||||
fSettings);
|
||||
if (downloadWindowFrame == defaultDownloadWindowFrame) {
|
||||
// Initially put download window in lower right of screen.
|
||||
BRect screenFrame = BScreen().Frame();
|
||||
BMessage decoratorSettings;
|
||||
fDownloadWindow->GetDecoratorSettings(&decoratorSettings);
|
||||
float borderWidth = 0;
|
||||
if (decoratorSettings.FindFloat("border width", &borderWidth) != B_OK)
|
||||
borderWidth = 5;
|
||||
fDownloadWindow->MoveTo(screenFrame.Width() - fDownloadWindow->Frame().Width() - borderWidth,
|
||||
screenFrame.Height() - fDownloadWindow->Frame().Height() - borderWidth);
|
||||
}
|
||||
fSettingsWindow = new SettingsWindow(settingsWindowFrame, fSettings);
|
||||
|
||||
BWebPage::SetDownloadListener(BMessenger(fDownloadWindow));
|
||||
|
||||
fInitialized = true;
|
||||
|
||||
int32 pagesCreated = 0;
|
||||
bool fullscreen = false;
|
||||
if (fLaunchRefsMessage) {
|
||||
_RefsReceived(fLaunchRefsMessage, &pagesCreated, &fullscreen);
|
||||
delete fLaunchRefsMessage;
|
||||
fLaunchRefsMessage = NULL;
|
||||
}
|
||||
if (pagesCreated == 0)
|
||||
_CreateNewWindow("", fullscreen);
|
||||
|
||||
PostMessage(PRELOAD_BROWSING_HISTORY);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BrowserApp::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch (message->what) {
|
||||
case PRELOAD_BROWSING_HISTORY:
|
||||
// Accessing the default instance will load the history from disk.
|
||||
BrowsingHistory::DefaultInstance();
|
||||
break;
|
||||
case B_SILENT_RELAUNCH:
|
||||
_CreateNewPage("");
|
||||
break;
|
||||
case NEW_WINDOW: {
|
||||
BString url;
|
||||
if (message->FindString("url", &url) != B_OK)
|
||||
break;
|
||||
_CreateNewWindow(url);
|
||||
break;
|
||||
}
|
||||
case NEW_TAB: {
|
||||
BrowserWindow* window;
|
||||
if (message->FindPointer("window", reinterpret_cast<void**>(&window)) != B_OK)
|
||||
break;
|
||||
BString url;
|
||||
message->FindString("url", &url);
|
||||
bool select = false;
|
||||
message->FindBool("select", &select);
|
||||
_CreateNewTab(window, url, select);
|
||||
break;
|
||||
}
|
||||
case WINDOW_OPENED:
|
||||
fWindowCount++;
|
||||
fDownloadWindow->SetMinimizeOnClose(false);
|
||||
break;
|
||||
case WINDOW_CLOSED:
|
||||
fWindowCount--;
|
||||
message->FindRect("window frame", &fLastWindowFrame);
|
||||
if (fWindowCount <= 0)
|
||||
PostMessage(B_QUIT_REQUESTED);
|
||||
break;
|
||||
|
||||
case SHOW_DOWNLOAD_WINDOW:
|
||||
_ShowWindow(message, fDownloadWindow);
|
||||
break;
|
||||
case SHOW_SETTINGS_WINDOW:
|
||||
_ShowWindow(message, fSettingsWindow);
|
||||
break;
|
||||
|
||||
default:
|
||||
BApplication::MessageReceived(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BrowserApp::RefsReceived(BMessage* message)
|
||||
{
|
||||
if (!fInitialized) {
|
||||
delete fLaunchRefsMessage;
|
||||
fLaunchRefsMessage = new BMessage(*message);
|
||||
return;
|
||||
}
|
||||
|
||||
_RefsReceived(message);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BrowserApp::QuitRequested()
|
||||
{
|
||||
if (fDownloadWindow->DownloadsInProgress()) {
|
||||
BAlert* alert = new BAlert("Downloads in progress",
|
||||
"There are still downloads in progress, do you really want to "
|
||||
"quit WebPositive now?", "Quit", "Continue downloads");
|
||||
int32 choice = alert->Go();
|
||||
if (choice == 1) {
|
||||
if (fWindowCount == 0) {
|
||||
if (fDownloadWindow->Lock()) {
|
||||
fDownloadWindow->SetWorkspaces(1 << current_workspace());
|
||||
if (fDownloadWindow->IsHidden())
|
||||
fDownloadWindow->Show();
|
||||
else
|
||||
fDownloadWindow->Activate();
|
||||
fDownloadWindow->SetMinimizeOnClose(true);
|
||||
fDownloadWindow->Unlock();
|
||||
return false;
|
||||
}
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; BWindow* window = WindowAt(i); i++) {
|
||||
BrowserWindow* webWindow = dynamic_cast<BrowserWindow*>(window);
|
||||
if (!webWindow)
|
||||
continue;
|
||||
if (!webWindow->Lock())
|
||||
continue;
|
||||
if (webWindow->QuitRequested()) {
|
||||
fLastWindowFrame = webWindow->WindowFrame();
|
||||
webWindow->Quit();
|
||||
i--;
|
||||
} else {
|
||||
webWindow->Unlock();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
BWebPage::ShutdownOnce();
|
||||
|
||||
fSettings->SetValue("window frame", fLastWindowFrame);
|
||||
if (fDownloadWindow->Lock()) {
|
||||
fSettings->SetValue("downloads window frame", fDownloadWindow->Frame());
|
||||
fSettings->SetValue("show downloads", !fDownloadWindow->IsHidden());
|
||||
fDownloadWindow->Unlock();
|
||||
}
|
||||
if (fSettingsWindow->Lock()) {
|
||||
fSettings->SetValue("settings window frame", fSettingsWindow->Frame());
|
||||
fSettingsWindow->Unlock();
|
||||
}
|
||||
|
||||
BMessage cookieArchive;
|
||||
if (fCookieJar != NULL && fCookieJar->Archive(&cookieArchive) == B_OK)
|
||||
fCookies->SetValue("cookies", cookieArchive);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BrowserApp::_RefsReceived(BMessage* message, int32* _pagesCreated,
|
||||
bool* _fullscreen)
|
||||
{
|
||||
int32 pagesCreated = 0;
|
||||
|
||||
bool fullscreen;
|
||||
if (message->FindBool("fullscreen", &fullscreen) != B_OK)
|
||||
fullscreen = false;
|
||||
|
||||
entry_ref ref;
|
||||
for (int32 i = 0; message->FindRef("refs", i, &ref) == B_OK; i++) {
|
||||
BEntry entry(&ref, true);
|
||||
if (!entry.Exists())
|
||||
continue;
|
||||
BPath path;
|
||||
if (entry.GetPath(&path) != B_OK)
|
||||
continue;
|
||||
BString url;
|
||||
url << path.Path();
|
||||
_CreateNewPage(url, fullscreen);
|
||||
pagesCreated++;
|
||||
}
|
||||
|
||||
BString url;
|
||||
for (int32 i = 0; message->FindString("url", i, &url) == B_OK; i++) {
|
||||
_CreateNewPage(url, fullscreen);
|
||||
pagesCreated++;
|
||||
}
|
||||
|
||||
if (_pagesCreated != NULL)
|
||||
*_pagesCreated = pagesCreated;
|
||||
if (_fullscreen != NULL)
|
||||
*_fullscreen = fullscreen;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BrowserApp::_CreateNewPage(const BString& url, bool fullscreen)
|
||||
{
|
||||
uint32 workspace = 1 << current_workspace();
|
||||
|
||||
bool loadedInWindowOnCurrentWorkspace = false;
|
||||
for (int i = 0; BWindow* window = WindowAt(i); i++) {
|
||||
BrowserWindow* webWindow = dynamic_cast<BrowserWindow*>(window);
|
||||
if (!webWindow)
|
||||
continue;
|
||||
if (webWindow->Lock()) {
|
||||
if (webWindow->Workspaces() & workspace) {
|
||||
if (webWindow->IsBlankTab()) {
|
||||
if (url.Length() != 0)
|
||||
webWindow->CurrentWebView()->LoadURL(url);
|
||||
} else
|
||||
webWindow->CreateNewTab(url, true);
|
||||
webWindow->Activate();
|
||||
webWindow->CurrentWebView()->MakeFocus(true);
|
||||
loadedInWindowOnCurrentWorkspace = true;
|
||||
}
|
||||
webWindow->Unlock();
|
||||
}
|
||||
if (loadedInWindowOnCurrentWorkspace)
|
||||
return;
|
||||
}
|
||||
_CreateNewWindow(url, fullscreen);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BrowserApp::_CreateNewWindow(const BString& url, bool fullscreen)
|
||||
{
|
||||
// Offset the window frame unless this is the first window created in the
|
||||
// session.
|
||||
if (fWindowCount > 0)
|
||||
fLastWindowFrame.OffsetBy(20, 20);
|
||||
if (!BScreen().Frame().Contains(fLastWindowFrame))
|
||||
fLastWindowFrame.OffsetTo(50, 50);
|
||||
|
||||
BrowserWindow* window = new BrowserWindow(fLastWindowFrame, fSettings,
|
||||
url);
|
||||
if (fullscreen)
|
||||
window->ToggleFullscreen();
|
||||
window->Show();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BrowserApp::_CreateNewTab(BrowserWindow* window, const BString& url,
|
||||
bool select)
|
||||
{
|
||||
if (!window->Lock())
|
||||
return;
|
||||
window->CreateNewTab(url, select);
|
||||
window->Unlock();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BrowserApp::_ShowWindow(const BMessage* message, BWindow* window)
|
||||
{
|
||||
BAutolock _(window);
|
||||
uint32 workspaces;
|
||||
if (message->FindUInt32("workspaces", &workspaces) == B_OK)
|
||||
window->SetWorkspaces(workspaces);
|
||||
if (window->IsHidden())
|
||||
window->Show();
|
||||
else
|
||||
window->Activate();
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
int
|
||||
main(int, char**)
|
||||
{
|
||||
try {
|
||||
new BrowserApp();
|
||||
be_app->Run();
|
||||
delete be_app;
|
||||
} catch (...) {
|
||||
debugger("Exception caught.");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
|
||||
* Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef BROWSER_APP_H
|
||||
#define BROWSER_APP_H
|
||||
|
||||
|
||||
#include <Application.h>
|
||||
#include <Catalog.h>
|
||||
#include <Rect.h>
|
||||
|
||||
class BNetworkCookieJar;
|
||||
class DownloadWindow;
|
||||
class BrowserWindow;
|
||||
class SettingsMessage;
|
||||
class SettingsWindow;
|
||||
|
||||
|
||||
class BrowserApp : public BApplication {
|
||||
public:
|
||||
BrowserApp();
|
||||
virtual ~BrowserApp();
|
||||
|
||||
virtual void AboutRequested();
|
||||
virtual void ArgvReceived(int32 agrc, char** argv);
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
virtual void RefsReceived(BMessage* message);
|
||||
virtual void ReadyToRun();
|
||||
virtual bool QuitRequested();
|
||||
|
||||
private:
|
||||
void _RefsReceived(BMessage* message,
|
||||
int32* pagesCreated = NULL,
|
||||
bool* fullscreen = NULL);
|
||||
void _CreateNewPage(const BString& url,
|
||||
bool fullscreen = false);
|
||||
void _CreateNewWindow(const BString& url,
|
||||
bool fullscreen = false);
|
||||
void _CreateNewTab(BrowserWindow* window,
|
||||
const BString& url, bool select);
|
||||
void _ShowWindow(const BMessage* message,
|
||||
BWindow* window);
|
||||
|
||||
private:
|
||||
int fWindowCount;
|
||||
BRect fLastWindowFrame;
|
||||
BMessage* fLaunchRefsMessage;
|
||||
bool fInitialized;
|
||||
|
||||
SettingsMessage* fSettings;
|
||||
SettingsMessage* fCookies;
|
||||
BNetworkCookieJar* fCookieJar;
|
||||
|
||||
DownloadWindow* fDownloadWindow;
|
||||
SettingsWindow* fSettingsWindow;
|
||||
};
|
||||
|
||||
|
||||
extern const char* kApplicationSignature;
|
||||
extern const char* kApplicationName;
|
||||
|
||||
|
||||
#endif // BROWSER_APP_H
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
|
||||
* Copyright (C) 2009 Maxime Simon <simon.maxime@gmail.com>
|
||||
* Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef BROWSER_WINDOW_H
|
||||
#define BROWSER_WINDOW_H
|
||||
|
||||
|
||||
#include "WebWindow.h"
|
||||
#include <Messenger.h>
|
||||
#include <String.h>
|
||||
|
||||
class BButton;
|
||||
class BCheckBox;
|
||||
class BDirectory;
|
||||
class BFile;
|
||||
class BLayoutItem;
|
||||
class BMenu;
|
||||
class BMenuItem;
|
||||
class BMessageRunner;
|
||||
class BPath;
|
||||
class BStatusBar;
|
||||
class BStringView;
|
||||
class BTextControl;
|
||||
class BWebView;
|
||||
class IconButton;
|
||||
class SettingsMessage;
|
||||
class TabManager;
|
||||
class URLInputGroup;
|
||||
|
||||
enum {
|
||||
INTERFACE_ELEMENT_MENU = 1 << 0,
|
||||
INTERFACE_ELEMENT_TABS = 1 << 1,
|
||||
INTERFACE_ELEMENT_NAVIGATION = 1 << 2,
|
||||
INTERFACE_ELEMENT_STATUS = 1 << 3,
|
||||
|
||||
INTERFACE_ELEMENT_ALL = 0xffff
|
||||
};
|
||||
|
||||
enum NewPagePolicy {
|
||||
OpenBlankPage = 0,
|
||||
OpenStartPage = 1,
|
||||
OpenSearchPage = 2,
|
||||
CloneCurrentPage = 3
|
||||
};
|
||||
|
||||
enum {
|
||||
NEW_WINDOW = 'nwnd',
|
||||
NEW_TAB = 'ntab',
|
||||
WINDOW_OPENED = 'wndo',
|
||||
WINDOW_CLOSED = 'wndc',
|
||||
SHOW_DOWNLOAD_WINDOW = 'sdwd',
|
||||
SHOW_SETTINGS_WINDOW = 'sswd'
|
||||
};
|
||||
|
||||
#define INTEGRATE_MENU_INTO_TAB_BAR 0
|
||||
|
||||
|
||||
class BrowserWindow : public BWebWindow {
|
||||
public:
|
||||
BrowserWindow(BRect frame,
|
||||
SettingsMessage* appSettings,
|
||||
const BString& url,
|
||||
uint32 interfaceElements
|
||||
= INTERFACE_ELEMENT_ALL,
|
||||
BWebView* webView = NULL);
|
||||
virtual ~BrowserWindow();
|
||||
|
||||
virtual void DispatchMessage(BMessage* message,
|
||||
BHandler* target);
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
virtual bool QuitRequested();
|
||||
virtual void MenusBeginning();
|
||||
|
||||
virtual void Zoom(BPoint origin, float width, float height);
|
||||
virtual void ScreenChanged(BRect screenSize,
|
||||
color_space format);
|
||||
virtual void WorkspacesChanged(uint32 oldWorkspaces,
|
||||
uint32 newWorkspaces);
|
||||
|
||||
virtual void SetCurrentWebView(BWebView* view);
|
||||
|
||||
bool IsBlankTab() const;
|
||||
void CreateNewTab(const BString& url, bool select,
|
||||
BWebView* webView = 0);
|
||||
|
||||
BRect WindowFrame() const;
|
||||
|
||||
void ToggleFullscreen();
|
||||
|
||||
private:
|
||||
// WebPage notification API implementations
|
||||
virtual void NavigationRequested(const BString& url,
|
||||
BWebView* view);
|
||||
virtual void NewWindowRequested(const BString& url,
|
||||
bool primaryAction);
|
||||
virtual void CloseWindowRequested(BWebView* view);
|
||||
virtual void NewPageCreated(BWebView* view,
|
||||
BRect windowFrame, bool modalDialog,
|
||||
bool resizable, bool activate);
|
||||
virtual void LoadNegotiating(const BString& url,
|
||||
BWebView* view);
|
||||
virtual void LoadCommitted(const BString& url,
|
||||
BWebView* view);
|
||||
virtual void LoadProgress(float progress, BWebView* view);
|
||||
virtual void LoadFailed(const BString& url, BWebView* view);
|
||||
virtual void LoadFinished(const BString& url,
|
||||
BWebView* view);
|
||||
virtual void MainDocumentError(const BString& failingURL,
|
||||
const BString& localizedDescription,
|
||||
BWebView* view);
|
||||
virtual void TitleChanged(const BString& title,
|
||||
BWebView* view);
|
||||
virtual void IconReceived(const BBitmap* icon,
|
||||
BWebView* view);
|
||||
virtual void ResizeRequested(float width, float height,
|
||||
BWebView* view);
|
||||
virtual void SetToolBarsVisible(bool flag, BWebView* view);
|
||||
virtual void SetStatusBarVisible(bool flag, BWebView* view);
|
||||
virtual void SetMenuBarVisible(bool flag, BWebView* view);
|
||||
virtual void SetResizable(bool flag, BWebView* view);
|
||||
virtual void StatusChanged(const BString& status,
|
||||
BWebView* view);
|
||||
virtual void NavigationCapabilitiesChanged(
|
||||
bool canGoBackward, bool canGoForward,
|
||||
bool canStop, BWebView* view);
|
||||
virtual void UpdateGlobalHistory(const BString& url);
|
||||
virtual bool AuthenticationChallenge(BString message,
|
||||
BString& inOutUser, BString& inOutPassword,
|
||||
bool& inOutRememberCredentials,
|
||||
uint32 failureCount, BWebView* view);
|
||||
|
||||
private:
|
||||
void _UpdateTitle(const BString &title);
|
||||
void _UpdateTabGroupVisibility();
|
||||
bool _TabGroupShouldBeVisible() const;
|
||||
void _ShutdownTab(int32 index);
|
||||
void _TabChanged(int32 index);
|
||||
|
||||
status_t _BookmarkPath(BPath& path) const;
|
||||
void _CreateBookmark();
|
||||
void _ShowBookmarks();
|
||||
bool _CheckBookmarkExists(BDirectory& directory,
|
||||
const BString& fileName,
|
||||
const BString& url) const;
|
||||
bool _ReadURLAttr(BFile& bookmarkFile,
|
||||
BString& url) const;
|
||||
void _AddBookmarkURLsRecursively(
|
||||
BDirectory& directory,
|
||||
BMessage* message,
|
||||
uint32& addedCount) const;
|
||||
|
||||
void _SetPageIcon(BWebView* view,
|
||||
const BBitmap* icon);
|
||||
|
||||
void _UpdateHistoryMenu();
|
||||
void _UpdateClipboardItems();
|
||||
|
||||
bool _ShowPage(BWebView* view);
|
||||
|
||||
void _ToggleFullscreen();
|
||||
void _ResizeToScreen();
|
||||
void _SetAutoHideInterfaceInFullscreen(bool doIt);
|
||||
void _CheckAutoHideInterface();
|
||||
void _ShowInterface(bool show);
|
||||
void _ShowProgressBar(bool);
|
||||
void _InvokeButtonVisibly(BButton* button);
|
||||
|
||||
BString _NewTabURL(bool isNewWindow) const;
|
||||
BString _SmartURLHandler(const BString& url) const;
|
||||
|
||||
void _HandlePageSourceResult(
|
||||
const BMessage* message);
|
||||
|
||||
private:
|
||||
BMenu* fHistoryMenu;
|
||||
int32 fHistoryMenuFixedItemCount;
|
||||
|
||||
BMenuItem* fCutMenuItem;
|
||||
BMenuItem* fCopyMenuItem;
|
||||
BMenuItem* fPasteMenuItem;
|
||||
BMenuItem* fFindPreviousMenuItem;
|
||||
BMenuItem* fFindNextMenuItem;
|
||||
BMenuItem* fZoomTextOnlyMenuItem;
|
||||
BMenuItem* fFullscreenItem;
|
||||
BMenuItem* fBackMenuItem;
|
||||
BMenuItem* fForwardMenuItem;
|
||||
|
||||
IconButton* fBackButton;
|
||||
IconButton* fForwardButton;
|
||||
IconButton* fStopButton;
|
||||
IconButton* fHomeButton;
|
||||
URLInputGroup* fURLInputGroup;
|
||||
BStringView* fStatusText;
|
||||
BStatusBar* fLoadingProgressBar;
|
||||
|
||||
BLayoutItem* fMenuGroup;
|
||||
BLayoutItem* fTabGroup;
|
||||
BLayoutItem* fNavigationGroup;
|
||||
BLayoutItem* fFindGroup;
|
||||
BLayoutItem* fStatusGroup;
|
||||
BLayoutItem* fToggleFullscreenButton;
|
||||
|
||||
BTextControl* fFindTextControl;
|
||||
BButton* fFindPreviousButton;
|
||||
BButton* fFindNextButton;
|
||||
BButton* fFindCloseButton;
|
||||
BCheckBox* fFindCaseSensitiveCheckBox;
|
||||
TabManager* fTabManager;
|
||||
|
||||
bool fIsFullscreen;
|
||||
bool fInterfaceVisible;
|
||||
BRect fNonFullscreenWindowFrame;
|
||||
BMessageRunner* fPulseRunner;
|
||||
uint32 fVisibleInterfaceElements;
|
||||
bigtime_t fLastMouseMovedTime;
|
||||
BPoint fLastMousePos;
|
||||
|
||||
// cached settings
|
||||
SettingsMessage* fAppSettings;
|
||||
bool fZoomTextOnly;
|
||||
bool fShowTabsIfSinglePageOpen;
|
||||
bool fAutoHideInterfaceInFullscreenMode;
|
||||
bool fAutoHidePointer;
|
||||
uint32 fNewWindowPolicy;
|
||||
uint32 fNewTabPolicy;
|
||||
BString fStartPageURL;
|
||||
BString fSearchPageURL;
|
||||
};
|
||||
|
||||
|
||||
#endif // BROWSER_WINDOW_H
|
||||
|
||||
@@ -0,0 +1,381 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "BrowsingHistory.h"
|
||||
|
||||
#include <new>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <Autolock.h>
|
||||
#include <Entry.h>
|
||||
#include <File.h>
|
||||
#include <FindDirectory.h>
|
||||
#include <Message.h>
|
||||
#include <Path.h>
|
||||
|
||||
#include "BrowserApp.h"
|
||||
|
||||
|
||||
BrowsingHistoryItem::BrowsingHistoryItem(const BString& url)
|
||||
:
|
||||
fURL(url),
|
||||
fDateTime(BDateTime::CurrentDateTime(B_LOCAL_TIME)),
|
||||
fInvokationCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BrowsingHistoryItem::BrowsingHistoryItem(const BrowsingHistoryItem& other)
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
|
||||
|
||||
BrowsingHistoryItem::BrowsingHistoryItem(const BMessage* archive)
|
||||
{
|
||||
if (!archive)
|
||||
return;
|
||||
BMessage dateTimeArchive;
|
||||
if (archive->FindMessage("date time", &dateTimeArchive) == B_OK)
|
||||
fDateTime = BDateTime(&dateTimeArchive);
|
||||
archive->FindString("url", &fURL);
|
||||
archive->FindUInt32("invokations", &fInvokationCount);
|
||||
}
|
||||
|
||||
|
||||
BrowsingHistoryItem::~BrowsingHistoryItem()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BrowsingHistoryItem::Archive(BMessage* archive) const
|
||||
{
|
||||
if (!archive)
|
||||
return B_BAD_VALUE;
|
||||
BMessage dateTimeArchive;
|
||||
status_t status = fDateTime.Archive(&dateTimeArchive);
|
||||
if (status == B_OK)
|
||||
status = archive->AddMessage("date time", &dateTimeArchive);
|
||||
if (status == B_OK)
|
||||
status = archive->AddString("url", fURL.String());
|
||||
if (status == B_OK)
|
||||
status = archive->AddUInt32("invokations", fInvokationCount);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
BrowsingHistoryItem&
|
||||
BrowsingHistoryItem::operator=(const BrowsingHistoryItem& other)
|
||||
{
|
||||
if (this == &other)
|
||||
return *this;
|
||||
|
||||
fURL = other.fURL;
|
||||
fDateTime = other.fDateTime;
|
||||
fInvokationCount = other.fInvokationCount;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BrowsingHistoryItem::operator==(const BrowsingHistoryItem& other) const
|
||||
{
|
||||
if (this == &other)
|
||||
return true;
|
||||
|
||||
return fURL == other.fURL && fDateTime == other.fDateTime
|
||||
&& fInvokationCount == other.fInvokationCount;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BrowsingHistoryItem::operator!=(const BrowsingHistoryItem& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BrowsingHistoryItem::operator<(const BrowsingHistoryItem& other) const
|
||||
{
|
||||
if (this == &other)
|
||||
return false;
|
||||
|
||||
return fDateTime < other.fDateTime || fURL < other.fURL;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BrowsingHistoryItem::operator<=(const BrowsingHistoryItem& other) const
|
||||
{
|
||||
return (*this == other) || (*this < other);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BrowsingHistoryItem::operator>(const BrowsingHistoryItem& other) const
|
||||
{
|
||||
if (this == &other)
|
||||
return false;
|
||||
|
||||
return fDateTime > other.fDateTime || fURL > other.fURL;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BrowsingHistoryItem::operator>=(const BrowsingHistoryItem& other) const
|
||||
{
|
||||
return (*this == other) || (*this > other);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BrowsingHistoryItem::Invoked()
|
||||
{
|
||||
// Eventually, we may overflow...
|
||||
uint32 count = fInvokationCount + 1;
|
||||
if (count > fInvokationCount)
|
||||
fInvokationCount = count;
|
||||
fDateTime = BDateTime::CurrentDateTime(B_LOCAL_TIME);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - BrowsingHistory
|
||||
|
||||
|
||||
BrowsingHistory
|
||||
BrowsingHistory::sDefaultInstance;
|
||||
|
||||
|
||||
BrowsingHistory::BrowsingHistory()
|
||||
:
|
||||
BLocker("browsing history"),
|
||||
fHistoryItems(64),
|
||||
fMaxHistoryItemAge(7),
|
||||
fSettingsLoaded(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BrowsingHistory::~BrowsingHistory()
|
||||
{
|
||||
_SaveSettings();
|
||||
_Clear();
|
||||
}
|
||||
|
||||
|
||||
/*static*/ BrowsingHistory*
|
||||
BrowsingHistory::DefaultInstance()
|
||||
{
|
||||
if (sDefaultInstance.Lock()) {
|
||||
sDefaultInstance._LoadSettings();
|
||||
sDefaultInstance.Unlock();
|
||||
}
|
||||
return &sDefaultInstance;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BrowsingHistory::AddItem(const BrowsingHistoryItem& item)
|
||||
{
|
||||
BAutolock _(this);
|
||||
|
||||
return _AddItem(item, false);
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
BrowsingHistory::BrowsingHistory::CountItems() const
|
||||
{
|
||||
BAutolock _(const_cast<BrowsingHistory*>(this));
|
||||
|
||||
return fHistoryItems.CountItems();
|
||||
}
|
||||
|
||||
|
||||
BrowsingHistoryItem
|
||||
BrowsingHistory::HistoryItemAt(int32 index) const
|
||||
{
|
||||
BAutolock _(const_cast<BrowsingHistory*>(this));
|
||||
|
||||
BrowsingHistoryItem* existingItem = reinterpret_cast<BrowsingHistoryItem*>(
|
||||
fHistoryItems.ItemAt(index));
|
||||
if (!existingItem)
|
||||
return BrowsingHistoryItem(BString());
|
||||
|
||||
return BrowsingHistoryItem(*existingItem);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BrowsingHistory::Clear()
|
||||
{
|
||||
BAutolock _(this);
|
||||
_Clear();
|
||||
_SaveSettings();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BrowsingHistory::SetMaxHistoryItemAge(int32 days)
|
||||
{
|
||||
BAutolock _(this);
|
||||
if (fMaxHistoryItemAge != days) {
|
||||
fMaxHistoryItemAge = days;
|
||||
_SaveSettings();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
BrowsingHistory::MaxHistoryItemAge() const
|
||||
{
|
||||
return fMaxHistoryItemAge;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - private
|
||||
|
||||
|
||||
void
|
||||
BrowsingHistory::_Clear()
|
||||
{
|
||||
int32 count = CountItems();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
BrowsingHistoryItem* item = reinterpret_cast<BrowsingHistoryItem*>(
|
||||
fHistoryItems.ItemAtFast(i));
|
||||
delete item;
|
||||
}
|
||||
fHistoryItems.MakeEmpty();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BrowsingHistory::_AddItem(const BrowsingHistoryItem& item, bool internal)
|
||||
{
|
||||
int32 count = CountItems();
|
||||
int32 insertionIndex = count;
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
BrowsingHistoryItem* existingItem
|
||||
= reinterpret_cast<BrowsingHistoryItem*>(
|
||||
fHistoryItems.ItemAtFast(i));
|
||||
if (item.URL() == existingItem->URL()) {
|
||||
if (!internal) {
|
||||
existingItem->Invoked();
|
||||
_SaveSettings();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (item < *existingItem)
|
||||
insertionIndex = i;
|
||||
}
|
||||
BrowsingHistoryItem* newItem = new(std::nothrow) BrowsingHistoryItem(item);
|
||||
if (!newItem || !fHistoryItems.AddItem(newItem, insertionIndex)) {
|
||||
delete newItem;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!internal) {
|
||||
newItem->Invoked();
|
||||
_SaveSettings();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BrowsingHistory::_LoadSettings()
|
||||
{
|
||||
if (fSettingsLoaded)
|
||||
return;
|
||||
|
||||
fSettingsLoaded = true;
|
||||
|
||||
BFile settingsFile;
|
||||
if (_OpenSettingsFile(settingsFile, B_READ_ONLY)) {
|
||||
BMessage settingsArchive;
|
||||
settingsArchive.Unflatten(&settingsFile);
|
||||
if (settingsArchive.FindInt32("max history item age",
|
||||
&fMaxHistoryItemAge) != B_OK) {
|
||||
fMaxHistoryItemAge = 7;
|
||||
}
|
||||
BDateTime oldestAllowedDateTime
|
||||
= BDateTime::CurrentDateTime(B_LOCAL_TIME);
|
||||
oldestAllowedDateTime.Date().AddDays(-fMaxHistoryItemAge);
|
||||
|
||||
BMessage historyItemArchive;
|
||||
for (int32 i = 0; settingsArchive.FindMessage("history item", i,
|
||||
&historyItemArchive) == B_OK; i++) {
|
||||
BrowsingHistoryItem item(&historyItemArchive);
|
||||
if (oldestAllowedDateTime < item.DateTime())
|
||||
_AddItem(item, true);
|
||||
historyItemArchive.MakeEmpty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BrowsingHistory::_SaveSettings()
|
||||
{
|
||||
BFile settingsFile;
|
||||
if (_OpenSettingsFile(settingsFile,
|
||||
B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY)) {
|
||||
BMessage settingsArchive;
|
||||
settingsArchive.AddInt32("max history item age", fMaxHistoryItemAge);
|
||||
BMessage historyItemArchive;
|
||||
int32 count = CountItems();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
BrowsingHistoryItem item = HistoryItemAt(i);
|
||||
if (item.Archive(&historyItemArchive) != B_OK)
|
||||
break;
|
||||
if (settingsArchive.AddMessage("history item",
|
||||
&historyItemArchive) != B_OK) {
|
||||
break;
|
||||
}
|
||||
historyItemArchive.MakeEmpty();
|
||||
}
|
||||
settingsArchive.Flatten(&settingsFile);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BrowsingHistory::_OpenSettingsFile(BFile& file, uint32 mode)
|
||||
{
|
||||
BPath path;
|
||||
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK
|
||||
|| path.Append(kApplicationName) != B_OK
|
||||
|| path.Append("BrowsingHistory") != B_OK) {
|
||||
return false;
|
||||
}
|
||||
return file.SetTo(path.Path(), mode) == B_OK;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef BROWSING_HISTORY_H
|
||||
#define BROWSING_HISTORY_H
|
||||
|
||||
#include "DateTime.h"
|
||||
#include <List.h>
|
||||
#include <Locker.h>
|
||||
|
||||
class BFile;
|
||||
class BString;
|
||||
|
||||
|
||||
class BrowsingHistoryItem {
|
||||
public:
|
||||
BrowsingHistoryItem(const BString& url);
|
||||
BrowsingHistoryItem(
|
||||
const BrowsingHistoryItem& other);
|
||||
BrowsingHistoryItem(const BMessage* archive);
|
||||
~BrowsingHistoryItem();
|
||||
|
||||
status_t Archive(BMessage* archive) const;
|
||||
|
||||
BrowsingHistoryItem& operator=(const BrowsingHistoryItem& other);
|
||||
|
||||
bool operator==(
|
||||
const BrowsingHistoryItem& other) const;
|
||||
bool operator!=(
|
||||
const BrowsingHistoryItem& other) const;
|
||||
bool operator<(
|
||||
const BrowsingHistoryItem& other) const;
|
||||
bool operator<=(
|
||||
const BrowsingHistoryItem& other) const;
|
||||
bool operator>(
|
||||
const BrowsingHistoryItem& other) const;
|
||||
bool operator>=(
|
||||
const BrowsingHistoryItem& other) const;
|
||||
|
||||
const BString& URL() const { return fURL; }
|
||||
const BDateTime& DateTime() const { return fDateTime; }
|
||||
uint32 InvokationCount() const {
|
||||
return fInvokationCount; }
|
||||
void Invoked();
|
||||
|
||||
private:
|
||||
BString fURL;
|
||||
BDateTime fDateTime;
|
||||
uint32 fInvokationCount;
|
||||
};
|
||||
|
||||
|
||||
class BrowsingHistory : public BLocker {
|
||||
public:
|
||||
static BrowsingHistory* DefaultInstance();
|
||||
|
||||
bool AddItem(const BrowsingHistoryItem& item);
|
||||
|
||||
// Should Lock() the object when using these in some loop or so:
|
||||
int32 CountItems() const;
|
||||
BrowsingHistoryItem HistoryItemAt(int32 index) const;
|
||||
void Clear();
|
||||
|
||||
void SetMaxHistoryItemAge(int32 days);
|
||||
int32 MaxHistoryItemAge() const;
|
||||
|
||||
private:
|
||||
BrowsingHistory();
|
||||
virtual ~BrowsingHistory();
|
||||
|
||||
void _Clear();
|
||||
bool _AddItem(const BrowsingHistoryItem& item,
|
||||
bool invoke);
|
||||
|
||||
void _LoadSettings();
|
||||
void _SaveSettings();
|
||||
bool _OpenSettingsFile(BFile& file, uint32 mode);
|
||||
|
||||
private:
|
||||
BList fHistoryItems;
|
||||
int32 fMaxHistoryItemAge;
|
||||
|
||||
static BrowsingHistory sDefaultInstance;
|
||||
bool fSettingsLoaded;
|
||||
};
|
||||
|
||||
|
||||
#endif // BROWSING_HISTORY_H
|
||||
|
||||
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "CredentialsStorage.h"
|
||||
|
||||
#include <new>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <Autolock.h>
|
||||
#include <Entry.h>
|
||||
#include <File.h>
|
||||
#include <FindDirectory.h>
|
||||
#include <Message.h>
|
||||
#include <Path.h>
|
||||
|
||||
#include "BrowserApp.h"
|
||||
|
||||
|
||||
Credentials::Credentials()
|
||||
:
|
||||
fUsername(),
|
||||
fPassword()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Credentials::Credentials(const BString& username, const BString& password)
|
||||
:
|
||||
fUsername(username),
|
||||
fPassword(password)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Credentials::Credentials(const Credentials& other)
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
|
||||
|
||||
Credentials::Credentials(const BMessage* archive)
|
||||
{
|
||||
if (archive == NULL)
|
||||
return;
|
||||
archive->FindString("username", &fUsername);
|
||||
archive->FindString("password", &fPassword);
|
||||
}
|
||||
|
||||
|
||||
Credentials::~Credentials()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Credentials::Archive(BMessage* archive) const
|
||||
{
|
||||
if (archive == NULL)
|
||||
return B_BAD_VALUE;
|
||||
status_t status = archive->AddString("username", fUsername);
|
||||
if (status == B_OK)
|
||||
status = archive->AddString("password", fPassword);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
Credentials&
|
||||
Credentials::operator=(const Credentials& other)
|
||||
{
|
||||
if (this == &other)
|
||||
return *this;
|
||||
|
||||
fUsername = other.fUsername;
|
||||
fPassword = other.fPassword;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Credentials::operator==(const Credentials& other) const
|
||||
{
|
||||
if (this == &other)
|
||||
return true;
|
||||
|
||||
return fUsername == other.fUsername && fPassword == other.fPassword;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Credentials::operator!=(const Credentials& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
|
||||
const BString&
|
||||
Credentials::Username() const
|
||||
{
|
||||
return fUsername;
|
||||
}
|
||||
|
||||
|
||||
const BString&
|
||||
Credentials::Password() const
|
||||
{
|
||||
return fPassword;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - CredentialsStorage
|
||||
|
||||
|
||||
CredentialsStorage
|
||||
CredentialsStorage::sPersistentInstance(true);
|
||||
|
||||
|
||||
CredentialsStorage
|
||||
CredentialsStorage::sSessionInstance(false);
|
||||
|
||||
|
||||
CredentialsStorage::CredentialsStorage(bool persistent)
|
||||
:
|
||||
BLocker(persistent ? "persistent credential storage"
|
||||
: "credential storage"),
|
||||
fCredentialMap(),
|
||||
fSettingsLoaded(false),
|
||||
fPersistent(persistent)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
CredentialsStorage::~CredentialsStorage()
|
||||
{
|
||||
_SaveSettings();
|
||||
}
|
||||
|
||||
|
||||
/*static*/ CredentialsStorage*
|
||||
CredentialsStorage::SessionInstance()
|
||||
{
|
||||
return &sSessionInstance;
|
||||
}
|
||||
|
||||
|
||||
/*static*/ CredentialsStorage*
|
||||
CredentialsStorage::PersistentInstance()
|
||||
{
|
||||
if (sPersistentInstance.Lock()) {
|
||||
sPersistentInstance._LoadSettings();
|
||||
sPersistentInstance.Unlock();
|
||||
}
|
||||
return &sPersistentInstance;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
CredentialsStorage::Contains(const HashKeyString& key)
|
||||
{
|
||||
BAutolock _(this);
|
||||
|
||||
return fCredentialMap.ContainsKey(key);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
CredentialsStorage::PutCredentials(const HashKeyString& key,
|
||||
const Credentials& credentials)
|
||||
{
|
||||
BAutolock _(this);
|
||||
|
||||
return fCredentialMap.Put(key, credentials);
|
||||
}
|
||||
|
||||
|
||||
Credentials
|
||||
CredentialsStorage::GetCredentials(const HashKeyString& key)
|
||||
{
|
||||
BAutolock _(this);
|
||||
|
||||
return fCredentialMap.Get(key);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - private
|
||||
|
||||
|
||||
void
|
||||
CredentialsStorage::_LoadSettings()
|
||||
{
|
||||
if (!fPersistent || fSettingsLoaded)
|
||||
return;
|
||||
|
||||
fSettingsLoaded = true;
|
||||
|
||||
BFile settingsFile;
|
||||
if (_OpenSettingsFile(settingsFile, B_READ_ONLY)) {
|
||||
BMessage settingsArchive;
|
||||
settingsArchive.Unflatten(&settingsFile);
|
||||
BMessage credentialsArchive;
|
||||
for (int32 i = 0; settingsArchive.FindMessage("credentials", i,
|
||||
&credentialsArchive) == B_OK; i++) {
|
||||
BString key;
|
||||
if (credentialsArchive.FindString("key", &key) == B_OK) {
|
||||
Credentials credentials(&credentialsArchive);
|
||||
fCredentialMap.Put(key, credentials);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CredentialsStorage::_SaveSettings() const
|
||||
{
|
||||
BFile settingsFile;
|
||||
if (_OpenSettingsFile(settingsFile,
|
||||
B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY)) {
|
||||
BMessage settingsArchive;
|
||||
BMessage credentialsArchive;
|
||||
CredentialMap::Iterator iterator = fCredentialMap.GetIterator();
|
||||
while (iterator.HasNext()) {
|
||||
const CredentialMap::Entry& entry = iterator.Next();
|
||||
if (entry.value.Archive(&credentialsArchive) != B_OK
|
||||
|| credentialsArchive.AddString("key",
|
||||
entry.key.value) != B_OK) {
|
||||
break;
|
||||
}
|
||||
if (settingsArchive.AddMessage("credentials",
|
||||
&credentialsArchive) != B_OK) {
|
||||
break;
|
||||
}
|
||||
credentialsArchive.MakeEmpty();
|
||||
}
|
||||
settingsArchive.Flatten(&settingsFile);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
CredentialsStorage::_OpenSettingsFile(BFile& file, uint32 mode) const
|
||||
{
|
||||
BPath path;
|
||||
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK
|
||||
|| path.Append(kApplicationName) != B_OK
|
||||
|| path.Append("CredentialsStorage") != B_OK) {
|
||||
return false;
|
||||
}
|
||||
return file.SetTo(path.Path(), mode) == B_OK;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef CREDENTIAL_STORAGE_H
|
||||
#define CREDENTIAL_STORAGE_H
|
||||
|
||||
#include "HashKeys.h"
|
||||
#include "HashMap.h"
|
||||
#include <Locker.h>
|
||||
#include <String.h>
|
||||
|
||||
|
||||
class BFile;
|
||||
class BMessage;
|
||||
class BString;
|
||||
|
||||
|
||||
class Credentials {
|
||||
public:
|
||||
Credentials();
|
||||
Credentials(const BString& username,
|
||||
const BString& password);
|
||||
Credentials(
|
||||
const Credentials& other);
|
||||
Credentials(const BMessage* archive);
|
||||
~Credentials();
|
||||
|
||||
status_t Archive(BMessage* archive) const;
|
||||
|
||||
Credentials& operator=(const Credentials& other);
|
||||
|
||||
bool operator==(const Credentials& other) const;
|
||||
bool operator!=(const Credentials& other) const;
|
||||
|
||||
const BString& Username() const;
|
||||
const BString& Password() const;
|
||||
|
||||
private:
|
||||
BString fUsername;
|
||||
BString fPassword;
|
||||
};
|
||||
|
||||
|
||||
class CredentialsStorage : public BLocker {
|
||||
public:
|
||||
static CredentialsStorage* SessionInstance();
|
||||
static CredentialsStorage* PersistentInstance();
|
||||
|
||||
bool Contains(const HashKeyString& key);
|
||||
status_t PutCredentials(const HashKeyString& key,
|
||||
const Credentials& credentials);
|
||||
Credentials GetCredentials(const HashKeyString& key);
|
||||
|
||||
private:
|
||||
CredentialsStorage(bool persistent);
|
||||
virtual ~CredentialsStorage();
|
||||
|
||||
void _LoadSettings();
|
||||
void _SaveSettings() const;
|
||||
bool _OpenSettingsFile(BFile& file,
|
||||
uint32 mode) const;
|
||||
|
||||
private:
|
||||
typedef HashMap<HashKeyString, Credentials> CredentialMap;
|
||||
CredentialMap fCredentialMap;
|
||||
|
||||
static CredentialsStorage sPersistentInstance;
|
||||
static CredentialsStorage sSessionInstance;
|
||||
bool fSettingsLoaded;
|
||||
bool fPersistent;
|
||||
};
|
||||
|
||||
|
||||
#endif // CREDENTIAL_STORAGE_H
|
||||
|
||||
@@ -0,0 +1,838 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "DownloadProgressView.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <Alert.h>
|
||||
#include <Bitmap.h>
|
||||
#include <Button.h>
|
||||
#include <Clipboard.h>
|
||||
#include <Directory.h>
|
||||
#include <Entry.h>
|
||||
#include <FindDirectory.h>
|
||||
#include <GroupLayoutBuilder.h>
|
||||
#include <MenuItem.h>
|
||||
#include <NodeInfo.h>
|
||||
#include <NodeMonitor.h>
|
||||
#include <PopUpMenu.h>
|
||||
#include <Roster.h>
|
||||
#include <SpaceLayoutItem.h>
|
||||
#include <StatusBar.h>
|
||||
#include <StringView.h>
|
||||
|
||||
#include "WebDownload.h"
|
||||
#include "WebPage.h"
|
||||
#include "StringForSize.h"
|
||||
|
||||
|
||||
enum {
|
||||
OPEN_DOWNLOAD = 'opdn',
|
||||
RESTART_DOWNLOAD = 'rsdn',
|
||||
CANCEL_DOWNLOAD = 'cndn',
|
||||
REMOVE_DOWNLOAD = 'rmdn',
|
||||
COPY_URL_TO_CLIPBOARD = 'curl',
|
||||
OPEN_CONTAINING_FOLDER = 'opfd',
|
||||
};
|
||||
|
||||
const bigtime_t kMaxUpdateInterval = 100000LL;
|
||||
const bigtime_t kSpeedReferenceInterval = 500000LL;
|
||||
const bigtime_t kShowSpeedInterval = 8000000LL;
|
||||
const bigtime_t kShowEstimatedFinishInterval = 4000000LL;
|
||||
|
||||
bigtime_t DownloadProgressView::sLastEstimatedFinishSpeedToggleTime = -1;
|
||||
bool DownloadProgressView::sShowSpeed = true;
|
||||
|
||||
|
||||
class IconView : public BView {
|
||||
public:
|
||||
IconView(const BEntry& entry)
|
||||
:
|
||||
BView("Download icon", B_WILL_DRAW),
|
||||
fIconBitmap(BRect(0, 0, 31, 31), 0, B_RGBA32),
|
||||
fDimmedIcon(false)
|
||||
{
|
||||
SetDrawingMode(B_OP_OVER);
|
||||
SetTo(entry);
|
||||
}
|
||||
|
||||
IconView()
|
||||
:
|
||||
BView("Download icon", B_WILL_DRAW),
|
||||
fIconBitmap(BRect(0, 0, 31, 31), 0, B_RGBA32),
|
||||
fDimmedIcon(false)
|
||||
{
|
||||
SetDrawingMode(B_OP_OVER);
|
||||
memset(fIconBitmap.Bits(), 0, fIconBitmap.BitsLength());
|
||||
}
|
||||
|
||||
IconView(BMessage* archive)
|
||||
:
|
||||
BView("Download icon", B_WILL_DRAW),
|
||||
fIconBitmap(archive),
|
||||
fDimmedIcon(true)
|
||||
{
|
||||
SetDrawingMode(B_OP_OVER);
|
||||
}
|
||||
|
||||
void SetTo(const BEntry& entry)
|
||||
{
|
||||
BNode node(&entry);
|
||||
BNodeInfo info(&node);
|
||||
info.GetTrackerIcon(&fIconBitmap, B_LARGE_ICON);
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
void SetIconDimmed(bool iconDimmed)
|
||||
{
|
||||
if (fDimmedIcon != iconDimmed) {
|
||||
fDimmedIcon = iconDimmed;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
bool IsIconDimmed() const
|
||||
{
|
||||
return fDimmedIcon;
|
||||
}
|
||||
|
||||
status_t SaveSettings(BMessage* archive)
|
||||
{
|
||||
return fIconBitmap.Archive(archive);
|
||||
}
|
||||
|
||||
virtual void AttachedToWindow()
|
||||
{
|
||||
SetViewColor(Parent()->ViewColor());
|
||||
}
|
||||
|
||||
virtual void Draw(BRect updateRect)
|
||||
{
|
||||
if (fDimmedIcon) {
|
||||
SetDrawingMode(B_OP_ALPHA);
|
||||
SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY);
|
||||
SetHighColor(0, 0, 0, 100);
|
||||
}
|
||||
DrawBitmapAsync(&fIconBitmap);
|
||||
}
|
||||
|
||||
virtual BSize MinSize()
|
||||
{
|
||||
return BSize(fIconBitmap.Bounds().Width(), fIconBitmap.Bounds().Height());
|
||||
}
|
||||
|
||||
virtual BSize PreferredSize()
|
||||
{
|
||||
return MinSize();
|
||||
}
|
||||
|
||||
virtual BSize MaxSize()
|
||||
{
|
||||
return MinSize();
|
||||
}
|
||||
|
||||
private:
|
||||
BBitmap fIconBitmap;
|
||||
bool fDimmedIcon;
|
||||
};
|
||||
|
||||
|
||||
class SmallButton : public BButton {
|
||||
public:
|
||||
SmallButton(const char* label, BMessage* message = NULL)
|
||||
:
|
||||
BButton(label, message)
|
||||
{
|
||||
BFont font;
|
||||
GetFont(&font);
|
||||
float size = ceilf(font.Size() * 0.8);
|
||||
font.SetSize(max_c(8, size));
|
||||
SetFont(&font, B_FONT_SIZE);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark - DownloadProgressView
|
||||
|
||||
|
||||
DownloadProgressView::DownloadProgressView(BWebDownload* download)
|
||||
:
|
||||
BGroupView(B_HORIZONTAL, 8),
|
||||
fDownload(download),
|
||||
fURL(download->URL()),
|
||||
fPath(download->Path())
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
DownloadProgressView::DownloadProgressView(const BMessage* archive)
|
||||
:
|
||||
BGroupView(B_HORIZONTAL, 8),
|
||||
fDownload(NULL),
|
||||
fURL(),
|
||||
fPath()
|
||||
{
|
||||
const char* string;
|
||||
if (archive->FindString("path", &string) == B_OK)
|
||||
fPath.SetTo(string);
|
||||
if (archive->FindString("url", &string) == B_OK)
|
||||
fURL = string;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DownloadProgressView::Init(BMessage* archive)
|
||||
{
|
||||
fCurrentSize = 0;
|
||||
fExpectedSize = 0;
|
||||
fLastUpdateTime = 0;
|
||||
fBytesPerSecond = 0.0;
|
||||
for (size_t i = 0; i < kBytesPerSecondSlots; i++)
|
||||
fBytesPerSecondSlot[i] = 0.0;
|
||||
fCurrentBytesPerSecondSlot = 0;
|
||||
fLastSpeedReferenceSize = 0;
|
||||
fEstimatedFinishReferenceSize = 0;
|
||||
|
||||
fProcessStartTime = fLastSpeedReferenceTime = fEstimatedFinishReferenceTime
|
||||
= system_time();
|
||||
|
||||
SetViewColor(245, 245, 245);
|
||||
SetFlags(Flags() | B_FULL_UPDATE_ON_RESIZE | B_WILL_DRAW);
|
||||
|
||||
if (archive) {
|
||||
fStatusBar = new BStatusBar("download progress", fPath.Leaf());
|
||||
float value;
|
||||
if (archive->FindFloat("value", &value) == B_OK)
|
||||
fStatusBar->SetTo(value);
|
||||
} else
|
||||
fStatusBar = new BStatusBar("download progress", "Download");
|
||||
fStatusBar->SetMaxValue(100);
|
||||
fStatusBar->SetBarHeight(12);
|
||||
|
||||
// fPath is only valid when constructed from archive (fDownload == NULL)
|
||||
BEntry entry(fPath.Path());
|
||||
|
||||
if (archive) {
|
||||
if (!entry.Exists())
|
||||
fIconView = new IconView(archive);
|
||||
else
|
||||
fIconView = new IconView(entry);
|
||||
} else
|
||||
fIconView = new IconView();
|
||||
|
||||
if (!fDownload && (fStatusBar->CurrentValue() < 100 || !entry.Exists()))
|
||||
fTopButton = new SmallButton("Restart", new BMessage(RESTART_DOWNLOAD));
|
||||
else {
|
||||
fTopButton = new SmallButton("Open", new BMessage(OPEN_DOWNLOAD));
|
||||
fTopButton->SetEnabled(fDownload == NULL);
|
||||
}
|
||||
if (fDownload)
|
||||
fBottomButton = new SmallButton("Cancel", new BMessage(CANCEL_DOWNLOAD));
|
||||
else {
|
||||
fBottomButton = new SmallButton("Remove", new BMessage(REMOVE_DOWNLOAD));
|
||||
fBottomButton->SetEnabled(fDownload == NULL);
|
||||
}
|
||||
|
||||
fInfoView = new BStringView("info view", "");
|
||||
|
||||
BGroupLayout* layout = GroupLayout();
|
||||
layout->SetInsets(8, 5, 5, 6);
|
||||
layout->AddView(fIconView);
|
||||
BView* verticalGroup = BGroupLayoutBuilder(B_VERTICAL, 3)
|
||||
.Add(fStatusBar)
|
||||
.Add(fInfoView)
|
||||
.TopView()
|
||||
;
|
||||
verticalGroup->SetViewColor(ViewColor());
|
||||
layout->AddView(verticalGroup);
|
||||
verticalGroup = BGroupLayoutBuilder(B_VERTICAL, 3)
|
||||
.Add(fTopButton)
|
||||
.Add(fBottomButton)
|
||||
.TopView()
|
||||
;
|
||||
verticalGroup->SetViewColor(ViewColor());
|
||||
layout->AddView(verticalGroup);
|
||||
|
||||
BFont font;
|
||||
fInfoView->GetFont(&font);
|
||||
float fontSize = font.Size() * 0.8f;
|
||||
font.SetSize(max_c(8.0f, fontSize));
|
||||
fInfoView->SetFont(&font, B_FONT_SIZE);
|
||||
fInfoView->SetHighColor(tint_color(fInfoView->LowColor(),
|
||||
B_DARKEN_4_TINT));
|
||||
fInfoView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
DownloadProgressView::SaveSettings(BMessage* archive)
|
||||
{
|
||||
if (!archive)
|
||||
return B_BAD_VALUE;
|
||||
status_t ret = archive->AddString("path", fPath.Path());
|
||||
if (ret == B_OK)
|
||||
ret = archive->AddString("url", fURL.String());
|
||||
if (ret == B_OK)
|
||||
ret = archive->AddFloat("value", fStatusBar->CurrentValue());
|
||||
if (ret == B_OK)
|
||||
ret = fIconView->SaveSettings(archive);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DownloadProgressView::AttachedToWindow()
|
||||
{
|
||||
if (fDownload) {
|
||||
fDownload->SetProgressListener(BMessenger(this));
|
||||
// Will start node monitor upon receiving the B_DOWNLOAD_STARTED
|
||||
// message.
|
||||
} else {
|
||||
BEntry entry(fPath.Path());
|
||||
if (entry.Exists())
|
||||
_StartNodeMonitor(entry);
|
||||
}
|
||||
|
||||
fTopButton->SetTarget(this);
|
||||
fBottomButton->SetTarget(this);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DownloadProgressView::DetachedFromWindow()
|
||||
{
|
||||
_StopNodeMonitor();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DownloadProgressView::AllAttached()
|
||||
{
|
||||
SetViewColor(B_TRANSPARENT_COLOR);
|
||||
SetLowColor(245, 245, 245);
|
||||
SetHighColor(tint_color(LowColor(), B_DARKEN_1_TINT));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DownloadProgressView::Draw(BRect updateRect)
|
||||
{
|
||||
BRect bounds(Bounds());
|
||||
bounds.bottom--;
|
||||
FillRect(bounds, B_SOLID_LOW);
|
||||
bounds.bottom++;
|
||||
StrokeLine(bounds.LeftBottom(), bounds.RightBottom());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DownloadProgressView::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch (message->what) {
|
||||
case B_DOWNLOAD_STARTED:
|
||||
{
|
||||
BString path;
|
||||
if (message->FindString("path", &path) != B_OK)
|
||||
break;
|
||||
fPath.SetTo(path);
|
||||
BEntry entry(fPath.Path());
|
||||
fIconView->SetTo(entry);
|
||||
fStatusBar->Reset(fPath.Leaf());
|
||||
_StartNodeMonitor(entry);
|
||||
|
||||
// Immediately switch to speed display whenever a new download
|
||||
// starts.
|
||||
sShowSpeed = true;
|
||||
sLastEstimatedFinishSpeedToggleTime
|
||||
= fProcessStartTime = fLastSpeedReferenceTime
|
||||
= fEstimatedFinishReferenceTime = system_time();
|
||||
break;
|
||||
}
|
||||
case B_DOWNLOAD_PROGRESS:
|
||||
{
|
||||
int64 currentSize;
|
||||
int64 expectedSize;
|
||||
if (message->FindInt64("current size", ¤tSize) == B_OK
|
||||
&& message->FindInt64("expected size", &expectedSize) == B_OK) {
|
||||
_UpdateStatus(currentSize, expectedSize);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case B_DOWNLOAD_REMOVED:
|
||||
// TODO: This is a bit asymetric. The removed notification
|
||||
// arrives here, but it would be nicer if it arrived
|
||||
// at the window...
|
||||
Window()->PostMessage(message);
|
||||
break;
|
||||
case OPEN_DOWNLOAD:
|
||||
{
|
||||
// TODO: In case of executable files, ask the user first!
|
||||
entry_ref ref;
|
||||
status_t status = get_ref_for_path(fPath.Path(), &ref);
|
||||
if (status == B_OK)
|
||||
status = be_roster->Launch(&ref);
|
||||
if (status != B_OK && status != B_ALREADY_RUNNING) {
|
||||
BAlert* alert = new BAlert("Open download error",
|
||||
"The download could not be opened.", "OK");
|
||||
alert->Go(NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RESTART_DOWNLOAD:
|
||||
BWebPage::RequestDownload(fURL);
|
||||
break;
|
||||
|
||||
case CANCEL_DOWNLOAD:
|
||||
fDownload->Cancel();
|
||||
DownloadCanceled();
|
||||
break;
|
||||
|
||||
case REMOVE_DOWNLOAD:
|
||||
{
|
||||
Window()->PostMessage(SAVE_SETTINGS);
|
||||
RemoveSelf();
|
||||
delete this;
|
||||
// TOAST!
|
||||
return;
|
||||
}
|
||||
case B_NODE_MONITOR:
|
||||
{
|
||||
int32 opCode;
|
||||
if (message->FindInt32("opcode", &opCode) != B_OK)
|
||||
break;
|
||||
switch (opCode) {
|
||||
case B_ENTRY_REMOVED:
|
||||
fIconView->SetIconDimmed(true);
|
||||
DownloadCanceled();
|
||||
break;
|
||||
case B_ENTRY_MOVED:
|
||||
{
|
||||
// Follow the entry to the new location
|
||||
dev_t device;
|
||||
ino_t directory;
|
||||
const char* name;
|
||||
if (message->FindInt32("device",
|
||||
reinterpret_cast<int32*>(&device)) != B_OK
|
||||
|| message->FindInt64("to directory",
|
||||
reinterpret_cast<int64*>(&directory)) != B_OK
|
||||
|| message->FindString("name", &name) != B_OK
|
||||
|| strlen(name) == 0) {
|
||||
break;
|
||||
}
|
||||
// Construct the BEntry and update fPath
|
||||
entry_ref ref(device, directory, name);
|
||||
BEntry entry(&ref);
|
||||
if (entry.GetPath(&fPath) != B_OK)
|
||||
break;
|
||||
|
||||
// Find out if the directory is the Trash for this
|
||||
// volume
|
||||
char trashPath[B_PATH_NAME_LENGTH];
|
||||
if (find_directory(B_TRASH_DIRECTORY, device, false,
|
||||
trashPath, B_PATH_NAME_LENGTH) == B_OK) {
|
||||
BPath trashDirectory(trashPath);
|
||||
BPath parentDirectory;
|
||||
fPath.GetParent(&parentDirectory);
|
||||
if (parentDirectory == trashDirectory) {
|
||||
// The entry was moved into the Trash.
|
||||
// If the download is still in progress,
|
||||
// cancel it.
|
||||
if (fDownload)
|
||||
fDownload->Cancel();
|
||||
fIconView->SetIconDimmed(true);
|
||||
DownloadCanceled();
|
||||
break;
|
||||
} else if (fIconView->IsIconDimmed()) {
|
||||
// Maybe it was moved out of the trash.
|
||||
fIconView->SetIconDimmed(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Inform download of the new path
|
||||
if (fDownload)
|
||||
fDownload->HasMovedTo(fPath);
|
||||
|
||||
float value = fStatusBar->CurrentValue();
|
||||
fStatusBar->Reset(name);
|
||||
fStatusBar->SetTo(value);
|
||||
Window()->PostMessage(SAVE_SETTINGS);
|
||||
break;
|
||||
}
|
||||
case B_ATTR_CHANGED:
|
||||
{
|
||||
BEntry entry(fPath.Path());
|
||||
fIconView->SetIconDimmed(false);
|
||||
fIconView->SetTo(entry);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Context menu messages
|
||||
case COPY_URL_TO_CLIPBOARD:
|
||||
if (be_clipboard->Lock()) {
|
||||
BMessage* data = be_clipboard->Data();
|
||||
if (data != NULL) {
|
||||
be_clipboard->Clear();
|
||||
data->AddData("text/plain", B_MIME_TYPE, fURL.String(),
|
||||
fURL.Length());
|
||||
}
|
||||
be_clipboard->Commit();
|
||||
be_clipboard->Unlock();
|
||||
}
|
||||
break;
|
||||
case OPEN_CONTAINING_FOLDER:
|
||||
if (fPath.InitCheck() == B_OK) {
|
||||
BPath containingFolder;
|
||||
if (fPath.GetParent(&containingFolder) != B_OK)
|
||||
break;
|
||||
BEntry entry(containingFolder.Path());
|
||||
if (!entry.Exists())
|
||||
break;
|
||||
entry_ref ref;
|
||||
if (entry.GetRef(&ref) != B_OK)
|
||||
break;
|
||||
be_roster->Launch(&ref);
|
||||
|
||||
// Use Tracker scripting and select the download pose
|
||||
// in the window.
|
||||
// TODO: We should somehow get the window that just openend.
|
||||
// Using the name like this is broken when there are multiple
|
||||
// windows open with this name. Also Tracker does not scroll
|
||||
// to this entry.
|
||||
BString windowName = ref.name;
|
||||
BString fullWindowName = containingFolder.Path();
|
||||
|
||||
BMessenger trackerMessenger("application/x-vnd.Be-TRAK");
|
||||
if (trackerMessenger.IsValid()
|
||||
&& get_ref_for_path(fPath.Path(), &ref) == B_OK) {
|
||||
// We need to wait a bit until the folder is open.
|
||||
// TODO: This is also too fragile... we should be able
|
||||
// to wait for the roster message.
|
||||
snooze(250000);
|
||||
int32 tries = 2;
|
||||
while (tries > 0) {
|
||||
BMessage selectionCommand(B_SET_PROPERTY);
|
||||
selectionCommand.AddSpecifier("Selection");
|
||||
selectionCommand.AddSpecifier("Poses");
|
||||
selectionCommand.AddSpecifier("Window",
|
||||
windowName.String());
|
||||
selectionCommand.AddRef("data", &ref);
|
||||
BMessage reply;
|
||||
trackerMessenger.SendMessage(&selectionCommand, &reply);
|
||||
int32 error;
|
||||
if (reply.FindInt32("error", &error) != B_OK
|
||||
|| error == B_OK) {
|
||||
break;
|
||||
}
|
||||
windowName = fullWindowName;
|
||||
tries--;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
BGroupView::MessageReceived(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DownloadProgressView::ShowContextMenu(BPoint screenWhere)
|
||||
{
|
||||
screenWhere += BPoint(2, 2);
|
||||
|
||||
BPopUpMenu* contextMenu = new BPopUpMenu("download context");
|
||||
BMenuItem* copyURL = new BMenuItem("Copy URL to clipboard",
|
||||
new BMessage(COPY_URL_TO_CLIPBOARD));
|
||||
copyURL->SetEnabled(fURL.Length() > 0);
|
||||
contextMenu->AddItem(copyURL);
|
||||
BMenuItem* openFolder = new BMenuItem("Open containing folder",
|
||||
new BMessage(OPEN_CONTAINING_FOLDER));
|
||||
contextMenu->AddItem(openFolder);
|
||||
|
||||
contextMenu->SetTargetForItems(this);
|
||||
contextMenu->Go(screenWhere, true, true, true);
|
||||
}
|
||||
|
||||
|
||||
BWebDownload*
|
||||
DownloadProgressView::Download() const
|
||||
{
|
||||
return fDownload;
|
||||
}
|
||||
|
||||
|
||||
const BString&
|
||||
DownloadProgressView::URL() const
|
||||
{
|
||||
return fURL;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DownloadProgressView::IsMissing() const
|
||||
{
|
||||
return fIconView->IsIconDimmed();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DownloadProgressView::IsFinished() const
|
||||
{
|
||||
return !fDownload && fStatusBar->CurrentValue() == 100;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DownloadProgressView::DownloadFinished()
|
||||
{
|
||||
fDownload = NULL;
|
||||
if (fExpectedSize == -1) {
|
||||
fStatusBar->SetTo(100.0);
|
||||
fExpectedSize = fCurrentSize;
|
||||
}
|
||||
fTopButton->SetEnabled(true);
|
||||
fBottomButton->SetLabel("Remove");
|
||||
fBottomButton->SetMessage(new BMessage(REMOVE_DOWNLOAD));
|
||||
fBottomButton->SetEnabled(true);
|
||||
fInfoView->SetText("");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DownloadProgressView::DownloadCanceled()
|
||||
{
|
||||
fDownload = NULL;
|
||||
fTopButton->SetLabel("Restart");
|
||||
fTopButton->SetMessage(new BMessage(RESTART_DOWNLOAD));
|
||||
fTopButton->SetEnabled(true);
|
||||
fBottomButton->SetLabel("Remove");
|
||||
fBottomButton->SetMessage(new BMessage(REMOVE_DOWNLOAD));
|
||||
fBottomButton->SetEnabled(true);
|
||||
fInfoView->SetText("");
|
||||
fPath.Unset();
|
||||
}
|
||||
|
||||
|
||||
/*static*/ void
|
||||
DownloadProgressView::SpeedVersusEstimatedFinishTogglePulse()
|
||||
{
|
||||
bigtime_t now = system_time();
|
||||
if (sShowSpeed
|
||||
&& sLastEstimatedFinishSpeedToggleTime + kShowSpeedInterval
|
||||
<= now) {
|
||||
sShowSpeed = false;
|
||||
sLastEstimatedFinishSpeedToggleTime = now;
|
||||
} else if (!sShowSpeed
|
||||
&& sLastEstimatedFinishSpeedToggleTime
|
||||
+ kShowEstimatedFinishInterval <= now) {
|
||||
sShowSpeed = true;
|
||||
sLastEstimatedFinishSpeedToggleTime = now;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - private
|
||||
|
||||
|
||||
void
|
||||
DownloadProgressView::_UpdateStatus(off_t currentSize, off_t expectedSize)
|
||||
{
|
||||
fCurrentSize = currentSize;
|
||||
fExpectedSize = expectedSize;
|
||||
|
||||
fStatusBar->SetTo(100.0 * currentSize / expectedSize);
|
||||
|
||||
bigtime_t currentTime = system_time();
|
||||
if ((currentTime - fLastUpdateTime) > kMaxUpdateInterval) {
|
||||
fLastUpdateTime = currentTime;
|
||||
|
||||
if (currentTime >= fLastSpeedReferenceTime + kSpeedReferenceInterval) {
|
||||
// update current speed every kSpeedReferenceInterval
|
||||
fCurrentBytesPerSecondSlot
|
||||
= (fCurrentBytesPerSecondSlot + 1) % kBytesPerSecondSlots;
|
||||
fBytesPerSecondSlot[fCurrentBytesPerSecondSlot]
|
||||
= (double)(currentSize - fLastSpeedReferenceSize)
|
||||
* 1000000LL / (currentTime - fLastSpeedReferenceTime);
|
||||
fLastSpeedReferenceSize = currentSize;
|
||||
fLastSpeedReferenceTime = currentTime;
|
||||
fBytesPerSecond = 0.0;
|
||||
size_t count = 0;
|
||||
for (size_t i = 0; i < kBytesPerSecondSlots; i++) {
|
||||
if (fBytesPerSecondSlot[i] != 0.0) {
|
||||
fBytesPerSecond += fBytesPerSecondSlot[i];
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (count > 0)
|
||||
fBytesPerSecond /= count;
|
||||
}
|
||||
_UpdateStatusText();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DownloadProgressView::_UpdateStatusText()
|
||||
{
|
||||
fInfoView->SetText("");
|
||||
BString buffer;
|
||||
if (sShowSpeed && fBytesPerSecond != 0.0) {
|
||||
// Draw speed info
|
||||
char sizeBuffer[128];
|
||||
buffer = "(";
|
||||
// Get strings for current and expected size and remove the unit
|
||||
// from the current size string if it's the same as the expected
|
||||
// size unit.
|
||||
BString currentSize = string_for_size((double)fCurrentSize, sizeBuffer,
|
||||
sizeof(sizeBuffer));
|
||||
BString expectedSize = string_for_size((double)fExpectedSize, sizeBuffer,
|
||||
sizeof(sizeBuffer));
|
||||
int currentSizeUnitPos = currentSize.FindLast(' ');
|
||||
int expectedSizeUnitPos = expectedSize.FindLast(' ');
|
||||
if (currentSizeUnitPos >= 0 && expectedSizeUnitPos >= 0
|
||||
&& strcmp(currentSize.String() + currentSizeUnitPos,
|
||||
expectedSize.String() + expectedSizeUnitPos) == 0) {
|
||||
currentSize.Truncate(currentSizeUnitPos);
|
||||
}
|
||||
buffer << currentSize;
|
||||
buffer << " of ";
|
||||
buffer << expectedSize;
|
||||
buffer << ", ";
|
||||
buffer << string_for_size(fBytesPerSecond, sizeBuffer,
|
||||
sizeof(sizeBuffer));
|
||||
buffer << "/s)";
|
||||
float stringWidth = fInfoView->StringWidth(buffer.String());
|
||||
if (stringWidth < fInfoView->Bounds().Width())
|
||||
fInfoView->SetText(buffer.String());
|
||||
else {
|
||||
// complete string too wide, try with shorter version
|
||||
buffer << string_for_size(fBytesPerSecond, sizeBuffer,
|
||||
sizeof(sizeBuffer));
|
||||
buffer << "/s";
|
||||
stringWidth = fInfoView->StringWidth(buffer.String());
|
||||
if (stringWidth < fInfoView->Bounds().Width())
|
||||
fInfoView->SetText(buffer.String());
|
||||
}
|
||||
} else if (!sShowSpeed && fCurrentSize < fExpectedSize) {
|
||||
double totalBytesPerSecond = (double)(fCurrentSize
|
||||
- fEstimatedFinishReferenceSize)
|
||||
* 1000000LL / (system_time() - fEstimatedFinishReferenceTime);
|
||||
double secondsRemaining = (fExpectedSize - fCurrentSize)
|
||||
/ totalBytesPerSecond;
|
||||
time_t now = (time_t)real_time_clock();
|
||||
time_t finishTime = (time_t)(now + secondsRemaining);
|
||||
|
||||
tm _time;
|
||||
tm* time = localtime_r(&finishTime, &_time);
|
||||
int32 year = time->tm_year + 1900;
|
||||
|
||||
char timeText[32];
|
||||
time_t secondsPerDay = 24 * 60 * 60;
|
||||
// TODO: Localization of time string...
|
||||
if (now < finishTime - secondsPerDay) {
|
||||
// process is going to take more than a day!
|
||||
sprintf(timeText, "%0*d:%0*d %0*d/%0*d/%ld",
|
||||
2, time->tm_hour, 2, time->tm_min,
|
||||
2, time->tm_mon + 1, 2, time->tm_mday, year);
|
||||
} else {
|
||||
sprintf(timeText, "%0*d:%0*d",
|
||||
2, time->tm_hour, 2, time->tm_min);
|
||||
}
|
||||
|
||||
BString buffer1("Finish: ");
|
||||
buffer1 << timeText;
|
||||
finishTime -= now;
|
||||
time = gmtime(&finishTime);
|
||||
|
||||
BString buffer2;
|
||||
if (finishTime > secondsPerDay) {
|
||||
int64 days = finishTime / secondsPerDay;
|
||||
if (days == 1)
|
||||
buffer2 << "Over 1 day";
|
||||
else
|
||||
buffer2 << "Over " << days << " days";
|
||||
} else if (finishTime > 60 * 60) {
|
||||
int64 hours = finishTime / (60 * 60);
|
||||
if (hours == 1)
|
||||
buffer2 << "Over 1 hour";
|
||||
else
|
||||
buffer2 << "Over " << hours << " hours";
|
||||
} else if (finishTime > 60) {
|
||||
int64 minutes = finishTime / 60;
|
||||
if (minutes == 1)
|
||||
buffer2 << "Over 1 minute";
|
||||
else
|
||||
buffer2 << minutes << " minutes";
|
||||
} else {
|
||||
if (finishTime == 1)
|
||||
buffer2 << "1 second";
|
||||
else
|
||||
buffer2 << finishTime << " seconds";
|
||||
}
|
||||
|
||||
buffer2 << " left";
|
||||
|
||||
buffer = "(";
|
||||
buffer << buffer1 << " - " << buffer2 << ")";
|
||||
|
||||
float stringWidth = fInfoView->StringWidth(buffer.String());
|
||||
if (stringWidth < fInfoView->Bounds().Width())
|
||||
fInfoView->SetText(buffer.String());
|
||||
else {
|
||||
// complete string too wide, try with shorter version
|
||||
buffer = "(";
|
||||
buffer << buffer1 << ")";
|
||||
stringWidth = fInfoView->StringWidth(buffer.String());
|
||||
if (stringWidth < fInfoView->Bounds().Width())
|
||||
fInfoView->SetText(buffer.String());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DownloadProgressView::_StartNodeMonitor(const BEntry& entry)
|
||||
{
|
||||
node_ref nref;
|
||||
if (entry.GetNodeRef(&nref) == B_OK)
|
||||
watch_node(&nref, B_WATCH_ALL, this);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DownloadProgressView::_StopNodeMonitor()
|
||||
{
|
||||
stop_watching(this);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef DOWNLOAD_PROGRESS_VIEW_H
|
||||
#define DOWNLOAD_PROGRESS_VIEW_H
|
||||
|
||||
|
||||
#include <GroupView.h>
|
||||
#include <Path.h>
|
||||
#include <String.h>
|
||||
|
||||
class BEntry;
|
||||
class BStatusBar;
|
||||
class BStringView;
|
||||
class BWebDownload;
|
||||
class IconView;
|
||||
class SmallButton;
|
||||
|
||||
|
||||
enum {
|
||||
SAVE_SETTINGS = 'svst'
|
||||
};
|
||||
|
||||
|
||||
class DownloadProgressView : public BGroupView {
|
||||
public:
|
||||
DownloadProgressView(BWebDownload* download);
|
||||
DownloadProgressView(const BMessage* archive);
|
||||
|
||||
bool Init(BMessage* archive = NULL);
|
||||
|
||||
status_t SaveSettings(BMessage* archive);
|
||||
virtual void AttachedToWindow();
|
||||
virtual void DetachedFromWindow();
|
||||
virtual void AllAttached();
|
||||
|
||||
virtual void Draw(BRect updateRect);
|
||||
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
|
||||
void ShowContextMenu(BPoint screenWhere);
|
||||
|
||||
BWebDownload* Download() const;
|
||||
const BString& URL() const;
|
||||
bool IsMissing() const;
|
||||
bool IsFinished() const;
|
||||
|
||||
void DownloadFinished();
|
||||
void DownloadCanceled();
|
||||
|
||||
static void SpeedVersusEstimatedFinishTogglePulse();
|
||||
|
||||
private:
|
||||
void _UpdateStatus(off_t currentSize,
|
||||
off_t expectedSize);
|
||||
void _UpdateStatusText();
|
||||
void _StartNodeMonitor(const BEntry& entry);
|
||||
void _StopNodeMonitor();
|
||||
|
||||
private:
|
||||
IconView* fIconView;
|
||||
BStatusBar* fStatusBar;
|
||||
BStringView* fInfoView;
|
||||
SmallButton* fTopButton;
|
||||
SmallButton* fBottomButton;
|
||||
BWebDownload* fDownload;
|
||||
BString fURL;
|
||||
BPath fPath;
|
||||
|
||||
off_t fCurrentSize;
|
||||
off_t fExpectedSize;
|
||||
off_t fLastSpeedReferenceSize;
|
||||
off_t fEstimatedFinishReferenceSize;
|
||||
bigtime_t fLastUpdateTime;
|
||||
bigtime_t fLastSpeedReferenceTime;
|
||||
bigtime_t fProcessStartTime;
|
||||
bigtime_t fLastSpeedUpdateTime;
|
||||
bigtime_t fEstimatedFinishReferenceTime;
|
||||
static const size_t kBytesPerSecondSlots = 10;
|
||||
size_t fCurrentBytesPerSecondSlot;
|
||||
double fBytesPerSecondSlot[kBytesPerSecondSlots];
|
||||
double fBytesPerSecond;
|
||||
|
||||
static bigtime_t sLastEstimatedFinishSpeedToggleTime;
|
||||
static bool sShowSpeed;
|
||||
};
|
||||
|
||||
#endif // DOWNLOAD_PROGRESS_VIEW_H
|
||||
@@ -0,0 +1,573 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "DownloadWindow.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <Alert.h>
|
||||
#include <Button.h>
|
||||
#include <ControlLook.h>
|
||||
#include <Entry.h>
|
||||
#include <File.h>
|
||||
#include <FindDirectory.h>
|
||||
#include <GroupLayout.h>
|
||||
#include <GroupLayoutBuilder.h>
|
||||
#include <MenuBar.h>
|
||||
#include <MenuItem.h>
|
||||
#include <Path.h>
|
||||
#include <Roster.h>
|
||||
#include <ScrollView.h>
|
||||
#include <SeparatorView.h>
|
||||
#include <SpaceLayoutItem.h>
|
||||
|
||||
#include "BrowserApp.h"
|
||||
#include "BrowserWindow.h"
|
||||
#include "DownloadProgressView.h"
|
||||
#include "SettingsKeys.h"
|
||||
#include "SettingsMessage.h"
|
||||
#include "WebDownload.h"
|
||||
#include "WebPage.h"
|
||||
|
||||
|
||||
enum {
|
||||
INIT = 'init',
|
||||
OPEN_DOWNLOADS_FOLDER = 'odnf',
|
||||
REMOVE_FINISHED_DOWNLOADS = 'rmfd',
|
||||
REMOVE_MISSING_DOWNLOADS = 'rmmd'
|
||||
};
|
||||
|
||||
|
||||
class DownloadsContainerView : public BGroupView {
|
||||
public:
|
||||
DownloadsContainerView()
|
||||
:
|
||||
BGroupView(B_VERTICAL, 0.0)
|
||||
{
|
||||
SetFlags(Flags() | B_PULSE_NEEDED);
|
||||
SetViewColor(245, 245, 245);
|
||||
AddChild(BSpaceLayoutItem::CreateGlue());
|
||||
}
|
||||
|
||||
virtual BSize MinSize()
|
||||
{
|
||||
BSize minSize = BGroupView::MinSize();
|
||||
return BSize(minSize.width, 80);
|
||||
}
|
||||
|
||||
virtual void Pulse()
|
||||
{
|
||||
DownloadProgressView::SpeedVersusEstimatedFinishTogglePulse();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void DoLayout()
|
||||
{
|
||||
BGroupView::DoLayout();
|
||||
if (BScrollBar* scrollBar = ScrollBar(B_VERTICAL)) {
|
||||
BSize minSize = BGroupView::MinSize();
|
||||
float height = Bounds().Height();
|
||||
float max = minSize.height - height;
|
||||
scrollBar->SetRange(0, max);
|
||||
if (minSize.height > 0)
|
||||
scrollBar->SetProportion(height / minSize.height);
|
||||
else
|
||||
scrollBar->SetProportion(1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class DownloadContainerScrollView : public BScrollView {
|
||||
public:
|
||||
DownloadContainerScrollView(BView* target)
|
||||
:
|
||||
BScrollView("Downloads scroll view", target, 0, false, true,
|
||||
B_NO_BORDER)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void DoLayout()
|
||||
{
|
||||
BScrollView::DoLayout();
|
||||
// Tweak scroll bar layout to hide part of the frame for better looks.
|
||||
BScrollBar* scrollBar = ScrollBar(B_VERTICAL);
|
||||
scrollBar->MoveBy(1, -1);
|
||||
scrollBar->ResizeBy(0, 2);
|
||||
Target()->ResizeBy(1, 0);
|
||||
// Set the scroll steps
|
||||
if (BView* item = Target()->ChildAt(0)) {
|
||||
scrollBar->SetSteps(item->MinSize().height + 1,
|
||||
item->MinSize().height + 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
DownloadWindow::DownloadWindow(BRect frame, bool visible,
|
||||
SettingsMessage* settings)
|
||||
: BWindow(frame, "Downloads",
|
||||
B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
|
||||
B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE),
|
||||
fMinimizeOnClose(false)
|
||||
{
|
||||
SetPulseRate(1000000);
|
||||
|
||||
settings->AddListener(BMessenger(this));
|
||||
BPath downloadPath;
|
||||
if (find_directory(B_DESKTOP_DIRECTORY, &downloadPath) != B_OK)
|
||||
downloadPath.SetTo("/boot/home/Desktop");
|
||||
fDownloadPath = settings->GetValue(kSettingsKeyDownloadPath,
|
||||
downloadPath.Path());
|
||||
settings->SetValue(kSettingsKeyDownloadPath, fDownloadPath);
|
||||
|
||||
SetLayout(new BGroupLayout(B_VERTICAL, 0.0));
|
||||
|
||||
DownloadsContainerView* downloadsGroupView = new DownloadsContainerView();
|
||||
fDownloadViewsLayout = downloadsGroupView->GroupLayout();
|
||||
|
||||
BMenuBar* menuBar = new BMenuBar("Menu bar");
|
||||
BMenu* menu = new BMenu("Downloads");
|
||||
menu->AddItem(new BMenuItem("Open downloads folder",
|
||||
new BMessage(OPEN_DOWNLOADS_FOLDER)));
|
||||
BMessage* newWindowMessage = new BMessage(NEW_WINDOW);
|
||||
newWindowMessage->AddString("url", "");
|
||||
BMenuItem* newWindowItem = new BMenuItem("New browser window",
|
||||
newWindowMessage, 'N');
|
||||
menu->AddItem(newWindowItem);
|
||||
newWindowItem->SetTarget(be_app);
|
||||
menu->AddSeparatorItem();
|
||||
menu->AddItem(new BMenuItem("Hide", new BMessage(B_QUIT_REQUESTED), 'D'));
|
||||
menuBar->AddItem(menu);
|
||||
|
||||
fDownloadsScrollView = new DownloadContainerScrollView(downloadsGroupView);
|
||||
|
||||
fRemoveFinishedButton = new BButton("Remove finished",
|
||||
new BMessage(REMOVE_FINISHED_DOWNLOADS));
|
||||
fRemoveFinishedButton->SetEnabled(false);
|
||||
|
||||
fRemoveMissingButton = new BButton("Remove missing",
|
||||
new BMessage(REMOVE_MISSING_DOWNLOADS));
|
||||
fRemoveMissingButton->SetEnabled(false);
|
||||
|
||||
const float spacing = be_control_look->DefaultItemSpacing();
|
||||
|
||||
AddChild(BGroupLayoutBuilder(B_VERTICAL, 0.0)
|
||||
.Add(menuBar)
|
||||
.Add(fDownloadsScrollView)
|
||||
.Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER))
|
||||
.Add(BGroupLayoutBuilder(B_HORIZONTAL, spacing)
|
||||
.AddGlue()
|
||||
.Add(fRemoveMissingButton)
|
||||
.Add(fRemoveFinishedButton)
|
||||
.SetInsets(12, 5, 12, 5)
|
||||
)
|
||||
);
|
||||
|
||||
PostMessage(INIT);
|
||||
|
||||
if (!visible)
|
||||
Hide();
|
||||
Show();
|
||||
}
|
||||
|
||||
|
||||
DownloadWindow::~DownloadWindow()
|
||||
{
|
||||
// Only necessary to save the current progress of unfinished downloads:
|
||||
_SaveSettings();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DownloadWindow::DispatchMessage(BMessage* message, BHandler* target)
|
||||
{
|
||||
// We need to intercept mouse down events inside the area of download
|
||||
// progress views (regardless of whether they have children at the click),
|
||||
// so that they may display a context menu.
|
||||
BPoint where;
|
||||
int32 buttons;
|
||||
if (message->what == B_MOUSE_DOWN
|
||||
&& message->FindPoint("screen_where", &where) == B_OK
|
||||
&& message->FindInt32("buttons", &buttons) == B_OK
|
||||
&& (buttons & B_SECONDARY_MOUSE_BUTTON) != 0) {
|
||||
for (int32 i = fDownloadViewsLayout->CountItems() - 1;
|
||||
BLayoutItem* item = fDownloadViewsLayout->ItemAt(i); i--) {
|
||||
DownloadProgressView* view = dynamic_cast<DownloadProgressView*>(
|
||||
item->View());
|
||||
if (!view)
|
||||
continue;
|
||||
BPoint viewWhere(where);
|
||||
view->ConvertFromScreen(&viewWhere);
|
||||
if (view->Bounds().Contains(viewWhere)) {
|
||||
view->ShowContextMenu(where);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
BWindow::DispatchMessage(message, target);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DownloadWindow::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch (message->what) {
|
||||
case INIT:
|
||||
{
|
||||
_LoadSettings();
|
||||
// Small trick to get the correct enabled status of the Remove
|
||||
// finished button
|
||||
_DownloadFinished(NULL);
|
||||
break;
|
||||
}
|
||||
case B_DOWNLOAD_ADDED:
|
||||
{
|
||||
BWebDownload* download;
|
||||
if (message->FindPointer("download", reinterpret_cast<void**>(
|
||||
&download)) == B_OK) {
|
||||
_DownloadStarted(download);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case B_DOWNLOAD_REMOVED:
|
||||
{
|
||||
BWebDownload* download;
|
||||
if (message->FindPointer("download", reinterpret_cast<void**>(
|
||||
&download)) == B_OK) {
|
||||
_DownloadFinished(download);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OPEN_DOWNLOADS_FOLDER:
|
||||
{
|
||||
entry_ref ref;
|
||||
status_t status = get_ref_for_path(fDownloadPath.String(), &ref);
|
||||
if (status == B_OK)
|
||||
status = be_roster->Launch(&ref);
|
||||
if (status != B_OK && status != B_ALREADY_RUNNING) {
|
||||
BString errorString("The downloads folder could not be "
|
||||
"opened.\n\n");
|
||||
errorString << "Error: " << strerror(status);
|
||||
BAlert* alert = new BAlert("Error opening downloads folder",
|
||||
errorString.String(), "OK");
|
||||
alert->Go(NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case REMOVE_FINISHED_DOWNLOADS:
|
||||
_RemoveFinishedDownloads();
|
||||
break;
|
||||
case REMOVE_MISSING_DOWNLOADS:
|
||||
_RemoveMissingDownloads();
|
||||
break;
|
||||
case SAVE_SETTINGS:
|
||||
_ValidateButtonStatus();
|
||||
_SaveSettings();
|
||||
break;
|
||||
|
||||
case SETTINGS_VALUE_CHANGED:
|
||||
{
|
||||
BString string;
|
||||
if (message->FindString("name", &string) == B_OK
|
||||
&& string == kSettingsKeyDownloadPath
|
||||
&& message->FindString("value", &string) == B_OK) {
|
||||
fDownloadPath = string;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
BWindow::MessageReceived(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DownloadWindow::QuitRequested()
|
||||
{
|
||||
if (fMinimizeOnClose) {
|
||||
if (!IsMinimized())
|
||||
Minimize(true);
|
||||
} else {
|
||||
if (!IsHidden())
|
||||
Hide();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DownloadWindow::DownloadsInProgress()
|
||||
{
|
||||
bool downloadsInProgress = false;
|
||||
if (!Lock())
|
||||
return downloadsInProgress;
|
||||
|
||||
for (int32 i = fDownloadViewsLayout->CountItems() - 1;
|
||||
BLayoutItem* item = fDownloadViewsLayout->ItemAt(i); i--) {
|
||||
DownloadProgressView* view = dynamic_cast<DownloadProgressView*>(
|
||||
item->View());
|
||||
if (!view)
|
||||
continue;
|
||||
if (view->Download() != NULL) {
|
||||
downloadsInProgress = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Unlock();
|
||||
|
||||
return downloadsInProgress;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DownloadWindow::SetMinimizeOnClose(bool minimize)
|
||||
{
|
||||
if (Lock()) {
|
||||
fMinimizeOnClose = minimize;
|
||||
Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - private
|
||||
|
||||
|
||||
void
|
||||
DownloadWindow::_DownloadStarted(BWebDownload* download)
|
||||
{
|
||||
download->Start(BPath(fDownloadPath.String()));
|
||||
|
||||
int32 finishedCount = 0;
|
||||
int32 missingCount = 0;
|
||||
int32 index = 0;
|
||||
for (int32 i = fDownloadViewsLayout->CountItems() - 1;
|
||||
BLayoutItem* item = fDownloadViewsLayout->ItemAt(i); i--) {
|
||||
DownloadProgressView* view = dynamic_cast<DownloadProgressView*>(
|
||||
item->View());
|
||||
if (!view)
|
||||
continue;
|
||||
if (view->URL() == download->URL()) {
|
||||
index = i;
|
||||
view->RemoveSelf();
|
||||
delete view;
|
||||
continue;
|
||||
}
|
||||
if (view->IsFinished())
|
||||
finishedCount++;
|
||||
if (view->IsMissing())
|
||||
missingCount++;
|
||||
}
|
||||
fRemoveFinishedButton->SetEnabled(finishedCount > 0);
|
||||
fRemoveMissingButton->SetEnabled(missingCount > 0);
|
||||
DownloadProgressView* view = new DownloadProgressView(download);
|
||||
if (!view->Init()) {
|
||||
delete view;
|
||||
return;
|
||||
}
|
||||
fDownloadViewsLayout->AddView(index, view);
|
||||
|
||||
// Scroll new download into view
|
||||
if (BScrollBar* scrollBar = fDownloadsScrollView->ScrollBar(B_VERTICAL)) {
|
||||
float min;
|
||||
float max;
|
||||
scrollBar->GetRange(&min, &max);
|
||||
float viewHeight = view->MinSize().height + 1;
|
||||
float scrollOffset = min + index * viewHeight;
|
||||
float scrollBarHeight = scrollBar->Bounds().Height() - 1;
|
||||
float value = scrollBar->Value();
|
||||
if (scrollOffset < value)
|
||||
scrollBar->SetValue(scrollOffset);
|
||||
else if (scrollOffset + viewHeight > value + scrollBarHeight) {
|
||||
float diff = scrollOffset + viewHeight - (value + scrollBarHeight);
|
||||
scrollBar->SetValue(value + diff);
|
||||
}
|
||||
}
|
||||
|
||||
_SaveSettings();
|
||||
|
||||
SetWorkspaces(B_CURRENT_WORKSPACE);
|
||||
if (IsHidden())
|
||||
Show();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DownloadWindow::_DownloadFinished(BWebDownload* download)
|
||||
{
|
||||
int32 finishedCount = 0;
|
||||
int32 missingCount = 0;
|
||||
for (int32 i = 0;
|
||||
BLayoutItem* item = fDownloadViewsLayout->ItemAt(i); i++) {
|
||||
DownloadProgressView* view = dynamic_cast<DownloadProgressView*>(
|
||||
item->View());
|
||||
if (!view)
|
||||
continue;
|
||||
if (download && view->Download() == download) {
|
||||
view->DownloadFinished();
|
||||
finishedCount++;
|
||||
continue;
|
||||
}
|
||||
if (view->IsFinished())
|
||||
finishedCount++;
|
||||
if (view->IsMissing())
|
||||
missingCount++;
|
||||
}
|
||||
fRemoveFinishedButton->SetEnabled(finishedCount > 0);
|
||||
fRemoveMissingButton->SetEnabled(missingCount > 0);
|
||||
if (download)
|
||||
_SaveSettings();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DownloadWindow::_RemoveFinishedDownloads()
|
||||
{
|
||||
int32 missingCount = 0;
|
||||
for (int32 i = fDownloadViewsLayout->CountItems() - 1;
|
||||
BLayoutItem* item = fDownloadViewsLayout->ItemAt(i); i--) {
|
||||
DownloadProgressView* view = dynamic_cast<DownloadProgressView*>(
|
||||
item->View());
|
||||
if (!view)
|
||||
continue;
|
||||
if (view->IsFinished()) {
|
||||
view->RemoveSelf();
|
||||
delete view;
|
||||
} else if (view->IsMissing())
|
||||
missingCount++;
|
||||
}
|
||||
fRemoveFinishedButton->SetEnabled(false);
|
||||
fRemoveMissingButton->SetEnabled(missingCount > 0);
|
||||
_SaveSettings();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DownloadWindow::_RemoveMissingDownloads()
|
||||
{
|
||||
int32 finishedCount = 0;
|
||||
for (int32 i = fDownloadViewsLayout->CountItems() - 1;
|
||||
BLayoutItem* item = fDownloadViewsLayout->ItemAt(i); i--) {
|
||||
DownloadProgressView* view = dynamic_cast<DownloadProgressView*>(
|
||||
item->View());
|
||||
if (!view)
|
||||
continue;
|
||||
if (view->IsMissing()) {
|
||||
view->RemoveSelf();
|
||||
delete view;
|
||||
} else if (view->IsFinished())
|
||||
finishedCount++;
|
||||
}
|
||||
fRemoveMissingButton->SetEnabled(false);
|
||||
fRemoveFinishedButton->SetEnabled(finishedCount > 0);
|
||||
_SaveSettings();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DownloadWindow::_ValidateButtonStatus()
|
||||
{
|
||||
int32 finishedCount = 0;
|
||||
int32 missingCount = 0;
|
||||
for (int32 i = fDownloadViewsLayout->CountItems() - 1;
|
||||
BLayoutItem* item = fDownloadViewsLayout->ItemAt(i); i--) {
|
||||
DownloadProgressView* view = dynamic_cast<DownloadProgressView*>(
|
||||
item->View());
|
||||
if (!view)
|
||||
continue;
|
||||
if (view->IsFinished())
|
||||
finishedCount++;
|
||||
if (view->IsMissing())
|
||||
missingCount++;
|
||||
}
|
||||
fRemoveFinishedButton->SetEnabled(finishedCount > 0);
|
||||
fRemoveMissingButton->SetEnabled(missingCount > 0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DownloadWindow::_SaveSettings()
|
||||
{
|
||||
BFile file;
|
||||
if (!_OpenSettingsFile(file, B_ERASE_FILE | B_CREATE_FILE | B_WRITE_ONLY))
|
||||
return;
|
||||
BMessage message;
|
||||
for (int32 i = fDownloadViewsLayout->CountItems() - 1;
|
||||
BLayoutItem* item = fDownloadViewsLayout->ItemAt(i); i--) {
|
||||
DownloadProgressView* view = dynamic_cast<DownloadProgressView*>(
|
||||
item->View());
|
||||
if (!view)
|
||||
continue;
|
||||
BMessage downloadArchive;
|
||||
if (view->SaveSettings(&downloadArchive) == B_OK)
|
||||
message.AddMessage("download", &downloadArchive);
|
||||
}
|
||||
message.Flatten(&file);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DownloadWindow::_LoadSettings()
|
||||
{
|
||||
BFile file;
|
||||
if (!_OpenSettingsFile(file, B_READ_ONLY))
|
||||
return;
|
||||
BMessage message;
|
||||
if (message.Unflatten(&file) != B_OK)
|
||||
return;
|
||||
BMessage downloadArchive;
|
||||
for (int32 i = 0;
|
||||
message.FindMessage("download", i, &downloadArchive) == B_OK;
|
||||
i++) {
|
||||
DownloadProgressView* view = new DownloadProgressView(
|
||||
&downloadArchive);
|
||||
if (!view->Init(&downloadArchive))
|
||||
continue;
|
||||
fDownloadViewsLayout->AddView(0, view);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DownloadWindow::_OpenSettingsFile(BFile& file, uint32 mode)
|
||||
{
|
||||
BPath path;
|
||||
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK
|
||||
|| path.Append(kApplicationName) != B_OK
|
||||
|| path.Append("Downloads") != B_OK) {
|
||||
return false;
|
||||
}
|
||||
return file.SetTo(path.Path(), mode) == B_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef DOWNLOAD_WINDOW_H
|
||||
#define DOWNLOAD_WINDOW_H
|
||||
|
||||
|
||||
#include <String.h>
|
||||
#include <Window.h>
|
||||
|
||||
class BButton;
|
||||
class BFile;
|
||||
class BGroupLayout;
|
||||
class BScrollView;
|
||||
class BWebDownload;
|
||||
class SettingsMessage;
|
||||
|
||||
|
||||
class DownloadWindow : public BWindow {
|
||||
public:
|
||||
DownloadWindow(BRect frame, bool visible,
|
||||
SettingsMessage* settings);
|
||||
virtual ~DownloadWindow();
|
||||
|
||||
virtual void DispatchMessage(BMessage* message,
|
||||
BHandler* target);
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
virtual bool QuitRequested();
|
||||
|
||||
bool DownloadsInProgress();
|
||||
void SetMinimizeOnClose(bool minimize);
|
||||
|
||||
private:
|
||||
void _DownloadStarted(BWebDownload* download);
|
||||
void _DownloadFinished(BWebDownload* download);
|
||||
void _RemoveFinishedDownloads();
|
||||
void _RemoveMissingDownloads();
|
||||
void _ValidateButtonStatus();
|
||||
void _SaveSettings();
|
||||
void _LoadSettings();
|
||||
bool _OpenSettingsFile(BFile& file, uint32 mode);
|
||||
|
||||
private:
|
||||
BScrollView* fDownloadsScrollView;
|
||||
BGroupLayout* fDownloadViewsLayout;
|
||||
BButton* fRemoveFinishedButton;
|
||||
BButton* fRemoveMissingButton;
|
||||
BString fDownloadPath;
|
||||
bool fMinimizeOnClose;
|
||||
};
|
||||
|
||||
#endif // DOWNLOAD_WINDOW_H
|
||||
@@ -0,0 +1,71 @@
|
||||
SubDir HAIKU_TOP src apps webpositive ;
|
||||
|
||||
SubDirSysHdrs $(HAIKU_WEBKIT_HEADERS) ;
|
||||
|
||||
SubDirC++Flags $(defines) -Wno-error=sequence-point ;
|
||||
SubDirCcFlags $(defines) -Wno-error=sequence-point ;
|
||||
|
||||
# source directories
|
||||
local sourceDirs =
|
||||
autocompletion
|
||||
support
|
||||
tabview
|
||||
;
|
||||
|
||||
local sourceDir ;
|
||||
for sourceDir in $(sourceDirs) {
|
||||
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src apps webpositive $(sourceDir) ] ;
|
||||
}
|
||||
|
||||
local sources =
|
||||
# autocompletion
|
||||
AutoCompleter.cpp
|
||||
AutoCompleterDefaultImpl.cpp
|
||||
TextViewCompleter.cpp
|
||||
|
||||
# support
|
||||
BaseURL.cpp
|
||||
BitmapButton.cpp
|
||||
DateTime.cpp
|
||||
FontSelectionView.cpp
|
||||
IconButton.cpp
|
||||
SettingsMessage.cpp
|
||||
StringForSize.cpp
|
||||
|
||||
# tabview
|
||||
TabContainerView.cpp
|
||||
TabManager.cpp
|
||||
TabView.cpp
|
||||
|
||||
AuthenticationPanel.cpp
|
||||
BrowserApp.cpp
|
||||
BrowserWindow.cpp
|
||||
BrowsingHistory.cpp
|
||||
CredentialsStorage.cpp
|
||||
DownloadProgressView.cpp
|
||||
DownloadWindow.cpp
|
||||
SettingsKeys.cpp
|
||||
SettingsWindow.cpp
|
||||
svn_revision.cpp
|
||||
URLInputGroup.cpp
|
||||
;
|
||||
|
||||
|
||||
Includes [ FGristFiles $(sources) ] : $(HAIKU_WEBKIT_HEADERS_DEPENDENCY) ;
|
||||
# Dependency needed to trigger downloading/unzipping the package before
|
||||
# compiling the files.
|
||||
|
||||
# SVN revision
|
||||
#local svnRevisionFile = [ FGristFiles svn_revision ] ;
|
||||
#MakeLocate $(svnRevisionFile) : $(LOCATE_TARGET) ;
|
||||
#CreateSVNRevisionFile $(svnRevisionFile) ;
|
||||
|
||||
Application WebPositive :
|
||||
$(sources)
|
||||
:
|
||||
$(HAIKU_WEBKIT_LIBS)
|
||||
$(TARGET_LIBSTDC++) $(HAIKU_LOCALE_LIBS)
|
||||
be network tracker translation
|
||||
:
|
||||
WebPositive.rdef
|
||||
;
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "SettingsKeys.h"
|
||||
|
||||
const char* kSettingsKeyDownloadPath = "download path";
|
||||
const char* kSettingsKeyShowTabsIfSinglePageOpen
|
||||
= "show tabs if single page open";
|
||||
const char* kSettingsKeyAutoHideInterfaceInFullscreenMode
|
||||
= "auto hide interface in full screen mode";
|
||||
const char* kSettingsKeyAutoHidePointer = "auto hide pointer";
|
||||
const char* kSettingsKeyShowHomeButton = "show home button";
|
||||
|
||||
const char* kSettingsKeyNewWindowPolicy = "new window policy";
|
||||
const char* kSettingsKeyNewTabPolicy = "new tab policy";
|
||||
const char* kSettingsKeyStartPageURL = "start page url";
|
||||
const char* kSettingsKeySearchPageURL = "search page url";
|
||||
|
||||
|
||||
const char* kDefaultDownloadPath = "/boot/home/Desktop/";
|
||||
const char* kDefaultStartPageURL
|
||||
= "file:///boot/home/config/settings/WebPositive/LoaderPages/Welcome";
|
||||
const char* kDefaultSearchPageURL = "http://www.google.com";
|
||||
|
||||
const char* kSettingsKeyUseProxy = "use http proxy";
|
||||
const char* kSettingsKeyProxyAddress = "http proxy address";
|
||||
const char* kSettingsKeyProxyPort = "http proxy port";
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef SETTINGS_KEYS_H
|
||||
#define SETTINGS_KEYS_H
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
|
||||
extern const char* kSettingsKeyDownloadPath;
|
||||
extern const char* kSettingsKeyShowTabsIfSinglePageOpen;
|
||||
extern const char* kSettingsKeyAutoHideInterfaceInFullscreenMode;
|
||||
extern const char* kSettingsKeyAutoHidePointer;
|
||||
extern const char* kSettingsKeyShowHomeButton;
|
||||
|
||||
extern const char* kSettingsKeyNewWindowPolicy;
|
||||
extern const char* kSettingsKeyNewTabPolicy;
|
||||
extern const char* kSettingsKeyStartPageURL;
|
||||
extern const char* kSettingsKeySearchPageURL;
|
||||
|
||||
extern const char* kDefaultDownloadPath;
|
||||
extern const char* kDefaultStartPageURL;
|
||||
extern const char* kDefaultSearchPageURL;
|
||||
|
||||
extern const char* kSettingsKeyUseProxy;
|
||||
extern const char* kSettingsKeyProxyAddress;
|
||||
extern const char* kSettingsKeyProxyPort;
|
||||
|
||||
#endif // SETTINGS_KEYS_H
|
||||
@@ -0,0 +1,885 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "SettingsWindow.h"
|
||||
|
||||
#include <Button.h>
|
||||
#include <CheckBox.h>
|
||||
#include <ControlLook.h>
|
||||
#include <GridLayoutBuilder.h>
|
||||
#include <GroupLayout.h>
|
||||
#include <GroupLayoutBuilder.h>
|
||||
#include <Locale.h>
|
||||
#include <MenuItem.h>
|
||||
#include <MenuField.h>
|
||||
#include <Message.h>
|
||||
#include <PopUpMenu.h>
|
||||
#include <ScrollView.h>
|
||||
#include <SeparatorView.h>
|
||||
#include <SpaceLayoutItem.h>
|
||||
#include <TabView.h>
|
||||
#include <TextControl.h>
|
||||
#include <debugger.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "BrowserApp.h"
|
||||
#include "BrowsingHistory.h"
|
||||
#include "BrowserWindow.h"
|
||||
#include "FontSelectionView.h"
|
||||
#include "SettingsKeys.h"
|
||||
#include "SettingsMessage.h"
|
||||
#include "WebSettings.h"
|
||||
|
||||
|
||||
#undef B_TRANSLATION_CONTEXT
|
||||
#define B_TRANSLATION_CONTEXT "Settings Window"
|
||||
|
||||
enum {
|
||||
MSG_APPLY = 'aply',
|
||||
MSG_CANCEL = 'cncl',
|
||||
MSG_REVERT = 'rvrt',
|
||||
|
||||
MSG_START_PAGE_CHANGED = 'hpch',
|
||||
MSG_SEARCH_PAGE_CHANGED = 'spch',
|
||||
MSG_DOWNLOAD_FOLDER_CHANGED = 'dnfc',
|
||||
MSG_NEW_WINDOWS_BEHAVIOR_CHANGED = 'nwbc',
|
||||
MSG_NEW_TABS_BEHAVIOR_CHANGED = 'ntbc',
|
||||
MSG_HISTORY_MENU_DAYS_CHANGED = 'digm',
|
||||
MSG_TAB_DISPLAY_BEHAVIOR_CHANGED = 'tdbc',
|
||||
MSG_AUTO_HIDE_INTERFACE_BEHAVIOR_CHANGED = 'ahic',
|
||||
MSG_AUTO_HIDE_POINTER_BEHAVIOR_CHANGED = 'ahpc',
|
||||
MSG_SHOW_HOME_BUTTON_CHANGED = 'shbc',
|
||||
|
||||
MSG_STANDARD_FONT_CHANGED = 'stfc',
|
||||
MSG_SERIF_FONT_CHANGED = 'sefc',
|
||||
MSG_SANS_SERIF_FONT_CHANGED = 'ssfc',
|
||||
MSG_FIXED_FONT_CHANGED = 'ffch',
|
||||
|
||||
MSG_STANDARD_FONT_SIZE_SELECTED = 'sfss',
|
||||
MSG_FIXED_FONT_SIZE_SELECTED = 'ffss',
|
||||
|
||||
MSG_USE_PROXY_CHANGED = 'upsc',
|
||||
MSG_PROXY_ADDRESS_CHANGED = 'psac',
|
||||
MSG_PROXY_PORT_CHANGED = 'pspc',
|
||||
};
|
||||
|
||||
static const int32 kDefaultFontSize = 14;
|
||||
|
||||
|
||||
SettingsWindow::SettingsWindow(BRect frame, SettingsMessage* settings)
|
||||
:
|
||||
BWindow(frame, B_TRANSLATE("Settings"), B_TITLED_WINDOW_LOOK,
|
||||
B_NORMAL_WINDOW_FEEL, B_AUTO_UPDATE_SIZE_LIMITS
|
||||
| B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE),
|
||||
fSettings(settings)
|
||||
{
|
||||
SetLayout(new BGroupLayout(B_VERTICAL));
|
||||
|
||||
fApplyButton = new BButton(B_TRANSLATE("Apply"), new BMessage(MSG_APPLY));
|
||||
fCancelButton = new BButton(B_TRANSLATE("Cancel"),
|
||||
new BMessage(MSG_CANCEL));
|
||||
fRevertButton = new BButton(B_TRANSLATE("Revert"),
|
||||
new BMessage(MSG_REVERT));
|
||||
|
||||
float spacing = be_control_look->DefaultItemSpacing();
|
||||
|
||||
BTabView* tabView = new BTabView("settings pages", B_WIDTH_FROM_LABEL);
|
||||
|
||||
AddChild(BGroupLayoutBuilder(B_VERTICAL, spacing)
|
||||
.Add(tabView)
|
||||
.Add(BGroupLayoutBuilder(B_HORIZONTAL, spacing)
|
||||
.Add(fRevertButton)
|
||||
.AddGlue()
|
||||
.Add(fCancelButton)
|
||||
.Add(fApplyButton)
|
||||
)
|
||||
.SetInsets(spacing, spacing, spacing, spacing)
|
||||
);
|
||||
|
||||
tabView->AddTab(_CreateGeneralPage(spacing));
|
||||
tabView->AddTab(_CreateFontsPage(spacing));
|
||||
tabView->AddTab(_CreateProxyPage(spacing));
|
||||
|
||||
_SetupFontSelectionView(fStandardFontView,
|
||||
new BMessage(MSG_STANDARD_FONT_CHANGED));
|
||||
_SetupFontSelectionView(fSerifFontView,
|
||||
new BMessage(MSG_SERIF_FONT_CHANGED));
|
||||
_SetupFontSelectionView(fSansSerifFontView,
|
||||
new BMessage(MSG_SANS_SERIF_FONT_CHANGED));
|
||||
_SetupFontSelectionView(fFixedFontView,
|
||||
new BMessage(MSG_FIXED_FONT_CHANGED));
|
||||
|
||||
fApplyButton->MakeDefault(true);
|
||||
|
||||
if (!frame.IsValid())
|
||||
CenterOnScreen();
|
||||
|
||||
// load settings from disk
|
||||
_RevertSettings();
|
||||
// apply to WebKit
|
||||
_ApplySettings();
|
||||
|
||||
// Start hidden
|
||||
Hide();
|
||||
Show();
|
||||
}
|
||||
|
||||
|
||||
SettingsWindow::~SettingsWindow()
|
||||
{
|
||||
RemoveHandler(fStandardFontView);
|
||||
delete fStandardFontView;
|
||||
RemoveHandler(fSerifFontView);
|
||||
delete fSerifFontView;
|
||||
RemoveHandler(fSansSerifFontView);
|
||||
delete fSansSerifFontView;
|
||||
RemoveHandler(fFixedFontView);
|
||||
delete fFixedFontView;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SettingsWindow::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch (message->what) {
|
||||
case MSG_APPLY:
|
||||
_ApplySettings();
|
||||
break;
|
||||
case MSG_CANCEL:
|
||||
_RevertSettings();
|
||||
PostMessage(B_QUIT_REQUESTED);
|
||||
break;
|
||||
case MSG_REVERT:
|
||||
_RevertSettings();
|
||||
break;
|
||||
|
||||
case MSG_STANDARD_FONT_SIZE_SELECTED:
|
||||
{
|
||||
int32 size = _SizesMenuValue(fStandardSizesMenu->Menu());
|
||||
fStandardFontView->SetSize(size);
|
||||
fSerifFontView->SetSize(size);
|
||||
fSansSerifFontView->SetSize(size);
|
||||
_ValidateControlsEnabledStatus();
|
||||
break;
|
||||
}
|
||||
case MSG_FIXED_FONT_SIZE_SELECTED:
|
||||
{
|
||||
int32 size = _SizesMenuValue(fFixedSizesMenu->Menu());
|
||||
fFixedFontView->SetSize(size);
|
||||
_ValidateControlsEnabledStatus();
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_START_PAGE_CHANGED:
|
||||
case MSG_SEARCH_PAGE_CHANGED:
|
||||
case MSG_DOWNLOAD_FOLDER_CHANGED:
|
||||
case MSG_NEW_WINDOWS_BEHAVIOR_CHANGED:
|
||||
case MSG_NEW_TABS_BEHAVIOR_CHANGED:
|
||||
case MSG_HISTORY_MENU_DAYS_CHANGED:
|
||||
case MSG_TAB_DISPLAY_BEHAVIOR_CHANGED:
|
||||
case MSG_AUTO_HIDE_INTERFACE_BEHAVIOR_CHANGED:
|
||||
case MSG_AUTO_HIDE_POINTER_BEHAVIOR_CHANGED:
|
||||
case MSG_SHOW_HOME_BUTTON_CHANGED:
|
||||
case MSG_STANDARD_FONT_CHANGED:
|
||||
case MSG_SERIF_FONT_CHANGED:
|
||||
case MSG_SANS_SERIF_FONT_CHANGED:
|
||||
case MSG_FIXED_FONT_CHANGED:
|
||||
case MSG_USE_PROXY_CHANGED:
|
||||
case MSG_PROXY_ADDRESS_CHANGED:
|
||||
case MSG_PROXY_PORT_CHANGED:
|
||||
// TODO: Some settings could change live, some others not?
|
||||
_ValidateControlsEnabledStatus();
|
||||
break;
|
||||
|
||||
default:
|
||||
BWindow::MessageReceived(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
SettingsWindow::QuitRequested()
|
||||
{
|
||||
if (!IsHidden())
|
||||
Hide();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SettingsWindow::Show()
|
||||
{
|
||||
// When showing the window, the this is always the
|
||||
// point to which we can revert the settings.
|
||||
_RevertSettings();
|
||||
BWindow::Show();
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - private
|
||||
|
||||
|
||||
BView*
|
||||
SettingsWindow::_CreateGeneralPage(float spacing)
|
||||
{
|
||||
fStartPageControl = new BTextControl("start page",
|
||||
B_TRANSLATE("Start page:"), "", new BMessage(MSG_START_PAGE_CHANGED));
|
||||
fStartPageControl->SetModificationMessage(
|
||||
new BMessage(MSG_START_PAGE_CHANGED));
|
||||
fStartPageControl->SetText(
|
||||
fSettings->GetValue(kSettingsKeyStartPageURL, kDefaultStartPageURL));
|
||||
|
||||
fSearchPageControl = new BTextControl("search page",
|
||||
B_TRANSLATE("Search page:"), "",
|
||||
new BMessage(MSG_SEARCH_PAGE_CHANGED));
|
||||
fSearchPageControl->SetModificationMessage(
|
||||
new BMessage(MSG_SEARCH_PAGE_CHANGED));
|
||||
fSearchPageControl->SetText(
|
||||
fSettings->GetValue(kSettingsKeySearchPageURL, kDefaultSearchPageURL));
|
||||
|
||||
fDownloadFolderControl = new BTextControl("download folder",
|
||||
B_TRANSLATE("Download folder:"), "",
|
||||
new BMessage(MSG_DOWNLOAD_FOLDER_CHANGED));
|
||||
fDownloadFolderControl->SetModificationMessage(
|
||||
new BMessage(MSG_DOWNLOAD_FOLDER_CHANGED));
|
||||
fDownloadFolderControl->SetText(
|
||||
fSettings->GetValue(kSettingsKeyDownloadPath, kDefaultDownloadPath));
|
||||
|
||||
fNewWindowBehaviorOpenHomeItem = new BMenuItem(
|
||||
B_TRANSLATE("Open start page"),
|
||||
new BMessage(MSG_NEW_WINDOWS_BEHAVIOR_CHANGED));
|
||||
fNewWindowBehaviorOpenSearchItem = new BMenuItem(
|
||||
B_TRANSLATE("Open search page"),
|
||||
new BMessage(MSG_NEW_WINDOWS_BEHAVIOR_CHANGED));
|
||||
fNewWindowBehaviorOpenBlankItem = new BMenuItem(
|
||||
B_TRANSLATE("Open blank page"),
|
||||
new BMessage(MSG_NEW_WINDOWS_BEHAVIOR_CHANGED));
|
||||
|
||||
fNewTabBehaviorCloneCurrentItem = new BMenuItem(
|
||||
B_TRANSLATE("Clone current page"),
|
||||
new BMessage(MSG_NEW_TABS_BEHAVIOR_CHANGED));
|
||||
fNewTabBehaviorOpenHomeItem = new BMenuItem(
|
||||
B_TRANSLATE("Open start page"),
|
||||
new BMessage(MSG_NEW_TABS_BEHAVIOR_CHANGED));
|
||||
fNewTabBehaviorOpenSearchItem = new BMenuItem(
|
||||
B_TRANSLATE("Open search page"),
|
||||
new BMessage(MSG_NEW_TABS_BEHAVIOR_CHANGED));
|
||||
fNewTabBehaviorOpenBlankItem = new BMenuItem(
|
||||
B_TRANSLATE("Open blank page"),
|
||||
new BMessage(MSG_NEW_TABS_BEHAVIOR_CHANGED));
|
||||
|
||||
fNewWindowBehaviorOpenHomeItem->SetMarked(true);
|
||||
fNewTabBehaviorOpenBlankItem->SetMarked(true);
|
||||
|
||||
BPopUpMenu* newWindowBehaviorMenu = new BPopUpMenu("New windows");
|
||||
newWindowBehaviorMenu->AddItem(fNewWindowBehaviorOpenHomeItem);
|
||||
newWindowBehaviorMenu->AddItem(fNewWindowBehaviorOpenSearchItem);
|
||||
newWindowBehaviorMenu->AddItem(fNewWindowBehaviorOpenBlankItem);
|
||||
fNewWindowBehaviorMenu = new BMenuField("new window behavior",
|
||||
B_TRANSLATE("New windows:"), newWindowBehaviorMenu);
|
||||
|
||||
BPopUpMenu* newTabBehaviorMenu = new BPopUpMenu("New tabs");
|
||||
newTabBehaviorMenu->AddItem(fNewTabBehaviorOpenBlankItem);
|
||||
newTabBehaviorMenu->AddItem(fNewTabBehaviorOpenHomeItem);
|
||||
newTabBehaviorMenu->AddItem(fNewTabBehaviorOpenSearchItem);
|
||||
newTabBehaviorMenu->AddItem(fNewTabBehaviorCloneCurrentItem);
|
||||
fNewTabBehaviorMenu = new BMenuField("new tab behavior",
|
||||
B_TRANSLATE("New tabs:"), newTabBehaviorMenu);
|
||||
|
||||
fDaysInHistoryMenuControl = new BTextControl("days in history",
|
||||
B_TRANSLATE("Number of days to keep links in History menu:"), "",
|
||||
new BMessage(MSG_HISTORY_MENU_DAYS_CHANGED));
|
||||
fDaysInHistoryMenuControl->SetModificationMessage(
|
||||
new BMessage(MSG_HISTORY_MENU_DAYS_CHANGED));
|
||||
BString maxHistoryAge;
|
||||
maxHistoryAge << BrowsingHistory::DefaultInstance()->MaxHistoryItemAge();
|
||||
fDaysInHistoryMenuControl->SetText(maxHistoryAge.String());
|
||||
for (uchar i = 0; i < '0'; i++)
|
||||
fDaysInHistoryMenuControl->TextView()->DisallowChar(i);
|
||||
for (uchar i = '9' + 1; i <= 128; i++)
|
||||
fDaysInHistoryMenuControl->TextView()->DisallowChar(i);
|
||||
|
||||
fShowTabsIfOnlyOnePage = new BCheckBox("show tabs if only one page",
|
||||
B_TRANSLATE("Show tabs if only one page is open."),
|
||||
new BMessage(MSG_TAB_DISPLAY_BEHAVIOR_CHANGED));
|
||||
fShowTabsIfOnlyOnePage->SetValue(B_CONTROL_ON);
|
||||
|
||||
fAutoHideInterfaceInFullscreenMode = new BCheckBox("auto-hide interface",
|
||||
B_TRANSLATE("Auto-hide interface in fullscreen mode."),
|
||||
new BMessage(MSG_AUTO_HIDE_INTERFACE_BEHAVIOR_CHANGED));
|
||||
fAutoHideInterfaceInFullscreenMode->SetValue(B_CONTROL_OFF);
|
||||
|
||||
fAutoHidePointer = new BCheckBox("auto-hide pointer",
|
||||
B_TRANSLATE("Auto-hide mouse pointer."),
|
||||
new BMessage(MSG_AUTO_HIDE_POINTER_BEHAVIOR_CHANGED));
|
||||
fAutoHidePointer->SetValue(B_CONTROL_OFF);
|
||||
|
||||
fShowHomeButton = new BCheckBox("show home button",
|
||||
B_TRANSLATE("Show Home Button"),
|
||||
new BMessage(MSG_SHOW_HOME_BUTTON_CHANGED));
|
||||
fShowHomeButton->SetValue(B_CONTROL_ON);
|
||||
|
||||
BView* view = BGroupLayoutBuilder(B_VERTICAL, spacing / 2)
|
||||
.Add(BGridLayoutBuilder(spacing / 2, spacing / 2)
|
||||
.Add(fStartPageControl->CreateLabelLayoutItem(), 0, 0)
|
||||
.Add(fStartPageControl->CreateTextViewLayoutItem(), 1, 0)
|
||||
|
||||
.Add(fSearchPageControl->CreateLabelLayoutItem(), 0, 1)
|
||||
.Add(fSearchPageControl->CreateTextViewLayoutItem(), 1, 1)
|
||||
|
||||
.Add(fDownloadFolderControl->CreateLabelLayoutItem(), 0, 2)
|
||||
.Add(fDownloadFolderControl->CreateTextViewLayoutItem(), 1, 2)
|
||||
|
||||
.Add(fNewWindowBehaviorMenu->CreateLabelLayoutItem(), 0, 3)
|
||||
.Add(fNewWindowBehaviorMenu->CreateMenuBarLayoutItem(), 1, 3)
|
||||
|
||||
.Add(fNewTabBehaviorMenu->CreateLabelLayoutItem(), 0, 4)
|
||||
.Add(fNewTabBehaviorMenu->CreateMenuBarLayoutItem(), 1, 4)
|
||||
)
|
||||
.Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing))
|
||||
.Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER))
|
||||
.Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing))
|
||||
.Add(fShowTabsIfOnlyOnePage)
|
||||
.Add(fAutoHideInterfaceInFullscreenMode)
|
||||
.Add(fAutoHidePointer)
|
||||
.Add(fShowHomeButton)
|
||||
.Add(fDaysInHistoryMenuControl)
|
||||
.Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing))
|
||||
|
||||
.SetInsets(spacing, spacing, spacing, spacing)
|
||||
|
||||
.TopView()
|
||||
;
|
||||
view->SetName(B_TRANSLATE("General"));
|
||||
return view;
|
||||
}
|
||||
|
||||
|
||||
BView*
|
||||
SettingsWindow::_CreateFontsPage(float spacing)
|
||||
{
|
||||
fStandardFontView = new FontSelectionView("standard",
|
||||
B_TRANSLATE("Standard font:"), true, be_plain_font);
|
||||
BFont defaultSerifFont = _FindDefaultSerifFont();
|
||||
fSerifFontView = new FontSelectionView("serif",
|
||||
B_TRANSLATE("Serif font:"), true, &defaultSerifFont);
|
||||
fSansSerifFontView = new FontSelectionView("sans serif",
|
||||
B_TRANSLATE("Sans serif font:"), true, be_plain_font);
|
||||
fFixedFontView = new FontSelectionView("fixed",
|
||||
B_TRANSLATE("Fixed font:"), true, be_fixed_font);
|
||||
|
||||
fStandardSizesMenu = new BMenuField("standard font size",
|
||||
B_TRANSLATE("Default standard font size:"), new BPopUpMenu("sizes"),
|
||||
B_WILL_DRAW);
|
||||
_BuildSizesMenu(fStandardSizesMenu->Menu(),
|
||||
MSG_STANDARD_FONT_SIZE_SELECTED);
|
||||
|
||||
fFixedSizesMenu = new BMenuField("fixed font size",
|
||||
B_TRANSLATE("Default fixed font size:"), new BPopUpMenu("sizes"),
|
||||
B_WILL_DRAW);
|
||||
_BuildSizesMenu(fFixedSizesMenu->Menu(), MSG_FIXED_FONT_SIZE_SELECTED);
|
||||
|
||||
BView* view = BGridLayoutBuilder(spacing / 2, spacing / 2)
|
||||
.Add(fStandardFontView->CreateFontsLabelLayoutItem(), 0, 0)
|
||||
.Add(fStandardFontView->CreateFontsMenuBarLayoutItem(), 1, 0)
|
||||
.Add(fStandardFontView->PreviewBox(), 0, 1, 2)
|
||||
.Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing), 0, 2, 2)
|
||||
|
||||
.Add(fSerifFontView->CreateFontsLabelLayoutItem(), 0, 3)
|
||||
.Add(fSerifFontView->CreateFontsMenuBarLayoutItem(), 1, 3)
|
||||
.Add(fSerifFontView->PreviewBox(), 0, 4, 2)
|
||||
.Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing), 0, 5, 2)
|
||||
|
||||
.Add(fSansSerifFontView->CreateFontsLabelLayoutItem(), 0, 6)
|
||||
.Add(fSansSerifFontView->CreateFontsMenuBarLayoutItem(), 1, 6)
|
||||
.Add(fSansSerifFontView->PreviewBox(), 0, 7, 2)
|
||||
.Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing), 0, 8, 2)
|
||||
|
||||
.Add(fFixedFontView->CreateFontsLabelLayoutItem(), 0, 9)
|
||||
.Add(fFixedFontView->CreateFontsMenuBarLayoutItem(), 1, 9)
|
||||
.Add(fFixedFontView->PreviewBox(), 0, 10, 2)
|
||||
.Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing), 0, 11, 2)
|
||||
|
||||
.Add(fStandardSizesMenu->CreateLabelLayoutItem(), 0, 12)
|
||||
.Add(fStandardSizesMenu->CreateMenuBarLayoutItem(), 1, 12)
|
||||
.Add(fFixedSizesMenu->CreateLabelLayoutItem(), 0, 13)
|
||||
.Add(fFixedSizesMenu->CreateMenuBarLayoutItem(), 1, 13)
|
||||
|
||||
.SetInsets(spacing, spacing, spacing, spacing)
|
||||
|
||||
.View()
|
||||
;
|
||||
|
||||
view->SetName(B_TRANSLATE("Fonts"));
|
||||
return view;
|
||||
}
|
||||
|
||||
|
||||
BView*
|
||||
SettingsWindow::_CreateProxyPage(float spacing)
|
||||
{
|
||||
fUseProxyCheckBox = new BCheckBox("use proxy",
|
||||
B_TRANSLATE("Use proxy server to connect to the internet."),
|
||||
new BMessage(MSG_USE_PROXY_CHANGED));
|
||||
fUseProxyCheckBox->SetValue(B_CONTROL_ON);
|
||||
|
||||
fProxyAddressControl = new BTextControl("proxy address",
|
||||
B_TRANSLATE("Proxy server address:"), "",
|
||||
new BMessage(MSG_PROXY_ADDRESS_CHANGED));
|
||||
fProxyAddressControl->SetModificationMessage(
|
||||
new BMessage(MSG_PROXY_ADDRESS_CHANGED));
|
||||
fProxyAddressControl->SetText(
|
||||
fSettings->GetValue(kSettingsKeyProxyAddress, ""));
|
||||
|
||||
fProxyPortControl = new BTextControl("proxy port",
|
||||
B_TRANSLATE("Proxy server port:"), "",
|
||||
new BMessage(MSG_PROXY_PORT_CHANGED));
|
||||
fProxyPortControl->SetModificationMessage(
|
||||
new BMessage(MSG_PROXY_PORT_CHANGED));
|
||||
fProxyPortControl->SetText(
|
||||
fSettings->GetValue(kSettingsKeyProxyAddress, ""));
|
||||
|
||||
BView* view = BGroupLayoutBuilder(B_VERTICAL, spacing / 2)
|
||||
.Add(fUseProxyCheckBox)
|
||||
.Add(BGridLayoutBuilder(spacing / 2, spacing / 2)
|
||||
.Add(fProxyAddressControl->CreateLabelLayoutItem(), 0, 0)
|
||||
.Add(fProxyAddressControl->CreateTextViewLayoutItem(), 1, 0)
|
||||
|
||||
.Add(fProxyPortControl->CreateLabelLayoutItem(), 0, 1)
|
||||
.Add(fProxyPortControl->CreateTextViewLayoutItem(), 1, 1)
|
||||
)
|
||||
.Add(BSpaceLayoutItem::CreateGlue())
|
||||
|
||||
.SetInsets(spacing, spacing, spacing, spacing)
|
||||
|
||||
.TopView()
|
||||
;
|
||||
view->SetName(B_TRANSLATE("Proxy server"));
|
||||
return view;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SettingsWindow::_BuildSizesMenu(BMenu* menu, uint32 messageWhat)
|
||||
{
|
||||
const float kMinSize = 8.0;
|
||||
const float kMaxSize = 18.0;
|
||||
|
||||
const int32 kSizes[] = {7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 21, 24, 0};
|
||||
|
||||
for (int32 i = 0; kSizes[i]; i++) {
|
||||
int32 size = kSizes[i];
|
||||
if (size < kMinSize || size > kMaxSize)
|
||||
continue;
|
||||
|
||||
char label[32];
|
||||
snprintf(label, sizeof(label), "%ld", size);
|
||||
|
||||
BMessage* message = new BMessage(messageWhat);
|
||||
message->AddInt32("size", size);
|
||||
|
||||
BMenuItem* item = new BMenuItem(label, message);
|
||||
|
||||
menu->AddItem(item);
|
||||
item->SetTarget(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SettingsWindow::_SetupFontSelectionView(FontSelectionView* view,
|
||||
BMessage* message)
|
||||
{
|
||||
AddHandler(view);
|
||||
view->AttachedToLooper();
|
||||
view->SetMessage(message);
|
||||
view->SetTarget(this);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
bool
|
||||
SettingsWindow::_CanApplySettings() const
|
||||
{
|
||||
bool canApply = false;
|
||||
|
||||
// General settings
|
||||
canApply = canApply || (strcmp(fStartPageControl->Text(),
|
||||
fSettings->GetValue(kSettingsKeyStartPageURL,
|
||||
kDefaultStartPageURL)) != 0);
|
||||
|
||||
canApply = canApply || (strcmp(fSearchPageControl->Text(),
|
||||
fSettings->GetValue(kSettingsKeySearchPageURL,
|
||||
kDefaultSearchPageURL)) != 0);
|
||||
|
||||
canApply = canApply || (strcmp(fDownloadFolderControl->Text(),
|
||||
fSettings->GetValue(kSettingsKeyDownloadPath,
|
||||
kDefaultDownloadPath)) != 0);
|
||||
|
||||
canApply = canApply || ((fShowTabsIfOnlyOnePage->Value() == B_CONTROL_ON)
|
||||
!= fSettings->GetValue(kSettingsKeyShowTabsIfSinglePageOpen, true));
|
||||
|
||||
canApply = canApply || (
|
||||
(fAutoHideInterfaceInFullscreenMode->Value() == B_CONTROL_ON)
|
||||
!= fSettings->GetValue(kSettingsKeyAutoHideInterfaceInFullscreenMode,
|
||||
false));
|
||||
|
||||
canApply = canApply || (
|
||||
(fAutoHidePointer->Value() == B_CONTROL_ON)
|
||||
!= fSettings->GetValue(kSettingsKeyAutoHidePointer, false));
|
||||
|
||||
canApply = canApply || ((fShowHomeButton->Value() == B_CONTROL_ON)
|
||||
!= fSettings->GetValue(kSettingsKeyShowHomeButton, true));
|
||||
|
||||
canApply = canApply || (_MaxHistoryAge()
|
||||
!= BrowsingHistory::DefaultInstance()->MaxHistoryItemAge());
|
||||
|
||||
// New window policy
|
||||
canApply = canApply || (_NewWindowPolicy()
|
||||
!= fSettings->GetValue(kSettingsKeyNewWindowPolicy,
|
||||
(uint32)OpenStartPage));
|
||||
|
||||
// New tab policy
|
||||
canApply = canApply || (_NewTabPolicy()
|
||||
!= fSettings->GetValue(kSettingsKeyNewTabPolicy,
|
||||
(uint32)OpenBlankPage));
|
||||
|
||||
// Font settings
|
||||
canApply = canApply || (fStandardFontView->Font()
|
||||
!= fSettings->GetValue("standard font", *be_plain_font));
|
||||
|
||||
canApply = canApply || (fSerifFontView->Font()
|
||||
!= fSettings->GetValue("serif font", _FindDefaultSerifFont()));
|
||||
|
||||
canApply = canApply || (fSansSerifFontView->Font()
|
||||
!= fSettings->GetValue("sans serif font", *be_plain_font));
|
||||
|
||||
canApply = canApply || (fFixedFontView->Font()
|
||||
!= fSettings->GetValue("fixed font", *be_fixed_font));
|
||||
|
||||
canApply = canApply || (_SizesMenuValue(fStandardSizesMenu->Menu())
|
||||
!= fSettings->GetValue("standard font size", kDefaultFontSize));
|
||||
|
||||
canApply = canApply || (_SizesMenuValue(fFixedSizesMenu->Menu())
|
||||
!= fSettings->GetValue("fixed font size", kDefaultFontSize));
|
||||
|
||||
// Proxy settings
|
||||
canApply = canApply || ((fUseProxyCheckBox->Value() == B_CONTROL_ON)
|
||||
!= fSettings->GetValue(kSettingsKeyUseProxy, false));
|
||||
|
||||
canApply = canApply || (strcmp(fProxyAddressControl->Text(),
|
||||
fSettings->GetValue(kSettingsKeyProxyAddress, "")) != 0);
|
||||
|
||||
canApply = canApply || (_ProxyPort()
|
||||
!= fSettings->GetValue(kSettingsKeyProxyPort, (uint32)0));
|
||||
|
||||
return canApply;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SettingsWindow::_ApplySettings()
|
||||
{
|
||||
// Store general settings
|
||||
int32 maxHistoryAge = _MaxHistoryAge();
|
||||
BString text;
|
||||
text << maxHistoryAge;
|
||||
fDaysInHistoryMenuControl->SetText(text.String());
|
||||
BrowsingHistory::DefaultInstance()->SetMaxHistoryItemAge(maxHistoryAge);
|
||||
|
||||
fSettings->SetValue(kSettingsKeyStartPageURL, fStartPageControl->Text());
|
||||
fSettings->SetValue(kSettingsKeySearchPageURL, fSearchPageControl->Text());
|
||||
fSettings->SetValue(kSettingsKeyDownloadPath, fDownloadFolderControl->Text());
|
||||
fSettings->SetValue(kSettingsKeyShowTabsIfSinglePageOpen,
|
||||
fShowTabsIfOnlyOnePage->Value() == B_CONTROL_ON);
|
||||
fSettings->SetValue(kSettingsKeyAutoHideInterfaceInFullscreenMode,
|
||||
fAutoHideInterfaceInFullscreenMode->Value() == B_CONTROL_ON);
|
||||
fSettings->SetValue(kSettingsKeyAutoHidePointer,
|
||||
fAutoHidePointer->Value() == B_CONTROL_ON);
|
||||
fSettings->SetValue(kSettingsKeyShowHomeButton,
|
||||
fShowHomeButton->Value() == B_CONTROL_ON);
|
||||
|
||||
// New page policies
|
||||
fSettings->SetValue(kSettingsKeyNewWindowPolicy, _NewWindowPolicy());
|
||||
fSettings->SetValue(kSettingsKeyNewTabPolicy, _NewTabPolicy());
|
||||
|
||||
// Store fond settings
|
||||
fSettings->SetValue("standard font", fStandardFontView->Font());
|
||||
fSettings->SetValue("serif font", fSerifFontView->Font());
|
||||
fSettings->SetValue("sans serif font", fSansSerifFontView->Font());
|
||||
fSettings->SetValue("fixed font", fFixedFontView->Font());
|
||||
int32 standardFontSize = _SizesMenuValue(fStandardSizesMenu->Menu());
|
||||
int32 fixedFontSize = _SizesMenuValue(fFixedSizesMenu->Menu());
|
||||
fSettings->SetValue("standard font size", standardFontSize);
|
||||
fSettings->SetValue("fixed font size", fixedFontSize);
|
||||
|
||||
// Store proxy settings
|
||||
|
||||
fSettings->SetValue(kSettingsKeyUseProxy,
|
||||
fUseProxyCheckBox->Value() == B_CONTROL_ON);
|
||||
fSettings->SetValue(kSettingsKeyProxyAddress,
|
||||
fProxyAddressControl->Text());
|
||||
uint32 proxyPort = _ProxyPort();
|
||||
fSettings->SetValue(kSettingsKeyProxyPort, proxyPort);
|
||||
|
||||
fSettings->Save();
|
||||
|
||||
// Apply settings to default web page settings.
|
||||
BWebSettings::Default()->SetStandardFont(fStandardFontView->Font());
|
||||
BWebSettings::Default()->SetSerifFont(fSerifFontView->Font());
|
||||
BWebSettings::Default()->SetSansSerifFont(fSansSerifFontView->Font());
|
||||
BWebSettings::Default()->SetFixedFont(fFixedFontView->Font());
|
||||
BWebSettings::Default()->SetDefaultStandardFontSize(standardFontSize);
|
||||
BWebSettings::Default()->SetDefaultFixedFontSize(fixedFontSize);
|
||||
|
||||
if (fUseProxyCheckBox->Value() == B_CONTROL_ON) {
|
||||
BWebSettings::Default()->SetProxyInfo(fProxyAddressControl->Text(),
|
||||
proxyPort, B_PROXY_TYPE_HTTP, "", "");
|
||||
} else
|
||||
BWebSettings::Default()->SetProxyInfo();
|
||||
|
||||
// This will find all currently instantiated page settings and apply
|
||||
// the default values, unless the page settings have local overrides.
|
||||
BWebSettings::Default()->Apply();
|
||||
|
||||
|
||||
_ValidateControlsEnabledStatus();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SettingsWindow::_RevertSettings()
|
||||
{
|
||||
fStartPageControl->SetText(
|
||||
fSettings->GetValue(kSettingsKeyStartPageURL, kDefaultStartPageURL));
|
||||
|
||||
fSearchPageControl->SetText(
|
||||
fSettings->GetValue(kSettingsKeySearchPageURL, kDefaultSearchPageURL));
|
||||
|
||||
fDownloadFolderControl->SetText(
|
||||
fSettings->GetValue(kSettingsKeyDownloadPath, kDefaultDownloadPath));
|
||||
fShowTabsIfOnlyOnePage->SetValue(
|
||||
fSettings->GetValue(kSettingsKeyShowTabsIfSinglePageOpen, true));
|
||||
fAutoHideInterfaceInFullscreenMode->SetValue(
|
||||
fSettings->GetValue(kSettingsKeyAutoHideInterfaceInFullscreenMode,
|
||||
false));
|
||||
fAutoHidePointer->SetValue(
|
||||
fSettings->GetValue(kSettingsKeyAutoHidePointer, false));
|
||||
fShowHomeButton->SetValue(
|
||||
fSettings->GetValue(kSettingsKeyShowHomeButton, true));
|
||||
|
||||
BString text;
|
||||
text << BrowsingHistory::DefaultInstance()->MaxHistoryItemAge();
|
||||
fDaysInHistoryMenuControl->SetText(text.String());
|
||||
|
||||
// New window policy
|
||||
uint32 newWindowPolicy = fSettings->GetValue(kSettingsKeyNewWindowPolicy,
|
||||
(uint32)OpenStartPage);
|
||||
switch (newWindowPolicy) {
|
||||
default:
|
||||
case OpenStartPage:
|
||||
fNewWindowBehaviorOpenHomeItem->SetMarked(true);
|
||||
break;
|
||||
case OpenSearchPage:
|
||||
fNewWindowBehaviorOpenSearchItem->SetMarked(true);
|
||||
break;
|
||||
case OpenBlankPage:
|
||||
fNewWindowBehaviorOpenBlankItem->SetMarked(true);
|
||||
break;
|
||||
}
|
||||
|
||||
// New tab policy
|
||||
uint32 newTabPolicy = fSettings->GetValue(kSettingsKeyNewTabPolicy,
|
||||
(uint32)OpenBlankPage);
|
||||
switch (newTabPolicy) {
|
||||
default:
|
||||
case OpenBlankPage:
|
||||
fNewTabBehaviorOpenBlankItem->SetMarked(true);
|
||||
break;
|
||||
case OpenStartPage:
|
||||
fNewTabBehaviorOpenHomeItem->SetMarked(true);
|
||||
break;
|
||||
case OpenSearchPage:
|
||||
fNewTabBehaviorOpenSearchItem->SetMarked(true);
|
||||
break;
|
||||
case CloneCurrentPage:
|
||||
fNewTabBehaviorCloneCurrentItem->SetMarked(true);
|
||||
break;
|
||||
}
|
||||
|
||||
// Font settings
|
||||
int32 defaultFontSize = fSettings->GetValue("standard font size",
|
||||
kDefaultFontSize);
|
||||
int32 defaultFixedFontSize = fSettings->GetValue("fixed font size",
|
||||
kDefaultFontSize);
|
||||
|
||||
_SetSizesMenuValue(fStandardSizesMenu->Menu(), defaultFontSize);
|
||||
_SetSizesMenuValue(fFixedSizesMenu->Menu(), defaultFixedFontSize);
|
||||
|
||||
fStandardFontView->SetFont(fSettings->GetValue("standard font",
|
||||
*be_plain_font), defaultFontSize);
|
||||
fSerifFontView->SetFont(fSettings->GetValue("serif font",
|
||||
_FindDefaultSerifFont()), defaultFontSize);
|
||||
fSansSerifFontView->SetFont(fSettings->GetValue("sans serif font",
|
||||
*be_plain_font), defaultFontSize);
|
||||
fFixedFontView->SetFont(fSettings->GetValue("fixed font",
|
||||
*be_fixed_font), defaultFixedFontSize);
|
||||
|
||||
// Proxy settings
|
||||
fUseProxyCheckBox->SetValue(fSettings->GetValue(kSettingsKeyUseProxy,
|
||||
false));
|
||||
fProxyAddressControl->SetText(fSettings->GetValue(kSettingsKeyProxyAddress,
|
||||
""));
|
||||
text = "";
|
||||
text << fSettings->GetValue(kSettingsKeyProxyPort, (uint32)0);
|
||||
fProxyPortControl->SetText(text.String());
|
||||
|
||||
_ValidateControlsEnabledStatus();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SettingsWindow::_ValidateControlsEnabledStatus()
|
||||
{
|
||||
bool canApply = _CanApplySettings();
|
||||
fApplyButton->SetEnabled(canApply);
|
||||
fRevertButton->SetEnabled(canApply);
|
||||
// Let the Cancel button be enabled always, as another way to close the
|
||||
// window...
|
||||
fCancelButton->SetEnabled(true);
|
||||
|
||||
bool useProxy = fUseProxyCheckBox->Value() == B_CONTROL_ON;
|
||||
fProxyAddressControl->SetEnabled(useProxy);
|
||||
fProxyPortControl->SetEnabled(useProxy);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
uint32
|
||||
SettingsWindow::_NewWindowPolicy() const
|
||||
{
|
||||
uint32 newWindowPolicy = OpenStartPage;
|
||||
BMenuItem* markedItem = fNewWindowBehaviorMenu->Menu()->FindMarked();
|
||||
if (markedItem == fNewWindowBehaviorOpenSearchItem)
|
||||
newWindowPolicy = OpenSearchPage;
|
||||
else if (markedItem == fNewWindowBehaviorOpenBlankItem)
|
||||
newWindowPolicy = OpenBlankPage;
|
||||
return newWindowPolicy;
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
SettingsWindow::_NewTabPolicy() const
|
||||
{
|
||||
uint32 newTabPolicy = OpenBlankPage;
|
||||
BMenuItem* markedItem = fNewTabBehaviorMenu->Menu()->FindMarked();
|
||||
if (markedItem == fNewTabBehaviorCloneCurrentItem)
|
||||
newTabPolicy = CloneCurrentPage;
|
||||
else if (markedItem == fNewTabBehaviorOpenHomeItem)
|
||||
newTabPolicy = OpenStartPage;
|
||||
else if (markedItem == fNewTabBehaviorOpenSearchItem)
|
||||
newTabPolicy = OpenSearchPage;
|
||||
return newTabPolicy;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
SettingsWindow::_MaxHistoryAge() const
|
||||
{
|
||||
int32 maxHistoryAge = atoi(fDaysInHistoryMenuControl->Text());
|
||||
if (maxHistoryAge <= 0)
|
||||
maxHistoryAge = 1;
|
||||
if (maxHistoryAge >= 35)
|
||||
maxHistoryAge = 35;
|
||||
return maxHistoryAge;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SettingsWindow::_SetSizesMenuValue(BMenu* menu, int32 value)
|
||||
{
|
||||
for (int32 i = 0; BMenuItem* item = menu->ItemAt(i); i++) {
|
||||
bool marked = false;
|
||||
if (BMessage* message = item->Message()) {
|
||||
int32 size;
|
||||
if (message->FindInt32("size", &size) == B_OK && size == value)
|
||||
marked = true;
|
||||
}
|
||||
item->SetMarked(marked);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
SettingsWindow::_SizesMenuValue(BMenu* menu) const
|
||||
{
|
||||
if (BMenuItem* item = menu->FindMarked()) {
|
||||
if (BMessage* message = item->Message()) {
|
||||
int32 size;
|
||||
if (message->FindInt32("size", &size) == B_OK)
|
||||
return size;
|
||||
}
|
||||
}
|
||||
return kDefaultFontSize;
|
||||
}
|
||||
|
||||
|
||||
BFont
|
||||
SettingsWindow::_FindDefaultSerifFont() const
|
||||
{
|
||||
// Default to the first "serif" font we find.
|
||||
BFont serifFont(*be_plain_font);
|
||||
font_family family;
|
||||
int32 familyCount = count_font_families();
|
||||
for (int32 i = 0; i < familyCount; i++) {
|
||||
if (get_font_family(i, &family) == B_OK) {
|
||||
BString familyString(family);
|
||||
if (familyString.IFindFirst("sans") >= 0)
|
||||
continue;
|
||||
if (familyString.IFindFirst("serif") >= 0) {
|
||||
serifFont.SetFamilyAndFace(family, B_REGULAR_FACE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return serifFont;
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
SettingsWindow::_ProxyPort() const
|
||||
{
|
||||
return atoul(fProxyPortControl->Text());
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef SETTINGS_WINDOW_H
|
||||
#define SETTINGS_WINDOW_H
|
||||
|
||||
#include <Window.h>
|
||||
|
||||
class BButton;
|
||||
class BCheckBox;
|
||||
class BMenu;
|
||||
class BMenuField;
|
||||
class BMenuItem;
|
||||
class BTextControl;
|
||||
class FontSelectionView;
|
||||
class SettingsMessage;
|
||||
|
||||
|
||||
class SettingsWindow : public BWindow {
|
||||
public:
|
||||
SettingsWindow(BRect frame,
|
||||
SettingsMessage* settings);
|
||||
virtual ~SettingsWindow();
|
||||
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
virtual bool QuitRequested();
|
||||
|
||||
virtual void Show();
|
||||
|
||||
private:
|
||||
BView* _CreateGeneralPage(float spacing);
|
||||
BView* _CreateFontsPage(float spacing);
|
||||
BView* _CreateProxyPage(float spacing);
|
||||
void _BuildSizesMenu(BMenu* menu,
|
||||
uint32 messageWhat);
|
||||
void _SetupFontSelectionView(
|
||||
FontSelectionView* view,
|
||||
BMessage* message);
|
||||
|
||||
bool _CanApplySettings() const;
|
||||
void _ApplySettings();
|
||||
void _RevertSettings();
|
||||
void _ValidateControlsEnabledStatus();
|
||||
|
||||
uint32 _NewWindowPolicy() const;
|
||||
uint32 _NewTabPolicy() const;
|
||||
int32 _MaxHistoryAge() const;
|
||||
|
||||
void _SetSizesMenuValue(BMenu* menu, int32 value);
|
||||
int32 _SizesMenuValue(BMenu* menu) const;
|
||||
|
||||
BFont _FindDefaultSerifFont() const;
|
||||
|
||||
uint32 _ProxyPort() const;
|
||||
|
||||
private:
|
||||
SettingsMessage* fSettings;
|
||||
|
||||
BTextControl* fStartPageControl;
|
||||
BTextControl* fSearchPageControl;
|
||||
BTextControl* fDownloadFolderControl;
|
||||
|
||||
BMenuField* fNewWindowBehaviorMenu;
|
||||
BMenuItem* fNewWindowBehaviorOpenHomeItem;
|
||||
BMenuItem* fNewWindowBehaviorOpenSearchItem;
|
||||
BMenuItem* fNewWindowBehaviorOpenBlankItem;
|
||||
|
||||
BMenuField* fNewTabBehaviorMenu;
|
||||
BMenuItem* fNewTabBehaviorCloneCurrentItem;
|
||||
BMenuItem* fNewTabBehaviorOpenHomeItem;
|
||||
BMenuItem* fNewTabBehaviorOpenSearchItem;
|
||||
BMenuItem* fNewTabBehaviorOpenBlankItem;
|
||||
|
||||
BTextControl* fDaysInHistoryMenuControl;
|
||||
BCheckBox* fShowTabsIfOnlyOnePage;
|
||||
BCheckBox* fAutoHideInterfaceInFullscreenMode;
|
||||
BCheckBox* fAutoHidePointer;
|
||||
BCheckBox* fShowHomeButton;
|
||||
|
||||
FontSelectionView* fStandardFontView;
|
||||
FontSelectionView* fSerifFontView;
|
||||
FontSelectionView* fSansSerifFontView;
|
||||
FontSelectionView* fFixedFontView;
|
||||
|
||||
BCheckBox* fUseProxyCheckBox;
|
||||
BTextControl* fProxyAddressControl;
|
||||
BTextControl* fProxyPortControl;
|
||||
|
||||
BButton* fApplyButton;
|
||||
BButton* fCancelButton;
|
||||
BButton* fRevertButton;
|
||||
|
||||
BMenuField* fStandardSizesMenu;
|
||||
BMenuField* fFixedSizesMenu;
|
||||
};
|
||||
|
||||
|
||||
#endif // SETTINGS_WINDOW_H
|
||||
|
||||
@@ -0,0 +1,654 @@
|
||||
/*
|
||||
* Copyright 2010 Stephan Aßmus <superstippi@gmx.de>
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include "URLInputGroup.h"
|
||||
|
||||
#include <Bitmap.h>
|
||||
#include <Button.h>
|
||||
#include <ControlLook.h>
|
||||
#include <Clipboard.h>
|
||||
#include <GroupLayout.h>
|
||||
#include <GroupLayoutBuilder.h>
|
||||
#include <LayoutUtils.h>
|
||||
#include <MenuItem.h>
|
||||
#include <PopUpMenu.h>
|
||||
#include <SeparatorView.h>
|
||||
#include <TextView.h>
|
||||
#include <Window.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "BaseURL.h"
|
||||
#include "BitmapButton.h"
|
||||
#include "BrowsingHistory.h"
|
||||
#include "IconButton.h"
|
||||
#include "TextViewCompleter.h"
|
||||
|
||||
|
||||
class URLChoice : public BAutoCompleter::Choice {
|
||||
public:
|
||||
URLChoice(const BString& choiceText, const BString& displayText,
|
||||
int32 matchPos, int32 matchLen, int32 priority)
|
||||
:
|
||||
BAutoCompleter::Choice(choiceText, displayText, matchPos, matchLen),
|
||||
fPriority(priority)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator<(const URLChoice& other) const
|
||||
{
|
||||
if (fPriority > other.fPriority)
|
||||
return true;
|
||||
return DisplayText() < other.DisplayText();
|
||||
}
|
||||
|
||||
bool operator==(const URLChoice& other) const
|
||||
{
|
||||
return fPriority == other.fPriority
|
||||
&& DisplayText() < other.DisplayText();
|
||||
}
|
||||
|
||||
private:
|
||||
int32 fPriority;
|
||||
};
|
||||
|
||||
|
||||
class BrowsingHistoryChoiceModel : public BAutoCompleter::ChoiceModel {
|
||||
virtual void FetchChoicesFor(const BString& pattern)
|
||||
{
|
||||
int32 count = CountChoices();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
delete reinterpret_cast<BAutoCompleter::Choice*>(
|
||||
fChoices.ItemAtFast(i));
|
||||
}
|
||||
fChoices.MakeEmpty();
|
||||
|
||||
// Search through BrowsingHistory for any matches.
|
||||
BrowsingHistory* history = BrowsingHistory::DefaultInstance();
|
||||
if (!history->Lock())
|
||||
return;
|
||||
|
||||
BString lastBaseURL;
|
||||
int32 priority = INT_MAX;
|
||||
|
||||
count = history->CountItems();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
BrowsingHistoryItem item = history->HistoryItemAt(i);
|
||||
const BString& choiceText = item.URL();
|
||||
int32 matchPos = choiceText.IFindFirst(pattern);
|
||||
if (matchPos < 0)
|
||||
continue;
|
||||
if (lastBaseURL.Length() > 0
|
||||
&& choiceText.FindFirst(lastBaseURL) >= 0) {
|
||||
priority--;
|
||||
} else
|
||||
priority = INT_MAX;
|
||||
lastBaseURL = baseURL(choiceText);
|
||||
fChoices.AddItem(new URLChoice(choiceText,
|
||||
choiceText, matchPos, pattern.Length(), priority));
|
||||
}
|
||||
|
||||
history->Unlock();
|
||||
|
||||
fChoices.SortItems(_CompareChoices);
|
||||
}
|
||||
|
||||
virtual int32 CountChoices() const
|
||||
{
|
||||
return fChoices.CountItems();
|
||||
}
|
||||
|
||||
virtual const BAutoCompleter::Choice* ChoiceAt(int32 index) const
|
||||
{
|
||||
return reinterpret_cast<BAutoCompleter::Choice*>(
|
||||
fChoices.ItemAt(index));
|
||||
}
|
||||
|
||||
static int _CompareChoices(const void* a, const void* b)
|
||||
{
|
||||
const URLChoice* aChoice
|
||||
= *reinterpret_cast<const URLChoice* const *>(a);
|
||||
const URLChoice* bChoice
|
||||
= *reinterpret_cast<const URLChoice* const *>(b);
|
||||
if (*aChoice < *bChoice)
|
||||
return -1;
|
||||
else if (*aChoice == *bChoice)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
private:
|
||||
BList fChoices;
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark - URLTextView
|
||||
|
||||
|
||||
static const float kHorizontalTextRectInset = 4.0;
|
||||
|
||||
|
||||
class URLInputGroup::URLTextView : public BTextView {
|
||||
private:
|
||||
static const uint32 MSG_CLEAR = 'cler';
|
||||
|
||||
public:
|
||||
URLTextView(URLInputGroup* parent);
|
||||
virtual ~URLTextView();
|
||||
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
virtual void FrameResized(float width, float height);
|
||||
virtual void MouseDown(BPoint where);
|
||||
virtual void KeyDown(const char* bytes, int32 numBytes);
|
||||
virtual void MakeFocus(bool focused = true);
|
||||
|
||||
virtual BSize MinSize();
|
||||
virtual BSize MaxSize();
|
||||
|
||||
void SetUpdateAutoCompleterChoices(bool update);
|
||||
|
||||
protected:
|
||||
virtual void InsertText(const char* inText, int32 inLength,
|
||||
int32 inOffset,
|
||||
const text_run_array* inRuns);
|
||||
virtual void DeleteText(int32 fromOffset, int32 toOffset);
|
||||
|
||||
private:
|
||||
void _AlignTextRect();
|
||||
|
||||
private:
|
||||
URLInputGroup* fURLInputGroup;
|
||||
TextViewCompleter* fURLAutoCompleter;
|
||||
BString fPreviousText;
|
||||
bool fUpdateAutoCompleterChoices;
|
||||
};
|
||||
|
||||
|
||||
URLInputGroup::URLTextView::URLTextView(URLInputGroup* parent)
|
||||
:
|
||||
BTextView("url"),
|
||||
fURLInputGroup(parent),
|
||||
fURLAutoCompleter(new TextViewCompleter(this,
|
||||
new BrowsingHistoryChoiceModel())),
|
||||
fPreviousText(""),
|
||||
fUpdateAutoCompleterChoices(true)
|
||||
{
|
||||
MakeResizable(true);
|
||||
SetStylable(true);
|
||||
fURLAutoCompleter->SetModificationsReported(true);
|
||||
}
|
||||
|
||||
|
||||
URLInputGroup::URLTextView::~URLTextView()
|
||||
{
|
||||
delete fURLAutoCompleter;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
URLInputGroup::URLTextView::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch (message->what) {
|
||||
case MSG_CLEAR:
|
||||
SetText("");
|
||||
break;
|
||||
default:
|
||||
BTextView::MessageReceived(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
URLInputGroup::URLTextView::FrameResized(float width, float height)
|
||||
{
|
||||
BTextView::FrameResized(width, height);
|
||||
_AlignTextRect();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
URLInputGroup::URLTextView::MouseDown(BPoint where)
|
||||
{
|
||||
bool wasFocus = IsFocus();
|
||||
if (!wasFocus)
|
||||
MakeFocus(true);
|
||||
|
||||
int32 buttons;
|
||||
if (Window()->CurrentMessage()->FindInt32("buttons", &buttons) != B_OK)
|
||||
buttons = B_PRIMARY_MOUSE_BUTTON;
|
||||
|
||||
if ((buttons & B_SECONDARY_MOUSE_BUTTON) != 0) {
|
||||
// Display context menu
|
||||
int32 selectionStart;
|
||||
int32 selectionEnd;
|
||||
GetSelection(&selectionStart, &selectionEnd);
|
||||
bool canCutOrCopy = selectionEnd > selectionStart;
|
||||
|
||||
bool canPaste = false;
|
||||
if (be_clipboard->Lock()) {
|
||||
if (BMessage* data = be_clipboard->Data())
|
||||
canPaste = data->HasData("text/plain", B_MIME_TYPE);
|
||||
be_clipboard->Unlock();
|
||||
}
|
||||
|
||||
BMenuItem* cutItem = new BMenuItem("Cut", new BMessage(B_CUT));
|
||||
BMenuItem* copyItem = new BMenuItem("Copy", new BMessage(B_COPY));
|
||||
BMenuItem* pasteItem = new BMenuItem("Paste", new BMessage(B_PASTE));
|
||||
BMenuItem* clearItem = new BMenuItem("Clear", new BMessage(MSG_CLEAR));
|
||||
cutItem->SetEnabled(canCutOrCopy);
|
||||
copyItem->SetEnabled(canCutOrCopy);
|
||||
pasteItem->SetEnabled(canPaste);
|
||||
clearItem->SetEnabled(strlen(Text()) > 0);
|
||||
|
||||
BPopUpMenu* menu = new BPopUpMenu("url context");
|
||||
menu->AddItem(cutItem);
|
||||
menu->AddItem(copyItem);
|
||||
menu->AddItem(pasteItem);
|
||||
menu->AddItem(clearItem);
|
||||
|
||||
menu->SetTargetForItems(this);
|
||||
menu->Go(ConvertToScreen(where), true, true, true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Only pass through to base class if we already have focus.
|
||||
if (!wasFocus)
|
||||
return;
|
||||
|
||||
BTextView::MouseDown(where);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
URLInputGroup::URLTextView::KeyDown(const char* bytes, int32 numBytes)
|
||||
{
|
||||
switch (bytes[0]) {
|
||||
case B_TAB:
|
||||
BView::KeyDown(bytes, numBytes);
|
||||
break;
|
||||
|
||||
case B_ESCAPE:
|
||||
// Revert to text as it was when we received keyboard focus.
|
||||
SetText(fPreviousText.String());
|
||||
SelectAll();
|
||||
break;
|
||||
|
||||
case B_RETURN:
|
||||
// Don't let this through to the text view.
|
||||
break;
|
||||
|
||||
default:
|
||||
BTextView::KeyDown(bytes, numBytes);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
URLInputGroup::URLTextView::MakeFocus(bool focus)
|
||||
{
|
||||
if (focus == IsFocus())
|
||||
return;
|
||||
|
||||
BTextView::MakeFocus(focus);
|
||||
|
||||
if (focus) {
|
||||
fPreviousText = Text();
|
||||
SelectAll();
|
||||
}
|
||||
|
||||
fURLInputGroup->Invalidate();
|
||||
}
|
||||
|
||||
|
||||
BSize
|
||||
URLInputGroup::URLTextView::MinSize()
|
||||
{
|
||||
BSize min;
|
||||
min.height = ceilf(LineHeight(0) + kHorizontalTextRectInset);
|
||||
// we always add at least one pixel vertical inset top/bottom for
|
||||
// the text rect.
|
||||
min.width = min.height * 3;
|
||||
return BLayoutUtils::ComposeSize(ExplicitMinSize(), min);
|
||||
}
|
||||
|
||||
|
||||
BSize
|
||||
URLInputGroup::URLTextView::MaxSize()
|
||||
{
|
||||
BSize max(MinSize());
|
||||
max.width = B_SIZE_UNLIMITED;
|
||||
return BLayoutUtils::ComposeSize(ExplicitMaxSize(), max);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
URLInputGroup::URLTextView::SetUpdateAutoCompleterChoices(bool update)
|
||||
{
|
||||
fUpdateAutoCompleterChoices = update;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
URLInputGroup::URLTextView::InsertText(const char* inText, int32 inLength,
|
||||
int32 inOffset, const text_run_array* inRuns)
|
||||
{
|
||||
// Filter all line breaks, note that inText is not terminated.
|
||||
if (inLength == 1) {
|
||||
if (*inText == '\n' || *inText == '\r')
|
||||
BTextView::InsertText(" ", 1, inOffset, inRuns);
|
||||
else
|
||||
BTextView::InsertText(inText, 1, inOffset, inRuns);
|
||||
} else {
|
||||
BString filteredText(inText, inLength);
|
||||
filteredText.ReplaceAll('\n', ' ');
|
||||
filteredText.ReplaceAll('\r', ' ');
|
||||
BTextView::InsertText(filteredText.String(), inLength, inOffset,
|
||||
inRuns);
|
||||
}
|
||||
|
||||
// Make the base URL part bold.
|
||||
BString text(Text(), TextLength());
|
||||
int32 baseUrlStart = text.FindFirst("://");
|
||||
if (baseUrlStart >= 0)
|
||||
baseUrlStart += 3;
|
||||
else
|
||||
baseUrlStart = 0;
|
||||
int32 baseUrlEnd = text.FindFirst("/", baseUrlStart);
|
||||
if (baseUrlEnd < 0)
|
||||
baseUrlEnd = TextLength();
|
||||
BFont font;
|
||||
GetFont(&font);
|
||||
const rgb_color black = (rgb_color){ 0, 0, 0, 255 };
|
||||
const rgb_color gray = (rgb_color){ 60, 60, 60, 255 };
|
||||
if (baseUrlStart > 0)
|
||||
SetFontAndColor(0, baseUrlStart - 1, &font, B_FONT_ALL, &gray);
|
||||
if (baseUrlEnd > baseUrlStart) {
|
||||
font.SetFace(B_BOLD_FACE);
|
||||
SetFontAndColor(baseUrlStart, baseUrlEnd, &font, B_FONT_ALL, &black);
|
||||
}
|
||||
if (baseUrlEnd < TextLength()) {
|
||||
font.SetFace(B_REGULAR_FACE);
|
||||
SetFontAndColor(baseUrlEnd, TextLength(), &font, B_FONT_ALL, &gray);
|
||||
}
|
||||
|
||||
fURLAutoCompleter->TextModified(fUpdateAutoCompleterChoices);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
URLInputGroup::URLTextView::DeleteText(int32 fromOffset, int32 toOffset)
|
||||
{
|
||||
BTextView::DeleteText(fromOffset, toOffset);
|
||||
|
||||
fURLAutoCompleter->TextModified(fUpdateAutoCompleterChoices);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
URLInputGroup::URLTextView::_AlignTextRect()
|
||||
{
|
||||
// Layout the text rect to be in the middle, normally this means there
|
||||
// is one pixel spacing on each side.
|
||||
BRect textRect(Bounds());
|
||||
textRect.left = 0.0;
|
||||
float vInset = max_c(1,
|
||||
floorf((textRect.Height() - LineHeight(0)) / 2.0 + 0.5));
|
||||
float hInset = kHorizontalTextRectInset;
|
||||
|
||||
if (be_control_look)
|
||||
hInset = be_control_look->DefaultLabelSpacing();
|
||||
|
||||
textRect.InsetBy(hInset, vInset);
|
||||
SetTextRect(textRect);
|
||||
}
|
||||
|
||||
|
||||
const uint32 kGoBitmapWidth = 14;
|
||||
const uint32 kGoBitmapHeight = 14;
|
||||
const color_space kGoBitmapFormat = B_RGBA32;
|
||||
|
||||
const unsigned char kGoBitmapBits[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x17, 0x17, 0x21,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x17, 0x17, 0x17, 0x21, 0x49, 0x49, 0x49, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x17, 0x17, 0x17, 0x21, 0x49, 0x49, 0x49, 0xe0, 0x50, 0x50, 0x50, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x17, 0x17, 0x21, 0x49, 0x49, 0x49, 0xe0,
|
||||
0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x2f, 0x2f, 0x2f, 0x56, 0x50, 0x50, 0x50, 0xff, 0x4d, 0x4d, 0x4d, 0xed,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x17, 0x17, 0x21,
|
||||
0x49, 0x49, 0x49, 0xe0, 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff,
|
||||
0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff,
|
||||
0x50, 0x50, 0x50, 0xff, 0x37, 0x37, 0x37, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x17, 0x17, 0x17, 0x21, 0x49, 0x49, 0x49, 0xe0, 0x50, 0x50, 0x50, 0xff,
|
||||
0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff,
|
||||
0x50, 0x50, 0x50, 0xff, 0x4b, 0x4b, 0x4b, 0xec, 0x37, 0x37, 0x37, 0x77, 0x00, 0x00, 0x00, 0x02,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x17, 0x17, 0x17, 0x21, 0x49, 0x49, 0x49, 0xe1, 0x50, 0x50, 0x50, 0xff, 0x50, 0x50, 0x50, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x17, 0x17, 0x21,
|
||||
0x49, 0x49, 0x49, 0xe1, 0x50, 0x50, 0x50, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x17, 0x17, 0x21, 0x49, 0x49, 0x49, 0xe1,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x17, 0x17, 0x17, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark - PageIconView
|
||||
|
||||
|
||||
class URLInputGroup::PageIconView : public BView {
|
||||
public:
|
||||
PageIconView()
|
||||
:
|
||||
BView("page icon view", B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
|
||||
fIcon(NULL)
|
||||
{
|
||||
SetDrawingMode(B_OP_ALPHA);
|
||||
SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
|
||||
}
|
||||
|
||||
~PageIconView()
|
||||
{
|
||||
delete fIcon;
|
||||
}
|
||||
|
||||
virtual void Draw(BRect updateRect)
|
||||
{
|
||||
if (fIcon == NULL)
|
||||
return;
|
||||
|
||||
BRect bounds(Bounds());
|
||||
BRect iconBounds(0, 0, 15, 15);
|
||||
iconBounds.OffsetTo(
|
||||
floorf((bounds.left + bounds.right
|
||||
- (iconBounds.left + iconBounds.right)) / 2 + 0.5f),
|
||||
floorf((bounds.top + bounds.bottom
|
||||
- (iconBounds.top + iconBounds.bottom)) / 2 + 0.5f));
|
||||
DrawBitmap(fIcon, fIcon->Bounds(), iconBounds,
|
||||
B_FILTER_BITMAP_BILINEAR);
|
||||
}
|
||||
|
||||
virtual BSize MinSize()
|
||||
{
|
||||
if (fIcon != NULL)
|
||||
return BSize(18, 18);
|
||||
return BSize(0, 0);
|
||||
}
|
||||
|
||||
virtual BSize MaxSize()
|
||||
{
|
||||
return BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED);
|
||||
}
|
||||
|
||||
virtual BSize PreferredSize()
|
||||
{
|
||||
return MinSize();
|
||||
}
|
||||
|
||||
void SetIcon(const BBitmap* icon)
|
||||
{
|
||||
if (icon == NULL && fIcon == NULL)
|
||||
return;
|
||||
if (!(fIcon != NULL && icon != NULL))
|
||||
InvalidateLayout();
|
||||
delete fIcon;
|
||||
if (icon)
|
||||
fIcon = new BBitmap(icon);
|
||||
else
|
||||
fIcon = NULL;
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
private:
|
||||
BBitmap* fIcon;
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark - URLInputGroup
|
||||
|
||||
|
||||
URLInputGroup::URLInputGroup(BMessage* goMessage)
|
||||
:
|
||||
BGroupView(B_HORIZONTAL, 0.0),
|
||||
fWindowActive(false)
|
||||
{
|
||||
GroupLayout()->SetInsets(2, 2, 2, 2);
|
||||
|
||||
fIconView = new PageIconView();
|
||||
GroupLayout()->AddView(fIconView, 0.0f);
|
||||
|
||||
fTextView = new URLTextView(this);
|
||||
AddChild(fTextView);
|
||||
|
||||
AddChild(new BSeparatorView(B_VERTICAL, B_PLAIN_BORDER));
|
||||
|
||||
// TODO: Fix in Haiku, no in-built support for archived BBitmaps from
|
||||
// resources?
|
||||
// fGoButton = new BitmapButton("kActionGo", NULL);
|
||||
fGoButton = new BitmapButton(kGoBitmapBits, kGoBitmapWidth,
|
||||
kGoBitmapHeight, kGoBitmapFormat, goMessage);
|
||||
GroupLayout()->AddView(fGoButton, 0.0f);
|
||||
|
||||
SetFlags(Flags() | B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE);
|
||||
SetLowColor(ViewColor());
|
||||
SetViewColor(B_TRANSPARENT_COLOR);
|
||||
|
||||
SetExplicitAlignment(BAlignment(B_ALIGN_USE_FULL_WIDTH,
|
||||
B_ALIGN_VERTICAL_CENTER));
|
||||
}
|
||||
|
||||
|
||||
URLInputGroup::~URLInputGroup()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
URLInputGroup::AttachedToWindow()
|
||||
{
|
||||
BGroupView::AttachedToWindow();
|
||||
fWindowActive = Window()->IsActive();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
URLInputGroup::WindowActivated(bool active)
|
||||
{
|
||||
BGroupView::WindowActivated(active);
|
||||
if (fWindowActive != active) {
|
||||
fWindowActive = active;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
URLInputGroup::Draw(BRect updateRect)
|
||||
{
|
||||
BRect bounds(Bounds());
|
||||
rgb_color base(LowColor());
|
||||
uint32 flags = 0;
|
||||
if (fWindowActive && fTextView->IsFocus())
|
||||
flags |= BControlLook::B_FOCUSED;
|
||||
be_control_look->DrawTextControlBorder(this, bounds, updateRect, base,
|
||||
flags);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
URLInputGroup::MakeFocus(bool focus)
|
||||
{
|
||||
// Forward this to the text view, we never accept focus ourselves.
|
||||
fTextView->MakeFocus(focus);
|
||||
}
|
||||
|
||||
|
||||
BTextView*
|
||||
URLInputGroup::TextView() const
|
||||
{
|
||||
return fTextView;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
URLInputGroup::SetText(const char* text)
|
||||
{
|
||||
if (!text || !Text() || strcmp(Text(), text) != 0) {
|
||||
fTextView->SetUpdateAutoCompleterChoices(false);
|
||||
fTextView->SetText(text);
|
||||
fTextView->SetUpdateAutoCompleterChoices(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const char*
|
||||
URLInputGroup::Text() const
|
||||
{
|
||||
return fTextView->Text();
|
||||
}
|
||||
|
||||
|
||||
BButton*
|
||||
URLInputGroup::GoButton() const
|
||||
{
|
||||
return fGoButton;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
URLInputGroup::SetPageIcon(const BBitmap* icon)
|
||||
{
|
||||
fIconView->SetIcon(icon);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2010 Stephan Aßmus <superstippi@gmx.de>
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef URL_INPUT_GROUP_H
|
||||
#define URL_INPUT_GROUP_H
|
||||
|
||||
#include <GroupView.h>
|
||||
|
||||
class BButton;
|
||||
class BTextView;
|
||||
|
||||
|
||||
class URLInputGroup : public BGroupView {
|
||||
public:
|
||||
URLInputGroup(BMessage* goMessage);
|
||||
virtual ~URLInputGroup();
|
||||
|
||||
virtual void AttachedToWindow();
|
||||
virtual void WindowActivated(bool active);
|
||||
virtual void Draw(BRect updateRect);
|
||||
virtual void MakeFocus(bool focus = true);
|
||||
|
||||
BTextView* TextView() const;
|
||||
void SetText(const char* text);
|
||||
const char* Text() const;
|
||||
|
||||
BButton* GoButton() const;
|
||||
|
||||
void SetPageIcon(const BBitmap* icon);
|
||||
|
||||
private:
|
||||
class PageIconView;
|
||||
class URLTextView;
|
||||
|
||||
PageIconView* fIconView;
|
||||
URLTextView* fTextView;
|
||||
BButton* fGoButton;
|
||||
bool fWindowActive;
|
||||
};
|
||||
|
||||
#endif // URL_INPUT_GROUP_H
|
||||
|
||||
@@ -0,0 +1,350 @@
|
||||
resource app_signature "application/x-vnd.Haiku-WebPositive";
|
||||
|
||||
resource app_version {
|
||||
major = 0,
|
||||
middle = 0,
|
||||
minor = 1,
|
||||
variety = B_APPV_ALPHA,
|
||||
internal = 0,
|
||||
short_info = "WebPositive",
|
||||
long_info = "WebPositive ©2007-2010 The WebKit Haiku Project"
|
||||
};
|
||||
|
||||
resource app_flags B_SINGLE_LAUNCH;
|
||||
|
||||
resource file_types message {
|
||||
"types" = "text/html",
|
||||
"types" = "image/svg+xml",
|
||||
"types" = "application/x-vnd.Be.URL.file",
|
||||
"types" = "application/x-vnd.Be.URL.ftp",
|
||||
"types" = "application/x-vnd.Be.URL.http",
|
||||
"types" = "application/x-vnd.Be.URL.https"
|
||||
};
|
||||
|
||||
resource vector_icon {
|
||||
$"6E636966450500020106033D0AFE000000000000BD0AFE48F10748A0783133FF"
|
||||
$"FFC80066FFFF0034CC020106033D0AFE000000000000BD0AFE48F10748A07854"
|
||||
$"09B4B6D8033784FF051D61020106043D950B0000000000003D950B494FBC479B"
|
||||
$"EC00FFFFFF4C00FF008F00B200FF008000050002030605B812A5BE03E13DE784"
|
||||
$"B8021049F79F49EDD800F1F1F136D9DDF48A9996B9B4B8BEDBFFF4F4F404EBD0"
|
||||
$"020006023C92C0388F5FB854503C576348D8DF48895B004137A9FFB9B9B90401"
|
||||
$"7E03FF360003FFFF0003FF9C0003FF000002010202BB36AEBA1760B80FFF392B"
|
||||
$"574ACCFB48652300000001FFFF0000013205400500020004024AFFFC00FFFFBA"
|
||||
$"360500020106033D0AFE000000000000BD0AFE48F10748A0783133FFFFC80066"
|
||||
$"FFFF0034CC020106023D0AFE000000000000BD0AFE48F10748A0780033FFFFFF"
|
||||
$"0033CC020106023D0AFE000000000000BD0AFE48F10748A0780033FFFFFF0066"
|
||||
$"FF020004027AFFFC00DDFFBA360201040289FF0000A9C000000200040200FFE5"
|
||||
$"CED0ECB989020004020DEFBC8CFFD4AA820200040200FFCB9CE9ECB989020004"
|
||||
$"0200FFCB9CE9ECB98902000402B3FFCB9CBBD4AA820500020106033D0AFE0000"
|
||||
$"00000000BD0AFE48F10748A0783133FFFFC80066FFFF0034CC020106033D0AFE"
|
||||
$"000000000000BD0AFE48F10748A0785409B4B6D8033784FF051D61020106043D"
|
||||
$"950B0000000000003D950B494FBC479BEC00FFFFFF4C00FF008F00B200FF0080"
|
||||
$"00050002030605B812A5BE03E13DE784B8021049F79F49EDD800F1F1F136D9DD"
|
||||
$"F48A9996B9B4B8BEDBFFF4F4F404EBD0020006023C92C0388F5FB854503C5763"
|
||||
$"48D8DF48895B004137A9FFB9B9B904017E03FF360003FFFF000200040200FFBC"
|
||||
$"34FFFF9C0003FF000002010202BB36AEBA1760B80FFF392B574ACCFB48652300"
|
||||
$"000001FFFF00000132054003FFFFC9020014020026FF1C0500050002030605B8"
|
||||
$"12A5BE03E13DE784B8021049F79F49EDD800F1F1F136D9DDF48A9996B9B4B8BE"
|
||||
$"DBFFF4F4F404EBD0020006023C92C0388F5FB854503C576348D8DF48895B0041"
|
||||
$"37A9FFB9B9B904017E03FF360003FFFF0003FF9C0003FF000002010202BB36AE"
|
||||
$"BA1760B80FFF392B574ACCFB48652300000001FFFF0000013205400500030052"
|
||||
$"7502001002F8006BFF003E04006C050003900000020310020000006E00650400"
|
||||
$"6B05000359463503C3A414039D816035000000000204BFC1B55A36B55AC3BEB5"
|
||||
$"5AC6FABC92C6FAB895C6FAC08FBFC1C3CBC3BEC3CB36C3CBB889BC92B889C08F"
|
||||
$"B889B895066EFFFFF30FFFFEFFFFBFBFFEFFFEFFFEFFFFFFFFBFFFEFDFFBFBFF"
|
||||
$"FF0FC5DBB8B5C713BA9FC4CAB706C10FB579C307B5D4C0A226BFC1B55AC031B5"
|
||||
$"5ABDBCB55ABA69B7BA36B63AB8F9B94EB89CBD9BB84EBB7EB8C7BE9AB924BF76"
|
||||
$"B8E0BEE7B9DEC11FBCDFC332BB37C278BEC4C405C2D7C31AC0FAC3FCC2C5C2C0"
|
||||
$"C22EC2B7C279C2BDC22EC2B7C226C240C2BDC240C2BDC206C2AFC199C2DAC1D0"
|
||||
$"C2CB44C2EEC0D4C2DCC114C2E5C051C2CEBF42C312BFB0C2B4BF3DC312BF35BF"
|
||||
$"1FBDECC312BE23C312BDB8C2EDBD57C2DEBD86C2E2BD53C2DBBD3EC2C2BD3EC2"
|
||||
$"C2BD31C2B4BD12C2A4BD26C2AABD12C2A4BCA4C27EBC31C254BC31C254BC27C2"
|
||||
$"51BC11C24FBC1DC250BC10C24BBC0FC241BC10C245BC0FC241BBF5C219BBF5C2"
|
||||
$"19BBD2C1DDBB68C194BBADC1A4BB70C16EBB58C128BB62C14EBB4BC101BB4BC0"
|
||||
$"ACBB47C0D7BB4BC0ACBB4EC087BB4EC087BB51C054BB4DBFEEBB54C021BB9DBF"
|
||||
$"92BBA9BEBFBBAFBF35BBA9BEBFBBA7BE92BBA7BE92BBA7BE52BBBBBE2FBBA8BE"
|
||||
$"4BBBBBBE2FBBC6BE20BBC6BE20BC00BDD4BBE2BCFBBC5BBD3DBBE2BCFBBAB7BC"
|
||||
$"58BA8ABC43BA90BC45BA8ABC43BA8ABC42BA8ABC42BA88BBEABA22BB78BA6ABB"
|
||||
$"ACBA22BB78BA12BB6AB9F8BB48B9ADBAEFB9ADBAEFB97DBAC3B927BAB0B94FBA"
|
||||
$"B5B924BAA9B91ABA9AB920BAA0B984BA6DB9DEB996B9B5B9F9B9F6B95DBA36B8"
|
||||
$"EFBA0AB91FBA5EB8C4BA78B85EBA83B89EBACCB83CBB60B7E7BB18B813BB60B7"
|
||||
$"E7BB6AB7E1BBFEB787BBFEB787BC65B749BCB6B683BC93B6F5BCF5B689BD58B6"
|
||||
$"64BD2CB67BBDA8B695BE6CB6503C29BE6FB64FBE88B64FBE7CB64FBE62B6A0BE"
|
||||
$"E1B72FBE88B70EBEE4B733BEE8B73DBEE5B73ABED8B743BEC5B749BE74B7A5BE"
|
||||
$"74B7A5BE63B7DCBE8FB848BE74B816BE90B84CBE91B852BE91B852BE93B85BBE"
|
||||
$"9CB87ABE97B86BBE93B883BE8CB88DBE8CB88DBE39B8EFBD91B98FBDB6B906BD"
|
||||
$"91B98FBD8DB9A0BD8DB9A0BD64B9D7BD7EBA54BD59BA19BD7ABA5CBD76BA62BD"
|
||||
$"76BA62BD56BA9FBD4DBB2BBD38BAE6BD5FBB6FBDCCBBCEBD98BBA1BDFFBBF9BE"
|
||||
$"73BC3FBE33BC27BEBEBC5CBF5DBC42BF11BC55BF5DBC42BFAB37BFAB37BFD0BC"
|
||||
$"1DC01CBC0FBFF4BC0BC045BC13C083BC4EC066BC35C04DBCD9C0F3BDDAC0B6BD"
|
||||
$"63C0F3BDDAC107BDF8C102BDF2C0BABE83C126BF90C0B1BF1CC126BF90C133BF"
|
||||
$"9CC133BF9CC130C00EC1C4C0F8C135C0D6C258C11CC347C059C2EEC0C8C347C0"
|
||||
$"59C36BC02EC388C018C388C018C3A7C003C3DABFC4C3C9BFE8C3EEBF9FC408BF"
|
||||
$"51C3EFBF73C408BF51C408BF52C408BF52C40CBF99C49540C450BFCEC4EBBFB3"
|
||||
$"C541BF0FC51FBF56C541BF0FC551BEF24EBEEA4EBEEAC57FBEA3C568BDFCC59E"
|
||||
$"BE46C53ABDBAC4A2BDDEC4E0BDA9C4A2BDCABDB5C4A4BD31C4A4BD31C4A7BD1D"
|
||||
$"C4E8BCDEC4D2BCF5C4E8BCDEC4FEBCC8C516BCB3C516BCB3C544BC8BC582BC1F"
|
||||
$"C570BC5DC58BBC04C587BBBBC586BBD9C587BBBBC587BBA8C587BB9DC587BB9D"
|
||||
$"C58CBB604EBAF9C584BB23C589BADAC5C1BA5DC5B0BAA1C5C3BA61C5CBBA6FC5"
|
||||
$"CBBA6FC5D8BA8EC60EBAD3C5EDBAB3C609BB1EC648BBAAC626BB67C669BBEAC6"
|
||||
$"6EBC7AC66FBC33C66EBC7AC671BCC3C671BCC3C673BCE9C66DBD36C677BD10C6"
|
||||
$"64BD5AC649BD9BC652BD78C633BDEBC62BBE91C62DBE3F50BED5C67FBF2BC648"
|
||||
$"BF16C750BD0F0006BC11B6E3BC11B6E3BC32B6AFBC54B637BC46B674BB81B6AA"
|
||||
$"BA2BB801BAC4B747BA87B7E2BB2FB77DBADDB7AFBB59B764BBAAB733BB82B74D"
|
||||
$"BBCBB71CBC11B6E3BBFBB707BC11B6E3001DBACDBFD1BACDBFD1BAEBBFA9BB29"
|
||||
$"BF5BBB12BF89BB43BF24BB34BE92BB34BECFBB34BE4DBB5FBDE9BB34BE25BB80"
|
||||
$"BDBEBBAABD5FBBA0BD98BB47BD29BA81BCBEBAE5BCF3BA67BCB1BA1FBC8332BC"
|
||||
$"9FBA0FBC5BBA0DBC02BA1FBC28B9FDBBE5B9B9BBB6B9D0BBD0B99BBB91B95FBB"
|
||||
$"44B983BB66B93DBB23B8EFBB2CB91BBB15B8C0BB47B8BEBADEB8C2BAFFB8B1BB"
|
||||
$"13B89FBB7EB8A7BB48B8C8BB7EB8C5BBB2B8C2BB89B8C6BBDBB8C8BC2DB8C7BC"
|
||||
$"04B8CFBC40B8BABC48B8CBBC48B8B3BC4BB8A9BC4EB8AEBC4DB8A0BC57B893BC"
|
||||
$"4BB898BC55B881BC4AB88EBD0FB88DBD00B893BD49B8E0BDE7B88DBE02B90DBE"
|
||||
$"03B922BE74B906BE4BB946BEA7B985BF00B972BEC1B996BF3EB9A240B997BF80"
|
||||
$"B9AFC010BA16C05EB9DBC02DBA24C0B3BA75C126BA3CC0E7BA8FC143BAC0C17F"
|
||||
$"BAA9C15FBAD7C19FBAFBC17BBAE3C19DBADDC13ABAD6C0A5BAD2C0EFBADBC060"
|
||||
$"BACDBFD1BAEAC012BACDBFD10009BD5DB5D6BD5DB5D6BD81B5EDBDB1B60DBD83"
|
||||
$"B605BDCFB613BE19B600BE01B619BE55B5C3BEF5B5C3BEB0B5EFBF2CB5A1BFA3"
|
||||
$"B55D3FB55DBFCEB55DC00CB58CBFE9B577C03CB5A6C08FB566C063B574BF39B5"
|
||||
$"40BCA7B60DBDDCB57ABCEBB623BD5DB5D6BD29B600BD5DB5D60005BF34B6E9BF"
|
||||
$"34B6E9BF55B6EBBF99B6F5BF7BB702BFCEB6E0BF87B67CBF9BB693BF77B66DBF"
|
||||
$"3CB663BF2FB623BF44B68FBF34B6E9BF6AB6CBBF34B6E90004BA06B87FBA06B8"
|
||||
$"7FBA0BB867B9EEB84FB9FDB85FB982B8E4B8EFBA35B92CB987B97D31BA06B87F"
|
||||
$"B974B8EFBA06B87F0066C6F6BC24C6F6BC24C6DBBB09C6002FC68AB9F1C5B9B8"
|
||||
$"7BC4FFB79BC563B805C4CEB768C463B708C49AB736C452B6FBC427B6EFC43FB6"
|
||||
$"E2C411B6FAC407B6C1C401B6D0C315B60FC0D0B56EC1F8B59AC0FAB58AC15EB5"
|
||||
$"9CC130B589C170B5A1C178B5C9C19FB5BDC12CB5E2C08AB5C9C0D7B5C3C059B5"
|
||||
$"CDC03FB60DC042B5DDC03DB629C03FB676C036B65CC04AB694C0B6B65EC0A7B6"
|
||||
$"6FC0CDB643C0F1B619C0B0B607C108B64AC0D0B6B0C13AB6D5C0B5B6A7C066B6"
|
||||
$"89C083B67CC063B689C05CB6AFC05EB6AAC053B6C0C030B6CFC043B6CABFE5B6"
|
||||
$"E4BF94B741BFB0B6EFBF87B768BF5CB790BF88B781BF3BB79CBEF6B7B2BF17B7"
|
||||
$"A3BECCB7C7BEF9B81BBEE9B7FFBF05B82FBF19B86CBF02B860BF59B891BFBEB7"
|
||||
$"E0BFA3B801BFE0B7B3C038B7ADC008B7BCC04FB7A6C084B776C06CB76EC0D3B7"
|
||||
$"95C0F7B83EC0EBB7F4C10FB83FC135B80FC100B801C10CB7E5C0ECB76F43B7AA"
|
||||
$"C125B795C15EB7FCC14DB7BCC170B83CC1C1B820C18DB860C1CFB813C1FCB7D4"
|
||||
$"C1E1B7BCC213B7E9C1F1B838C2142DC206B84BC23AB83CC222B842C259B83447"
|
||||
$"B841C26CB835C2AEB84FC2F9B856C2D5B854C320B859C346B898C335B87AC376"
|
||||
$"B8E6C249B8C5C258B8C6C227B8C2C1E1B8CFC202B8C1C1C8B8DAC199B8EFC1B6"
|
||||
$"2FC178B8E5C13EB8B5C15AB8C7C117B89BC0C4B872C0EFB885C07EB853BFE2B8"
|
||||
$"4EC02EB83FBFBFB855BF7FB87BBF9BB866BF5BB896BF10B8A4BF34B87FBEDBB8"
|
||||
$"DBBE6DB941BEB5B91FBE50B94FBE19B976BE2DB95BBE03B990BDF5B9D1BE03B9"
|
||||
$"B4BDE8B9EDBDE2BA1DBDCAB9FBBDF7BA3BBDEFBA76BDFEBA52BDD9BAA9BDC9BB"
|
||||
$"27BD9EBAEEBDF235BE71BBBBBE39BB93BEAFBBE9BF40BBD1BEFBBBE5BF82BBC1"
|
||||
$"C009BB9CBFC4BBA0C05EBB95C0DCBC03C0A1BBCDC104BC26C0F4BC67C113BC34"
|
||||
$"C0D3BC9EC103BD00C0E8BCC7C11FBD3644BDA3C13CBD6CC166BDB9C182BDE8C1"
|
||||
$"76BDCFC18DBE03C16DBE2CC17ABE15C152BE5DC13EBECEC13EBE97C13EBF0DC1"
|
||||
$"85BF4CC15CBF24C1A9BF71C1A4BFE2C1A7BFB3C1A0C025C1DAC087C1B3C053C2"
|
||||
$"15C08AC289C06CC253C086C2CBC04DC319BFDDC2E8C00EC346BFB0C386BF66C3"
|
||||
$"77BFAAC396BF12C3FEBEBFC3C1BEF2C435BE8FC430BE0CC42DBE4DC432BDC0C4"
|
||||
$"33BD21C428BD6CC43BBCDDC4AABC77C47EBCA7C4CDBC55C511BC03C505BC34C5"
|
||||
$"19BBE7C512BBA8C51236C512BB92C51035C51ABB70C4F7BB29C47EBB2BC489BB"
|
||||
$"5DC475BB0EC48ABB01C476BB13C4A1BAECC477BACDC48ABAD7C441BAACC3F0BA"
|
||||
$"66C418BA9AC3CCBA36C390B9CAC3ADBA00C389B9BDC36CB93AC341B92DC39AB9"
|
||||
$"4AC3E1B9A2C3C3B981C419B9DFC46DBA6AC44ABA1FC46EBA73C496BA89C48EBA"
|
||||
$"85C4AFBA9CC4EABAA8C4CABAABC533BAA1C559BA1F4EBA60C56231C4E8B9AEC5"
|
||||
$"1DB9DAC4CAB996C49EB958C4B6B975C48EB946C473B90DC466B92AC492B8F9C4"
|
||||
$"BCB91CC49FB90BC4DFB932C52BB951C505B9444EB95EC5B4B96CC591B952C5C9"
|
||||
$"B97BC5E7B9B8C5D8B9A1C5FEB9DCC626BA26C614BA00C644BA60C694BA9EC64D"
|
||||
$"BA88C667BAE8C6B6BB83C693BB3FC6DEBBD3C6E3BC7BC6E4BC22C6E2BCCEC6D0"
|
||||
$"BD78C6F4BD2BC6A6BDCCC69FBE9AC69FBE3EC6A0BE95C6A4BE88C6A2BE8DC6A1"
|
||||
$"3DC6A0BEC0C696BEBEC6B2BEC3C6D5BE01C6D2BE15C6F5BD65C6F6BC24C700BC"
|
||||
$"C3C6F6BC240008C301B7D8C301B7D8C2E6B7DBC2D4B7A3C2E8B7AEC2B1B792C2"
|
||||
$"69B7B7C288B7A7C204B7EEC236B742C221B77BC239B73AC285B743C279B746C2"
|
||||
$"A6B740C2F2B74EC2D7B730C30BB76AC33CB7A1C31FB787C35FB7C1C301B7D8C3"
|
||||
$"1CB7D4C301B7D80004BB52C203BB52C203BB44C20CBB26C221BB37C21DBB54C2"
|
||||
$"48BBB9C290BB86C26EBB91C265BB52C203BB84C226BB52C2030005C4F3BE2DC4"
|
||||
$"F3BE2DC4D3BE57C48BBEA4C4A5BE75C46EBEDAC47DBF52C47DBF18C4B6BF37C4"
|
||||
$"EDBEB8C4D0BEEBC502BE92C4F3BE2DC531BE48C4F3BE2D0009C212C326C212C3"
|
||||
$"26C17FC38FBFF6C344C09DC332BFD0C348BF8DC36ABFABC350BF66C38BBF1FC3"
|
||||
$"86BF56C386BEAFC386BDCDC386BE3EC386BEC1C3CBC0BFC3BABFC3C3DCC137C3"
|
||||
$"A9C221C367C1AEC38DC229C364C261C32AC280C337C248C322C212C326C229C3"
|
||||
$"31C212C32602024E284E2C542E4C324C30482E020250304C3252344C364E344C"
|
||||
$"34020258B81858305C32543654324E300202583456365836563C5A3854380204"
|
||||
$"BCD5C1F1BACDC36FBEA5C09BC4A6BFA6C360BE3CC67FC1B0C064C5ACC23AC444"
|
||||
$"BE90C715B827C85CB961C9B8B682C68B0204C3CFC072C309BF45C521C2733DC6"
|
||||
$"5EC0DDC4E4BC10C7F6B880C76BB8DAC831B841C6E2BC6FC2E2B880C5CDBE42C1"
|
||||
$"890622AEAAE6BAEAAAAF9A0EB9E4C6DEB9CB50B985C672BA12C5CDBAABC593BA"
|
||||
$"C54DBAB8C4BBBAEBC3C8BAABC37CBA85C0CBBC88BE0E36B8E6B993B8DA2EB874"
|
||||
$"B92DB970B7AFBCD5BA52BCEEB87ABE3AB7AEBD61B7AEBF12B7AEBF852EBF92BA"
|
||||
$"78C0D2BB91C49BBB6AC51ABC10C51ABBB6C51ABC5AC49BBCB6C21DBCC3BF9FBD"
|
||||
$"CEBFCBC18BC1FCC323BF00C13E46C33BC196C43B46C3DBC12AC484C02BC493C0"
|
||||
$"11C3EFC091C36FBE20C2BDBF40BC50C14ABBF74EBB8451BBE8C66EBA9EC6B906"
|
||||
$"11AAAAA8BA02BBEFB9ECBB49BAB8BCC8BB9DBCE1BE4EBB70C018BC7BC0A5BE07"
|
||||
$"BF73BE6044BF9FBF6CBDDBC06CBD0245BCAEC1C9BC2FBF40BAABBE0EBB04BF0D"
|
||||
$"BB04BD82BB04BD14BAB8BCAEBA38060BBAAA2A31C653BA0BC6C4BB84C645BB2B"
|
||||
$"C69FBBB6C614BBAFC5A0BBDDC309BC1DC163BCAEC0CABB70BFE5BAD7C0CABADE"
|
||||
$"C36FBAE3C5C5060AAAAB0ABE46C125BF99C130BF80454448C1FCC394C21DC361"
|
||||
$"C1C3C3F0C11EC447C052C493C02BC3EFC105C389BE67470605EA02BB37BAC5BB"
|
||||
$"D6BA12B9ACB887B8E0B8ADB90BB869B887B939B920B96C0A05C16BBB91C473BB"
|
||||
$"91C4D9BC36C4A6BCC3C16BBCE906078A2EBD4F2EBDB5B814BEA7BF402EBF4DBA"
|
||||
$"45BE0EBB04BEA7BB2BBD8ABAE2BD29BA520607AA3A39B8EDBE012F3CB99F3EB9"
|
||||
$"93BEDAB920BF99B946BE34B77BBFF5B7C239B74804032EBCE932BDCEBB2BBD34"
|
||||
$"BB12BECDBB51BF4DBA380208CA68BA5FCB40BD02CA39B9D0CA0EB6BCCAF3B7AE"
|
||||
$"C947B5E955B58A55B58A55B58AC843B841C8FFB76C53B953C718B814C6E62FC7"
|
||||
$"4BB728C5A02FC601B84EC2703DC645BCB6C5ACBC1DC711BD82C89DBEE7C79E40"
|
||||
$"C89DBEE7060ABFFB0FC6F1C097C625BFCBC6F1BFCB5A345C3758315A2E5A305A"
|
||||
$"2C582A562E582C54305230C691B854C691B920C691B7DAC53ABAAB4FB9ACC501"
|
||||
$"BB1EC46EBBF7C4ADBB9DC3FABCB6C56DBE0EC38EBE4EC64DBDF00207C86FBE74"
|
||||
$"C86FBE74C7A3BDA8C78ABB44C80ABB28C71835C633BBB7C6D4BBEFC5DABB98C5"
|
||||
$"01BB44C509BB79C4F1BAEDC3F4BC43C43EBBD1C4B4BC83C6FF38C63336C7CB3A"
|
||||
$"C83CBE9AC5B3BF8DC908BD020202C6392F4DB9F9C66CBAC54DBBE24FBB16C46E"
|
||||
$"BAEB0202C969B7CEC967B915CAFFB9E1543654324E300202583456365836C876"
|
||||
$"BD8FC969BB84C7AABBF70604EAC2BD4448C110C32EC07EC361C17DC33CC0E4C3"
|
||||
$"7BC1E30205C5ACB861C65E31C52BB75D50204E224E20C3E1BA5FC37BB94FC455"
|
||||
$"BB91C606BD02C493BCB6C722BE0DCB1BBDA8CB97BDE4C79EBBF702044EB44BC4"
|
||||
$"D4284EB5174BB9B9C408B8BAC43DBAD755BD4F4BBBD057BD4FC744BB77C818BC"
|
||||
$"3B51BAC502034E28C4A1B847C53AB61650BA52C592B8A0C690BBAEC4E0BAAB59"
|
||||
$"BD8FC4E0B7A104032EB77BC612B63CC969B50AC7AAB777CB35BCA9C99C04032E"
|
||||
$"B965B906B953B7D4B8D3B86D31B748BAB82C0406BE0BB689BE67B5FDC04BB607"
|
||||
$"BF7FB5F0C11CB689C1D7B65BC1A2B73BC2A3B85448B77BC33CB801C31EB70849"
|
||||
$"B609C32304032EBDA8B887BEB4B76EBE10B775BFEC2BC059B8AD04032E28BE01"
|
||||
$"B3FFC0D8B4253FB3D2C288B5BDC2FB0406FE0BC79EBB2BC8F5BBAAC840BB47C9"
|
||||
$"EBBC2ECB26BDDBCB05BD14CB40BE74CA4FC07ECA99BFCACA0EC117C9CFC27CCA"
|
||||
$"0EC1E3C998C30058C3890A04C6FFBB11C856BC50C8BCBCC3C889BD4F040CAAFA"
|
||||
$"BABC6FC74BC091C699C303C5CDC3DAC54DC440C4CEC44EC382C1EAC303C237C3"
|
||||
$"4DC1D5C2EEC05EC402C149C3DFBF754BBD87C460BD47C4F9BE46C513BE2D4DBE"
|
||||
$"98C58BBDBAC5870608BAAABFECC1FC4448C1FCC394C21DC361C1C3C3F0C11EC4"
|
||||
$"47C052C493C02BC3EFC105C389BED3C2BD0A04C369BC83C6D738C666BD1CC35B"
|
||||
$"BD350A03B46542B4BE41B4BE420605AF03B6AFC969B63CC9F1B72FC8D0BE4155"
|
||||
$"B821CA8DC11CC6FAC42DC5C5C55FC53ABE67C91DC1E8C7EAB86DCB260604EEBF"
|
||||
$"CBBB51C1FCBBD0C13EBC43C29FBB6EC18BBAAB43BB1EC145BAF2C09ABB4B0A04"
|
||||
$"30303050505050302C0A0001021240BAB100000000000040B755C6CCDBBE9979"
|
||||
$"01178300040A0101020240BAB100000000000040B755C6CCDBBE99790A020103"
|
||||
$"0240BAB100000000000040B755C6CCDBBE99790A030A05060708090A0C0D040B"
|
||||
$"0240BAB100000000000040B755C6CCDBBE99790A110113124084473AE65BBB05"
|
||||
$"39406A8F40BD7AC6ED3001178400040A00012712401CCA0000000000004031D6"
|
||||
$"BEA7B4C5651401178100040A150112024046733A7FB6BABB05401508437714C3"
|
||||
$"BB840A3B012E0A401CC92E6813AE6813401CC9C0B293C4BE831DFF0A11011412"
|
||||
$"402E52374883B74883402E5243A84DC5C35901178200040A16011502402E5237"
|
||||
$"4883B74883402E5243A84DC5C3590A17011602402E52374883B74883402E5243"
|
||||
$"A84DC5C3590A18011702402E52374883B74883402E5243A84DC5C3590A170118"
|
||||
$"02402E52374883B74883402E5243A84DC5C3590A1801190240268F36C1F1B73C"
|
||||
$"D33FA9DD442903C369B00A1B011A02402E52374883B74883402E5243A84DC5C3"
|
||||
$"590A2C011B02402E52374883B74883402E5243A84DC5C3590A11011C12402E52"
|
||||
$"374883B74883402E5243A84DC5C35901178100040A20011D124018A13C2DD3BC"
|
||||
$"6F843F776243040C3B35B701178400040A28011D024018A13C481BBC6F843FA1"
|
||||
$"3143AD0CC180CE0A27011E024018A13C3669BC6F843F850B43AD0CBDA6830A26"
|
||||
$"03212022023F94B53C057BBC14913F373546DE4E423FFC0A2B012202401CCA00"
|
||||
$"0000000000401CCAC64FB846E7CF0A2B01230241774E3E9634BD97FB40685AC6"
|
||||
$"A141CA33220A0001291240075E0000000000004029CCC0DC88C59D5C01178100"
|
||||
$"040A2E0124123E3A7739EBE1BA96D53D1E7BC874E948577D01178400040A3601"
|
||||
$"24023DE4F539818BBA43313CC9E6C7EFC848861D0A350125023DE4F539818BBA"
|
||||
$"43313CC9E6C7EFC848861D0A340126023DE4F539D28CBA43313D0A55C7EFC848"
|
||||
$"5E9A0A000128123FEA4E3675EFB6F2733F44E3440366C2D26601178200040A00"
|
||||
$"012A12402E52374883B74883402E5241C554C5CE0401178100040A00012B1240"
|
||||
$"1CCA000000000000401CCAC0623FC4B46E01178100040A00012C124031960000"
|
||||
$"00000000401CCAC3AEA8C4B46E01178100040A3A012D02401CCA000000000000"
|
||||
$"401CCAC0E971C4B46E0A3C012F0A401CCA000000000000401CCAC0E971C4B46E"
|
||||
$"1DFF0A3B01300A3FEC520000000000003C6A0B41051D473FEE1DFF0A3E013102"
|
||||
$"40FA05000000000000417C4D3E5061C9E26E0A3F013212401CCA000000000000"
|
||||
$"401CCAC0E971C42D3C01178200040A4001330A401CCA000000000000401CCAC0"
|
||||
$"E971C4B46E1DFF0A420134023600000000000000003600004890004AE8000A42"
|
||||
$"0134023600000000000000003600004870004AE8000A43013402360000000000"
|
||||
$"0000003600004850004AF8000A43013402360000000000000000360000487000"
|
||||
$"4AF8000A430134023600000000000000003600004890004AF8000A4401340236"
|
||||
$"0000000000000000360000485000466000"
|
||||
};
|
||||
|
||||
resource(201, "kActionBack") #'VICN' array {
|
||||
$"6E636966070500020006023B2FA63AC896BCCBD33D335A4A6980490D0B00ACE2"
|
||||
$"FFFF6ECDFF0200060236D841374D6EBD38553CC6154AA9DF4607770026A8EBFF"
|
||||
$"0694DE020006023729EA388C8FBC29073AAE614A51AF4A729A00035E8CFF0585"
|
||||
$"C70200060238E8A83647FBBA8E2D3D42294AF6F7496CE200047BB8FF0694DE02"
|
||||
$"0006023957BB3923F0BC39AC3C5E604AA873475AB1000592DAFD67CBFF04FF49"
|
||||
$"080A092E3C3A53424C484F5047503A4435442B3A300A072E3C3A533A48484F48"
|
||||
$"403A3A3A300A043A303A3A4435442B0A033A483A53424C0A044840484F504750"
|
||||
$"3A0A043A3A4435503A48400803C125B7D43AB99FB8D3BE0E08023A3A4840070A"
|
||||
$"0001001001178400040A010101000A020102000A030103000A040104000A0501"
|
||||
$"05000A06020607100117812004"
|
||||
};
|
||||
|
||||
resource(202, "kActionForward") #'VICN' array {
|
||||
$"6E636966050500020006023B2FA63AC896BCCBD33D335A4A6980490D0B00ACE2"
|
||||
$"FFFF6ECDFF0200060239AF2C39E19BBC89D83C68DC4AFA1247CFA20006A5F7FF"
|
||||
$"069EEC02000602B8EEBEB986C33C7FB4BC13FB46FA0C49FBDD000592DAFD3EBD"
|
||||
$"FF04FF49050A0A2E423A483A524847503F432A3A2F3A3136302E350A0748473A"
|
||||
$"2F3A392E352E423A483A520A043A2F4847503F432A0A042E3536303A313A3908"
|
||||
$"0536B9932FBB773B3A3BB939C0E5B755050A0001001001178400040A01010100"
|
||||
$"0A020102000A030103000A040104100117812004"
|
||||
};
|
||||
|
||||
resource(203, "kActionForward2") #'VICN' array {
|
||||
$"6E63696607050002000602396DF23A056B3B94FCBB09F547CD484AAB5F0090D9"
|
||||
$"FFFF6ECDFF02000602B5E5793878A83E023B3B2AC34893F147CC490060C8FFFF"
|
||||
$"44BEFD02000602B6F90538542D3C2FCA3ACA9249A8634A929A00034F77FF0468"
|
||||
$"9C020006023AC62E392AB63B6BA0BCFF0B49DAAA4AAE4500046FA7FF2BA5E502"
|
||||
$"0006023A1CB834EBA6383E33BD3E8D499DE44A647800ACE2FFFD6DCCFF04FF49"
|
||||
$"080A09523A48533F503C532E4C2E3E3A363A2B482E0A07523A485348473C533C"
|
||||
$"43483A482E0A04482E483A3A363A2B0A03484748533F500A043C433C532E4C2E"
|
||||
$"3E0A04483A3A362E3E3C430802BD8FB795C2BDB8E008023C43B8C7BF0D070A00"
|
||||
$"01001001178400040A040101000A020102000A030103000A010104000A050105"
|
||||
$"000A06020607100117812004"
|
||||
};
|
||||
|
||||
resource(204, "kActionStop") #'VICN' array {
|
||||
$"6E63696606050102000602393D323BB602BEA28F3C4CC64B601449439F00FF3E"
|
||||
$"3EFFF70606020006033B27153C10C7BDF9893D088A4B2F634882C500C805057D"
|
||||
$"9D0404FFB4040403750303020006023B06EB3B5469BC08EB3BB31F4AB15D4478"
|
||||
$"7700FF9090FFFF757504FF440A0A0C2E4C364E3C4742524A5440434A3842353C"
|
||||
$"BE1B36312E2E38400A0636313C3C40434A54504E402E0A03364E3E483C470A04"
|
||||
$"483FC712BADE4A3840430A042E2E3631402E382C0A0442354A38C712BADE4AB9"
|
||||
$"EC0A0E2E4C364EBEB6C37042524A54504E483FC712BADE4AB9EC4335402E382C"
|
||||
$"2E2E384008022FB8A0BCC3B80708033C3C42364ABA120802BCA9BFF3B8D3C47B"
|
||||
$"060A0001061001178400040A020101000A03020302000A010100000A04020504"
|
||||
$"000A0503070809100117810004"
|
||||
};
|
||||
|
||||
resource(206, "kActionGoStart") #'VICN' array {
|
||||
$"6E63696605050002001602B53D77BAF2653D77A7B7CFFC460F874A2D7700F0FF"
|
||||
$"D50200160236FB2637191CBC57873C40E14B0E7149D82700A2FFBB0200060239"
|
||||
$"FB483A6DC2BDAC713D02DB4B384746086300EA0606FFD005050200060238B0C7"
|
||||
$"397C47BD2A963C71B74A82C348B2B700FF4444FFF106060A0A06304942525044"
|
||||
$"50383E32303D0A09303B3049324A32C0723643364C4252424036320A04503650"
|
||||
$"44425242400A082D3E3535434645455439462C35312B3C0A062B3C2D3E353543"
|
||||
$"46454535310A0445455439462C35310A0432C072324A364C36430A043A453A4A"
|
||||
$"3E4C3EC2630A044645464A484848430A044C3F4C444E424E3D070A0001001001"
|
||||
$"178400040A010101000A020102000A000406070809000A000103100117840004"
|
||||
$"0A030105000A04010400"
|
||||
};
|
||||
|
||||
resource(205, "kActionGo") archive BBitmap {
|
||||
"_frame" = rect { 0.0, 0.0, 15.0, 15.0 },
|
||||
"_cspace" = 8200,
|
||||
"_bmflags" = 0,
|
||||
"_rowbytes" = 64,
|
||||
"_data" = array {
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000C1000000DE00000061000000070000000100000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000FF9BD4A5FF48634EFF000000C00000003500000004"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000FFB6F9C2FFB3F9C0FF84B68EFF263426FD0000009B"
|
||||
$"0000001600000002000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000FFB6F9C2FF7EF995FFA3F9B3FFAAE9B6FF69906FFF"
|
||||
$"000000E200000064000000070000000100000000000000000000000000000000"
|
||||
$"0000000000000000000000FFB6F9C2FF6AFB85FF6AFB85FF83FA98FFA4F5B2FF"
|
||||
$"7CC88AFF325C3BFF000000C00000003500000004000000000000000000000000"
|
||||
$"0000000000000000000000FFB6F9C2FF5DFC7BFF5DFC7BFF5DFC7BFF5DFB7CFF"
|
||||
$"60ED7AFF54D76DFF389A48FF002A14FD0000009B000000160000000200000000"
|
||||
$"0000000000000000000000FFB5F8C1FF59FC77FF59FC77FF59FC77FF59FC77FF"
|
||||
$"59FC77FF55F674FF40DB5CFF2BBC48FF1C752BFF000000D00000002000000003"
|
||||
$"0000000000000000000000FFA8F4B5FF2EFA54FF2EFA54FF2EFA54FF2EFA54FF"
|
||||
$"2EFA54FF2BF350FF22D542FF1CB638FF157027FF000000D00000003D00000009"
|
||||
$"0000000000000000000000FF92ECA2FF15F940FF15F940FF15F940FF15F740FF"
|
||||
$"15DE35FF00BE2EFF008922FF002600FD0000009B000000430000002000000003"
|
||||
$"0000000000000000000000FF7EE591FF15F83DFF15F83DFF1CEA3DFF00C732FF"
|
||||
$"009E22FF004815FF000000BF000000560000002D0000000F0000000200000000"
|
||||
$"0000000000000000000000FF6DDF81FF1CF340FF2BDA4AFF1CB638FF006D1CFF"
|
||||
$"000000E200000074000000360000001900000004000000000000000000000000"
|
||||
$"0000000000000000000000FF5DDA75FF44D25FFF229338FF002600FD0000009B"
|
||||
$"0000004300000023000000070000000100000000000000000000000000000000"
|
||||
$"0000000000000000000000FF46B65CFF1C5222FF000000BF000000560000002D"
|
||||
$"0000000F00000002000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000C2000000DE00000074000000360000001900000004"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000030000001F00000020000000080000000100000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* Copyright 2002-2006, project beam (http://sourceforge.net/projects/beam).
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Oliver Tappe <beam@hirschkaefer.de>
|
||||
*/
|
||||
|
||||
#include "AutoCompleter.h"
|
||||
|
||||
#include <Looper.h>
|
||||
#include <Message.h>
|
||||
|
||||
#include "AutoCompleterDefaultImpl.h"
|
||||
|
||||
|
||||
// #pragma mark - DefaultPatternSelector
|
||||
|
||||
|
||||
class DefaultPatternSelector : public BAutoCompleter::PatternSelector {
|
||||
public:
|
||||
virtual void SelectPatternBounds(const BString& text, int32 caretPos,
|
||||
int32* start, int32* length);
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
DefaultPatternSelector::SelectPatternBounds(const BString& text,
|
||||
int32 caretPos, int32* start, int32* length)
|
||||
{
|
||||
if (!start || !length)
|
||||
return;
|
||||
*start = 0;
|
||||
*length = text.Length();
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - CompletionStyle
|
||||
|
||||
|
||||
BAutoCompleter::CompletionStyle::CompletionStyle(EditView* editView,
|
||||
ChoiceModel* choiceModel, ChoiceView* choiceView,
|
||||
PatternSelector* patternSelector)
|
||||
:
|
||||
fEditView(editView),
|
||||
fPatternSelector(patternSelector ? patternSelector
|
||||
: new DefaultPatternSelector()),
|
||||
fChoiceModel(choiceModel),
|
||||
fChoiceView(choiceView)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BAutoCompleter::CompletionStyle::~CompletionStyle()
|
||||
{
|
||||
delete fEditView;
|
||||
delete fChoiceModel;
|
||||
delete fChoiceView;
|
||||
delete fPatternSelector;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BAutoCompleter::CompletionStyle::SetEditView(EditView* view)
|
||||
{
|
||||
delete fEditView;
|
||||
fEditView = view;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BAutoCompleter::CompletionStyle::SetPatternSelector(
|
||||
PatternSelector* selector)
|
||||
{
|
||||
delete fPatternSelector;
|
||||
fPatternSelector = selector;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BAutoCompleter::CompletionStyle::SetChoiceModel(ChoiceModel* model)
|
||||
{
|
||||
delete fChoiceModel;
|
||||
fChoiceModel = model;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BAutoCompleter::CompletionStyle::SetChoiceView(ChoiceView* view)
|
||||
{
|
||||
delete fChoiceView;
|
||||
fChoiceView = view;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - BAutoCompleter
|
||||
|
||||
|
||||
BAutoCompleter::BAutoCompleter(CompletionStyle* completionStyle)
|
||||
:
|
||||
fCompletionStyle(completionStyle)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BAutoCompleter::BAutoCompleter(EditView* editView, ChoiceModel* choiceModel,
|
||||
ChoiceView* choiceView, PatternSelector* patternSelector)
|
||||
:
|
||||
fCompletionStyle(new BDefaultCompletionStyle(editView, choiceModel,
|
||||
choiceView, patternSelector))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BAutoCompleter::~BAutoCompleter()
|
||||
{
|
||||
delete fCompletionStyle;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BAutoCompleter::Select(int32 index)
|
||||
{
|
||||
if (fCompletionStyle)
|
||||
return fCompletionStyle->Select(index);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BAutoCompleter::SelectNext(bool wrap)
|
||||
{
|
||||
if (fCompletionStyle)
|
||||
return fCompletionStyle->SelectNext(wrap);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BAutoCompleter::SelectPrevious(bool wrap)
|
||||
{
|
||||
if (fCompletionStyle)
|
||||
return fCompletionStyle->SelectPrevious(wrap);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BAutoCompleter::IsChoiceSelected() const
|
||||
{
|
||||
if (fCompletionStyle)
|
||||
return fCompletionStyle->IsChoiceSelected();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
BAutoCompleter::CountChoices() const
|
||||
{
|
||||
if (fCompletionStyle && fCompletionStyle->GetChoiceModel())
|
||||
return fCompletionStyle->GetChoiceModel()->CountChoices();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
BAutoCompleter::CountVisibleChoices() const
|
||||
{
|
||||
if (fCompletionStyle && fCompletionStyle->GetChoiceView())
|
||||
return fCompletionStyle->GetChoiceView()->CountVisibleChoices();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
BAutoCompleter::SelectedChoiceIndex() const
|
||||
{
|
||||
if (fCompletionStyle)
|
||||
return fCompletionStyle->SelectedChoiceIndex();
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BAutoCompleter::ApplyChoice(bool hideChoices)
|
||||
{
|
||||
if (fCompletionStyle)
|
||||
fCompletionStyle->ApplyChoice(hideChoices);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BAutoCompleter::CancelChoice()
|
||||
{
|
||||
if (fCompletionStyle)
|
||||
fCompletionStyle->CancelChoice();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BAutoCompleter::EditViewStateChanged(bool updateChoices)
|
||||
{
|
||||
if (fCompletionStyle)
|
||||
fCompletionStyle->EditViewStateChanged(updateChoices);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BAutoCompleter::SetEditView(EditView* view)
|
||||
{
|
||||
if (fCompletionStyle)
|
||||
fCompletionStyle->SetEditView(view);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BAutoCompleter::SetPatternSelector(PatternSelector* selector)
|
||||
{
|
||||
if (fCompletionStyle)
|
||||
fCompletionStyle->SetPatternSelector(selector);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BAutoCompleter::SetChoiceModel(ChoiceModel* model)
|
||||
{
|
||||
if (fCompletionStyle)
|
||||
fCompletionStyle->SetChoiceModel(model);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BAutoCompleter::SetChoiceView(ChoiceView* view)
|
||||
{
|
||||
if (fCompletionStyle)
|
||||
fCompletionStyle->SetChoiceView(view);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BAutoCompleter::SetCompletionStyle(CompletionStyle* style)
|
||||
{
|
||||
delete fCompletionStyle;
|
||||
fCompletionStyle = style;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user