diff --git a/build/jam/images/definitions/minimum b/build/jam/images/definitions/minimum index fa836795e7..04c2b8d815 100644 --- a/build/jam/images/definitions/minimum +++ b/build/jam/images/definitions/minimum @@ -26,7 +26,7 @@ SYSTEM_BIN = [ FFilterByBuildFeatures route safemode screen_blanker screeninfo screenmode setarch setmime settype setversion setvolume shutdown - strace su sysinfo + strace su sysinfo system_time tcptester telnet telnetd top traceroute trash unchop unmount diff --git a/build/jam/packages/HaikuDevel b/build/jam/packages/HaikuDevel index b18f7d8b0a..de160cdb6f 100644 --- a/build/jam/packages/HaikuDevel +++ b/build/jam/packages/HaikuDevel @@ -21,7 +21,6 @@ AddFilesToPackage develop lib : kernel.so : _KERNEL_ ; # additional libraries local developmentLibs = libroot_debug.so - libroot_guarded.so ; AddFilesToPackage lib : $(developmentLibs) ; diff --git a/build/jam/repositories/HaikuPorts/x86 b/build/jam/repositories/HaikuPorts/x86 index cd30088f69..41cd7b1842 100644 --- a/build/jam/repositories/HaikuPorts/x86 +++ b/build/jam/repositories/HaikuPorts/x86 @@ -22,7 +22,7 @@ RemotePackageRepository HaikuPorts apr_util_devel-1.4.1-4 autoconf-2.69-6 automake-1.13.1-4 - bash-4.3.39-1 + bash-4.3.42-1 beam-1.2-1 bepdf-1.2.0-1 bescreencapture-1.9.4-1 @@ -37,12 +37,12 @@ RemotePackageRepository HaikuPorts clang-3.4-3 clang_analysis-3.4-3 clipdinger-0.4-1 - cmake-3.0.0_rc3-1 + cmake-3.3.1-1 coreutils-8.24-1 cpio-2.10-1 ctags-5.8-3 - curl-7.43.0-1 - curl_devel-7.43.0-1 + curl-7.44.0-1 + curl_devel-7.44.0-1 cvs-1.12.13.1-6 cvsps-2.2b1-1 diffutils-3.3-2 @@ -90,8 +90,8 @@ RemotePackageRepository HaikuPorts gutenprint-5.2.10-1 gutenprint_devel-5.2.10-1 gzip-1.6-2 - haikuwebkit-1.4.10-1 - haikuwebkit_devel-1.4.10-1 + haikuwebkit-1.4.12-1 + haikuwebkit_devel-1.4.12-1 help2man-1.46.6-1 htmldoc-1.8.27-3 icu-55.1-4 @@ -124,8 +124,8 @@ RemotePackageRepository HaikuPorts liblayout_devel-1.4.2-1 libogg-1.3.0-2 libogg_devel-1.3.0-2 - libpcap-1.7.3-1 - libpcap_devel-1.7.3-1 + libpcap-1.7.4-1 + libpcap_devel-1.7.4-1 libpcre-8.21-5 libpcre_devel-8.21-5 libpng-1.5.22-1 @@ -175,12 +175,14 @@ RemotePackageRepository HaikuPorts mpc_devel-1.0.3-1 mpfr-3.1.3-1 mpfr_devel-3.1.3-1 - mpg123-1.22.3-1 - mpg123_devel-1.22.3-1 + mpg123-1.22.4-1 + mpg123_devel-1.22.4-1 nano-2.4.2-1 nasm-2.11.08-1 ncurses-5.9-10 ncurses_devel-5.9-10 + ncurses6-6.0-1 + ncurses6_devel-6.0-1 neon-0.29.6-7 neon_devel-0.29.6-7 netcat-1.10-1 @@ -218,7 +220,7 @@ RemotePackageRepository HaikuPorts subversion-1.6.18-6 subversion_devel-1.6.18-6 tar-1.27.1-2 - tcpdump-4.7.4-1 + tcpdump-4.7.4-2 texinfo-4.13a-7 tiff-3.9.6-2 tiff_devel-3.9.6-2 @@ -226,7 +228,7 @@ RemotePackageRepository HaikuPorts tinyxml-2.6.2-1 tinyxml_devel-2.6.2-1 transmission-2.84-3 - unrar-5.1.5-1 + unrar-5.3.2-1 unzip-6.0-2 vision-0.9.7.r949-3 vim-7.4-1 @@ -236,7 +238,7 @@ RemotePackageRepository HaikuPorts xml_parser-2.36-1 xz_utils-5.0.8-2 xz_utils_devel-5.0.8-2 - yasm-1.2.0-3 + yasm-1.3.0-1 zip-3.0-2 zlib-1.2.8-4 zlib_devel-1.2.8-4 @@ -245,8 +247,8 @@ RemotePackageRepository HaikuPorts binutils_x86_gcc2-2.17_2013_04_21-2 bzip2_x86_gcc2-1.0.6-5 bzip2_x86_gcc2_devel-1.0.6-5 - curl_x86_gcc2-7.43.0-1 - curl_x86_gcc2_devel-7.43.0-1 + curl_x86_gcc2-7.44.0-1 + curl_x86_gcc2_devel-7.44.0-1 expat_x86_gcc2-2.1.0-1 expat_x86_gcc2_devel-2.1.0-1 ffmpeg_x86_gcc2-0.10.2-4 @@ -303,6 +305,8 @@ RemotePackageRepository HaikuPorts mesa_x86_gcc2_swrast-7.9.2-5 ncurses_x86_gcc2-5.9-10 ncurses_x86_gcc2_devel-5.9-10 + ncurses6_x86_gcc2-6.0-1 + ncurses6_x86_gcc2_devel-6.0-1 openssl_x86_gcc2-1.0.0s-1 openssl_x86_gcc2_devel-1.0.0s-1 pkgconfig_x86_gcc2-0.27.1-2 @@ -419,6 +423,7 @@ RemotePackageRepository HaikuPorts nano nasm ncurses + ncurses6 neon netcat openssh diff --git a/build/jam/repositories/HaikuPorts/x86_64 b/build/jam/repositories/HaikuPorts/x86_64 index d299f495d3..2e67ef65af 100644 --- a/build/jam/repositories/HaikuPorts/x86_64 +++ b/build/jam/repositories/HaikuPorts/x86_64 @@ -23,7 +23,7 @@ RemotePackageRepository HaikuPorts apr_util_devel-1.5.4-1 autoconf-2.69-6 automake-1.13.1-4 - bash-4.3.39-1 + bash-4.3.42-1 # bepdf-1.1.1~beta5_2013_04_28-1 binutils-2.25_12015_07_31-1 bison-2.6.5-1 @@ -59,13 +59,13 @@ RemotePackageRepository HaikuPorts clang-3.5.1-1 clang_analysis-3.5.1-1 clipdinger-0.4-1 - cmake-3.2.3-1 + cmake-3.3.1-1 coreutils-8.24-1 cppunit-1.12.1-2 cppunit_devel-1.12.1-2 ctags-5.8-3 - curl-7.43.0-1 - curl_devel-7.43.0-1 + curl-7.44.0-1 + curl_devel-7.44.0-1 cvs-1.12.13.1-6 diffutils-3.3-2 dos2unix-7.2.2-1 @@ -88,8 +88,9 @@ RemotePackageRepository HaikuPorts fontconfig-2.11.1-3 fontconfig_devel-2.11.1-3 fossil-1.33-1 - freetype-2.6-1 - freetype_devel-2.6-1 + freeciv-2.5.1-1 + freetype-2.6-2 + freetype_devel-2.6-2 fribidi-0.19.6-2 fribidi_devel-0.19.6-2 gawk-4.1.0-2 @@ -128,17 +129,17 @@ RemotePackageRepository HaikuPorts gutenprint-5.2.10-1 gutenprint_devel-5.2.10-1 gzip-1.6-2 - haikuwebkit-1.4.10-1 - haikuwebkit_devel-1.4.10-1 + haikuwebkit-1.4.12-1 + haikuwebkit_devel-1.4.12-1 handbrake-0.10.1-1 harfbuzz-0.9.40-1 harfbuzz_devel-0.9.40-1 help2man-1.46.6-1 htmldoc-1.8.27-3 - icu-55.1-3 - icu_devel-55.1-3 - icu54-54.1-1 - icu54_devel-54.1-1 + icu-55.1-5 + icu_devel-55.1-5 + icu54-54.1-2 + icu54_devel-54.1-2 intltool-0.40.6-4 jam-2.5_2012_10_12-2 jasper-1.900.1-4 @@ -153,6 +154,8 @@ RemotePackageRepository HaikuPorts lcms-2.7-1 lcms_devel-2.7-1 less-451-4 + libasr-1.0.2-1 + libasr_devel-1.0.2-1 libass-0.12.2-1 libass_devel-0.12.2-1 libassuan-2.2.0-1 @@ -177,6 +180,10 @@ RemotePackageRepository HaikuPorts libicns_devel-0.8.1-1 libiconv-1.13.1-6 libiconv_devel-1.13.1-6 + libmad-0.15.1b-2 + libmad_devel-0.15.1b-2 + libmikmod-3.3.7-1 + libmikmod_devel-3.3.7-1 libmkv-0.6.5.1-3 libmkv_devel-0.6.5.1-3 libmp4v2-2.0.0-2 @@ -185,8 +192,8 @@ RemotePackageRepository HaikuPorts libmpeg2_devel-0.5.1-3 libogg-1.3.0-2 libogg_devel-1.3.0-2 - libpcap-1.7.3-1 - libpcap_devel-1.7.3-1 + libpcap-1.7.4-1 + libpcap_devel-1.7.4-1 libpcre-8.21-5 libpcre_devel-8.21-5 libpng-1.5.22-1 @@ -248,12 +255,14 @@ RemotePackageRepository HaikuPorts mpc_devel-1.0.3-1 mpfr-3.1.3-1 mpfr_devel-3.1.3-1 - mpg123-1.22.3-1 - mpg123_devel-1.22.3-1 + mpg123-1.22.4-1 + mpg123_devel-1.22.4-1 nano-2.4.2-1 nasm-2.11.08-1 ncurses-5.9-10 ncurses_devel-5.9-10 + ncurses6-6.0-1 + ncurses6_devel-6.0-1 neon-0.29.6-7 neon_devel-0.29.6-7 netcat-1.10-1 @@ -285,6 +294,10 @@ RemotePackageRepository HaikuPorts sdl_gfx_devel-2.0.25-2 sdl_image-1.2.12-5 sdl_image_devel-1.2.12-5 + sdl_mixer-1.2.12-6 + sdl_mixer_devel-1.2.12-6 + sdl_ttf-2.0.11-2 + sdl_ttf_devel-2.0.11-2 sed-4.2.1-6 serf-1.3.7-1 serf_devel-1.3.7-1 @@ -298,7 +311,7 @@ RemotePackageRepository HaikuPorts subversion-1.8.11-1 subversion_devel-1.8.11-1 tar-1.27.1-2 - tcpdump-4.7.4-1 + tcpdump-4.7.4-2 texinfo-4.13a-7 tiff-3.9.6-2 tiff_devel-3.9.6-2 @@ -306,7 +319,7 @@ RemotePackageRepository HaikuPorts tinyxml-2.6.2-1 tinyxml_devel-2.6.2-1 transmission-2.84-3 - unrar-5.1.5-1 + unrar-5.3.2-1 unzip-6.0-2 vim-7.4-2 vision-0.9.7.r949-3 @@ -318,7 +331,7 @@ RemotePackageRepository HaikuPorts x264_devel-20140308-1 xz_utils-5.0.8-2 xz_utils_devel-5.0.8-2 - yasm-1.2.0-3 + yasm-1.3.0-1 zip-3.0-2 zlib-1.2.8-4 zlib_devel-1.2.8-4 @@ -358,6 +371,7 @@ RemotePackageRepository HaikuPorts flex fontconfig fossil + freeciv freetype fribidi gawk @@ -392,6 +406,7 @@ RemotePackageRepository HaikuPorts lame lcms less + libasr libass libassuan libbluray @@ -404,6 +419,8 @@ RemotePackageRepository HaikuPorts libgpg_error libicns libiconv + libmad + libmikmod libmkv libmp4v2 libmpeg2 @@ -444,6 +461,7 @@ RemotePackageRepository HaikuPorts nano nasm ncurses + ncurses6 neon netcat ninja @@ -466,6 +484,8 @@ RemotePackageRepository HaikuPorts scons sdl_gfx sdl_image + sdl_mixer + sdl_ttf sed serf sharutils diff --git a/build/jam/repositories/HaikuPorts/x86_gcc2 b/build/jam/repositories/HaikuPorts/x86_gcc2 index bd7bd5789b..90809a2c3f 100644 --- a/build/jam/repositories/HaikuPorts/x86_gcc2 +++ b/build/jam/repositories/HaikuPorts/x86_gcc2 @@ -14,6 +14,8 @@ RemotePackageRepository HaikuPorts droid-113-1 flare_x86_data-0.19-3 freedroidrpg_x86_data-0.15.1-1 + gws-0.1.8-1 + haikuporter-1.0.0-1 hub-1.12.4-1 openttd_gfx-0.4.7-1 openttd_msx-0.3.1-1 @@ -43,7 +45,7 @@ RemotePackageRepository HaikuPorts autoconf-2.69-5 automake-1.13.1-4 avra-1.3.0-1 - bash-4.3.39-1 + bash-4.3.42-1 beae-1.2-3 beam-1.2-1 becjk-1.0.1-1 @@ -52,7 +54,7 @@ RemotePackageRepository HaikuPorts belife-1.0.0-2 bemines-1.0b2-1 bepdf-1.2.0-1 - bepodder-1.3.0-1 + bepodder-1.3.0-2 bescreencapture-1.9.4-1 bezilla-2.0.0.22-1 binutils-2.17_2013_04_21-2 @@ -79,8 +81,8 @@ RemotePackageRepository HaikuPorts ctags-5.8-3 colors-2.3-1 coreutils-8.24-1 - curl-7.43.0-1 - curl_devel-7.43.0-1 + curl-7.44.0-1 + curl_devel-7.44.0-1 cvs-1.12.13.1-6 d52-3.4.1-1 desknotes-1.1-4 @@ -162,6 +164,7 @@ RemotePackageRepository HaikuPorts gperf-3.0.4-1 gpgme-1.5.2-2 gpgme_devel-1.5.2-2 + grafx2-2.5-2 grep-2.20-1 groff-1.20.1-3 gtk_doc-1.20-1 @@ -182,6 +185,7 @@ RemotePackageRepository HaikuPorts imagemagick_devel-6.8.9_8-1 intltool-0.40.6-4 itstool-2.0.2-1 + jabber4haiku-1.2.1-1 jam-2.5_2012_10_12-2 jasper-1.900.1-4 jasper_devel-1.900.1-4 @@ -260,8 +264,8 @@ RemotePackageRepository HaikuPorts libogg_devel-1.3.0-2 libpaper-1.1.24-1 libpaper_devel-1.1.24-1 - libpcap-1.7.3-1 - libpcap_devel-1.7.3-1 + libpcap-1.7.4-1 + libpcap_devel-1.7.4-1 libpcre-8.21-5 libpcre_devel-8.21-5 libpng-1.5.22-1 @@ -308,15 +312,15 @@ RemotePackageRepository HaikuPorts libxml2-2.8.0-9 libxml2_devel-2.8.0-9 libxml2_python-2.8.0-9 - libxslt-1.1.28-4 - libxslt_devel-1.1.28-4 + libxslt-1.1.28-5 + libxslt_devel-1.1.28-5 libzip-0.11.2-1 libzip_devel-0.11.2-1 lighttpd-1.4.35-2 lighttpd_devel-1.4.35-2 links-2.8-1 lmarbles-1.0.8-2 - lnlauncher-1.1.2-1 + lnlauncher-1.1.2-2 ltris-1.0.19-1 lua-5.2.1-6 lua_devel-5.2.1-6 @@ -343,8 +347,8 @@ RemotePackageRepository HaikuPorts moe-1.1.2-1 mog-0.63.1548-1 most-pre5.1_15-1 - mpg123-1.22.3-1 - mpg123_devel-1.22.3-1 + mpg123-1.22.4-1 + mpg123_devel-1.22.4-1 mtr-0.73-1 multitalk-1.4-1 mupdf-1.7-1 @@ -356,6 +360,8 @@ RemotePackageRepository HaikuPorts nasm-2.11.08-1 ncurses-5.9-9 ncurses_devel-5.9-9 + ncurses6-6.0-1 + ncurses6_devel-6.0-1 neon-0.29.6-6 neon_devel-0.29.6-6 netcat-1.10-1 @@ -464,7 +470,7 @@ RemotePackageRepository HaikuPorts tar-1.26-6 tcl-8.5.18-1 tcl_devel-8.5.18-1 - tcpdump-4.7.4-1 + tcpdump-4.7.4-2 texinfo-4.13a-7 tiff-3.9.6-2 tiff_devel-3.9.6-2 @@ -474,7 +480,7 @@ RemotePackageRepository HaikuPorts twolame-0.3.13-1 twolame_devel-0.3.13-1 ubertuber-0.9.11-1 - unrar-5.2.6-1 + unrar-5.3.2-1 unzip-6.0-2 util_macros-1.19.0-2 vasm-1.7c-1 @@ -499,7 +505,7 @@ RemotePackageRepository HaikuPorts xrick-021212-2 yab-1.7.5-2 yab_ide-2.2.5-1 - yasm-1.2.0-3 + yasm-1.3.0-1 zip-3.0-2 zlib-1.2.8-4 zlib_devel-1.2.8-4 @@ -547,14 +553,16 @@ RemotePackageRepository HaikuPorts burnitnow_x86-0.1.0-1 bzip2_x86-1.0.6-5 bzip2_x86_devel-1.0.6-5 + cairo_x86-1.12.18-1 + cairo_x86_devel-1.12.18-1 capstone_x86-3.0.4-1 capstone_x86_devel-3.0.4-1 - cmake_x86-3.2.3-1 + cmake_x86-3.3.1-1 confuse_x86-2.7-2 confuse_x86_devel-2.7-2 copynametoclipboard-1.0.1-2 - curl_x86-7.43.0-1 - curl_x86_devel-7.43.0-1 + curl_x86-7.44.0-1 + curl_x86_devel-7.44.0-1 cvsps_x86-2.2b1-1 dbus_x86-1.8.6-1 dbus_x86_devel-1.8.6-1 @@ -584,8 +592,8 @@ RemotePackageRepository HaikuPorts flare_x86-0.19-3 fluidsynth_x86-1.1.6-2 fluidsynth_x86_devel-1.1.6-2 - fontconfig_x86-2.11.1-2 - fontconfig_x86_devel-2.11.1-2 + fontconfig_x86-2.11.1-3 + fontconfig_x86_devel-2.11.1-3 freedroidrpg_x86-0.15.1-1 freetype_x86-2.6-1 freetype_x86_devel-2.6-1 @@ -595,6 +603,8 @@ RemotePackageRepository HaikuPorts gcc_x86_syslibs-4.8.5_2015_07_11-2 gcc_x86_syslibs_devel-4.8.5_2015_07_11-2 gcc6809_x86-4.6.1-2 + gdk_pixbuf_x86-2.31.5-1 + gdk_pixbuf_x86_devel-2.31.5-1 gettext_x86-0.18.1.1-6 gettext_x86_libintl-0.18.1.1-6 giflib_x86-5.1.0-1 @@ -616,8 +626,8 @@ RemotePackageRepository HaikuPorts graphite2_x86_devel-1.2.4-1 guilib_x86-1.2.1-1 guilib_x86_devel-1.2.1-1 - haikuwebkit_x86-1.4.11-1 - haikuwebkit_x86_devel-1.4.11-1 + haikuwebkit_x86-1.4.12-1 + haikuwebkit_x86_devel-1.4.12-1 harfbuzz_x86-0.9.39-1 harfbuzz_x86_devel-0.9.39-1 icu_x86-55.1-1 @@ -721,6 +731,8 @@ RemotePackageRepository HaikuPorts libtheora_x86_devel-1.1.1-2 libtool_x86-2.4.2-1 libtool_x86_libltdl-2.4.2-1 + libtorrent_rasterbar_x86-1.0.6-1 + libtorrent_rasterbar_x86_devel-1.0.6-1 libusb_x86-1.0.18-1 libusb_x86_devel-1.0.18-1 libuuid_x86-1.0.3-2 @@ -733,8 +745,8 @@ RemotePackageRepository HaikuPorts libwebp_x86_devel-0.4.1-1 libxml2_x86-2.9.2-1 libxml2_x86_devel-2.9.2-1 - libxslt_x86-1.1.28-2 - libxslt_x86_devel-1.1.28-2 + libxslt_x86-1.1.28-5 + libxslt_x86_devel-1.1.28-5 libzip_x86-0.11.2-1 libzip_x86_devel-0.11.2-1 llvm_x86-3.5.2-1 @@ -759,8 +771,8 @@ RemotePackageRepository HaikuPorts mpd_x86-0.18.12_git-1 mpfr_x86-3.1.3-1 mpfr_x86_devel-3.1.3-1 - mpg123_x86-1.22.3-1 - mpg123_x86_devel-1.22.3-1 + mpg123_x86-1.22.4-1 + mpg123_x86_devel-1.22.4-1 mplayer_x86-1.1.1-3 mupdf_x86-1.7-1 mupdf_x86_devel-1.7-1 @@ -768,6 +780,8 @@ RemotePackageRepository HaikuPorts musicpc_x86-0.26-1 ncurses_x86-5.9-9 ncurses_x86_devel-5.9-9 + ncurses6_x86-6.0-1 + ncurses6_x86_devel-6.0-1 ninja_x86-1.5.1-2 ocp_x86-0.1.21_git-1 openal_x86-1.13.0-2 @@ -780,6 +794,8 @@ RemotePackageRepository HaikuPorts openssl_x86-1.0.0s-1 openssl_x86_devel-1.0.0s-1 openttd_x86-1.3.3-1 + pango_x86-1.37.0-1 + pango_x86_devel-1.37.0-1 pciutils_x86-3.2.1-1 pciutils_x86_devel-3.2.1-1 physfs_x86-2.0.3-1 @@ -792,6 +808,7 @@ RemotePackageRepository HaikuPorts protrekkr_x86-2.5.4-2 popt_x86-1.16-1 popt_x86_devel-1.16-1 + qbittorrent_x86-3.2.3-2 qemu_x86-2.1.2-1 qca2_x86-2.0.3-1 qca2_x86_devel-2.0.3-1 @@ -799,7 +816,7 @@ RemotePackageRepository HaikuPorts qjson_x86_devel-0.8.1-1 qmplay2_x86-15.05.30-2 quassel_x86-0.10.0-2 - quicklaunch-0.9.10-1 + quicklaunch-0.9.11-1 qupzilla_x86-1.8.6-1 radare2_x86-0.9.9-1 radare2_x86_devel-0.9.9-1 @@ -854,6 +871,8 @@ RemotePackageRepository HaikuPorts vacuum_x86-1.2.5-1 vcmi_x86-0.94-1 wizznic_x86-0.9.9-2 + xmlroff_x86-0.6.2-2 + xmlroff_x86_devel-0.6.2-2 xz_utils_x86-5.0.8-2 xz_utils_x86_devel-5.0.8-2 zlib_x86-1.2.8-4 @@ -908,6 +927,7 @@ RemotePackageRepository HaikuPorts burnitnow_x86 bzip2 bzr + cairo_x86 canna capitalbe capstone_x86 @@ -988,6 +1008,7 @@ RemotePackageRepository HaikuPorts gettext gettext_x86 gdb + gdk_pixbuf_x86 giflib git glew @@ -1002,6 +1023,7 @@ RemotePackageRepository HaikuPorts gperf gpgme gpgme_x86 + grafx2 graphite2_x86 grep groff @@ -1010,6 +1032,7 @@ RemotePackageRepository HaikuPorts gutenprint gyp gzip + haikuporter haikuwebkit_x86 harfbuzz_x86 help2man @@ -1021,6 +1044,7 @@ RemotePackageRepository HaikuPorts imagemagick intltool itstool + jabber4haiku jam jasper jbig2dec @@ -1106,6 +1130,7 @@ RemotePackageRepository HaikuPorts libtheora libtool libtool_x86 + libtorrent_rasterbar_x86 libunistring libusb libusb_x86 @@ -1172,6 +1197,7 @@ RemotePackageRepository HaikuPorts nano nasm ncurses + ncurses6 neon netcat netpulse @@ -1189,6 +1215,7 @@ RemotePackageRepository HaikuPorts openttd_x86 p7zip paladin + pango_x86 paragui patch pciutils @@ -1217,6 +1244,7 @@ RemotePackageRepository HaikuPorts python_setuptools python_twisted python_zope.interface + qbittorrent_x86 qemacs qemu_x86 qca2_x86 @@ -1305,6 +1333,7 @@ RemotePackageRepository HaikuPorts yasm youtube_dl xcb_proto + xmlroff_x86 xmlto xml_parser xproto diff --git a/data/catalogs/add-ons/disk_systems/bfs/fr.catkeys b/data/catalogs/add-ons/disk_systems/bfs/fr.catkeys index 7167a3ef89..d558f47501 100644 --- a/data/catalogs/add-ons/disk_systems/bfs/fr.catkeys +++ b/data/catalogs/add-ons/disk_systems/bfs/fr.catkeys @@ -2,7 +2,7 @@ Enable query support BFS_Initialize_Parameter Activer le support des requêtes 2048 (Recommended) BFS_Initialize_Parameter 2048 (Recommandé) 8192 (Mostly large files) BFS_Initialize_Parameter 8192 (Surtout des gros fichiers) -Disabling query support may speed up certain file system operations, but should only be used if one is absolutely certain that one will not need queries.\nAny volume that is intended for booting Haiku must have query support enabled. BFS_Initialize_Parameter Désactiver le support des requête peut accélérer certaines opérations du système de fichiers, mais vous devez être certains de ne jamais avoir besoin des requêtes.\nTout volume destiné à amorcer Haiku doit avoir le support des requête activé. +Disabling query support may speed up certain file system operations, but should only be used if one is absolutely certain that one will not need queries.\nAny volume that is intended for booting Haiku must have query support enabled. BFS_Initialize_Parameter Désactiver le support des requêtes peut accélérer certaines opérations du système de fichiers, mais vous devez être certain de ne jamais avoir besoin des requêtes.\nTout volume destiné à amorcer Haiku doit avoir le support des requêtes activé. 1024 (Mostly small files) BFS_Initialize_Parameter 1024 (Surtout des petits fichiers) Blocksize: BFS_Initialize_Parameter Taille de bloc : Name: BFS_Initialize_Parameter Nom : diff --git a/data/catalogs/add-ons/media/media-add-ons/mixer/fr.catkeys b/data/catalogs/add-ons/media/media-add-ons/mixer/fr.catkeys index a5b0fc7f71..5c74f1cd7f 100644 --- a/data/catalogs/add-ons/media/media-add-ons/mixer/fr.catkeys +++ b/data/catalogs/add-ons/media/media-add-ons/mixer/fr.catkeys @@ -7,7 +7,7 @@ Output mapping AudioMixer Correspondances de sorties Allow input channel remapping AudioMixer Autoriser la réassignation des canaux d’entrées Resampling algorithm AudioMixer Algorithme de ré-échantillonnage Attenuate mixer output by 3dB (like BeOS R5) AudioMixer Atténuer la sortie du mélangeur de 3 dB (comme BeOS R5) -Display balance control for stereo connections AudioMixer Afficher le contrôle de balance pour des connexions stéréo +Display balance control for stereo connections AudioMixer Afficher le contrôle de balance pour les connexions stéréo To output AudioMixer Vers la sortie not connected AudioMixer débranché Refuse input format changes AudioMixer Refuser les changements de formats d’entrées @@ -17,11 +17,11 @@ dB AudioMixer dB Gain controls AudioMixer Contrôles de gain Input mapping AudioMixer Correspondances d’entrées Mute AudioMixer Sourdine -Input channel destinations AudioMixer Destination des canaux d’entrées +Input channel destinations AudioMixer Destinations des canaux d’entrées To master AudioMixer Vers la sortie principale Master output AudioMixer Sortie principale Setup AudioMixer Réglages -Use non linear gain sliders (like BeOS R5) AudioMixer Utiliser les curseurs de gain non-linéaire (comme BeOS R5) +Use non linear gain sliders (like BeOS R5) AudioMixer Utiliser les curseurs de gain non-linéaires (comme BeOS R5) Gain AudioMixer Gain Allow output channel remapping AudioMixer Autoriser la réassignation des canaux de sorties Physical input channels AudioMixer Canaux d’entrées physiques diff --git a/data/catalogs/add-ons/network_settings/dnsclient/hu.catkeys b/data/catalogs/add-ons/network_settings/dnsclient/hu.catkeys index 1246c1d202..1bbc078e25 100644 --- a/data/catalogs/add-ons/network_settings/dnsclient/hu.catkeys +++ b/data/catalogs/add-ons/network_settings/dnsclient/hu.catkeys @@ -1,2 +1,10 @@ -1 hungarian x-vnd.Haiku-DNSClientService 3886749326 +1 hungarian x-vnd.Haiku-DNSClientService 2825577357 +DNS settings DNSClientServiceAddOn DNS-beállítások +Move down DNSSettingsView Mozgatás lefelé +DNS settings DNSSettingsView DNS-beállítások +Remove DNSSettingsView Eltávolítás Domain: DNSSettingsView Tartomány: +Add DNSSettingsView Hozzáad +Server: DNSSettingsView Kiszolgáló: +Move up DNSSettingsView Mozgatás felfelé +Apply DNSSettingsView Alkalmaz diff --git a/data/catalogs/add-ons/network_settings/ipv4/hu.catkeys b/data/catalogs/add-ons/network_settings/ipv4/hu.catkeys new file mode 100644 index 0000000000..bf0288fa1c --- /dev/null +++ b/data/catalogs/add-ons/network_settings/ipv4/hu.catkeys @@ -0,0 +1,2 @@ +1 hungarian x-vnd.Haiku-IPv4Interface 2854844856 +IPv4 IPv4InterfaceAddOn IPv4 diff --git a/data/catalogs/add-ons/network_settings/ipv6/hu.catkeys b/data/catalogs/add-ons/network_settings/ipv6/hu.catkeys new file mode 100644 index 0000000000..33e3e9a972 --- /dev/null +++ b/data/catalogs/add-ons/network_settings/ipv6/hu.catkeys @@ -0,0 +1,2 @@ +1 hungarian x-vnd.Haiku-IPv6Interface 1391114020 +IPv6 IPv6InterfaceAddOn IPv6 diff --git a/data/catalogs/apps/aboutsystem/ru.catkeys b/data/catalogs/apps/aboutsystem/ru.catkeys index 417aa0e07b..ed6e539ff3 100644 --- a/data/catalogs/apps/aboutsystem/ru.catkeys +++ b/data/catalogs/apps/aboutsystem/ru.catkeys @@ -1,4 +1,4 @@ -1 russian x-vnd.Haiku-About 14540716 +1 russian x-vnd.Haiku-About 3251436090 Copyright © 1999-2010 by the authors of Gutenprint. All rights reserved. AboutView Все права защищены © 1999-2010 авторы Gutenprint. Copyright © 1996-2002, 2006 David Turner, Robert Wilhelm and Werner Lemberg. AboutView Все права защищены © 1996-2002, 2006 David Turner, Robert Wilhelm и Werner Lemberg. Past website & marketing:\n AboutView Старый вебсайт и маркетинг:\n @@ -8,6 +8,7 @@ Copyright © 1996-2005 Julian R Seward. All rights reserved. AboutView Все %d MiB total AboutView Всего %d МБ Michael Phipps (project founder)\n\n AboutView Michael Phipps (основателю проекта)\n\n %d MiB used (%d%%) AboutView %d МБ использовано (%d%%) +Contains software from the GNU Project, released under the GPL and LGPL licenses:\nGNU C Library, GNU coretools, diffutils, findutils, sharutils, gawk, bison, m4, make, wget, ncurses, termcap, Bourne Again Shell.\nCopyright © The Free Software Foundation. AboutView Содержит программное обеспечение из проекта GNU, выпущен под лицензиями GPL и LGPL:\nGNU библиотека, GNU coretools, diffutils, findutils, sharutils, gawk, bison, m4, make, wget, ncurses, termcap, Bourne Again Shell.\n\nВсе права защищены © Фонд свободного программного обеспечения. AboutSystem System name О системе Copyright © 2003 Peter Hanappe and others. AboutView Все права защищены © 2003 Peter Hanappe и другие. Copyright © 1994-1997 Mark Kilgard. All rights reserved. AboutView Все права защищены © 1994-1997 Mark Kilgard. @@ -40,6 +41,7 @@ Copyright © 1996-1997 Jeff Prosise. All rights reserved. AboutView Все пр Copyright © 2006-2012 Kentaro Fukuchi AboutView Все права защищены © 2006-2012 Kentaro Fukuchi Copyright © 1994-2009, Thomas G. Lane, Guido Vollbeding. This software is based in part on the work of the Independent JPEG Group. AboutView Все права защищены © 1994-2009, Thomas G. Lane, Guido Vollbeding. Это программное обеспечение частично основано на работе Independent JPEG Group. Past maintainers:\n AboutView Предыдущие разработчики:\n +Contains software from the FreeBSD Project, released under the BSD license:\nftpd, ping, telnet, telnetd, traceroute\nCopyright © 1994-2008 The FreeBSD Project. All rights reserved. AboutView Содержит программное обеспечение из проекта FreeBSD, выпущен под лицензией BSD:\ncal, ftpd, ping, telnet, telnetd, tracerout\nВсе права защищены © 1994-2008 Проект FreeBSD. GNU GPL v3 AboutWindow GNU GPL v3 \n\nSpecial thanks to:\n AboutView \n\nОсобая благодарность:\n \n…and probably some more we forgot to mention (sorry!)\n\n AboutView \n…а также те, кого мы забыли упомянуть (простите!)\n\n diff --git a/data/catalogs/apps/drivesetup/ru.catkeys b/data/catalogs/apps/drivesetup/ru.catkeys index 62377017e2..b953cdc3f1 100644 --- a/data/catalogs/apps/drivesetup/ru.catkeys +++ b/data/catalogs/apps/drivesetup/ru.catkeys @@ -1,4 +1,4 @@ -1 russian x-vnd.Haiku-DriveSetup 1450212098 +1 russian x-vnd.Haiku-DriveSetup 2321187933 DriveSetup System name Разметка диска Could not acquire partitioning information. MainWindow Невозможно получить информацию о разделах. Cancel AbstractParametersPanel Отмена @@ -44,6 +44,7 @@ Change ChangeParametersPanel Изменить Are you sure you want to write the changes back to disk now?\n\nAll data on the disk %s will be irretrievably lost if you do so! MainWindow Вы уверены, что хотите записать изменения на диск прямо сейчас?\n\nВсе данные на диске %s будут безвозвратно потеряны, если вы продолжите! Are you sure you want to delete the selected partition?\n\nAll data on the partition will be irretrievably lost if you do so! MainWindow Вы уверены, что хотите удалить выбранный раздел?\n\nВсе данные на этом разделе будут безвозвратно потеряны, если вы продолжите! Create… MainWindow Создать… +Are you sure you want to format a raw disk? (Most people initialize the disk with a partitioning system first) You will be asked again before changes are written to the disk. MainWindow Вы уверены, что хотите отформатировать весь диск? (Обычно на диске сначала создаются разделы) Повторный запрос будет выдан непосредственно перед записью изменений на диск. The disk has been successfully initialized.\n MainWindow Диск был успешно инициализирован.\n Could not unmount partition %s. MainWindow Невозможно отключить раздел %s. Failed to change the parameters of the partition. No changes have been written to disk. MainWindow Не удалось изменить параметры раздела. Изменения не были записаны на диск. diff --git a/data/catalogs/apps/haikudepot/pt_BR.catkeys b/data/catalogs/apps/haikudepot/pt_BR.catkeys index adfaa949f3..a5a4049ef6 100644 --- a/data/catalogs/apps/haikudepot/pt_BR.catkeys +++ b/data/catalogs/apps/haikudepot/pt_BR.catkeys @@ -1,4 +1,4 @@ -1 portuguese (brazil) x-vnd.Haiku-HaikuDepot 3134988464 +1 portuguese (brazil) x-vnd.Haiku-HaikuDepot 4123398005 Name PackageListView Nome Available packages MainWindow Pacotes disponíveis Open %DeskbarLink% PackageManager Abrir %DeskbarLink% @@ -133,6 +133,7 @@ If you do not provide an email address, you will not be able to reset your passw Authentication failed. Connection to the service failed. UserLoginWindow Autenticação falhou. Conexão ao serviço falhou. Cancel RatePackageWindow Cancelar Package action failed PackageInfoView Ação do pacote falhou +OK UserLoginWindow OK Send RatePackageWindow Enviar Failed to create account UserLoginWindow Falhou ao criar conta There are problems with the data you entered:\n\n UserLoginWindow Existem problemas com os dados que você inseriu:\n\n diff --git a/data/catalogs/apps/haikudepot/ru.catkeys b/data/catalogs/apps/haikudepot/ru.catkeys index c68a262688..f5c0ff39a2 100644 --- a/data/catalogs/apps/haikudepot/ru.catkeys +++ b/data/catalogs/apps/haikudepot/ru.catkeys @@ -1,4 +1,4 @@ -1 russian x-vnd.Haiku-HaikuDepot 3588353727 +1 russian x-vnd.Haiku-HaikuDepot 4273323974 Name PackageListView Имя Available packages MainWindow Доступные пакеты Open %DeskbarLink% PackageManager Открыть %DeskbarLink% @@ -53,6 +53,7 @@ The user name needs to be at least 3 letters long. UserLoginWindow Имя по Log in UserLoginWindow Войти… Repeat pass phrase: UserLoginWindow Повторить пароль: Ratings PackageInfoView Оценки +But none could be listed here, sorry. UserLoginWindow Но не удалось определить с какими именно, извините. System & Utilities Model Система и утилиты Inactive PackageListView Неактивный Refresh depots MainWindow Обновить склады @@ -89,6 +90,7 @@ Failed to create or update rating: %s\n RatePackageWindow Не удалось You need to be logged into an account before you can rate packages. MainWindow Вы должны войти в свою учётную запись перед тем как оценить пакет. It responded with: RatePackageWindow Он ответил так: User name: UserLoginWindow Имя пользователя: +User Menu MainWindow Меню пользователя Unstable but usable RatePackageWindow Нестабилен, но пригодный для использования The email address appears to be malformed. UserLoginWindow Некорректный адрес электронной почты. Games Model Игры @@ -131,6 +133,7 @@ If you do not provide an email address, you will not be able to reset your passw It responded with: UserLoginWindow Он ответил так: Authentication failed. Connection to the service failed. UserLoginWindow Неверный логин/пароль. Соединение с сервисом прервано. Cancel RatePackageWindow Отмена +Package action failed PackageInfoView Действие с пакетом не удалось. OK UserLoginWindow OK Send RatePackageWindow Отправить - no package size - diff --git a/data/catalogs/apps/mail/hu.catkeys b/data/catalogs/apps/mail/hu.catkeys index ee41f920be..9e0341ec3d 100644 --- a/data/catalogs/apps/mail/hu.catkeys +++ b/data/catalogs/apps/mail/hu.catkeys @@ -1,4 +1,4 @@ -1 hungarian x-vnd.Be-MAIL 233997769 +1 hungarian x-vnd.Be-MAIL 1310033600 View Mail Nézet %d - Date Mail %d - dátum Attach attributes: Mail Jellemzők csatolása: @@ -146,6 +146,7 @@ Open attachment Mail Megnyitás sent B_USER_DIRECTORY/mail/sent Elküldött (Date unavailable) Mail (A dátum nem elérhető) Put your favorite e-mail queries and query templates in this folder. Mail Helyezze a kedvenc lekérdezéseket és a lekérdezési sablonokat ebbe a mappába. +Spam Mail Levélszemét Reply Mail Válasz From: Mail Feladó: Couldn't open this signature. Sorry. Mail Sajnálom, de nem nyitható meg ez az aláírás. diff --git a/data/catalogs/apps/mail/pl.catkeys b/data/catalogs/apps/mail/pl.catkeys index 44f6e1bea3..c64581502f 100644 --- a/data/catalogs/apps/mail/pl.catkeys +++ b/data/catalogs/apps/mail/pl.catkeys @@ -1,4 +1,4 @@ -1 polish x-vnd.Be-MAIL 233997769 +1 polish x-vnd.Be-MAIL 1310033600 View Mail Widok %d - Date Mail %d - Data Attach attributes: Mail Dołączaj atrybuty: @@ -146,6 +146,7 @@ Open attachment Mail Otwórz załącznik sent B_USER_DIRECTORY/mail/sent sent (Date unavailable) Mail (Data niedostępna) Put your favorite e-mail queries and query templates in this folder. Mail Umieść swoje ulubione zapytania wiadomości i szablony zapytań w tym katalogu. +Spam Mail Spam Reply Mail Odpowiedz From: Mail Od: Couldn't open this signature. Sorry. Mail Nie można otworzyć tej sygnaturki. Przepraszamy. diff --git a/data/catalogs/apps/mail/ru.catkeys b/data/catalogs/apps/mail/ru.catkeys index b2a4934f2f..5ed0a23f3c 100644 --- a/data/catalogs/apps/mail/ru.catkeys +++ b/data/catalogs/apps/mail/ru.catkeys @@ -1,4 +1,4 @@ -1 russian x-vnd.Be-MAIL 233997769 +1 russian x-vnd.Be-MAIL 1310033600 View Mail Вид %d - Date Mail %d - Дата Attach attributes: Mail Прикрепление атрибутов: @@ -146,6 +146,7 @@ Open attachment Mail Открыть вложение sent B_USER_DIRECTORY/mail/sent Отправленные (Date unavailable) Mail (Дата недоступна) Put your favorite e-mail queries and query templates in this folder. Mail Перенесите в эту папку ваши почтовые запросы. +Spam Mail Спам Reply Mail Ответить From: Mail От: Couldn't open this signature. Sorry. Mail Невозможно открыть эту подпись. Извините. diff --git a/data/catalogs/apps/mediaconverter/ru.catkeys b/data/catalogs/apps/mediaconverter/ru.catkeys index c9942293b0..b09d72e45e 100644 --- a/data/catalogs/apps/mediaconverter/ru.catkeys +++ b/data/catalogs/apps/mediaconverter/ru.catkeys @@ -1,6 +1,8 @@ -1 russian x-vnd.Haiku-MediaConverter 3111641182 +1 russian x-vnd.Haiku-MediaConverter 341686525 Video using parameters form settings MediaConverter Видео использует параметры из настроек +{0, plural, one{The file was not recognized as a supported media file:} other{# files were not recognized as supported media files:}} MediaConverter {0, plural, one{Файл не был распознан как поддерживаемый медиафайл:} few{# файла не были распознаны как поддерживаемые медиафайлы:} other{# файлов не было распознано как поддерживаемые медиафайлы:}} Video encoding: MediaConverter Кодирование видео: +%u x %u, %.2ffps MediaFileInfo Width x Height, fps %u x %u, %.2fкадр/с Error read audio frame %lld MediaConverter Ошибка чтения аудио кадра %lld No audio Audio codecs list Без аудио Error MediaConverter Ошибка diff --git a/data/catalogs/apps/terminal/ru.catkeys b/data/catalogs/apps/terminal/ru.catkeys index 723b0a2640..39019cf44c 100644 --- a/data/catalogs/apps/terminal/ru.catkeys +++ b/data/catalogs/apps/terminal/ru.catkeys @@ -1,4 +1,4 @@ -1 russian x-vnd.Haiku-Terminal 235954604 +1 russian x-vnd.Haiku-Terminal 2918699501 Not found. Terminal TermWindow Текст не найден Switch Terminals Terminal TermWindow Переключить терминалы Change directory Terminal TermView Сменить каталог @@ -34,6 +34,7 @@ Settings Terminal TermWindow Настройки Window size Terminal TermWindow Размер окна Selected text Terminal AppearancePrefView Выделенного текста Find Terminal FindWindow Найти +The pattern specifying the window titles. The following placeholders\ncan be used: Terminal AppearancePrefView Этот шаблон описывает заголовки окна.\nВозможно использовать следующие переменные:\n Appearance Terminal PrefWindow Внешний вид Tab title: Terminal AppearancePrefView Заголовок вкладки: OK Terminal SetTitleWindow ОК @@ -76,6 +77,7 @@ Midnight Terminal colors scheme Полночь Decrease Terminal TermWindow Уменьшить Default Terminal colors scheme По умолчанию Create link here Terminal TermView Создать ссылку здесь +The pattern specifying the tab titles. The following placeholders\ncan be used: Terminal AppearancePrefView Этот шаблон описывает заголовки вкладок.\nВозможно использовать следующие переменные: Close Terminal TermWindow Закрыть Text Terminal AppearancePrefView Текста Clear all Terminal TermWindow Очистить всё diff --git a/data/catalogs/kits/tracker/de.catkeys b/data/catalogs/kits/tracker/de.catkeys index 061712602d..ac4100ac7e 100644 --- a/data/catalogs/kits/tracker/de.catkeys +++ b/data/catalogs/kits/tracker/de.catkeys @@ -1,4 +1,4 @@ -1 german x-vnd.Haiku-libtracker 3987439873 +1 german x-vnd.Haiku-libtracker 1787267522 OK WidgetAttributeText OK Add-ons FilePanelPriv Add-ons Mount settings… ContainerWindow Einhänge-Einstellungen… @@ -19,6 +19,7 @@ Modified QueryPoseView Geändert Created ContainerWindow Erstellt Error %error loading add-On %name. ContainerWindow Fehler %error beim Laden von Add-On %name. If you %ifYouDoAction the settings folder, %osName may not behave properly!\n\nAre you sure you want to do this? FSUtils Wird der Settings-Ordner %ifYouDoAction, kann %osName vielleicht nicht mehr fehlerfrei arbeiten! +Skip all FSUtils Alle überspringen contains SelectionWindow enthält Sorry, you can't save things at the root of your system. FilePanelPriv Im Root-Verzeichnis des Systems kann leider nichts gespeichert werden. Show shared volumes on Desktop SettingsView Netzwerk-Laufwerke auf dem Desktop zeigen diff --git a/data/catalogs/kits/tracker/fr.catkeys b/data/catalogs/kits/tracker/fr.catkeys index 2c71f3aa77..24073de9f8 100644 --- a/data/catalogs/kits/tracker/fr.catkeys +++ b/data/catalogs/kits/tracker/fr.catkeys @@ -1,4 +1,4 @@ -1 french x-vnd.Haiku-libtracker 4204393626 +1 french x-vnd.Haiku-libtracker 2004221275 OK WidgetAttributeText OK Add-ons FilePanelPriv Extensions Mount settings… ContainerWindow Réglages du montage… @@ -19,6 +19,7 @@ Modified QueryPoseView Modifié Created ContainerWindow Créé Error %error loading add-On %name. ContainerWindow Erreur %error au chargement de l’extension %name. If you %ifYouDoAction the settings folder, %osName may not behave properly!\n\nAre you sure you want to do this? FSUtils Si vous %ifYouDoAction le dossier des réglages, %osName pourrait ne pas se comporter correctement !\n\nÊtes vous sûr de vouloir effectuer cette opération ? +Skip all FSUtils Tout ignorer contains SelectionWindow contient Sorry, you can't save things at the root of your system. FilePanelPriv Désolé, vous ne pouvez rien sauvegarder à la racine de votre système. Show shared volumes on Desktop SettingsView Afficher les volumes partagés sur le Bureau diff --git a/data/catalogs/kits/tracker/hu.catkeys b/data/catalogs/kits/tracker/hu.catkeys index a8724421a3..a1728d3eb0 100644 --- a/data/catalogs/kits/tracker/hu.catkeys +++ b/data/catalogs/kits/tracker/hu.catkeys @@ -1,4 +1,4 @@ -1 hungarian x-vnd.Haiku-libtracker 4204393626 +1 hungarian x-vnd.Haiku-libtracker 2004221275 OK WidgetAttributeText Rendben Add-ons FilePanelPriv Kiegészítők Mount settings… ContainerWindow Csatolási beállítások… @@ -19,6 +19,7 @@ Modified QueryPoseView Módosítva Created ContainerWindow Létrehozva Error %error loading add-On %name. ContainerWindow Hiba a bővítmény (%name) betöltése közben: %error. If you %ifYouDoAction the settings folder, %osName may not behave properly!\n\nAre you sure you want to do this? FSUtils Ha %ifYouDoAction a beállítások mappát, akkor lehet, hogy a %osName nem fog megfelelően működni!\n\nBiztosan folytatni akarja? +Skip all FSUtils Mindet kihagyja contains SelectionWindow tartalmaz Sorry, you can't save things at the root of your system. FilePanelPriv Sajnos nem lehet a rendszer gyökérmappájába menteni. Show shared volumes on Desktop SettingsView Megosztott lemezek megjelenítése az Asztalon diff --git a/data/catalogs/kits/tracker/ja.catkeys b/data/catalogs/kits/tracker/ja.catkeys index 0105412e1e..d58c101164 100644 --- a/data/catalogs/kits/tracker/ja.catkeys +++ b/data/catalogs/kits/tracker/ja.catkeys @@ -1,4 +1,4 @@ -1 japanese x-vnd.Haiku-libtracker 4204393626 +1 japanese x-vnd.Haiku-libtracker 2004221275 OK WidgetAttributeText OK Add-ons FilePanelPriv アドオン Mount settings… ContainerWindow マウント設定… @@ -19,6 +19,7 @@ Modified QueryPoseView 更新日時 Created ContainerWindow 作成日時 Error %error loading add-On %name. ContainerWindow %nameアドオンの読み込み中に%errorエラーが発生 If you %ifYouDoAction the settings folder, %osName may not behave properly!\n\nAre you sure you want to do this? FSUtils settings フォルダーを%ifYouDoActionした場合、%osName が正常に動作しなくなる可能性があります。\n\n続けますか? +Skip all FSUtils すべてスキップ contains SelectionWindow 含む Sorry, you can't save things at the root of your system. FilePanelPriv システムのルートフォルダーに保存は許可されていません。 Show shared volumes on Desktop SettingsView 共有ディスクをデスクトップに表示する diff --git a/docs/user/drivers/fs_modules.dox b/docs/user/drivers/fs_modules.dox index e386f195a9..80e2c0e9e9 100644 --- a/docs/user/drivers/fs_modules.dox +++ b/docs/user/drivers/fs_modules.dox @@ -316,6 +316,16 @@ entry_cache_add() function when it encounters an entry that might not yet be known to the entry cache and entry_cache_remove() when a directory entry has been removed. + The entry cache can also be used for negative caching. If the file system + determines that the requested entry is not present during a lookup, it can + cache this lookup failure by calling entry_cache_add_missing(). Further + calls to fs_vnode_ops::lookup() for the missing entry will then be + avoided. + Note that it is safe to call entry_cache_add() and + entry_cache_add_missing() with the same directory/name pair previously + given to either function to update a cache entry, without needing to call + entry_cache_remove() first. It is also safe to call entry_cache_remove() + for pairs that have never been added to the cache. */ // TODO: diff --git a/docs/user/interface/Alert.dox b/docs/user/interface/Alert.dox index b92ec9ad79..d4be24c132 100644 --- a/docs/user/interface/Alert.dox +++ b/docs/user/interface/Alert.dox @@ -227,7 +227,7 @@ int32 button_index = alert->Go(); See button_width for details. \param spacing Determines how the buttons are spaced. Options are \li \c B_EVEN_SPACING - \li \c B_OFFSET_SPACING + \li \c B_OFFSET_SPACING See button_spacing for details. \param type Constant that determines which alert icon is displayed. @@ -408,7 +408,7 @@ int32 button_index = alert->Go(); /*! \fn BTextView* BAlert::TextView() const - \brief Returns a TextView containing the text of the Alert. + \brief Returns the Alert's TextView. \since BeOS R3 */ diff --git a/headers/os/app/Roster.h b/headers/os/app/Roster.h index 559544ebf7..69a11a7777 100644 --- a/headers/os/app/Roster.h +++ b/headers/os/app/Roster.h @@ -183,7 +183,9 @@ private: const BList* messageList, int argc, const char* const* args, const char** environment, - team_id* appTeam) const; + team_id* appTeam, + thread_id* appThread, + bool launchSuspended) const; status_t _UpdateActiveApp(team_id team) const; diff --git a/headers/os/drivers/fs_cache.h b/headers/os/drivers/fs_cache.h index 64667699a5..9a71a5b5e1 100644 --- a/headers/os/drivers/fs_cache.h +++ b/headers/os/drivers/fs_cache.h @@ -104,6 +104,8 @@ extern status_t file_map_translate(void *map, off_t offset, size_t size, /* entry cache */ extern status_t entry_cache_add(dev_t mountID, ino_t dirID, const char* name, ino_t nodeID); +extern status_t entry_cache_add_missing(dev_t mountID, ino_t dirID, + const char* name); extern status_t entry_cache_remove(dev_t mountID, ino_t dirID, const char* name); diff --git a/headers/os/midi/Midi.h b/headers/os/midi/Midi.h index 2e41f05faa..fcada5b26a 100644 --- a/headers/os/midi/Midi.h +++ b/headers/os/midi/Midi.h @@ -10,8 +10,7 @@ class BList; class BMidiLocalProducer; class BMidiLocalConsumer; -class BMidi -{ +class BMidi { public: BMidi(); diff --git a/headers/os/midi/MidiDefs.h b/headers/os/midi/MidiDefs.h index a4d44c582c..4afb40390e 100644 --- a/headers/os/midi/MidiDefs.h +++ b/headers/os/midi/MidiDefs.h @@ -15,6 +15,8 @@ /* Synthesizer things */ #define B_SYNTH_DIRECTORY B_SYSTEM_DATA_DIRECTORY + +/* Deprecated */ #define B_BIG_SYNTH_FILE "synth/big_synth.sy" #define B_LITTLE_SYNTH_FILE "synth/little_synth.sy" diff --git a/headers/os/midi/MidiPort.h b/headers/os/midi/MidiPort.h index af86f6fd98..9a3c68b199 100644 --- a/headers/os/midi/MidiPort.h +++ b/headers/os/midi/MidiPort.h @@ -9,8 +9,7 @@ class BMidiProducer; namespace BPrivate { class BMidiPortGlue; } -class BMidiPort : public BMidi -{ +class BMidiPort : public BMidi { public: BMidiPort(const char* name = NULL); diff --git a/headers/os/midi/MidiStore.h b/headers/os/midi/MidiStore.h index e519a2727a..47c45ca84f 100644 --- a/headers/os/midi/MidiStore.h +++ b/headers/os/midi/MidiStore.h @@ -12,8 +12,7 @@ class BFile; class BList; class BMidiEvent; -class BMidiStore : public BMidi -{ +class BMidiStore : public BMidi { public: BMidiStore(); diff --git a/headers/os/midi/MidiSynth.h b/headers/os/midi/MidiSynth.h index c85f8b5f53..a9556901be 100644 --- a/headers/os/midi/MidiSynth.h +++ b/headers/os/midi/MidiSynth.h @@ -9,8 +9,7 @@ class BSynth; -class BMidiSynth : public BMidi -{ +class BMidiSynth : public BMidi { public: BMidiSynth(); diff --git a/headers/os/midi/MidiSynthFile.h b/headers/os/midi/MidiSynthFile.h index ffd0cb321e..7964b0872c 100644 --- a/headers/os/midi/MidiSynthFile.h +++ b/headers/os/midi/MidiSynthFile.h @@ -10,8 +10,7 @@ typedef void (*synth_file_hook)(int32 arg); class BMidiStore; -class BMidiSynthFile : public BMidiSynth -{ +class BMidiSynthFile : public BMidiSynth { public: BMidiSynthFile(); diff --git a/headers/os/midi/MidiText.h b/headers/os/midi/MidiText.h index 8a18593943..a70638d449 100644 --- a/headers/os/midi/MidiText.h +++ b/headers/os/midi/MidiText.h @@ -6,8 +6,7 @@ #include #include -class BMidiText : public BMidi -{ +class BMidiText : public BMidi { public: BMidiText(); diff --git a/headers/posix/assert.h b/headers/posix/assert.h index d916e02e60..628cd4c843 100644 --- a/headers/posix/assert.h +++ b/headers/posix/assert.h @@ -3,19 +3,19 @@ * Distributed under the terms of the MIT License. */ -/* Include guards are omitted, as assert.h is required +/* Include guards are only on part of the file, as assert.h is required to support being included multiple times. - + E.g. the following is required to be valid: - + #undef NDEBUG #include - + assert(0); // this assertion will be triggered - + #define NDEBUG #include - + assert(0); // this assertion will not be triggered */ @@ -24,6 +24,9 @@ #ifndef NDEBUG /* defining NDEBUG disables assert() functionality */ +#ifndef _ASSERT_H_ +#define _ASSERT_H_ + #ifdef __cplusplus extern "C" { #endif @@ -40,6 +43,8 @@ extern void __assert_perror_fail(int error, const char *file, } #endif +#endif /* !_ASSERT_H_ */ + #define assert(assertion) \ ((assertion) ? (void)0 : __assert_fail(#assertion, __FILE__, __LINE__, __PRETTY_FUNCTION__)) diff --git a/headers/private/app/RosterPrivate.h b/headers/private/app/RosterPrivate.h index 88006f1706..33c2e507c3 100644 --- a/headers/private/app/RosterPrivate.h +++ b/headers/private/app/RosterPrivate.h @@ -30,9 +30,10 @@ class BRoster::Private { status_t Launch(const char* mimeType, const entry_ref* ref, const BList* messageList, int argc, const char* const* args, - const char** environment, team_id* appTeam) + const char** environment, team_id* appTeam, + thread_id* appThread, bool launchSuspended) { return fRoster->_LaunchApp(mimeType, ref, messageList, argc, - args, environment, appTeam); } + args, environment, appTeam, appThread, launchSuspended); } status_t ShutDown(bool reboot, bool confirm, bool synchronous) { return fRoster->_ShutDown(reboot, confirm, synchronous); } diff --git a/headers/private/fs_shell/fssh_api_wrapper.h b/headers/private/fs_shell/fssh_api_wrapper.h index 337648f2e2..1651b2a041 100644 --- a/headers/private/fs_shell/fssh_api_wrapper.h +++ b/headers/private/fs_shell/fssh_api_wrapper.h @@ -871,6 +871,7 @@ /* entry cache */ #define entry_cache_add fssh_entry_cache_add +#define entry_cache_add_missing fssh_entry_cache_add_missing #define entry_cache_remove fssh_entry_cache_remove //////////////////////////////////////////////////////////////////////////////// diff --git a/headers/private/fs_shell/fssh_fs_cache.h b/headers/private/fs_shell/fssh_fs_cache.h index 87eef13f39..88cc9a392e 100644 --- a/headers/private/fs_shell/fssh_fs_cache.h +++ b/headers/private/fs_shell/fssh_fs_cache.h @@ -126,6 +126,8 @@ extern fssh_status_t fssh_file_map_translate(void *_map, fssh_off_t offset, extern fssh_status_t fssh_entry_cache_add(fssh_dev_t mountID, fssh_ino_t dirID, const char* name, fssh_ino_t nodeID); +extern fssh_status_t fssh_entry_cache_add_missing(fssh_dev_t mountID, + fssh_ino_t dirID, const char* name); extern fssh_status_t fssh_entry_cache_remove(fssh_dev_t mountID, fssh_ino_t dirID, const char* name); diff --git a/headers/private/interface/AbstractSpinner.h b/headers/private/interface/AbstractSpinner.h new file mode 100644 index 0000000000..9d961b1260 --- /dev/null +++ b/headers/private/interface/AbstractSpinner.h @@ -0,0 +1,168 @@ +/* + * Copyright 2004 DarkWyrm + * Copyright 2013 FeemanLou + * Copyright 2014-2015 Haiku, Inc. All rights reserved. + * + * Distributed under the terms of the MIT license. + * + * Originally written by DarkWyrm + * Updated by FreemanLou as part of Google GCI 2013 + * + * Authors: + * DarkWyrm, darkwyrm@earthlink.net + * FeemanLou + * John Scipione, jscipione@gmail.com + */ +#ifndef _ABSTRACT_SPINNER_H +#define _ABSTRACT_SPINNER_H + + +#include + + +typedef enum { + SPINNER_BUTTON_HORIZONTAL_ARROWS, + SPINNER_BUTTON_VERTICAL_ARROWS, + SPINNER_BUTTON_PLUS_MINUS +} spinner_button_style; + + +class BTextView; +class SpinnerButton; +class SpinnerTextView; + + +/*! BAbstractSpinner provides an input whose value can be nudged up or down + by way of two small buttons on the right. +*/ +class BAbstractSpinner : public BControl { +public: + BAbstractSpinner(BRect frame, const char* name, + const char* label, BMessage* message, + uint32 resizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP, + uint32 flags = B_WILL_DRAW | B_NAVIGABLE); + BAbstractSpinner(const char* name, const char* label, + BMessage* message, + uint32 flags = B_WILL_DRAW | B_NAVIGABLE); + BAbstractSpinner(BMessage* data); + virtual ~BAbstractSpinner(); + + static BArchivable* Instantiate(BMessage* data); + virtual status_t Archive(BMessage* data, bool deep = true) const; + + virtual status_t GetSupportedSuites(BMessage* message); + virtual BHandler* ResolveSpecifier(BMessage* message, int32 index, + BMessage* specifier, int32 form, + const char* property); + + virtual void AttachedToWindow(); + virtual void Draw(BRect updateRect); + virtual void FrameResized(float width, float height); + virtual void ValueChanged(); + + virtual void Decrement() = 0; + virtual void Increment() = 0; + virtual void MakeFocus(bool focus = true); + virtual void ResizeToPreferred(); + virtual void SetFlags(uint32 flags); + virtual void WindowActivated(bool active); + + alignment Alignment() const { return fAlignment; }; + virtual void SetAlignment(alignment align); + + spinner_button_style ButtonStyle() const { return fButtonStyle; }; + virtual void SetButtonStyle(spinner_button_style buttonStyle); + + float Divider() const { return fDivider; }; + virtual void SetDivider(float position); + + virtual void SetEnabled(bool enable); + + virtual void SetLabel(const char* label); + + virtual void SetValueFromText() = 0; + + bool IsDecrementEnabled() const; + virtual void SetDecrementEnabled(bool enable); + + bool IsIncrementEnabled() const; + virtual void SetIncrementEnabled(bool enable); + + virtual BSize MinSize(); + virtual BSize MaxSize(); + virtual BSize PreferredSize(); + virtual BAlignment LayoutAlignment(); + + BLayoutItem* CreateLabelLayoutItem(); + BLayoutItem* CreateTextViewLayoutItem(); + + BTextView* TextView() const; + +private: + // FBC padding + virtual void _ReservedAbstractSpinner20(); + virtual void _ReservedAbstractSpinner19(); + virtual void _ReservedAbstractSpinner18(); + virtual void _ReservedAbstractSpinner17(); + virtual void _ReservedAbstractSpinner16(); + virtual void _ReservedAbstractSpinner15(); + virtual void _ReservedAbstractSpinner14(); + virtual void _ReservedAbstractSpinner13(); + virtual void _ReservedAbstractSpinner12(); + virtual void _ReservedAbstractSpinner11(); + virtual void _ReservedAbstractSpinner10(); + virtual void _ReservedAbstractSpinner9(); + virtual void _ReservedAbstractSpinner8(); + virtual void _ReservedAbstractSpinner7(); + virtual void _ReservedAbstractSpinner6(); + virtual void _ReservedAbstractSpinner5(); + virtual void _ReservedAbstractSpinner4(); + virtual void _ReservedAbstractSpinner3(); + virtual void _ReservedAbstractSpinner2(); + virtual void _ReservedAbstractSpinner1(); + +protected: + virtual status_t AllArchived(BMessage* into) const; + virtual status_t AllUnarchived(const BMessage* from); + + virtual void LayoutInvalidated(bool descendants); + virtual void DoLayout(); + +private: + class LabelLayoutItem; + class TextViewLayoutItem; + struct LayoutData; + + friend class SpinnerButton; + friend class SpinnerTextView; + + friend class LabelLayoutItem; + friend class TextViewLayoutItem; + friend struct LayoutData; + + void _DrawLabel(BRect updateRect); + void _DrawTextView(BRect updateRect); + void _InitObject(); + void _LayoutTextView(); + void _UpdateFrame(); + void _UpdateTextViewColors(bool enable); + void _ValidateLayoutData(); + + BAbstractSpinner& operator=(const BAbstractSpinner& other); + + alignment fAlignment; + spinner_button_style fButtonStyle; + float fDivider; + + LayoutData* fLayoutData; + + SpinnerTextView* fTextView; + SpinnerButton* fIncrement; + SpinnerButton* fDecrement; + + // FBC padding + uint32 _reserved[20]; +}; + + +#endif // _ABSTRACT_SPINNER_H diff --git a/headers/private/interface/DecimalSpinner.h b/headers/private/interface/DecimalSpinner.h new file mode 100644 index 0000000000..46161c70bd --- /dev/null +++ b/headers/private/interface/DecimalSpinner.h @@ -0,0 +1,96 @@ +/* + * Copyright 2015 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT license. + * + * Authors: + * John Scipione, jscipione@gmail.com + */ +#ifndef _DECIMAL_SPINNER_H +#define _DECIMAL_SPINNER_H + + +#include + + +class BDecimalSpinner : public BAbstractSpinner { +public: + BDecimalSpinner(BRect frame, const char* name, + const char* label, BMessage* message, + uint32 resizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP, + uint32 flags = B_WILL_DRAW | B_NAVIGABLE); + BDecimalSpinner(const char* name, const char* label, + BMessage* message, + uint32 flags = B_WILL_DRAW | B_NAVIGABLE); + BDecimalSpinner(BMessage* data); + virtual ~BDecimalSpinner(); + + static BArchivable* Instantiate(BMessage* data); + virtual status_t Archive(BMessage* data, bool deep = true) const; + + virtual status_t GetSupportedSuites(BMessage* message); + + virtual void AttachedToWindow(); + + virtual void Increment(); + virtual void Decrement(); + + virtual void SetEnabled(bool enable); + + uint32 Precision() const { return fPrecision; }; + virtual void SetPrecision(uint32 precision) { fPrecision = precision; }; + + double MaxValue() const { return fMaxValue; } + virtual void SetMaxValue(double max); + + double MinValue() const { return fMinValue; } + virtual void SetMinValue(double min); + + void Range(double* min, double* max); + virtual void SetRange(double min, double max); + + double Step() const { return fStep; } + virtual void SetStep(double step) { fStep = step; }; + + double Value() const { return fValue; }; + virtual void SetValue(int32 value); + virtual void SetValue(double value); + virtual void SetValueFromText(); + +private: + // FBC padding + virtual void _ReservedDecimalSpinner20(); + virtual void _ReservedDecimalSpinner19(); + virtual void _ReservedDecimalSpinner18(); + virtual void _ReservedDecimalSpinner17(); + virtual void _ReservedDecimalSpinner16(); + virtual void _ReservedDecimalSpinner15(); + virtual void _ReservedDecimalSpinner14(); + virtual void _ReservedDecimalSpinner13(); + virtual void _ReservedDecimalSpinner12(); + virtual void _ReservedDecimalSpinner11(); + virtual void _ReservedDecimalSpinner10(); + virtual void _ReservedDecimalSpinner9(); + virtual void _ReservedDecimalSpinner8(); + virtual void _ReservedDecimalSpinner7(); + virtual void _ReservedDecimalSpinner6(); + virtual void _ReservedDecimalSpinner5(); + virtual void _ReservedDecimalSpinner4(); + virtual void _ReservedDecimalSpinner3(); + virtual void _ReservedDecimalSpinner2(); + virtual void _ReservedDecimalSpinner1(); + +private: + void _InitObject(); + + double fMinValue; + double fMaxValue; + double fStep; + double fValue; + uint32 fPrecision; + + // FBC padding + uint32 _reserved[20]; +}; + + +#endif // _DECIMAL_SPINNER_H diff --git a/headers/private/interface/Spinner.h b/headers/private/interface/Spinner.h new file mode 100644 index 0000000000..e106ded902 --- /dev/null +++ b/headers/private/interface/Spinner.h @@ -0,0 +1,87 @@ +/* + * Copyright 2015 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT license. + * + * Authors: + * John Scipione, jscipione@gmail.com + */ +#ifndef _SPINNER_H +#define _SPINNER_H + + +#include + + +class BSpinner : public BAbstractSpinner { +public: + BSpinner(BRect frame, const char* name, + const char* label, BMessage* message, + uint32 resizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP, + uint32 flags = B_WILL_DRAW | B_NAVIGABLE); + BSpinner(const char* name, const char* label, + BMessage* message, + uint32 flags = B_WILL_DRAW | B_NAVIGABLE); + BSpinner(BMessage* data); + virtual ~BSpinner(); + + static BArchivable* Instantiate(BMessage* data); + virtual status_t Archive(BMessage* data, bool deep = true) const; + + virtual void Increment(); + virtual void Decrement(); + + virtual status_t GetSupportedSuites(BMessage* message); + + virtual void AttachedToWindow(); + + virtual void SetEnabled(bool enable); + + int32 MaxValue() const { return fMaxValue; } + virtual void SetMaxValue(int32 max); + + int32 MinValue() const { return fMinValue; } + virtual void SetMinValue(int32 min); + + void Range(int32* min, int32* max); + virtual void SetRange(int32 min, int32 max); + + int32 Value() const { return fValue; }; + virtual void SetValue(int32 value); + virtual void SetValueFromText(); + +private: + // FBC padding + virtual void _ReservedSpinner20(); + virtual void _ReservedSpinner19(); + virtual void _ReservedSpinner18(); + virtual void _ReservedSpinner17(); + virtual void _ReservedSpinner16(); + virtual void _ReservedSpinner15(); + virtual void _ReservedSpinner14(); + virtual void _ReservedSpinner13(); + virtual void _ReservedSpinner12(); + virtual void _ReservedSpinner11(); + virtual void _ReservedSpinner10(); + virtual void _ReservedSpinner9(); + virtual void _ReservedSpinner8(); + virtual void _ReservedSpinner7(); + virtual void _ReservedSpinner6(); + virtual void _ReservedSpinner5(); + virtual void _ReservedSpinner4(); + virtual void _ReservedSpinner3(); + virtual void _ReservedSpinner2(); + virtual void _ReservedSpinner1(); + +private: + void _InitObject(); + + int32 fMinValue; + int32 fMaxValue; + int32 fValue; + + // FBC padding + uint32 _reserved[20]; +}; + + +#endif // _SPINNER_H diff --git a/headers/private/kernel/thread.h b/headers/private/kernel/thread.h index b4899ed945..a352f2eae0 100644 --- a/headers/private/kernel/thread.h +++ b/headers/private/kernel/thread.h @@ -302,7 +302,7 @@ thread_is_blocked(Thread* thread) especially with a client lock that uses the thread blocking API. After a blocked thread has been interrupted or the the time out occurred it cannot acquire the client lock (or any other lock using the thread blocking API) - without first making sure that the thread doesn't still appears to be + without first making sure that the thread doesn't still appear to be waiting to other client code. Otherwise another thread could try to unblock it which could erroneously unblock the thread while already waiting on the client lock. So usually when interruptions or timeouts are possible a diff --git a/headers/private/kernel/thread_types.h b/headers/private/kernel/thread_types.h index 1bbab89333..cf9e8fa872 100644 --- a/headers/private/kernel/thread_types.h +++ b/headers/private/kernel/thread_types.h @@ -453,7 +453,7 @@ struct Thread : TeamThreadIteratorEntry, KernelReferenceable { // modified by the thread itself and // thus freely readable by it - void (*cancel_function)(int); + void (*cancel_function)(int); struct { uint8 parameters[SYSCALL_RESTART_PARAMETER_SIZE]; diff --git a/headers/private/libroot/libroot_private.h b/headers/private/libroot/libroot_private.h index 1d5fad3045..d0676a63ed 100644 --- a/headers/private/libroot/libroot_private.h +++ b/headers/private/libroot/libroot_private.h @@ -33,8 +33,8 @@ status_t __flatten_process_args(const char* const* args, int32 argCount, char*** _flatArgs, size_t* _flatSize); void _call_atexit_hooks_for_range(addr_t start, addr_t size); void __init_env(const struct user_space_program_args *args); +void __init_env_post_heap(void); status_t __init_heap(void); -void __init_heap_post_env(void); void __heap_terminate_after(void); void __init_time(addr_t commPageTable); diff --git a/headers/private/media/MediaRosterEx.h b/headers/private/media/MediaRosterEx.h index ab8ba22b25..74bec127e5 100644 --- a/headers/private/media/MediaRosterEx.h +++ b/headers/private/media/MediaRosterEx.h @@ -37,6 +37,8 @@ public: BMediaRosterEx(status_t* out_error); virtual ~BMediaRosterEx(); + virtual void Quit(); + status_t SaveNodeConfiguration(BMediaNode* node); status_t LoadNodeConfiguration(media_addon_id addonid, int32 flavorid, BMessage* out_msg); diff --git a/headers/private/midi/MidiSettings.h b/headers/private/midi/MidiSettings.h new file mode 100644 index 0000000000..ddefc318b5 --- /dev/null +++ b/headers/private/midi/MidiSettings.h @@ -0,0 +1,24 @@ +/* + * Copyright 2015 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#ifndef MIDI_SETTINGS_PRIVATE_H_ +#define MIDI_SETTINGS_PRIVATE_H_ + +#include +#include + +namespace BPrivate { + +struct midi_settings { + char soundfont_file[B_FILE_NAME_LENGTH]; +}; + +status_t read_midi_settings(struct midi_settings* settings); +status_t write_midi_settings(struct midi_settings settings); + +}; + + +#endif /* MIDI_SETTINGS_PRIVATE_H_ */ diff --git a/headers/private/shared/OpenHashTable.h b/headers/private/shared/OpenHashTable.h index 8659b32c14..eb000595c6 100644 --- a/headers/private/shared/OpenHashTable.h +++ b/headers/private/shared/OpenHashTable.h @@ -233,21 +233,21 @@ template int32 OpenHashTable::ArraySize() const { - return fArraySize; + return fArraySize; } template int32 OpenHashTable::VectorSize() const { - return fElementVector->Size(); + return fElementVector->Size(); } template int32 OpenHashTable::CountElements() const { - return fElementCount; + return fElementCount; } diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h b/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h index c4b0101c18..b9c8c035e6 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h +++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_defs.h @@ -29,20 +29,21 @@ enum { CAP_SALP = (1 << 26), // Supports Aggressive Link Power Management CAP_SAL = (1 << 25), // Supports Activity LED CAP_SCLO = (1 << 24), // Supports Command List Override - CAP_ISS_MASK = 0xf, // Interface Speed Support + CAP_ISS_MASK = 0xf, // Interface Speed Support CAP_ISS_SHIFT = 20, - CAP_SNZO = (1 << 19), // Supports Non-Zero DMA Offsets - CAP_SAM = (1 << 18), // Supports AHCI mode only - CAP_SPM = (1 << 17), // Supports Port Multiplier - CAP_FBSS = (1 << 16), // FIS-based Switching Supported - CAP_PMD = (1 << 15), // PIO Multiple DRQ Block - CAP_SSC = (1 << 14), // Slumber State Capable - CAP_PSC = (1 << 13), // Partial State Capable - CAP_NCS_MASK = 0x1f, // Number of Command Slots (zero-based number) + CAP_SNZO = (1 << 19), // Supports Non-Zero DMA Offsets + CAP_SAM = (1 << 18), // Supports AHCI mode only + CAP_SPM = (1 << 17), // Supports Port Multiplier + CAP_FBSS = (1 << 16), // FIS-based Switching Supported + CAP_PMD = (1 << 15), // PIO Multiple DRQ Block + CAP_SSC = (1 << 14), // Slumber State Capable + CAP_PSC = (1 << 13), // Partial State Capable + CAP_NCS_MASK = 0x1f, // Number of Command Slots + // (zero-based number) CAP_NCS_SHIFT = 8, - CAP_CCCS = (1 << 7), // Command Completion Coalescing Supported - CAP_EMS = (1 << 6), // Enclosure Management Supported - CAP_SXS = (1 << 5), // Supports External SATA + CAP_CCCS = (1 << 7), // Command Completion Coalescing Supported + CAP_EMS = (1 << 6), // Enclosure Management Supported + CAP_SXS = (1 << 5), // Supports External SATA CAP_NP_MASK = 0x1f, // Number of Ports (zero-based number) CAP_NP_SHIFT = 0, }; @@ -73,19 +74,40 @@ enum { INT_SDB = (1 << 3), // Set Device Bits Interrupt/Enable INT_DS = (1 << 2), // DMA Setup FIS Interrupt/Enable INT_PS = (1 << 1), // PIO Setup FIS Interrupt/Enable - INT_DHR = (1 << 0), // Device to Host Register FIS Interrupt/Enable + INT_DHR = (1 << 0), // Device to Host Register FIS + // Interrupt/Enable }; +// Device Detection Initialization +#define SATA_CONTROL_DET_SHIFT 0 +#define SATA_CONTROL_DET_MASK 0x0000000f + +#define DET_NO_INITIALIZATION 0x0 +#define DET_INITIALIZATION 0x1 + +// Speed Allowed +#define SATA_CONTROL_SPD_SHIFT 4 +#define SATA_CONTROL_SPD_MASK 0x000000f0 + +// Interface Power Management Transitions Allowed +#define SATA_CONTROL_IPM_SHIFT 8 +#define SATA_CONTROL_IPM_MASK 0x00000f00 + +#define IPM_TRANSITIONS_TO_PARTIAL_DISABLED 0x1 +#define IPM_TRANSITIONS_TO_SLUMBER_DISABLED 0x2 + + typedef struct { - uint32 clb; // Command List Base Address (alignment 1024 byte) + uint32 clb; // Command List Base Address + // (alignment 1024 byte) uint32 clbu; // Command List Base Address Upper 32-Bits uint32 fb; // FIS Base Address (alignment 256 byte) uint32 fbu; // FIS Base Address Upper 32-Bits uint32 is; // Interrupt Status **RWC** uint32 ie; // Interrupt Enable uint32 cmd; // Command and Status - uint32 res1; // Reserved + uint32 res1; // Reserved uint32 tfd; // Task File Data uint32 sig; // Signature uint32 ssts; // Serial ATA Status (SCR0: SStatus) @@ -102,9 +124,9 @@ typedef struct { enum { - PORT_CMD_ICC_ACTIVE = (1 << 28), // Interface Communication control - PORT_CMD_ICC_SLUMBER = (6 << 28), // Interface Communication control - PORT_CMD_ICC_MASK = (0xf<<28), // Interface Communication control + PORT_CMD_ICC_ACTIVE = (1 << 28), // Interface Communication control + PORT_CMD_ICC_SLUMBER = (6 << 28), // Interface Communication control + PORT_CMD_ICC_MASK = (0xf<<28), // Interface Communication control PORT_CMD_ATAPI = (1 << 24), // Device is ATAPI PORT_CMD_CR = (1 << 15), // Command List Running (DMA active) PORT_CMD_FR = (1 << 14), // FIS Receive Running @@ -136,17 +158,17 @@ enum { PORT_INT_DHR = (1 << 0), // Device to Host Register FIS Interrupt }; -#define PORT_INT_ERROR (PORT_INT_TFE | PORT_INT_HBF | PORT_INT_HBD \ - | PORT_INT_IF | PORT_INT_INF | PORT_INT_OF \ - | PORT_INT_IPM | PORT_INT_PRC | PORT_INT_PC \ - | PORT_INT_UF) +#define PORT_INT_ERROR (PORT_INT_TFE | PORT_INT_HBF | PORT_INT_HBD \ + | PORT_INT_IF | PORT_INT_INF | PORT_INT_OF \ + | PORT_INT_IPM | PORT_INT_PRC | PORT_INT_PC \ + | PORT_INT_UF) #define PORT_INT_MASK (PORT_INT_ERROR | PORT_INT_DP | PORT_INT_SDB \ - | PORT_INT_DS | PORT_INT_PS | PORT_INT_DHR) + | PORT_INT_DS | PORT_INT_PS | PORT_INT_DHR) enum { - ATA_BSY = 0x80, - ATA_DF = 0x20, + ATA_BSY = 0x80, + ATA_DF = 0x20, ATA_DRQ = 0x08, ATA_ERR = 0x01, }; @@ -154,11 +176,11 @@ enum { enum { PORT_FBS_DWE_SHIFT = 16, // Device With Error - PORT_FBS_DWE_MASK = 0xf, + PORT_FBS_DWE_MASK = 0xf, PORT_FBS_ADO_SHIFT = 12, // Active Device Optimization - PORT_FBS_ADO_MASK = 0xf, + PORT_FBS_ADO_MASK = 0xf, PORT_FBS_DEV_SHIFT = 8, // Device To Issue - PORT_FBS_DEV_MASK = 0xf, + PORT_FBS_DEV_MASK = 0xf, PORT_FBS_SDE = 0x04, // Single Device Error PORT_FBS_DEC = 0x02, // Device Error Clear PORT_FBS_EN = 0x01, // Enable @@ -167,7 +189,7 @@ enum { enum { PORT_DEVSLP_DM_SHIFT = 25, // DITO Multiplier - PORT_DEVSLP_DM_MASK = 0xf, + PORT_DEVSLP_DM_MASK = 0xf, PORT_DEVSLP_DITO_SHIFT = 15, // Device Sleep Idle Timeout PORT_DEVSLP_DITO_MASK = 0x3ff, PORT_DEVSLP_MDAT_SHIFT = 10, // Minimum Device Sleep Assertion Time @@ -180,12 +202,13 @@ enum { enum { - CAP2_DESO = (1 << 5), // DevSleep Entrance from Slumber Only - CAP2_SADM = (1 << 4), // Supports Aggressive Device Sleep Management - CAP2_SDS = (1 << 3), // Supports Device Sleep - CAP2_APST = (1 << 2), // Automatic Partial to Slumber Transitions - CAP2_NVMP = (1 << 1), // NVMHCI Present - CAP2_BOH = (1 << 0), // BIOS/OS Handoff + CAP2_DESO = (1 << 5), // DevSleep Entrance from Slumber Only + CAP2_SADM = (1 << 4), // Supports Aggressive Device Sleep + // Management + CAP2_SDS = (1 << 3), // Supports Device Sleep + CAP2_APST = (1 << 2), // Automatic Partial to Slumber Transitions + CAP2_NVMP = (1 << 1), // NVMHCI Present + CAP2_BOH = (1 << 0), // BIOS/OS Handoff }; @@ -221,21 +244,22 @@ typedef struct { typedef struct { - union { - struct { - uint16 cfl : 5; // command FIS length - uint16 a : 1; // ATAPI - uint16 w : 1; // Write - uint16 p : 1; // Prefetchable - uint16 r : 1; // Reset - uint16 b : 1; // Build In Self Test - uint16 c : 1; // Clear Busy upon R_OK - uint16 : 1; - uint16 pmp : 4; // Port Multiplier Port - uint16 prdtl; // physical region description table length; - } _PACKED; - uint32 prdtl_flags_cfl; - } _PACKED; + union { + struct { + uint16 cfl : 5; // command FIS length + uint16 a : 1; // ATAPI + uint16 w : 1; // Write + uint16 p : 1; // Prefetchable + uint16 r : 1; // Reset + uint16 b : 1; // Build In Self Test + uint16 c : 1; // Clear Busy upon R_OK + uint16 : 1; + uint16 pmp : 4; // Port Multiplier Port + uint16 prdtl; // physical region description table + // length; + } _PACKED; + uint32 prdtl_flags_cfl; + } _PACKED; uint32 prdbc; // PRD Byte Count uint32 ctba; // command table desciptor base address // (alignment 128 byte) @@ -251,16 +275,16 @@ typedef struct { // 1 - C bit (0x80) // 2 - Command // 3 - Features -// 4 - Sector Number (LBA Low, bits 0-7) -// 5 - Cylinder Low (LBA Mid, bits 8-15) -// 6 - Cylinder High (LBA High, bits 16-23) -// 7 - Device / Head (for 28-bit LBA commands, bits 24-27) -// 8 - Sector Number expanded (LBA Low-previous, bits 24-31) -// 9 - Cylinder Low expanded (LBA Mid-previous, bits 32-39) -// 10 - Cylinder High expanded (LBA High-previous, bits 40-47) +// 4 - Sector Number (LBA Low, bits 0-7) +// 5 - Cylinder Low (LBA Mid, bits 8-15) +// 6 - Cylinder High (LBA High, bits 16-23) +// 7 - Device / Head (for 28-bit LBA commands, bits 24-27) +// 8 - Sector Number expanded (LBA Low-previous, bits 24-31) +// 9 - Cylinder Low expanded (LBA Mid-previous, bits 32-39) +// 10 - Cylinder High expanded (LBA High-previous, bits 40-47) // 11 - Features expanded -// 12 - Sector Count (Sector count, bits 0-7) -// 13 - Sector Count expanded (Sector count, bits 8-15) +// 12 - Sector Count (Sector count, bits 0-7) +// 13 - Sector Count expanded (Sector count, bits 8-15) // 14 - Reserved (0) // 15 - Control // 16 - Reserved (0) diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp index a045771926..25ba34ca3c 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp +++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2008-2014 Haiku, Inc. All rights reserved. + * Copyright 2008-2015 Haiku, Inc. All rights reserved. * Copyright 2007-2009, Marcus Overhagen. All rights reserved. * Distributed under the terms of the MIT License. */ @@ -110,7 +110,9 @@ AHCIPort::Init1() // prdt follows after command table // disable transitions to partial or slumber state - fRegs->sctl |= 0x300; + fRegs->sctl = (fRegs->sctl & ~SATA_CONTROL_IPM_MASK) + | (IPM_TRANSITIONS_TO_PARTIAL_DISABLED + | IPM_TRANSITIONS_TO_SLUMBER_DISABLED) << SATA_CONTROL_IPM_SHIFT; // clear IRQ status bits fRegs->is = fRegs->is; @@ -156,7 +158,12 @@ AHCIPort::Init2() TRACE("is 0x%08" B_PRIx32 "\n", fRegs->is); TRACE("cmd 0x%08" B_PRIx32 "\n", fRegs->cmd); TRACE("ssts 0x%08" B_PRIx32 "\n", fRegs->ssts); - TRACE("sctl 0x%08" B_PRIx32 "\n", fRegs->sctl); + TRACE("sctl.ipm 0x%02" B_PRIx32 "\n", + (fRegs->sctl & SATA_CONTROL_IPM_MASK) >> SATA_CONTROL_IPM_SHIFT); + TRACE("sctl.spd 0x%02" B_PRIx32 "\n", + (fRegs->sctl & SATA_CONTROL_SPD_MASK) >> SATA_CONTROL_SPD_SHIFT); + TRACE("sctl.det 0x%02" B_PRIx32 "\n", + (fRegs->sctl & SATA_CONTROL_DET_MASK) >> SATA_CONTROL_DET_SHIFT); TRACE("serr 0x%08" B_PRIx32 "\n", fRegs->serr); TRACE("sact 0x%08" B_PRIx32 "\n", fRegs->sact); TRACE("tfd 0x%08" B_PRIx32 "\n", fRegs->tfd); @@ -208,23 +215,13 @@ AHCIPort::Uninit() void AHCIPort::ResetDevice() { - if (fRegs->cmd & PORT_CMD_ST) - TRACE("AHCIPort::ResetDevice PORT_CMD_ST set, behaviour undefined\n"); - // perform a hard reset - fRegs->sctl = (fRegs->sctl & ~0xf) | 1; - FlushPostedWrites(); - spin(1100); - fRegs->sctl &= ~0xf; - FlushPostedWrites(); + _HardReset(); - if (wait_until_set(&fRegs->ssts, 0x1, 100000) < B_OK) { + if (wait_until_set(&fRegs->ssts, 0x1, 100000) < B_OK) TRACE("AHCIPort::ResetDevice port %d no device detected\n", fIndex); - } - // clear error bits - fRegs->serr = fRegs->serr; - FlushPostedWrites(); + _ClearErrorRegister(); if (fRegs->ssts & 1) { if (wait_until_set(&fRegs->ssts, 0x3, 500000) < B_OK) { @@ -233,9 +230,7 @@ AHCIPort::ResetDevice() } } - // clear error bits - fRegs->serr = fRegs->serr; - FlushPostedWrites(); + _ClearErrorRegister(); } @@ -364,10 +359,15 @@ AHCIPort::InterruptErrorHandler(uint32 is) TRACE("AHCIPort::InterruptErrorHandler port %d, fCommandsActive 0x%08" B_PRIx32 ", is 0x%08" B_PRIx32 ", ci 0x%08" B_PRIx32 "\n", fIndex, fCommandsActive, is, ci); - - TRACE("ssts 0x%08" B_PRIx32 ", sctl 0x%08" B_PRIx32 ", serr 0x%08" - B_PRIx32 ", sact 0x%08" B_PRIx32 "\n", - fRegs->ssts, fRegs->sctl, fRegs->serr, fRegs->sact); + TRACE("ssts 0x%08" B_PRIx32 "\n", fRegs->ssts); + TRACE("sctl.ipm 0x%02" B_PRIx32 "\n", + (fRegs->sctl & SATA_CONTROL_IPM_MASK) >> SATA_CONTROL_IPM_SHIFT); + TRACE("sctl.spd 0x%02" B_PRIx32 "\n", + (fRegs->sctl & SATA_CONTROL_SPD_MASK) >> SATA_CONTROL_SPD_SHIFT); + TRACE("sctl.det 0x%02" B_PRIx32 "\n", + (fRegs->sctl & SATA_CONTROL_DET_MASK) >> SATA_CONTROL_DET_SHIFT); + TRACE("serr 0x%08" B_PRIx32 "\n", fRegs->serr); + TRACE("sact 0x%08" B_PRIx32 "\n", fRegs->sact); } // read and clear SError @@ -413,7 +413,13 @@ AHCIPort::InterruptErrorHandler(uint32 is) } if (is & PORT_INT_PC) { TRACE("Port Connect Change\n"); -// fResetPort = true; + // Spec v1.3, §6.2.2.3 Recovery of Unsolicited COMINIT + + // perform a hard reset + _HardReset(); + + // clear error bits to clear PxSERR.DIAG.X + _ClearErrorRegister(); } if (is & PORT_INT_UF) { TRACE("Unknown FIS\n"); @@ -1224,3 +1230,31 @@ AHCIPort::ScsiGetRestrictions(bool* isATAPI, bool* noAutoSense, "maxBlocks %" B_PRIu32 "\n", fIndex, *isATAPI, *noAutoSense, *maxBlocks); } + + +void +AHCIPort::_HardReset() +{ + if ((fRegs->cmd & PORT_CMD_ST) != 0) { + // We shouldn't perform a reset, but at least document it + TRACE("AHCIPort::_HardReset() PORT_CMD_ST set, behaviour undefined\n"); + } + + fRegs->sctl = (fRegs->sctl & ~SATA_CONTROL_DET_MASK) + | DET_INITIALIZATION << SATA_CONTROL_DET_SHIFT; + FlushPostedWrites(); + spin(1100); + // You must wait 1ms at minimum + fRegs->sctl = (fRegs->sctl & ~SATA_CONTROL_DET_MASK) + | DET_NO_INITIALIZATION << SATA_CONTROL_DET_SHIFT; + FlushPostedWrites(); +} + + +void +AHCIPort::_ClearErrorRegister() +{ + // clear error bits + fRegs->serr = fRegs->serr; + FlushPostedWrites(); +} diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h index c08ea54a1f..7ebb1fcc49 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h +++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h @@ -51,6 +51,8 @@ private: status_t WaitForTransfer(int *tfd, bigtime_t timeout); void FinishTransfer(); + inline void _HardReset(); + inline void _ClearErrorRegister(); // uint8 * SetCommandFis(volatile command_list_entry *cmd, volatile fis *fis, const void *data, size_t dataSize); status_t FillPrdTable(volatile prd *prdTable, int *prdCount, int prdMax, const void *data, size_t dataSize); diff --git a/src/add-ons/kernel/drivers/graphics/radeon_hd/driver.cpp b/src/add-ons/kernel/drivers/graphics/radeon_hd/driver.cpp index e58455a68a..2f2df49c7e 100644 --- a/src/add-ons/kernel/drivers/graphics/radeon_hd/driver.cpp +++ b/src/add-ons/kernel/drivers/graphics/radeon_hd/driver.cpp @@ -229,11 +229,12 @@ const struct supported_device { {0x6767, 5, 0, RADEON_CAICOS, CHIP_STD, "Radeon HD Caicos"}, {0x6768, 5, 0, RADEON_CAICOS, CHIP_STD, "Radeon HD Caicos"}, {0x6770, 5, 0, RADEON_CAICOS, CHIP_STD, "Radeon HD 6400"}, - {0x6778, 5, 0, RADEON_CAICOS, CHIP_STD, "Radeon HD Caicos"}, - {0x6779, 5, 0, RADEON_CAICOS, CHIP_STD, "Radeon HD 6450"}, + {0x6778, 5, 0, RADEON_CAICOS, CHIP_STD, "Radeon HD 7470/8470"}, + {0x6779, 5, 0, RADEON_CAICOS, CHIP_STD, "Radeon HD 6450/7450/8450"}, {0x68fa, 5, 0, RADEON_CAICOS, CHIP_STD, "Radeon HD 7350"}, {0x677b, 5, 0, RADEON_CAICOS, CHIP_STD, "Radeon HD 7400"}, {0x6772, 5, 0, RADEON_CAICOS, CHIP_APU, "Radeon HD 7400A"}, + {0x6771, 5, 0, RADEON_CAICOS, CHIP_STD, "Radeon HD 8490"}, // Turks {0x6740, 5, 0, RADEON_TURKS, CHIP_MOBILE, "Radeon HD 6770M"}, {0x6741, 5, 0, RADEON_TURKS, CHIP_MOBILE, "Radeon HD 6650M"}, diff --git a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp b/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp index c6c0f03b95..fe2478aa6a 100644 --- a/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/bfs/kernel_interface.cpp @@ -587,6 +587,9 @@ bfs_lookup(fs_volume* _volume, fs_vnode* _directory, const char* file, status = tree->Find((uint8*)file, (uint16)strlen(file), _vnodeID); if (status != B_OK) { //PRINT(("bfs_walk() could not find %Ld:\"%s\": %s\n", directory->BlockNumber(), file, strerror(status))); + if (status == B_ENTRY_NOT_FOUND) + entry_cache_add_missing(volume->ID(), directory->ID(), file); + return status; } diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/haiku/entry_cache.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/haiku/entry_cache.cpp index 8ea12b8158..7aa60ac982 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/haiku/entry_cache.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/haiku/entry_cache.cpp @@ -17,6 +17,13 @@ entry_cache_add(dev_t mountID, ino_t dirID, const char* name, ino_t nodeID) } +status_t +entry_cache_add_missing(dev_t mountID, ino_t dirID, const char* name) +{ + return B_OK; +} + + status_t entry_cache_remove(dev_t mountID, ino_t dirID, const char* name) { diff --git a/src/add-ons/kernel/network/stack/interfaces.cpp b/src/add-ons/kernel/network/stack/interfaces.cpp index 20b4110ebd..ab2fa2d52a 100644 --- a/src/add-ons/kernel/network/stack/interfaces.cpp +++ b/src/add-ons/kernel/network/stack/interfaces.cpp @@ -445,6 +445,8 @@ InterfaceAddress::_Init(net_interface* netInterface, net_domain* netDomain) Interface::Interface(const char* interfaceName, net_device_interface* deviceInterface) + : + fBusy(false) { TRACE("Interface %p: new \"%s\", device interface %p\n", this, interfaceName, deviceInterface); @@ -933,13 +935,13 @@ Interface::SetDown() if ((flags & IFF_UP) == 0) return; - // TODO: We acquire also the net_interfaces lock here - // to avoid a lock inversion in the ipv6 protocol implementation - // (see ticket #9377). - // A better solution would be to avoid locking the interface lock (fLock) - // when calling the lower layers. RecursiveLocker interfacesLocker(sLock); - RecursiveLocker locker(fLock); + + if (IsBusy()) + return; + + SetBusy(true); + interfacesLocker.Unlock(); DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator(); while (domain_datalink* datalink = iterator.Next()) { @@ -947,6 +949,8 @@ Interface::SetDown() } flags &= ~IFF_UP; + + SetBusy(false); } @@ -1076,10 +1080,11 @@ Interface::_SetUp() if (status != B_OK) return status; + RecursiveLocker interfacesLocker(sLock); + SetBusy(true); + interfacesLocker.Unlock(); + // Propagate flag to all datalink protocols - - RecursiveLocker locker(fLock); - DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator(); while (domain_datalink* datalink = iterator.Next()) { status = datalink->first_info->interface_up(datalink->first_protocol); @@ -1097,6 +1102,7 @@ Interface::_SetUp() } down_device_interface(fDeviceInterface); + SetBusy(false); return status; } } @@ -1109,6 +1115,8 @@ Interface::_SetUp() } flags |= IFF_UP; + SetBusy(false); + return B_OK; } @@ -1409,7 +1417,7 @@ get_interface(net_domain* domain, uint32 index) interface = sInterfaces.First(); else interface = find_interface(index); - if (interface == NULL) + if (interface == NULL || interface->IsBusy()) return NULL; if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) @@ -1426,7 +1434,7 @@ get_interface(net_domain* domain, const char* name) RecursiveLocker locker(sLock); Interface* interface = find_interface(name); - if (interface == NULL) + if (interface == NULL || interface->IsBusy()) return NULL; if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) @@ -1445,6 +1453,8 @@ get_interface_for_device(net_domain* domain, uint32 index) InterfaceList::Iterator iterator = sInterfaces.GetIterator(); while (Interface* interface = iterator.Next()) { if (interface->device->index == index) { + if (interface->IsBusy()) + return NULL; if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) return NULL; @@ -1470,6 +1480,8 @@ get_interface_for_link(net_domain* domain, const sockaddr* _linkAddress) InterfaceList::Iterator iterator = sInterfaces.GetIterator(); while (Interface* interface = iterator.Next()) { + if (interface->IsBusy()) + continue; // Test if the hardware address matches, or if the given interface // matches, or if at least the index matches. if ((linkAddress.sdl_alen == interface->device->address.length @@ -1479,6 +1491,8 @@ get_interface_for_link(net_domain* domain, const sockaddr* _linkAddress) && !strcmp(interface->name, (const char*)linkAddress.sdl_data)) || (linkAddress.sdl_nlen == 0 && linkAddress.sdl_alen == 0 && linkAddress.sdl_index == interface->index)) { + if (interface->IsBusy()) + return NULL; if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK) return NULL; @@ -1516,6 +1530,9 @@ get_interface_address_for_destination(net_domain* domain, InterfaceList::Iterator iterator = sInterfaces.GetIterator(); while (Interface* interface = iterator.Next()) { + if (interface->IsBusy()) + continue; + InterfaceAddress* address = interface->AddressForDestination(domain, destination); if (address != NULL) @@ -1543,6 +1560,8 @@ get_interface_address_for_link(net_domain* domain, const sockaddr* address, InterfaceList::Iterator iterator = sInterfaces.GetIterator(); while (Interface* interface = iterator.Next()) { + if (interface->IsBusy()) + continue; // Test if the hardware address matches, or if the given interface // matches, or if at least the index matches. if (linkAddress.sdl_alen == interface->device->address.length diff --git a/src/add-ons/kernel/network/stack/interfaces.h b/src/add-ons/kernel/network/stack/interfaces.h index f7bc63b21e..9c0cb63e27 100644 --- a/src/add-ons/kernel/network/stack/interfaces.h +++ b/src/add-ons/kernel/network/stack/interfaces.h @@ -152,6 +152,9 @@ public: domain_datalink* DomainDatalink(net_domain* domain) { return DomainDatalink(domain->family); } + inline void SetBusy(bool busy) { atomic_set(&fBusy, busy ? 1 : 0); }; + inline bool IsBusy() const { return atomic_get((int32*)&fBusy) == 1 ;}; + #if ENABLE_DEBUGGER_COMMANDS void Dump() const; #endif @@ -166,6 +169,7 @@ private: private: recursive_lock fLock; + int32 fBusy; net_device_interface* fDeviceInterface; AddressList fAddresses; DatalinkTable fDatalinkTable; diff --git a/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp b/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp index ac417f4ded..48c47d8930 100644 --- a/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp +++ b/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.cpp @@ -57,6 +57,10 @@ // Otherwise the alternative code could simply be removed from this file. #endif +#if LIBAVCODEC_VERSION_INT > ((54 << 16) | (50 << 8)) +typedef AVCodecID CodecID; +#endif + struct wave_format_ex { uint16 format_tag; @@ -409,10 +413,10 @@ AVCodecDecoder::_NegotiateAudioOutputFormat(media_format* inOutFormat) if (fRawDecodedAudio->opaque == NULL) return B_NO_MEMORY; - TRACE(" bit_rate = %d, sample_rate = %d, channels = %d, init = %d, " + TRACE(" bit_rate = %d, sample_rate = %d, channels = %d, " "output frame size: %d, count: %ld, rate: %.2f\n", fContext->bit_rate, fContext->sample_rate, fContext->channels, - result, fOutputFrameSize, fOutputFrameCount, fOutputFrameRate); + fOutputFrameSize, fOutputFrameCount, fOutputFrameRate); return B_OK; } @@ -716,7 +720,7 @@ AVCodecDecoder::_DecodeNextAudioFrame() dump_ffframe_audio(fRawDecodedAudio, "ffaudi"); #endif - TRACE_AUDIO(" frame count: %lld current: %lld\n", + TRACE_AUDIO(" frame count: %ld current: %lld\n", fRawDecodedAudio->nb_samples, fFrame); return B_OK; @@ -1193,7 +1197,7 @@ AVCodecDecoder::_DecodeNextVideoFrame() fRawDecodedPicture, &gotVideoFrame, &fTempPacket); if (encodedDataSizeInBytes < 0) { TRACE("[v] AVCodecDecoder: ignoring error in decoding frame %lld:" - " %d\n", fFrame, len); + " %d\n", fFrame, encodedDataSizeInBytes); // NOTE: An error from avcodec_decode_video2() is ignored by the // FFMPEG 0.10.2 example decoding_encoding.c. Only the packet // buffers are flushed accordingly diff --git a/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.cpp b/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.cpp index 910b30b7fc..b30de87542 100644 --- a/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.cpp +++ b/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.cpp @@ -40,9 +40,9 @@ AVCodecEncoder::AVCodecEncoder(uint32 codecID, int bitRateScale) : Encoder(), fBitRateScale(bitRateScale), - fCodecID((enum CodecID)codecID), + fCodecID((CodecID)codecID), fCodec(NULL), - fOwnContext(avcodec_alloc_context()), + fOwnContext(avcodec_alloc_context3(NULL)), fContext(fOwnContext), fCodecInitStatus(CODEC_INIT_NEEDED), @@ -494,7 +494,7 @@ AVCodecEncoder::_OpenCodecIfNeeded() fContext->strict_std_compliance = -2; // Open the codec - int result = avcodec_open(fContext, fCodec); + int result = avcodec_open2(fContext, fCodec, NULL); if (result >= 0) fCodecInitStatus = CODEC_INIT_DONE; else @@ -591,43 +591,78 @@ status_t AVCodecEncoder::_EncodeAudio(const uint8* buffer, size_t bufferSize, int64 frameCount, media_encode_info* info) { - // Encode one audio chunk/frame. The bufferSize has already been adapted - // to the needed size for fContext->frame_size, or we are writing raw - // audio. - int usedBytes = avcodec_encode_audio(fContext, fChunkBuffer, - bufferSize, reinterpret_cast(buffer)); + status_t ret; - if (usedBytes < 0) { - TRACE(" avcodec_encode_audio() failed: %d\n", usedBytes); - return B_ERROR; + // Encode one audio chunk/frame. + AVPacket packet; + av_init_packet(&packet); + // By leaving these NULL, we let the encoder allocate memory as it needs. + // This way we don't risk iving a too small buffer. + packet.data = NULL; + packet.size = 0; + + // We need to wrap our input data into an AVFrame structure. + AVFrame frame; + int gotPacket = 0; + + if (buffer) { + avcodec_get_frame_defaults(&frame); + + frame.nb_samples = frameCount; + + ret = avcodec_fill_audio_frame(&frame, fContext->channels, + fContext->sample_fmt, (const uint8_t *) buffer, bufferSize, 1); + + if (ret != 0) + return B_ERROR; + + /* Set the presentation time of the frame */ + frame.pts = (bigtime_t)(fFramesWritten * 1000000LL + / fInputFormat.u.raw_audio.frame_rate); + fFramesWritten += frame.nb_samples; + + ret = avcodec_encode_audio2(fContext, &packet, &frame, &gotPacket); + } else { + // If called with NULL, ask the encoder to flush any buffers it may + // have pending. + ret = avcodec_encode_audio2(fContext, &packet, NULL, &gotPacket); } - if (usedBytes == 0) - return B_OK; -// // Maybe we need to use this PTS to calculate start_time: -// if (fContext->coded_frame->pts != kNoPTSValue) { -// TRACE(" codec frame PTS: %lld (codec time_base: %d/%d)\n", -// fContext->coded_frame->pts, fContext->time_base.num, -// fContext->time_base.den); -// } else { -// TRACE(" codec frame PTS: N/A (codec time_base: %d/%d)\n", -// fContext->time_base.num, fContext->time_base.den); -// } + if (buffer && frame.extended_data != frame.data) + av_freep(&frame.extended_data); - // Setup media_encode_info, most important is the time stamp. - info->start_time = (bigtime_t)(fFramesWritten * 1000000LL - / fInputFormat.u.raw_audio.frame_rate); - info->flags = B_MEDIA_KEY_FRAME; - - // Write the chunk - status_t ret = WriteChunk(fChunkBuffer, usedBytes, info); - if (ret != B_OK) { - TRACE(" error writing chunk: %s\n", strerror(ret)); - return ret; + if (ret != 0) { + TRACE(" avcodec_encode_audio() failed: %ld\n", ret); + return B_ERROR; } fFramesWritten += frameCount; + if (gotPacket) { + if (fContext->coded_frame) { + // Store information about the coded frame in the context. + fContext->coded_frame->pts = packet.pts; + fContext->coded_frame->key_frame = !!(packet.flags & AV_PKT_FLAG_KEY); + } + + // Setup media_encode_info, most important is the time stamp. + info->start_time = packet.pts; + + if (packet.flags & AV_PKT_FLAG_KEY) + info->flags = B_MEDIA_KEY_FRAME; + else + info->flags = 0; + + // We got a packet out of the encoder, write it to the output stream + ret = WriteChunk(packet.data, packet.size, info); + if (ret != B_OK) { + TRACE(" error writing chunk: %s\n", strerror(ret)); + av_free_packet(&packet); + return ret; + } + } + + av_free_packet(&packet); return B_OK; } diff --git a/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.h b/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.h index 79139f7db4..bf23ecb19a 100644 --- a/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.h +++ b/src/add-ons/media/plugins/ffmpeg/AVCodecEncoder.h @@ -17,6 +17,11 @@ extern "C" { #include "EncoderPlugin.h" +#if LIBAVCODEC_VERSION_INT > ((54 << 16) | (50 << 8)) +typedef AVCodecID CodecID; +#endif + + class AVCodecEncoder : public Encoder { public: AVCodecEncoder(uint32 codecID, diff --git a/src/add-ons/media/plugins/ffmpeg/AVFormatReader.cpp b/src/add-ons/media/plugins/ffmpeg/AVFormatReader.cpp index 742976f915..5da841ce59 100644 --- a/src/add-ons/media/plugins/ffmpeg/AVFormatReader.cpp +++ b/src/add-ons/media/plugins/ffmpeg/AVFormatReader.cpp @@ -257,7 +257,7 @@ StreamBase::Open() fContext->pb = fIOContext; // Allocate our context and probe the input format - if (avformat_open_input(&fContext, "", NULL, NULL) < 0) { + if (avformat_open_input(&fContext, ".mod", NULL, NULL) < 0) { TRACE("StreamBase::Open() - avformat_open_input() failed!\n"); // avformat_open_input() frees the context in case of failure fContext = NULL; @@ -1505,7 +1505,7 @@ AVFormatReader::Sniff(int32* _streamCount) streamDeleter.Detach(); #ifdef TRACE_AVFORMAT_READER - dump_format(const_cast(stream->Context()), 0, "", 0); + av_dump_format(const_cast(stream->Context()), 0, "", 0); #endif if (_streamCount != NULL) diff --git a/src/add-ons/media/plugins/ffmpeg/AVFormatWriter.cpp b/src/add-ons/media/plugins/ffmpeg/AVFormatWriter.cpp index 1095a7d7d6..2121722d4d 100644 --- a/src/add-ons/media/plugins/ffmpeg/AVFormatWriter.cpp +++ b/src/add-ons/media/plugins/ffmpeg/AVFormatWriter.cpp @@ -53,6 +53,9 @@ static const size_t kIOBufferSize = 64 * 1024; #define OPEN_CODEC_CONTEXT 1 #define GET_CONTEXT_DEFAULTS 0 +#if LIBAVCODEC_VERSION_INT > ((54 << 16) | (50 << 8)) +typedef AVCodecID CodecID; +#endif // #pragma mark - AVFormatWriter::StreamCookie @@ -109,7 +112,8 @@ AVFormatWriter::StreamCookie::Init(media_format* format, BAutolock _(fStreamLock); fPacket.stream_index = fContext->nb_streams; - fStream = av_new_stream(fContext, fPacket.stream_index); + fStream = avformat_new_stream(fContext, NULL); + fStream->id = fPacket.stream_index; if (fStream == NULL) { TRACE(" failed to add new stream\n"); @@ -200,6 +204,10 @@ AVFormatWriter::StreamCookie::Init(media_format* format, // Now negociate the actual format with the encoder // First check if the requested format is acceptable AVCodec* codec = avcodec_find_encoder(fStream->codec->codec_id); + + if (codec == NULL) + return B_MEDIA_BAD_FORMAT; + const enum AVSampleFormat *p = codec->sample_fmts; for (; *p != -1; p++) { if (*p == fStream->codec->sample_fmt) @@ -466,7 +474,7 @@ AVFormatWriter::CommitHeader() AVCodecContext* codecContext = stream->codec; codecContext->strict_std_compliance = -2; AVCodec* codec = avcodec_find_encoder(codecContext->codec_id); - if (codec == NULL || avcodec_open(codecContext, codec) < 0) { + if (codec == NULL || avcodec_open2(codecContext, codec, NULL) < 0) { TRACE(" stream[%u] - failed to open AVCodecContext\n", i); } TRACE(" stream[%u] time_base: (%d/%d), codec->time_base: (%d/%d)\n", diff --git a/src/add-ons/media/plugins/ffmpeg/CodecTable.cpp b/src/add-ons/media/plugins/ffmpeg/CodecTable.cpp index dd5e0ce5e2..bd04566d7a 100644 --- a/src/add-ons/media/plugins/ffmpeg/CodecTable.cpp +++ b/src/add-ons/media/plugins/ffmpeg/CodecTable.cpp @@ -11,9 +11,15 @@ extern "C" { #include "avformat.h" } + +#if LIBAVCODEC_VERSION_INT > ((54 << 16) | (50 << 8)) +typedef AVCodecID CodecID; +#endif + + //XXX: newer versions have it in libavformat/internal.h typedef struct AVCodecTag { - enum CodecID id; + CodecID id; unsigned int tag; } AVCodecTag; diff --git a/src/add-ons/media/plugins/ffmpeg/EncoderTable.h b/src/add-ons/media/plugins/ffmpeg/EncoderTable.h index 2e966de91b..c2d36184b8 100644 --- a/src/add-ons/media/plugins/ffmpeg/EncoderTable.h +++ b/src/add-ons/media/plugins/ffmpeg/EncoderTable.h @@ -13,6 +13,11 @@ extern "C" { } +#if LIBAVCODEC_VERSION_INT > ((54 << 16) | (50 << 8)) +typedef AVCodecID CodecID; +#endif + + struct EncoderDescription { media_codec_info codec_info; media_format_family format_family; diff --git a/src/add-ons/media/plugins/ffmpeg/FFmpegPlugin.cpp b/src/add-ons/media/plugins/ffmpeg/FFmpegPlugin.cpp index b17304b81f..e3ec9873b0 100644 --- a/src/add-ons/media/plugins/ffmpeg/FFmpegPlugin.cpp +++ b/src/add-ons/media/plugins/ffmpeg/FFmpegPlugin.cpp @@ -53,7 +53,7 @@ manage_locks(void** _lock, enum AVLockOp operation) case AV_LOCK_CREATE: TRACE(" AV_LOCK_CREATE\n"); *lock = new(std::nothrow) BLocker("FFmpeg lock"); - if (*lock == NULL) + if (*lock == NULL) return 1; break; diff --git a/src/add-ons/media/plugins/ffmpeg/MuxerTable.cpp b/src/add-ons/media/plugins/ffmpeg/MuxerTable.cpp index 2856694b98..ed22c4e303 100644 --- a/src/add-ons/media/plugins/ffmpeg/MuxerTable.cpp +++ b/src/add-ons/media/plugins/ffmpeg/MuxerTable.cpp @@ -318,6 +318,62 @@ const media_file_format gMuxerTable[] = { "webm", { 0 } }, + { + media_file_format::B_READABLE + | media_file_format::B_KNOWS_RAW_AUDIO + | media_file_format::B_KNOWS_ENCODED_AUDIO, + { 0 }, + B_MISC_FORMAT_FAMILY, + 100, + { 0 }, + "audio/xm", + "Fast Tracker eXtended Module", + "xm", + "xm", + { 0 } + }, + { + media_file_format::B_READABLE + | media_file_format::B_KNOWS_RAW_AUDIO + | media_file_format::B_KNOWS_ENCODED_AUDIO, + { 0 }, + B_MISC_FORMAT_FAMILY, + 100, + { 0 }, + "audio/s3m", + "Scream Tracker 3", + "s3m", + "s3m", + { 0 } + }, + { + media_file_format::B_READABLE + | media_file_format::B_KNOWS_RAW_AUDIO + | media_file_format::B_KNOWS_ENCODED_AUDIO, + { 0 }, + B_MISC_FORMAT_FAMILY, + 100, + { 0 }, + "audio/it", + "Impulse Tracker", + "it", + "it", + { 0 } + }, + { + media_file_format::B_READABLE + | media_file_format::B_KNOWS_RAW_AUDIO + | media_file_format::B_KNOWS_ENCODED_AUDIO, + { 0 }, + B_MISC_FORMAT_FAMILY, + 100, + { 0 }, + "audio/x-mod", + "Protracker MOD", + "mod", + "mod", + { 0 } + }, }; const size_t gMuxerCount = sizeof(gMuxerTable) / sizeof(media_file_format); diff --git a/src/apps/debuganalyzer/DebugAnalyzer.cpp b/src/apps/debuganalyzer/DebugAnalyzer.cpp index d800cfba7a..d319604165 100644 --- a/src/apps/debuganalyzer/DebugAnalyzer.cpp +++ b/src/apps/debuganalyzer/DebugAnalyzer.cpp @@ -38,11 +38,11 @@ printf("ReadyToRun()\n"); PostMessage(B_QUIT_REQUESTED); } - virtual void ArgvReceived(int32 argc, char** argv) + virtual void ArgvReceived(int32 argc, char** argv) { -printf("ArgvReceived()\n"); -for (int32 i = 0; i < argc; i++) -printf(" arg %ld: \"%s\"\n", i, argv[i]); + printf("ArgvReceived()\n"); + for (int32 i = 0; i < argc; i++) + printf(" arg %" B_PRId32 ": \"%s\"\n", i, argv[i]); for (int32 i = 1; i < argc; i++) { PathDataSource* dataSource = new(std::nothrow) PathDataSource; diff --git a/src/apps/debuganalyzer/gui/chart/BigtimeChartAxisLegendSource.cpp b/src/apps/debuganalyzer/gui/chart/BigtimeChartAxisLegendSource.cpp index 2a58e071b8..364c50e68d 100644 --- a/src/apps/debuganalyzer/gui/chart/BigtimeChartAxisLegendSource.cpp +++ b/src/apps/debuganalyzer/gui/chart/BigtimeChartAxisLegendSource.cpp @@ -59,7 +59,7 @@ BigtimeChartAxisLegendSource::GetAxisLegends(const ChartDataRange& range, decomposed_bigtime decomposed; decompose_time(time, decomposed); char buffer[128]; - snprintf(buffer, sizeof(buffer), "%02lld:%02d:%02d.%06d", + snprintf(buffer, sizeof(buffer), "%02" B_PRIu64 ":%02d:%02d.%06d", decomposed.hours, decomposed.minutes, decomposed.seconds, decomposed.micros); // TODO: Drop superfluous micro seconds digits, or even microseconds and seconds diff --git a/src/apps/debuganalyzer/gui/chart/LegendChartAxis.cpp b/src/apps/debuganalyzer/gui/chart/LegendChartAxis.cpp index 035f3d1326..c8bbc34cff 100644 --- a/src/apps/debuganalyzer/gui/chart/LegendChartAxis.cpp +++ b/src/apps/debuganalyzer/gui/chart/LegendChartAxis.cpp @@ -89,7 +89,7 @@ LegendChartAxis::_FilterLegends(int32 totalSize, int32 spacing, // Filter out all higher level legends colliding with lower level or // preceeding same-level legends. We iterate backwards from the lower to // the higher levels - for (int32 level = std::max(minLevel, 0L); level <= maxLevel;) { + for (int32 level = std::max(minLevel, (int32)0); level <= maxLevel;) { legendCount = fLegends.CountItems(); // get the first legend position/end diff --git a/src/apps/debuganalyzer/gui/chart/NanotimeChartAxisLegendSource.cpp b/src/apps/debuganalyzer/gui/chart/NanotimeChartAxisLegendSource.cpp index 49ebd4aba9..1e234b059a 100644 --- a/src/apps/debuganalyzer/gui/chart/NanotimeChartAxisLegendSource.cpp +++ b/src/apps/debuganalyzer/gui/chart/NanotimeChartAxisLegendSource.cpp @@ -60,7 +60,7 @@ NanotimeChartAxisLegendSource::GetAxisLegends(const ChartDataRange& range, decomposed_nanotime decomposed; decompose_time(time, decomposed); char buffer[128]; - snprintf(buffer, sizeof(buffer), "%02lld:%02d:%02d.%09d", + snprintf(buffer, sizeof(buffer), "%02" B_PRId64 ":%02d:%02d.%09d", decomposed.hours, decomposed.minutes, decomposed.seconds, decomposed.nanos); // TODO: Drop superfluous nanoseconds digits, or even nanoseconds and seconds diff --git a/src/apps/debuganalyzer/gui/main_window/GeneralPage.cpp b/src/apps/debuganalyzer/gui/main_window/GeneralPage.cpp index b1df7de5d9..6511319acd 100644 --- a/src/apps/debuganalyzer/gui/main_window/GeneralPage.cpp +++ b/src/apps/debuganalyzer/gui/main_window/GeneralPage.cpp @@ -68,11 +68,11 @@ MainWindow::GeneralPage::SetModel(Model* model) fIdleTimeView->SetText(buffer); // team count - snprintf(buffer, sizeof(buffer), "%ld", fModel->CountTeams()); + snprintf(buffer, sizeof(buffer), "%" B_PRId32, fModel->CountTeams()); fTeamCountView->SetText(buffer); // threads - snprintf(buffer, sizeof(buffer), "%ld", fModel->CountThreads()); + snprintf(buffer, sizeof(buffer), "%" B_PRId32, fModel->CountThreads()); fThreadCountView->SetText(buffer); } else { fDataSourceView->SetText(""); diff --git a/src/apps/debuganalyzer/gui/main_window/SchedulingPage.cpp b/src/apps/debuganalyzer/gui/main_window/SchedulingPage.cpp index 49a798b078..5def8141fa 100644 --- a/src/apps/debuganalyzer/gui/main_window/SchedulingPage.cpp +++ b/src/apps/debuganalyzer/gui/main_window/SchedulingPage.cpp @@ -318,7 +318,7 @@ protected: int32 lineHeight = (int32)fFontInfo.lineHeight; minLine = (int32)rect.top / lineHeight; maxLine = ((int32)ceilf(rect.bottom) + lineHeight - 1) / lineHeight; - minLine = std::max(minLine, 0L); + minLine = std::max(minLine, (int32)0); maxLine = std::min(maxLine, CountLines() - 1); } @@ -1449,7 +1449,8 @@ printf("failed to read event!\n"); Model::ThreadSchedulingState* thread = fState.LookupThread( event->thread); if (thread == NULL) { - printf("Schedule event for unknown thread: %ld\n", event->thread); + printf("Schedule event for unknown thread: %" B_PRId32 "\n", + event->thread); return; } @@ -1464,8 +1465,8 @@ printf("failed to read event!\n"); thread = fState.LookupThread(event->previous_thread); if (thread == NULL) { - printf("Schedule event for unknown previous thread: %ld\n", - event->previous_thread); + printf("Schedule event for unknown previous thread: %" B_PRId32 + "\n", event->previous_thread); return; } @@ -1529,8 +1530,8 @@ printf("failed to read event!\n"); Model::ThreadSchedulingState* thread = fState.LookupThread( event->thread); if (thread == NULL) { - printf("Enqueued in run queue event for unknown thread: %ld\n", - event->thread); + printf("Enqueued in run queue event for unknown thread: %" B_PRId32 + "\n", event->thread); return; } @@ -1559,8 +1560,8 @@ printf("failed to read event!\n"); Model::ThreadSchedulingState* thread = fState.LookupThread( event->thread); if (thread == NULL) { - printf("Removed from run queue event for unknown thread: %ld\n", - event->thread); + printf("Removed from run queue event for unknown thread: %" B_PRId32 + "\n", event->thread); return; } diff --git a/src/apps/debuganalyzer/gui/main_window/ThreadsPage.cpp b/src/apps/debuganalyzer/gui/main_window/ThreadsPage.cpp index 88e9965fb5..80e9180799 100644 --- a/src/apps/debuganalyzer/gui/main_window/ThreadsPage.cpp +++ b/src/apps/debuganalyzer/gui/main_window/ThreadsPage.cpp @@ -51,8 +51,8 @@ public: { char buffer[128]; Model::Team* team = thread->GetTeam(); - snprintf(buffer, sizeof(buffer), "%s (%ld)", team->Name(), - team->ID()); + snprintf(buffer, sizeof(buffer), "%s (%" B_PRId32 ")", + team->Name(), team->ID()); value.SetTo(buffer); return true; } diff --git a/src/apps/debuganalyzer/gui/thread_window/GeneralPage.cpp b/src/apps/debuganalyzer/gui/thread_window/GeneralPage.cpp index a0d17eb5bf..017afe7c5e 100644 --- a/src/apps/debuganalyzer/gui/thread_window/GeneralPage.cpp +++ b/src/apps/debuganalyzer/gui/thread_window/GeneralPage.cpp @@ -55,7 +55,7 @@ ThreadWindow::GeneralPage::SetModel(Model* model, Model::Thread* thread) // ID char buffer[128]; - snprintf(buffer, sizeof(buffer), "%ld", fThread->ID()); + snprintf(buffer, sizeof(buffer), "%" B_PRId32, fThread->ID()); fThreadIDView->SetText(buffer); // team @@ -65,28 +65,28 @@ ThreadWindow::GeneralPage::SetModel(Model* model, Model::Thread* thread) char timeBuffer[64]; format_nanotime(fThread->TotalRunTime(), timeBuffer, sizeof(timeBuffer)); - snprintf(buffer, sizeof(buffer), "%s (%lld)", timeBuffer, + snprintf(buffer, sizeof(buffer), "%s (%" B_PRId64 ")", timeBuffer, fThread->Runs()); fRunTimeView->SetText(buffer); // wait time format_nanotime(fThread->TotalWaitTime(), timeBuffer, sizeof(timeBuffer)); - snprintf(buffer, sizeof(buffer), "%s (%lld)", timeBuffer, + snprintf(buffer, sizeof(buffer), "%s (%" B_PRId64 ")", timeBuffer, fThread->Waits()); fWaitTimeView->SetText(buffer); // latencies format_nanotime(fThread->TotalLatency(), timeBuffer, sizeof(timeBuffer)); - snprintf(buffer, sizeof(buffer), "%s (%lld)", timeBuffer, + snprintf(buffer, sizeof(buffer), "%s (%" B_PRId64 ")", timeBuffer, fThread->Latencies()); fLatencyView->SetText(buffer); // preemptions format_nanotime(fThread->TotalRerunTime(), timeBuffer, sizeof(timeBuffer)); - snprintf(buffer, sizeof(buffer), "%s (%lld)", timeBuffer, + snprintf(buffer, sizeof(buffer), "%s (%" B_PRId64 ")", timeBuffer, fThread->Preemptions()); fPreemptionView->SetText(buffer); diff --git a/src/apps/debuganalyzer/gui/thread_window/ThreadWindow.cpp b/src/apps/debuganalyzer/gui/thread_window/ThreadWindow.cpp index a3bba76c8c..491b5b853e 100644 --- a/src/apps/debuganalyzer/gui/thread_window/ThreadWindow.cpp +++ b/src/apps/debuganalyzer/gui/thread_window/ThreadWindow.cpp @@ -27,8 +27,8 @@ static BString get_window_name(Model::Thread* thread) { char buffer[1024]; - snprintf(buffer, sizeof(buffer), "Thread: %s (%ld)", thread->Name(), - thread->ID()); + snprintf(buffer, sizeof(buffer), "Thread: %s (%" B_PRId32 ")", + thread->Name(), thread->ID()); return BString(buffer); } diff --git a/src/apps/debuganalyzer/model/Model.cpp b/src/apps/debuganalyzer/model/Model.cpp index f1e1f64b43..fe1119ab7d 100644 --- a/src/apps/debuganalyzer/model/Model.cpp +++ b/src/apps/debuganalyzer/model/Model.cpp @@ -785,7 +785,7 @@ Model::AddTeam(const system_profiler_team_added* event, nanotime_t time) { Team* team = TeamByID(event->team); if (team != NULL) { - fprintf(stderr, "Duplicate team: %ld\n", event->team); + fprintf(stderr, "Duplicate team: %" B_PRId32 "\n", event->team); // TODO: User feedback! return team; } @@ -830,7 +830,7 @@ Model::AddThread(const system_profiler_thread_added* event, nanotime_t time) // check whether we do already know the thread Thread* thread = ThreadByID(event->thread); if (thread != NULL) { - fprintf(stderr, "Duplicate thread: %ld\n", event->thread); + fprintf(stderr, "Duplicate thread: %" B_PRId32 "\n", event->thread); // TODO: User feedback! return thread; } @@ -838,7 +838,7 @@ Model::AddThread(const system_profiler_thread_added* event, nanotime_t time) // get its team Team* team = TeamByID(event->team); if (team == NULL) { - fprintf(stderr, "No team for thread: %ld\n", event->thread); + fprintf(stderr, "No team for thread: %" B_PRId32 "\n", event->thread); return NULL; } diff --git a/src/apps/debuganalyzer/model_loader/ModelLoader.cpp b/src/apps/debuganalyzer/model_loader/ModelLoader.cpp index e8acbbfcfc..7b75f2cfd0 100644 --- a/src/apps/debuganalyzer/model_loader/ModelLoader.cpp +++ b/src/apps/debuganalyzer/model_loader/ModelLoader.cpp @@ -721,9 +721,9 @@ ModelLoader::_ProcessEvent(uint32 event, uint32 cpu, const void* buffer, break; default: -printf("unsupported event type %lu, size: %lu\n", event, size); -return B_BAD_DATA; - break; + printf("unsupported event type %" B_PRIu32 ", size: %" B_PRIuSIZE + "\n", event, size); + return B_BAD_DATA; } return B_OK; @@ -889,8 +889,10 @@ ModelLoader::_HandleTeamRemoved(system_profiler_team_removed* event) { if (Model::Team* team = fModel->TeamByID(event->team)) team->SetDeletionTime(fState->LastEventTime()); - else - printf("Warning: Removed event for unknown team: %ld\n", event->team); + else { + printf("Warning: Removed event for unknown team: %" B_PRId32 "\n", + event->team); + } } @@ -913,7 +915,7 @@ ModelLoader::_HandleThreadRemoved(system_profiler_thread_removed* event) { ExtendedThreadSchedulingState* thread = fState->LookupThread(event->thread); if (thread == NULL) { - printf("Warning: Removed event for unknown thread: %ld\n", + printf("Warning: Removed event for unknown thread: %" B_PRId32 "\n", event->thread); thread = _AddUnknownThread(event->thread); } @@ -931,7 +933,7 @@ ModelLoader::_HandleThreadScheduled(uint32 cpu, ExtendedThreadSchedulingState* thread = fState->LookupThread(event->thread); if (thread == NULL) { - printf("Warning: Schedule event for unknown thread: %ld\n", + printf("Warning: Schedule event for unknown thread: %" B_PRId32 "\n", event->thread); thread = _AddUnknownThread(event->thread); return; @@ -966,8 +968,8 @@ ModelLoader::_HandleThreadScheduled(uint32 cpu, thread = fState->LookupThread(event->previous_thread); if (thread == NULL) { - printf("Warning: Schedule event for unknown previous thread: %ld\n", - event->previous_thread); + printf("Warning: Schedule event for unknown previous thread: %" B_PRId32 + "\n", event->previous_thread); thread = _AddUnknownThread(event->previous_thread); } @@ -1035,8 +1037,8 @@ ModelLoader::_HandleThreadEnqueuedInRunQueue( ExtendedThreadSchedulingState* thread = fState->LookupThread(event->thread); if (thread == NULL) { - printf("Warning: Enqueued in run queue event for unknown thread: %ld\n", - event->thread); + printf("Warning: Enqueued in run queue event for unknown thread: %" + B_PRId32 "\n", event->thread); thread = _AddUnknownThread(event->thread); } @@ -1073,7 +1075,7 @@ ModelLoader::_HandleThreadRemovedFromRunQueue(uint32 cpu, ExtendedThreadSchedulingState* thread = fState->LookupThread(event->thread); if (thread == NULL) { printf("Warning: Removed from run queue event for unknown thread: " - "%ld\n", event->thread); + "%" B_PRId32 "\n", event->thread); thread = _AddUnknownThread(event->thread); } @@ -1112,8 +1114,8 @@ ModelLoader::_HandleIOSchedulerAdded(system_profiler_io_scheduler_added* event) { Model::IOScheduler* scheduler = fModel->IOSchedulerByID(event->scheduler); if (scheduler != NULL) { - printf("Warning: Duplicate added event for I/O scheduler %ld\n", - event->scheduler); + printf("Warning: Duplicate added event for I/O scheduler %" B_PRId32 + "\n", event->scheduler); return; } @@ -1134,12 +1136,13 @@ ModelLoader::_HandleIORequestScheduled(io_request_scheduled* event) ExtendedThreadSchedulingState* thread = fState->LookupThread(event->thread); if (thread == NULL) { - printf("Warning: I/O request for unknown thread %ld\n", event->thread); + printf("Warning: I/O request for unknown thread %" B_PRId32 "\n", + event->thread); thread = _AddUnknownThread(event->thread); } if (fModel->IOSchedulerByID(event->scheduler) == NULL) { - printf("Warning: I/O requests for unknown scheduler %ld\n", + printf("Warning: I/O requests for unknown scheduler %" B_PRId32 "\n", event->scheduler); // TODO: Add state for unknown scheduler, as we do for threads. return; @@ -1307,8 +1310,8 @@ ModelLoader::_AddThreadWaitObject(ExtendedThreadSchedulingState* thread, = fModel->WaitObjectGroupFor(type, object); if (waitObjectGroup == NULL) { // The algorithm should prevent this case. -printf("ModelLoader::_AddThreadWaitObject(): Unknown wait object: type: %lu, " -"object: %#lx\n", type, object); + printf("ModelLoader::_AddThreadWaitObject(): Unknown wait object: type:" + " %" B_PRIu32 ", " "object: %#" B_PRIxADDR "\n", type, object); return; } diff --git a/src/apps/debuganalyzer/model_loader/ThreadModelLoader.cpp b/src/apps/debuganalyzer/model_loader/ThreadModelLoader.cpp index 192abfdb8e..3ff9a47fa0 100644 --- a/src/apps/debuganalyzer/model_loader/ThreadModelLoader.cpp +++ b/src/apps/debuganalyzer/model_loader/ThreadModelLoader.cpp @@ -114,9 +114,9 @@ ThreadModelLoader::_Load() // create the groups int32 waitObjectCount = waitObjects.CountItems(); -printf("%ld wait objects\n", waitObjectCount); + printf("%" B_PRId32 " wait objects\n", waitObjectCount); for (int32 i = 0; i < waitObjectCount;) { -printf("new wait object group at %ld\n", i); + printf("new wait object group at %" B_PRId32 "\n", i); // collect the objects for this group Model::ThreadWaitObject* firstObject = waitObjects.ItemAt(i); int32 k = i + 1; diff --git a/src/apps/debugger/Debugger.cpp b/src/apps/debugger/Debugger.cpp index 5b72949475..603a2124b9 100644 --- a/src/apps/debugger/Debugger.cpp +++ b/src/apps/debugger/Debugger.cpp @@ -1,6 +1,6 @@ /* * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de. - * Copyright 2011-2014, Rene Gollent, rene@gollent.com. + * Copyright 2011-2015, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ @@ -26,6 +26,7 @@ #include "GraphicalUserInterface.h" #include "ImageDebugLoadingStateHandlerRoster.h" #include "MessageCodes.h" +#include "ReportUserInterface.h" #include "SettingsManager.h" #include "SignalSet.h" #include "StartTeamWindow.h" @@ -143,7 +144,6 @@ parse_arguments(int argc, const char* const* argv, bool noOutput, case 's': { - options.useCLI = true; options.saveReport = true; options.reportPath = optarg; break; @@ -393,6 +393,21 @@ private: }; +class ReportDebugger : private TeamDebugger::Listener { +public: + ReportDebugger(); + ~ReportDebugger(); + bool Run(const Options& options); + +private: + // TeamDebugger::Listener + virtual void TeamDebuggerStarted(TeamDebugger* debugger); + virtual void TeamDebuggerRestartRequested( + TeamDebugger* debugger); + virtual void TeamDebuggerQuit(TeamDebugger* debugger); +}; + + // #pragma mark - Debugger application class @@ -723,8 +738,7 @@ CliDebugger::Run(const Options& options) // create the command line UI CommandLineUserInterface* userInterface - = new(std::nothrow) CommandLineUserInterface(options.saveReport, - options.reportPath, options.thread); + = new(std::nothrow) CommandLineUserInterface(); if (userInterface == NULL) { fprintf(stderr, "Error: Out of memory!\n"); return false; @@ -774,6 +788,89 @@ CliDebugger::TeamDebuggerQuit(TeamDebugger* debugger) } +// #pragma mark - ReportDebugger + + +ReportDebugger::ReportDebugger() +{ +} + + +ReportDebugger::~ReportDebugger() +{ +} + + +bool +ReportDebugger::Run(const Options& options) +{ + // initialize global objects and settings manager + status_t error = global_init(); + if (error != B_OK) { + fprintf(stderr, "Error: Global initialization failed: %s\n", + strerror(error)); + return false; + } + + SettingsManager settingsManager; + error = settingsManager.Init(); + if (error != B_OK) { + fprintf(stderr, "Error: Settings manager initialization failed: " + "%s\n", strerror(error)); + return false; + } + + // create the report UI + ReportUserInterface* userInterface + = new(std::nothrow) ReportUserInterface(options.thread, options.reportPath); + if (userInterface == NULL) { + fprintf(stderr, "Error: Out of memory!\n"); + return false; + } + BReference userInterfaceReference(userInterface, true); + + // get/run the program to be debugged and start the team debugger + DebuggedProgramInfo programInfo; + if (!get_debugged_program(options, programInfo)) + return false; + + TeamDebugger* teamDebugger = start_team_debugger(programInfo.team, + &settingsManager, this, programInfo.thread, + programInfo.commandLineArgc, programInfo.commandLineArgv, + programInfo.stopInMain, userInterface); + if (teamDebugger == NULL) + return false; + + thread_id teamDebuggerThread = teamDebugger->Thread(); + + // run the input loop + userInterface->Run(); + + // wait for the team debugger thread to terminate + wait_for_thread(teamDebuggerThread, NULL); + + return true; +} + + +void +ReportDebugger::TeamDebuggerStarted(TeamDebugger* debugger) +{ +} + + +void +ReportDebugger::TeamDebuggerRestartRequested(TeamDebugger* debugger) +{ +} + + +void +ReportDebugger::TeamDebuggerQuit(TeamDebugger* debugger) +{ +} + + // #pragma mark - @@ -792,6 +889,9 @@ main(int argc, const char* const* argv) if (options.useCLI) { CliDebugger debugger; return debugger.Run(options) ? 0 : 1; + } else if (options.saveReport) { + ReportDebugger debugger; + return debugger.Run(options) ? 0 : 1; } Debugger app; diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile index 0985601c1f..773da5f236 100644 --- a/src/apps/debugger/Jamfile +++ b/src/apps/debugger/Jamfile @@ -46,6 +46,7 @@ SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui teams_window ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui utility_windows ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui util ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface gui value ] ; +SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface report ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) user_interface util ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) util ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) value ] ; @@ -321,6 +322,9 @@ local sources = TableCellValueRenderer.cpp TableCellValueRendererUtils.cpp + # user_interface/report + ReportUserInterface.cpp + # user_interface/util UiUtils.cpp diff --git a/src/apps/debugger/controllers/TeamDebugger.cpp b/src/apps/debugger/controllers/TeamDebugger.cpp index 352b7d11f0..e86bfb90f2 100644 --- a/src/apps/debugger/controllers/TeamDebugger.cpp +++ b/src/apps/debugger/controllers/TeamDebugger.cpp @@ -13,6 +13,7 @@ #include #include +#include #include #include @@ -1369,10 +1370,37 @@ TeamDebugger::UserInterfaceQuitRequested(QuitOption quitOption) } +void +TeamDebugger::JobStarted(Job* job) +{ + BString description(job->GetDescription()); + if (!description.IsEmpty()) { + description.Append(B_UTF8_ELLIPSIS); + fUserInterface->NotifyBackgroundWorkStatus(description.String()); + } +} + + void TeamDebugger::JobDone(Job* job) { TRACE_JOBS("TeamDebugger::JobDone(%p)\n", job); + _ResetUserBackgroundStatusIfNeeded(); +} + + +void +TeamDebugger::JobWaitingForInput(Job* job) +{ + LoadImageDebugInfoJob* infoJob = dynamic_cast(job); + + if (infoJob == NULL) + return; + + BMessage message(MSG_DEBUG_INFO_NEEDS_USER_INPUT); + message.AddPointer("job", infoJob); + message.AddPointer("state", infoJob->GetLoadingState()); + PostMessage(&message); } @@ -1381,6 +1409,7 @@ TeamDebugger::JobFailed(Job* job) { TRACE_JOBS("TeamDebugger::JobFailed(%p)\n", job); // TODO: notify user + _ResetUserBackgroundStatusIfNeeded(); } @@ -1390,20 +1419,7 @@ TeamDebugger::JobAborted(Job* job) TRACE_JOBS("TeamDebugger::JobAborted(%p)\n", job); // TODO: For a stack frame source loader thread we should reset the // loading state! Asynchronously due to locking order. -} - - -void -TeamDebugger::ImageDebugInfoJobNeedsUserInput(Job* job, - ImageDebugInfoLoadingState* state) -{ - TRACE_JOBS("TeamDebugger::DebugInfoJobNeedsUserInput(%p, %p)\n", - job, state); - - BMessage message(MSG_DEBUG_INFO_NEEDS_USER_INPUT); - message.AddPointer("job", job); - message.AddPointer("state", state); - PostMessage(&message); + _ResetUserBackgroundStatusIfNeeded(); } @@ -1908,7 +1924,6 @@ TeamDebugger::_HandleImageDebugInfoChanged(image_id imageID) bool handlePostExecSetup = fExecPending && image->Type() == B_APP_IMAGE && state != IMAGE_DEBUG_INFO_LOADING; - // this needs to be done first so that breakpoints are loaded. // otherwise, UpdateImageBreakpoints() won't find the appropriate // UserBreakpoints to create/install instances for. @@ -1922,6 +1937,7 @@ TeamDebugger::_HandleImageDebugInfoChanged(image_id imageID) if (state == IMAGE_DEBUG_INFO_LOADED || state == IMAGE_DEBUG_INFO_UNAVAILABLE) { + // update breakpoints in the image fBreakpointManager->UpdateImageBreakpoints(image); @@ -2486,6 +2502,14 @@ TeamDebugger::_NotifyUser(const char* title, const char* text,...) } +void +TeamDebugger::_ResetUserBackgroundStatusIfNeeded() +{ + if (!fWorker->HasPendingJobs()) + fUserInterface->NotifyBackgroundWorkStatus("Ready."); +} + + // #pragma mark - Listener diff --git a/src/apps/debugger/controllers/TeamDebugger.h b/src/apps/debugger/controllers/TeamDebugger.h index d69e0f53f0..7e645860bf 100644 --- a/src/apps/debugger/controllers/TeamDebugger.h +++ b/src/apps/debugger/controllers/TeamDebugger.h @@ -32,8 +32,7 @@ class WatchpointManager; class TeamDebugger : public BLooper, private UserInterfaceListener, - private JobListener, private ImageDebugInfoJobListener, - private Team::Listener { + private JobListener, private Team::Listener { public: class Listener; @@ -134,13 +133,12 @@ private: QuitOption quitOption); // JobListener + virtual void JobStarted(Job* job); virtual void JobDone(Job* job); + virtual void JobWaitingForInput(Job* job); virtual void JobFailed(Job* job); virtual void JobAborted(Job* job); - virtual void ImageDebugInfoJobNeedsUserInput(Job* job, - ImageDebugInfoLoadingState* state); - // Team::Listener virtual void ThreadStateChanged( const ::Team::ThreadEvent& event); @@ -235,6 +233,11 @@ private: void _NotifyUser(const char* title, const char* text,...); + void _ResetUserBackgroundStatusIfNeeded(); + // updates user interface to + // ready/completed message + // for background work status + private: Listener* fListener; SettingsManager* fSettingsManager; diff --git a/src/apps/debugger/controllers/ThreadHandler.cpp b/src/apps/debugger/controllers/ThreadHandler.cpp index 999a6b0d12..fd5d228de5 100644 --- a/src/apps/debugger/controllers/ThreadHandler.cpp +++ b/src/apps/debugger/controllers/ThreadHandler.cpp @@ -76,14 +76,13 @@ private: ThreadHandler::ThreadHandler(Thread* thread, Worker* worker, - DebuggerInterface* debuggerInterface, - ImageDebugInfoJobListener* listener, + DebuggerInterface* debuggerInterface, JobListener* jobListener, BreakpointManager* breakpointManager) : fThread(thread), fWorker(worker), fDebuggerInterface(debuggerInterface), - fDebugInfoJobListener(listener), + fJobListener(jobListener), fBreakpointManager(breakpointManager), fStepMode(STEP_NONE), fStepStatement(NULL), @@ -113,7 +112,7 @@ void ThreadHandler::Init() { fWorker->ScheduleJob(new(std::nothrow) GetThreadStateJob(fDebuggerInterface, - fThread)); + fThread), fJobListener); fConditionWaitSem = create_sem(0, "breakpoint condition waiter"); } @@ -458,7 +457,8 @@ ThreadHandler::HandleThreadStateChanged() if (fThread->State() == THREAD_STATE_STOPPED && fThread->GetCpuState() == NULL) { fWorker->ScheduleJob( - new(std::nothrow) GetCpuStateJob(fDebuggerInterface, fThread)); + new(std::nothrow) GetCpuStateJob(fDebuggerInterface, fThread), + fJobListener); } } @@ -475,8 +475,8 @@ ThreadHandler::HandleCpuStateChanged() if (fThread->GetCpuState() != NULL && fThread->GetStackTrace() == NULL) { fWorker->ScheduleJob( new(std::nothrow) GetStackTraceJob(fDebuggerInterface, - fDebugInfoJobListener, fDebuggerInterface->GetArchitecture(), - fThread)); + fJobListener, fDebuggerInterface->GetArchitecture(), + fThread), fJobListener); } } @@ -954,7 +954,8 @@ ThreadHandler::_HandleBreakpointConditionIfNeeded(CpuState* cpuState) status_t error = fWorker->ScheduleJob( new(std::nothrow) ExpressionEvaluationJob(fThread->GetTeam(), - fDebuggerInterface, language, expressionInfo, frame, fThread)); + fDebuggerInterface, language, expressionInfo, frame, fThread), + fJobListener); BPrivate::ObjectDeleter deleter( listener); diff --git a/src/apps/debugger/controllers/ThreadHandler.h b/src/apps/debugger/controllers/ThreadHandler.h index 432eac1e9f..85ac8be6be 100644 --- a/src/apps/debugger/controllers/ThreadHandler.h +++ b/src/apps/debugger/controllers/ThreadHandler.h @@ -20,6 +20,7 @@ class BreakpointManager; class DebuggerInterface; class ExpressionResult; class ImageDebugInfoJobListener; +class JobListener; class StackFrame; class Statement; class Worker; @@ -30,7 +31,7 @@ class ThreadHandler : public BReferenceable, private ImageDebugInfoProvider, public: ThreadHandler(Thread* thread, Worker* worker, DebuggerInterface* debuggerInterface, - ImageDebugInfoJobListener* listener, + JobListener* listener, BreakpointManager* breakpointManager); ~ThreadHandler(); @@ -117,7 +118,7 @@ private: Thread* fThread; Worker* fWorker; DebuggerInterface* fDebuggerInterface; - ImageDebugInfoJobListener* fDebugInfoJobListener; + JobListener* fJobListener; BreakpointManager* fBreakpointManager; uint32 fStepMode; Statement* fStepStatement; diff --git a/src/apps/debugger/debug_info/loading_state_handlers/DwarfLoadingStateHandler.cpp b/src/apps/debugger/debug_info/loading_state_handlers/DwarfLoadingStateHandler.cpp index f174bfd11f..9cc89e0cc6 100644 --- a/src/apps/debugger/debug_info/loading_state_handlers/DwarfLoadingStateHandler.cpp +++ b/src/apps/debugger/debug_info/loading_state_handlers/DwarfLoadingStateHandler.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -108,6 +109,10 @@ DwarfLoadingStateHandler::HandleState( BString command; command.SetToFormat("/bin/pkgman install -y %s", requiredPackage.String()); + BString notification; + notification.SetToFormat("Installing package %s" B_UTF8_ELLIPSIS, + requiredPackage.String()); + interface->NotifyBackgroundWorkStatus(notification); int error = system(command.String()); if (interface->IsInteractive()) { if (WIFEXITED(error)) { diff --git a/src/apps/debugger/jobs/GetStackTraceJob.cpp b/src/apps/debugger/jobs/GetStackTraceJob.cpp index d0b28ce167..a44bbdbe36 100644 --- a/src/apps/debugger/jobs/GetStackTraceJob.cpp +++ b/src/apps/debugger/jobs/GetStackTraceJob.cpp @@ -18,12 +18,11 @@ GetStackTraceJob::GetStackTraceJob(DebuggerInterface* debuggerInterface, - ImageDebugInfoJobListener* listener, Architecture* architecture, - Thread* thread) + JobListener* listener, Architecture* architecture, Thread* thread) : fKey(thread, JOB_TYPE_GET_STACK_TRACE), fDebuggerInterface(debuggerInterface), - fDebugInfoJobListener(listener), + fJobListener(listener), fArchitecture(architecture), fThread(thread) { @@ -32,6 +31,9 @@ GetStackTraceJob::GetStackTraceJob(DebuggerInterface* debuggerInterface, fCpuState = fThread->GetCpuState(); if (fCpuState != NULL) fCpuState->AcquireReference(); + + + SetDescription("Retrieving stack trace for thread %" B_PRId32, fThread->ID()); } @@ -84,7 +86,7 @@ GetStackTraceJob::GetImageDebugInfo(Image* image, ImageDebugInfo*& _info) // schedule a job, if not loaded ImageDebugInfo* info; status_t error = LoadImageDebugInfoJob::ScheduleIfNecessary(GetWorker(), - image, fDebugInfoJobListener, &info); + image, fJobListener, &info); if (error != B_OK) return error; diff --git a/src/apps/debugger/jobs/Jobs.h b/src/apps/debugger/jobs/Jobs.h index 1f6b2444ca..e4b3e5bcab 100644 --- a/src/apps/debugger/jobs/Jobs.h +++ b/src/apps/debugger/jobs/Jobs.h @@ -92,19 +92,11 @@ private: }; -class ImageDebugInfoJobListener { -public: - virtual ~ImageDebugInfoJobListener(); - virtual void ImageDebugInfoJobNeedsUserInput(Job* job, - ImageDebugInfoLoadingState* state); -}; - - class GetStackTraceJob : public Job, private ImageDebugInfoProvider { public: GetStackTraceJob( DebuggerInterface* debuggerInterface, - ImageDebugInfoJobListener* listener, + JobListener* jobListener, Architecture* architecture, Thread* thread); virtual ~GetStackTraceJob(); @@ -119,7 +111,7 @@ private: private: SimpleJobKey fKey; DebuggerInterface* fDebuggerInterface; - ImageDebugInfoJobListener* fDebugInfoJobListener; + JobListener* fJobListener; Architecture* fArchitecture; Thread* fThread; CpuState* fCpuState; @@ -128,8 +120,7 @@ private: class LoadImageDebugInfoJob : public Job { public: - LoadImageDebugInfoJob(Image* image, - ImageDebugInfoJobListener* listener); + LoadImageDebugInfoJob(Image* image); virtual ~LoadImageDebugInfoJob(); virtual const JobKey& Key() const; @@ -137,7 +128,7 @@ public: static status_t ScheduleIfNecessary(Worker* worker, Image* image, - ImageDebugInfoJobListener* listener, + JobListener* jobListener, ImageDebugInfo** _imageDebugInfo = NULL); // If already loaded returns a // reference, if desired. If not loaded @@ -146,19 +137,16 @@ public: // if scheduling the job failed, or the // debug info already failed to load // earlier. -private: - void NotifyUserInputListener(); - -private: - typedef BObjectList ListenerList; + ImageDebugInfoLoadingState* + GetLoadingState() + { return &fState; } private: SimpleJobKey fKey; Image* fImage; ImageDebugInfoLoadingState fState; - ImageDebugInfoJobListener* fListener; }; diff --git a/src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp b/src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp index 600055c0f6..d576f08fb2 100644 --- a/src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp +++ b/src/apps/debugger/jobs/LoadImageDebugInfoJob.cpp @@ -14,33 +14,19 @@ #include "Team.h" -// #pragma mark - ImageDebugInfoJobListener - - -ImageDebugInfoJobListener::~ImageDebugInfoJobListener() -{ -} - - -void -ImageDebugInfoJobListener::ImageDebugInfoJobNeedsUserInput(Job* job, - ImageDebugInfoLoadingState* state) -{ -} - - // #pragma mark - LoadImageDebugInfoJob -LoadImageDebugInfoJob::LoadImageDebugInfoJob(Image* image, - ImageDebugInfoJobListener* listener) +LoadImageDebugInfoJob::LoadImageDebugInfoJob(Image* image) : fKey(image, JOB_TYPE_LOAD_IMAGE_DEBUG_INFO), fImage(image), - fState(), - fListener(listener) + fState() { fImage->AcquireReference(); + + SetDescription("Loading debugging information for %s", + fImage->Name().String()); } @@ -74,7 +60,6 @@ LoadImageDebugInfoJob::Do() locker.Lock(); if (fState.UserInputRequired()) { - NotifyUserInputListener(); return WaitForUserInput(); } else if (error == B_OK) { error = fImage->SetImageDebugInfo(debugInfo, IMAGE_DEBUG_INFO_LOADED); @@ -88,7 +73,7 @@ LoadImageDebugInfoJob::Do() /*static*/ status_t LoadImageDebugInfoJob::ScheduleIfNecessary(Worker* worker, Image* image, - ImageDebugInfoJobListener* listener, ImageDebugInfo** _imageDebugInfo) + JobListener* listener, ImageDebugInfo** _imageDebugInfo) { AutoLocker teamLocker(image->GetTeam()); @@ -113,12 +98,12 @@ LoadImageDebugInfoJob::ScheduleIfNecessary(Worker* worker, Image* image, return B_ERROR; // schedule a job - LoadImageDebugInfoJob* job = new(std::nothrow) LoadImageDebugInfoJob(image, - listener); + LoadImageDebugInfoJob* job = new(std::nothrow) LoadImageDebugInfoJob( + image); if (job == NULL) return B_NO_MEMORY; - status_t error = worker->ScheduleJob(job); + status_t error = worker->ScheduleJob(job, listener); if (error != B_OK) { image->SetImageDebugInfo(NULL, IMAGE_DEBUG_INFO_UNAVAILABLE); return error; @@ -130,12 +115,3 @@ LoadImageDebugInfoJob::ScheduleIfNecessary(Worker* worker, Image* image, *_imageDebugInfo = NULL; return B_OK; } - - -void -LoadImageDebugInfoJob::NotifyUserInputListener() -{ - if (fListener != NULL) - fListener->ImageDebugInfoJobNeedsUserInput(this, &fState); -} - diff --git a/src/apps/debugger/jobs/LoadSourceCodeJob.cpp b/src/apps/debugger/jobs/LoadSourceCodeJob.cpp index 402a9ab711..6265a03ff3 100644 --- a/src/apps/debugger/jobs/LoadSourceCodeJob.cpp +++ b/src/apps/debugger/jobs/LoadSourceCodeJob.cpp @@ -30,6 +30,9 @@ LoadSourceCodeJob::LoadSourceCodeJob( fLoadForFunction(loadForFunction) { fFunctionInstance->AcquireReference(); + + SetDescription("Loading source code for function %s", + fFunctionInstance->PrettyName().String()); } diff --git a/src/apps/debugger/user_interface/UserInterface.h b/src/apps/debugger/user_interface/UserInterface.h index b87fedf44f..8783cdfc18 100644 --- a/src/apps/debugger/user_interface/UserInterface.h +++ b/src/apps/debugger/user_interface/UserInterface.h @@ -66,6 +66,15 @@ public: virtual void NotifyUser(const char* title, const char* message, user_notification_type type) = 0; + virtual void NotifyBackgroundWorkStatus(const char* message) + = 0; + // this is used to inform the user about + // background processing work, but doesn't + // otherwise require any form of + // user interaction, i.e. for a status bar + // to indicate that debug information is + // being parsed. + virtual int32 SynchronouslyAskUser(const char* title, const char* message, const char* choice1, const char* choice2, const char* choice3) diff --git a/src/apps/debugger/user_interface/cli/CliContext.cpp b/src/apps/debugger/user_interface/cli/CliContext.cpp index 7c97d2d674..9a66b1a309 100644 --- a/src/apps/debugger/user_interface/cli/CliContext.cpp +++ b/src/apps/debugger/user_interface/cli/CliContext.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2012-2014, Rene Gollent, rene@gollent.com. + * Copyright 2012-2015, Rene Gollent, rene@gollent.com. * Copyright 2012, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ @@ -98,7 +98,6 @@ CliContext::CliContext() fInputLoopWaitingForEvents(0), fEventsOccurred(0), fInputLoopWaiting(false), - fInteractive(true), fTerminating(false), fCurrentThread(NULL), fCurrentStackTrace(NULL), @@ -219,13 +218,6 @@ CliContext::Terminating() } -void -CliContext::SetInteractive(bool interactive) -{ - fInteractive = interactive; -} - - thread_id CliContext::CurrentThreadID() const { @@ -415,6 +407,7 @@ CliContext::ProcessPendingEvents() switch (event->Type()) { case EVENT_QUIT: + case EVENT_DEBUG_REPORT_CHANGED: case EVENT_USER_INTERRUPT: break; case EVENT_THREAD_ADDED: @@ -453,13 +446,6 @@ CliContext::ProcessPendingEvents() if (fExpressionValue != NULL) fExpressionValue->AcquireReference(); break; - case EVENT_DEBUG_REPORT_CHANGED: - if (!IsInteractive()) { - Terminating(); - QuitSession(true); - } - break; - } } } diff --git a/src/apps/debugger/user_interface/cli/CliContext.h b/src/apps/debugger/user_interface/cli/CliContext.h index 8232c783c0..66f35e22d8 100644 --- a/src/apps/debugger/user_interface/cli/CliContext.h +++ b/src/apps/debugger/user_interface/cli/CliContext.h @@ -1,6 +1,6 @@ /* * Copyright 2012, Ingo Weinhold, ingo_weinhold@gmx.de. - * Copyright 2014, Rene Gollent, rene@gollent.com. + * Copyright 2014-2015, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ #ifndef CLI_CONTEXT_H @@ -57,9 +57,6 @@ public: bool IsTerminating() const { return fTerminating; } - bool IsInteractive() const { return fInteractive; } - void SetInteractive(bool interactive); - // service methods for the input loop thread follow Team* GetTeam() const { return fTeam; } @@ -150,7 +147,6 @@ private: uint32 fInputLoopWaitingForEvents; uint32 fEventsOccurred; bool fInputLoopWaiting; - bool fInteractive; volatile bool fTerminating; Thread* fCurrentThread; diff --git a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp index dfbe7c598d..faecbe7601 100644 --- a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp +++ b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2011-2014, Rene Gollent, rene@gollent.com. + * Copyright 2011-2015, Rene Gollent, rene@gollent.com. * Copyright 2012, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ @@ -93,13 +93,9 @@ private: // #pragma mark - CommandLineUserInterface -CommandLineUserInterface::CommandLineUserInterface(bool saveReport, - const char* reportPath, thread_id reportTargetThread) +CommandLineUserInterface::CommandLineUserInterface() : fCommands(20, true), - fReportPath(reportPath), - fSaveReport(saveReport), - fReportTargetThread(reportTargetThread), fShowSemaphore(-1), fShown(false), fTerminating(false) @@ -128,8 +124,6 @@ CommandLineUserInterface::Init(Team* team, UserInterfaceListener* listener) if (error != B_OK) return error; - fContext.SetInteractive(!fSaveReport); - error = _RegisterCommands(); if (error != B_OK) return error; @@ -138,8 +132,6 @@ CommandLineUserInterface::Init(Team* team, UserInterfaceListener* listener) if (fShowSemaphore < 0) return fShowSemaphore; - team->AddListener(this); - return B_OK; } @@ -176,9 +168,7 @@ CommandLineUserInterface::Terminate() bool CommandLineUserInterface::IsInteractive() const { - // if we were invoked solely for the purpose of saving a crash report, - // then we're not taking user input into account. - return !fSaveReport; + return true; } @@ -203,6 +193,12 @@ CommandLineUserInterface::NotifyUser(const char* title, const char* message, } +void +CommandLineUserInterface::NotifyBackgroundWorkStatus(const char* message) +{ +} + + int32 CommandLineUserInterface::SynchronouslyAskUser(const char* title, const char* message, const char* choice1, const char* choice2, @@ -231,43 +227,12 @@ CommandLineUserInterface::Run() if (error != B_OK) return; - if (fSaveReport) { - ArgumentVector args; - char buffer[256]; - const char* parseErrorLocation; - if (_ReportTargetThreadStopNeeded()) { - snprintf(buffer, sizeof(buffer), "stop %" B_PRId32, - fReportTargetThread); - args.Parse(buffer, &parseErrorLocation); - _ExecuteCommand(args.ArgumentCount(), args.Arguments()); - } else - _SubmitSaveReport(); - } - _InputLoop(); // Release the Show() semaphore to signal Terminate(). release_sem(fShowSemaphore); } -void -CommandLineUserInterface::ThreadStateChanged(const Team::ThreadEvent& event) -{ - if (fSaveReport) { - Thread* thread = event.GetThread(); - // If we were asked to attach/report on a specific thread - // rather than a team, and said thread was still - // running, when we attached, we need to wait for its corresponding - // stop state before generating a report, else we might not get its - // stack trace. - if (thread->ID() == fReportTargetThread - && thread->State() == THREAD_STATE_STOPPED) { - _SubmitSaveReport(); - } - } -} - - /*static*/ status_t CommandLineUserInterface::_InputLoopEntry(void* data) { @@ -467,32 +432,3 @@ CommandLineUserInterface::_CompareCommandEntries(const CommandEntry* command1, { return ::Compare(command1->Name(), command2->Name()); } - - -bool -CommandLineUserInterface::_ReportTargetThreadStopNeeded() const -{ - if (fReportTargetThread < 0) - return false; - - Team* team = fContext.GetTeam(); - AutoLocker teamLocker(team); - Thread* thread = team->ThreadByID(fReportTargetThread); - if (thread == NULL) - return false; - - return thread->State() != THREAD_STATE_STOPPED; -} - - -void -CommandLineUserInterface::_SubmitSaveReport() -{ - ArgumentVector args; - char buffer[256]; - const char* parseErrorLocation; - snprintf(buffer, sizeof(buffer), "save-report %s", - fReportPath != NULL ? fReportPath : ""); - args.Parse(buffer, &parseErrorLocation); - _ExecuteCommand(args.ArgumentCount(), args.Arguments()); -} diff --git a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.h b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.h index 8eec3a3c87..e908e2dcd1 100644 --- a/src/apps/debugger/user_interface/cli/CommandLineUserInterface.h +++ b/src/apps/debugger/user_interface/cli/CommandLineUserInterface.h @@ -1,5 +1,5 @@ /* - * Copyright 2011-2014, Rene Gollent, rene@gollent.com. + * Copyright 2011-2015, Rene Gollent, rene@gollent.com. * Copyright 2012, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ @@ -17,12 +17,9 @@ class CliCommand; -class CommandLineUserInterface : public UserInterface, - public ::Team::Listener { +class CommandLineUserInterface : public UserInterface { public: - CommandLineUserInterface(bool saveReport, - const char* reportPath, - thread_id reportTargetThread); + CommandLineUserInterface(); virtual ~CommandLineUserInterface(); virtual const char* ID() const; @@ -42,6 +39,8 @@ public: virtual void NotifyUser(const char* title, const char* message, user_notification_type type); + virtual void NotifyBackgroundWorkStatus( + const char* message); virtual int32 SynchronouslyAskUser(const char* title, const char* message, const char* choice1, const char* choice2, const char* choice3); @@ -52,10 +51,6 @@ public: // everything has been set up. Enters the // input loop. - // Team::Listener - virtual void ThreadStateChanged( - const Team::ThreadEvent& event); - private: struct CommandEntry; typedef BObjectList CommandList; @@ -80,15 +75,9 @@ private: const CommandEntry* command1, const CommandEntry* command2); - bool _ReportTargetThreadStopNeeded() const; - void _SubmitSaveReport(); - private: CliContext fContext; CommandList fCommands; - const char* fReportPath; - bool fSaveReport; - thread_id fReportTargetThread; sem_id fShowSemaphore; bool fShown; volatile bool fTerminating; diff --git a/src/apps/debugger/user_interface/gui/GraphicalUserInterface.cpp b/src/apps/debugger/user_interface/gui/GraphicalUserInterface.cpp index 8daac7f774..68a9e16134 100644 --- a/src/apps/debugger/user_interface/gui/GraphicalUserInterface.cpp +++ b/src/apps/debugger/user_interface/gui/GraphicalUserInterface.cpp @@ -248,6 +248,13 @@ GraphicalUserInterface::NotifyUser(const char* title, const char* message, } +void +GraphicalUserInterface::NotifyBackgroundWorkStatus(const char* message) +{ + fTeamWindow->DisplayBackgroundStatus(message); +} + + int32 GraphicalUserInterface::SynchronouslyAskUser(const char* title, const char* message, const char* choice1, const char* choice2, diff --git a/src/apps/debugger/user_interface/gui/GraphicalUserInterface.h b/src/apps/debugger/user_interface/gui/GraphicalUserInterface.h index 59ec0292a3..c86436f63c 100644 --- a/src/apps/debugger/user_interface/gui/GraphicalUserInterface.h +++ b/src/apps/debugger/user_interface/gui/GraphicalUserInterface.h @@ -1,6 +1,6 @@ /* * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. - * Copyright 2014, Rene Gollent, rene@gollent.com. + * Copyright 2014-2015, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ #ifndef GRAPHICAL_USER_INTERFACE_H @@ -38,6 +38,8 @@ public: virtual void NotifyUser(const char* title, const char* message, user_notification_type type); + virtual void NotifyBackgroundWorkStatus( + const char* message); virtual int32 SynchronouslyAskUser(const char* title, const char* message, const char* choice1, const char* choice2, const char* choice3); diff --git a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp index 4b7f15ed8b..8b6ce8757a 100644 --- a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp +++ b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.cpp @@ -74,7 +74,8 @@ enum { MSG_LOCATE_SOURCE_IF_NEEDED = 'lsin', MSG_SOURCE_ENTRY_QUERY_COMPLETE = 'seqc', MSG_CLEAR_STACK_TRACE = 'clst', - MSG_HANDLE_LOAD_SETTINGS = 'hlst' + MSG_HANDLE_LOAD_SETTINGS = 'hlst', + MSG_UPDATE_STATUS_BAR = 'upsb' }; @@ -133,6 +134,7 @@ TeamWindow::TeamWindow(::Team* team, UserInterfaceListener* listener) fStepOutButton(NULL), fMenuBar(NULL), fSourcePathView(NULL), + fStatusBarView(NULL), fConsoleOutputView(NULL), fFunctionSplitView(NULL), fSourceSplitView(NULL), @@ -525,6 +527,13 @@ TeamWindow::MessageReceived(BMessage* message) _LoadSettings(settings); break; } + case MSG_UPDATE_STATUS_BAR: + { + const char* messageText; + if (message->FindString("message", &messageText) == B_OK) + fStatusBarView->SetText(messageText); + break; + } case MSG_TEAM_RENAMED: { _UpdateTitle(); @@ -725,6 +734,15 @@ TeamWindow::SaveSettings(GuiTeamUiSettings* settings) } +void +TeamWindow::DisplayBackgroundStatus(const char* message) +{ + BMessage updateMessage(MSG_UPDATE_STATUS_BAR); + updateMessage.AddString("message", message); + PostMessage(&updateMessage); +} + + void TeamWindow::ThreadSelectionChanged(::Thread* thread) { @@ -995,7 +1013,11 @@ TeamWindow::_Init() .SetInsets(0.0) .Add(fConsoleOutputView = ConsoleOutputView::Create()) .End() - .End(); + .End() + .Add(fStatusBarView = new BStringView("status", "Ready.")); + + fStatusBarView->SetExplicitMinSize(BSize(50.0, B_SIZE_UNSET)); + fStatusBarView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); // add source view sourceScrollView->SetTarget(fSourceView = SourceView::Create(fTeam, this)); diff --git a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.h b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.h index f9be9461df..825ecf0d03 100644 --- a/src/apps/debugger/user_interface/gui/team_window/TeamWindow.h +++ b/src/apps/debugger/user_interface/gui/team_window/TeamWindow.h @@ -71,6 +71,8 @@ public: status_t SaveSettings( GuiTeamUiSettings* settings); + void DisplayBackgroundStatus(const char* message); + private: enum ActiveSourceObject { @@ -228,6 +230,7 @@ private: BButton* fStepOutButton; BMenuBar* fMenuBar; BStringView* fSourcePathView; + BStringView* fStatusBarView; ConsoleOutputView* fConsoleOutputView; BSplitView* fFunctionSplitView; BSplitView* fSourceSplitView; diff --git a/src/apps/debugger/user_interface/report/ReportUserInterface.cpp b/src/apps/debugger/user_interface/report/ReportUserInterface.cpp new file mode 100644 index 0000000000..57fcdf7534 --- /dev/null +++ b/src/apps/debugger/user_interface/report/ReportUserInterface.cpp @@ -0,0 +1,233 @@ +/* + * Copyright 2015, Rene Gollent, rene@gollent.com. + * Distributed under the terms of the MIT License. + */ + + +#include "ReportUserInterface.h" + +#include + +#include +#include +#include + +#include + +#include "MessageCodes.h" +#include "UiUtils.h" + + +ReportUserInterface::ReportUserInterface(thread_id targetThread, + const char* reportPath) + : + fTeam(NULL), + fListener(NULL), + fTargetThread(targetThread), + fReportPath(reportPath), + fShowSemaphore(-1), + fReportSemaphore(-1), + fShown(false), + fTerminating(false) +{ +} + + +ReportUserInterface::~ReportUserInterface() +{ + if (fShowSemaphore >= 0) + delete_sem(fShowSemaphore); + + fTeam->RemoveListener(this); +} + + +const char* +ReportUserInterface::ID() const +{ + return "ReportUserInterface"; +} + + +status_t +ReportUserInterface::Init(Team* team, UserInterfaceListener* listener) +{ + fShowSemaphore = create_sem(0, "show report"); + if (fShowSemaphore < 0) + return fShowSemaphore; + + fReportSemaphore = create_sem(0, "report generator wait"); + if (fReportSemaphore < 0) + return fReportSemaphore; + + fTeam = team; + fListener = listener; + + fTeam->AddListener(this); + + return B_OK; +} + + +void +ReportUserInterface::Show() +{ + fShown = true; + release_sem(fShowSemaphore); +} + + +void +ReportUserInterface::Terminate() +{ + fTerminating = true; +} + + +bool +ReportUserInterface::IsInteractive() const +{ + return false; +} + + +status_t +ReportUserInterface::LoadSettings(const TeamUiSettings* settings) +{ + return B_OK; +} + + +status_t +ReportUserInterface::SaveSettings(TeamUiSettings*& settings) const +{ + return B_OK; +} + + +void +ReportUserInterface::NotifyUser(const char* title, const char* message, + user_notification_type type) +{ +} + + +void +ReportUserInterface::NotifyBackgroundWorkStatus(const char* message) +{ +} + + +int32 +ReportUserInterface::SynchronouslyAskUser(const char* title, + const char* message, const char* choice1, const char* choice2, + const char* choice3) +{ + return -1; +} + + +status_t +ReportUserInterface::SynchronouslyAskUserForFile(entry_ref* _ref) +{ + return B_UNSUPPORTED; +} + + +void +ReportUserInterface::Run() +{ + // Wait for the Show() semaphore to be released. + status_t error; + do { + error = acquire_sem(fShowSemaphore); + } while (error == B_INTERRUPTED); + + if (error != B_OK) + return; + + bool waitNeeded = false; + if (fTargetThread > 0) { + AutoLocker< ::Team> teamLocker(fTeam); + ::Thread* thread = fTeam->ThreadByID(fTargetThread); + if (thread == NULL) + waitNeeded = true; + else if (thread->State() != THREAD_STATE_STOPPED) { + waitNeeded = true; + fListener->ThreadActionRequested(fTargetThread, MSG_THREAD_STOP); + } + } + + if (waitNeeded) { + do { + error = acquire_sem(fShowSemaphore); + } while (error == B_INTERRUPTED); + + if (error != B_OK) + return; + } + + entry_ref ref; + if (fReportPath != NULL && fReportPath[0] == '/') { + error = get_ref_for_path(fReportPath, &ref); + } else { + char filename[B_FILE_NAME_LENGTH]; + if (fReportPath != NULL) + strlcpy(filename, fReportPath, sizeof(filename)); + else + UiUtils::ReportNameForTeam(fTeam, filename, sizeof(filename)); + + BPath path; + error = find_directory(B_DESKTOP_DIRECTORY, &path); + if (error == B_OK) + error = path.Append(filename); + if (error == B_OK) + error = get_ref_for_path(path.Path(), &ref); + } + + if (error != B_OK) + printf("Unable to get ref for report path %s\n", strerror(error)); + else { + fListener->DebugReportRequested(&ref); + + do { + error = acquire_sem(fReportSemaphore); + } while (error == B_INTERRUPTED); + } + + fListener->UserInterfaceQuitRequested( + UserInterfaceListener::QUIT_OPTION_ASK_KILL_TEAM); +} + + +void +ReportUserInterface::ThreadAdded(const Team::ThreadEvent& event) +{ + ::Thread* thread = event.GetThread(); + if (thread->ID() != fTargetThread) + return; + + if (thread->State() != THREAD_STATE_STOPPED) + fListener->ThreadActionRequested(thread->ID(), MSG_THREAD_STOP); + else + release_sem(fShowSemaphore); +} + + +void +ReportUserInterface::ThreadStateChanged(const Team::ThreadEvent& event) +{ + ::Thread* thread = event.GetThread(); + if (thread->ID() != fTargetThread) + return; + else if (thread->State() == THREAD_STATE_STOPPED) + release_sem(fShowSemaphore); +} + + +void +ReportUserInterface::DebugReportChanged(const Team::DebugReportEvent& event) +{ + printf("Debug report saved to %s\n", event.GetReportPath()); + release_sem(fReportSemaphore); +} diff --git a/src/apps/debugger/user_interface/report/ReportUserInterface.h b/src/apps/debugger/user_interface/report/ReportUserInterface.h new file mode 100644 index 0000000000..8b06d30e3a --- /dev/null +++ b/src/apps/debugger/user_interface/report/ReportUserInterface.h @@ -0,0 +1,66 @@ +/* + * Copyright 2015, Rene Gollent, rene@gollent.com. + * Distributed under the terms of the MIT License. + */ +#ifndef REPORT_USER_INTERFACE_H +#define REPORT_USER_INTERFACE_H + + +#include +#include + +#include "UserInterface.h" +#include "Team.h" + + +class ReportUserInterface : public UserInterface, + private Team::Listener { +public: + ReportUserInterface(thread_id targetThread, + const char* reportPath); + virtual ~ReportUserInterface(); + + virtual const char* ID() const; + + virtual status_t Init(Team* team, + UserInterfaceListener* listener); + virtual void Show(); + virtual void Terminate(); + + virtual bool IsInteractive() const; + + virtual status_t LoadSettings(const TeamUiSettings* settings); + virtual status_t SaveSettings(TeamUiSettings*& settings) const; + + virtual void NotifyUser(const char* title, + const char* message, + user_notification_type type); + virtual void NotifyBackgroundWorkStatus( + const char* message); + virtual int32 SynchronouslyAskUser(const char* title, + const char* message, const char* choice1, + const char* choice2, const char* choice3); + virtual status_t SynchronouslyAskUserForFile(entry_ref* _ref); + + void Run(); + + // Team::Listener + virtual void ThreadAdded(const Team::ThreadEvent& event); + virtual void ThreadStateChanged( + const Team::ThreadEvent& event); + virtual void DebugReportChanged( + const Team::DebugReportEvent& event); + +private: + ::Team* fTeam; + UserInterfaceListener* fListener; + thread_id fTargetThread; + const char* fReportPath; + sem_id fShowSemaphore; + sem_id fReportSemaphore; + bool fShown; + volatile bool fTerminating; +}; + + +#endif // REPORT_USER_INTERFACE_H diff --git a/src/apps/debugger/util/Worker.cpp b/src/apps/debugger/util/Worker.cpp index 0a3133cbe5..0a184bdfbc 100644 --- a/src/apps/debugger/util/Worker.cpp +++ b/src/apps/debugger/util/Worker.cpp @@ -70,12 +70,24 @@ JobListener::~JobListener() } +void +JobListener::JobStarted(Job* job) +{ +} + + void JobListener::JobDone(Job* job) { } +void +JobListener::JobWaitingForInput(Job* job) +{ +} + + void JobListener::JobFailed(Job* job) { @@ -121,6 +133,15 @@ Job::WaitForUserInput() } +void +Job::SetDescription(const char* format, ...) +{ + va_list args; + va_start(args, format); + fDescription.SetToFormatVarArgs(format, args); +} + + void Job::SetWorker(Worker* worker) { @@ -179,6 +200,13 @@ Job::NotifyListeners() for (int32 i = count - 1; i >= 0; i--) { JobListener* listener = fListeners.ItemAt(i); switch (fState) { + case JOB_STATE_ACTIVE: + listener->JobStarted(this); + break; + case JOB_STATE_WAITING: + if (fWaitStatus == JOB_USER_INPUT_WAITING) + listener->JobWaitingForInput(this); + break; case JOB_STATE_SUCCEEDED: listener->JobDone(this); break; @@ -342,6 +370,14 @@ Worker::ResumeJob(Job* job) } +bool +Worker::HasPendingJobs() +{ + AutoLocker locker(this); + return !fJobs.IsEmpty(); +} + + status_t Worker::AddListener(const JobKey& key, JobListener* listener) { @@ -395,6 +431,7 @@ Worker::WaitForUserInput(Job* waitingJob) return B_INTERRUPTED; waitingJob->SetWaitStatus(JOB_USER_INPUT_WAITING); + waitingJob->NotifyListeners(); fSuspendedJobs.Add(waitingJob); return B_OK; @@ -451,6 +488,7 @@ Worker::_ProcessJobs() // process the next job if (Job* job = fUnscheduledJobs.RemoveHead()) { job->SetState(JOB_STATE_ACTIVE); + job->NotifyListeners(); locker.Unlock(); status_t error = job->Do(); diff --git a/src/apps/debugger/util/Worker.h b/src/apps/debugger/util/Worker.h index f0b6b176c8..d27abe7a07 100644 --- a/src/apps/debugger/util/Worker.h +++ b/src/apps/debugger/util/Worker.h @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -69,7 +70,9 @@ class JobListener { public: virtual ~JobListener(); + virtual void JobStarted(Job* job); virtual void JobDone(Job* job); + virtual void JobWaitingForInput(Job* job); virtual void JobFailed(Job* job); virtual void JobAborted(Job* job); }; @@ -89,9 +92,13 @@ public: Worker* GetWorker() const { return fWorker; } job_state State() const { return fState; } + const BString& GetDescription() const + { return fDescription; } + protected: job_wait_status WaitFor(const JobKey& key); status_t WaitForUserInput(); + void SetDescription(const char* format, ...); private: friend class Worker; @@ -122,6 +129,7 @@ private: JobList fDependentJobs; job_wait_status fWaitStatus; ListenerList fListeners; + BString fDescription; public: Job* fNext; @@ -149,6 +157,8 @@ public: // only valid for jobs that are // suspended pending user input + bool HasPendingJobs(); + status_t AddListener(const JobKey& key, JobListener* listener); void RemoveListener(const JobKey& key, diff --git a/src/apps/deskbar/PreferencesWindow.cpp b/src/apps/deskbar/PreferencesWindow.cpp index 480d7e2196..c3be5d630b 100644 --- a/src/apps/deskbar/PreferencesWindow.cpp +++ b/src/apps/deskbar/PreferencesWindow.cpp @@ -10,8 +10,6 @@ #include "PreferencesWindow.h" -#include - #include #include #include @@ -31,7 +29,7 @@ #include #include #include -#include +#include #include #include "BarApp.h" @@ -66,11 +64,11 @@ PreferencesWindow::PreferencesWindow(BRect frame) fMenuRecentFolders = new BCheckBox(B_TRANSLATE("Recent folders:"), new BMessage(kUpdateRecentCounts)); - fMenuRecentDocumentCount = new BTextControl(NULL, NULL, + fMenuRecentDocumentCount = new BSpinner("recent documents", NULL, new BMessage(kUpdateRecentCounts)); - fMenuRecentApplicationCount = new BTextControl(NULL, NULL, + fMenuRecentApplicationCount = new BSpinner("recent applications", NULL, new BMessage(kUpdateRecentCounts)); - fMenuRecentFolderCount = new BTextControl(NULL, NULL, + fMenuRecentFolderCount = new BSpinner("recent folders", NULL, new BMessage(kUpdateRecentCounts)); // Applications controls @@ -103,46 +101,20 @@ PreferencesWindow::PreferencesWindow(BRect frame) new BMessage(kAutoHide)); // Menu settings - BTextView* docTextView = fMenuRecentDocumentCount->TextView(); - BTextView* appTextView = fMenuRecentApplicationCount->TextView(); - BTextView* folderTextView = fMenuRecentFolderCount->TextView(); - - for (int32 i = 0; i < 256; i++) { - if (!isdigit(i)) { - docTextView->DisallowChar(i); - appTextView->DisallowChar(i); - folderTextView->DisallowChar(i); - } - } - - docTextView->SetMaxBytes(4); - appTextView->SetMaxBytes(4); - folderTextView->SetMaxBytes(4); - - int32 docCount = fSettings.recentDocsCount; - int32 appCount = fSettings.recentAppsCount; - int32 folderCount = fSettings.recentFoldersCount; - fMenuRecentDocuments->SetValue(fSettings.recentDocsEnabled); fMenuRecentDocumentCount->SetEnabled(fSettings.recentDocsEnabled); + fMenuRecentDocumentCount->SetRange(0, 50); + fMenuRecentDocumentCount->SetValue(fSettings.recentDocsCount); fMenuRecentApplications->SetValue(fSettings.recentAppsEnabled); fMenuRecentApplicationCount->SetEnabled(fSettings.recentAppsEnabled); + fMenuRecentApplicationCount->SetRange(0, 50); + fMenuRecentApplicationCount->SetValue(fSettings.recentAppsCount); fMenuRecentFolders->SetValue(fSettings.recentFoldersEnabled); fMenuRecentFolderCount->SetEnabled(fSettings.recentFoldersEnabled); - - BString docString; - BString appString; - BString folderString; - - docString << docCount; - appString << appCount; - folderString << folderCount; - - fMenuRecentDocumentCount->SetText(docString.String()); - fMenuRecentApplicationCount->SetText(appString.String()); - fMenuRecentFolderCount->SetText(folderString.String()); + fMenuRecentFolderCount->SetRange(0, 50); + fMenuRecentFolderCount->SetValue(fSettings.recentFoldersCount); // Applications settings fAppsSort->SetValue(fSettings.sortRunningApps); @@ -516,21 +488,15 @@ PreferencesWindow::_UpdatePreferences(desk_settings* settings) updateRecentCounts = true; } if (current->recentDocsCount != settings->recentDocsCount) { - BString docString; - docString << settings->recentDocsCount; - fMenuRecentDocumentCount->SetText(docString.String()); + fMenuRecentDocumentCount->SetValue(settings->recentDocsCount); updateRecentCounts = true; } if (current->recentFoldersCount != settings->recentFoldersCount) { - BString folderString; - folderString << settings->recentFoldersCount; - fMenuRecentFolderCount->SetText(folderString.String()); + fMenuRecentFolderCount->SetValue(settings->recentFoldersCount); updateRecentCounts = true; } if (current->recentAppsCount != settings->recentAppsCount) { - BString appString; - appString << settings->recentAppsCount; - fMenuRecentApplicationCount->SetText(appString.String()); + fMenuRecentApplicationCount->SetValue(settings->recentAppsCount); updateRecentCounts = true; } if (current->alwaysOnTop != settings->alwaysOnTop) { @@ -556,13 +522,9 @@ PreferencesWindow::_UpdateRecentCounts() { BMessage message(kUpdateRecentCounts); - int32 docCount = atoi(fMenuRecentDocumentCount->Text()); - int32 appCount = atoi(fMenuRecentApplicationCount->Text()); - int32 folderCount = atoi(fMenuRecentFolderCount->Text()); - - message.AddInt32("documents", max_c(0, docCount)); - message.AddInt32("applications", max_c(0, appCount)); - message.AddInt32("folders", max_c(0, folderCount)); + message.AddInt32("documents", fMenuRecentDocumentCount->Value()); + message.AddInt32("applications", fMenuRecentApplicationCount->Value()); + message.AddInt32("folders", fMenuRecentFolderCount->Value()); message.AddBool("documentsEnabled", fMenuRecentDocuments->Value()); message.AddBool("applicationsEnabled", fMenuRecentApplications->Value()); diff --git a/src/apps/deskbar/PreferencesWindow.h b/src/apps/deskbar/PreferencesWindow.h index 4a8beaea96..6daf790c8e 100644 --- a/src/apps/deskbar/PreferencesWindow.h +++ b/src/apps/deskbar/PreferencesWindow.h @@ -34,7 +34,7 @@ class BFile; class BMessage; class BRadioButton; class BSlider; -class BTextControl; +class BSpinner; class PreferencesWindow : public BWindow { @@ -67,9 +67,9 @@ private: BCheckBox* fMenuRecentApplications; BCheckBox* fMenuRecentFolders; - BTextControl* fMenuRecentDocumentCount; - BTextControl* fMenuRecentApplicationCount; - BTextControl* fMenuRecentFolderCount; + BSpinner* fMenuRecentDocumentCount; + BSpinner* fMenuRecentApplicationCount; + BSpinner* fMenuRecentFolderCount; BCheckBox* fAppsSort; BCheckBox* fAppsSortTrackerFirst; diff --git a/src/apps/haikudepot/ui/PackageContentsView.cpp b/src/apps/haikudepot/ui/PackageContentsView.cpp index 6e6b08cc52..17f0384325 100644 --- a/src/apps/haikudepot/ui/PackageContentsView.cpp +++ b/src/apps/haikudepot/ui/PackageContentsView.cpp @@ -239,7 +239,8 @@ private: PackageContentsView::PackageContentsView(const char* name) : BView("package_contents_view", B_WILL_DRAW), - fPackageLock("package contents populator lock") + fPackageLock("package contents populator lock"), + fLastPackageState(NONE) { fContentListView = new BOutlineListView("content list view", B_SINGLE_SELECTION_LIST); @@ -283,8 +284,14 @@ PackageContentsView::AllAttached() void PackageContentsView::SetPackage(const PackageInfoRef& package) { - if (fPackage == package) + // When getting a ref to the same package, don't return when the + // package state has changed, since in that case, we may now be able + // to read contents where we previously could not. (For example, the + // package has been installed.) + if (fPackage == package + && (package.Get() == NULL || package->State() == fLastPackageState)) { return; + } // printf("PackageContentsView::SetPackage(%s)\n", // package.Get() != NULL ? package->Name().String() : "NULL"); @@ -294,6 +301,7 @@ PackageContentsView::SetPackage(const PackageInfoRef& package) { BAutolock lock(&fPackageLock); fPackage = package; + fLastPackageState = package.Get() != NULL ? package->State() : NONE; } release_sem_etc(fContentPopulatorSem, 1, 0); } diff --git a/src/apps/haikudepot/ui/PackageContentsView.h b/src/apps/haikudepot/ui/PackageContentsView.h index 2cd58a2f09..136a53c459 100644 --- a/src/apps/haikudepot/ui/PackageContentsView.h +++ b/src/apps/haikudepot/ui/PackageContentsView.h @@ -39,6 +39,7 @@ private: sem_id fContentPopulatorSem; BLocker fPackageLock; PackageInfoRef fPackage; + PackageState fLastPackageState; }; #endif // PACKAGE_CONTENTS_VIEW_H diff --git a/src/apps/haikudepot/ui/PackageInfoView.cpp b/src/apps/haikudepot/ui/PackageInfoView.cpp index 5d95ce4387..03178c5e94 100644 --- a/src/apps/haikudepot/ui/PackageInfoView.cpp +++ b/src/apps/haikudepot/ui/PackageInfoView.cpp @@ -1426,6 +1426,7 @@ PackageInfoView::MessageReceived(BMessage* message) } if ((changes & PKG_CHANGED_STATE) != 0) { + fPagesView->SetPackage(package, false); fPackageActionView->SetPackage(*package.Get()); } diff --git a/src/apps/mail/ComboBox.cpp b/src/apps/mail/ComboBox.cpp index 68abfcd741..0424ac066c 100644 --- a/src/apps/mail/ComboBox.cpp +++ b/src/apps/mail/ComboBox.cpp @@ -1253,6 +1253,13 @@ BComboBox::Text() const } +int32 +BComboBox::TextLength() const +{ + return fText->TextLength(); +} + + BTextView * BComboBox::TextView() { diff --git a/src/apps/mail/ComboBox.h b/src/apps/mail/ComboBox.h index 35f6321c7f..1ab8886c3c 100644 --- a/src/apps/mail/ComboBox.h +++ b/src/apps/mail/ComboBox.h @@ -150,6 +150,7 @@ public: virtual void SetLabel(const char *text); virtual void SetText(const char *text); const char *Text() const; + int32 TextLength() const; BTextView *TextView(); virtual void SetDivider(float dividing_line); float Divider() const; diff --git a/src/apps/mail/MailWindow.cpp b/src/apps/mail/MailWindow.cpp index 7649ccf4a1..5453023210 100644 --- a/src/apps/mail/MailWindow.cpp +++ b/src/apps/mail/MailWindow.cpp @@ -93,7 +93,7 @@ of their respective holders. All rights reserved. using namespace BPrivate; -const char *kUndoStrings[] = { +const char* kUndoStrings[] = { "Undo", "Undo typing", "Undo cut", @@ -102,7 +102,7 @@ const char *kUndoStrings[] = { "Undo drop" }; -const char *kRedoStrings[] = { +const char* kRedoStrings[] = { "Redo", "Redo typing", "Redo cut", @@ -113,7 +113,7 @@ const char *kRedoStrings[] = { // Text for both the main menu and the pop-up menu. -static const char *kSpamMenuItemTextArray[] = { +static const char* kSpamMenuItemTextArray[] = { "Mark as spam and move to trash", // M_TRAIN_SPAM_AND_DELETE "Mark as spam", // M_TRAIN_SPAM "Unmark this message", // M_UNTRAIN @@ -122,12 +122,12 @@ static const char *kSpamMenuItemTextArray[] = { static const uint32 kMsgQuitAndKeepAllStatus = 'Casm'; -static const char *kQueriesDirectory = "mail/queries"; -static const char *kAttrQueryInitialMode = "_trk/qryinitmode"; +static const char* kQueriesDirectory = "mail/queries"; +static const char* kAttrQueryInitialMode = "_trk/qryinitmode"; // taken from src/kits/tracker/Attributes.h -static const char *kAttrQueryInitialString = "_trk/qryinitstr"; -static const char *kAttrQueryInitialNumAttrs = "_trk/qryinitnumattrs"; -static const char *kAttrQueryInitialAttrs = "_trk/qryinitattrs"; +static const char* kAttrQueryInitialString = "_trk/qryinitstr"; +static const char* kAttrQueryInitialNumAttrs = "_trk/qryinitnumattrs"; +static const char* kAttrQueryInitialAttrs = "_trk/qryinitattrs"; static const uint32 kAttributeItemMain = 'Fatr'; // taken from src/kits/tracker/FindPanel.h static const uint32 kByNameItem = 'Fbyn'; @@ -138,11 +138,30 @@ static const uint32 kByForumlaItem = 'Fbyq'; // taken from src/kits/tracker/FindPanel.h +// static bitmap cache +BObjectList TMailWindow::sBitmapCache; +BLocker TMailWindow::sBitmapCacheLock; + // static list for tracking of Windows BList TMailWindow::sWindowList; BLocker TMailWindow::sWindowListLock; +class HorizontalLine : public BView { +public: + HorizontalLine(BRect rect) + : + BView (rect, NULL, B_FOLLOW_ALL, B_WILL_DRAW) + { + } + + virtual void Draw(BRect rect) + { + FillRect(rect, B_SOLID_HIGH); + } +}; + + // #pragma mark - @@ -216,8 +235,7 @@ TMailWindow::TMailWindow(BRect rect, const char* title, TMailApp* app, // few seconds. if (!fIncoming) { - QueryMenu *queryMenu; - queryMenu = new QueryMenu(B_TRANSLATE("Open draft"), false); + QueryMenu* queryMenu = new QueryMenu(B_TRANSLATE("Open draft"), false); queryMenu->SetTargetForItems(be_app); queryMenu->SetPredicate("MAIL:draft==1"); @@ -377,7 +395,7 @@ TMailWindow::TMailWindow(BRect rect, const char* title, TMailApp* app, menu = new BMenu(B_TRANSLATE("Message")); if (!resending && fIncoming) { - BMenuItem *menuItem; + BMenuItem* menuItem; menu->AddItem(new BMenuItem(B_TRANSLATE("Reply"), new BMessage(M_REPLY),'R')); menu->AddItem(new BMenuItem(B_TRANSLATE("Reply to sender"), @@ -492,7 +510,7 @@ TMailWindow::TMailWindow(BRect rect, const char* title, TMailApp* app, r = Frame(); r.OffsetTo(0, 0); r.top = fHeaderView->Frame().bottom - 1; - fContentView = new TContentView(r, fIncoming, const_cast(font), + fContentView = new TContentView(r, fIncoming, const_cast(font), false, fApp->ColoredQuotes()); // TContentView needs to be properly const, for now cast away constness @@ -554,20 +572,17 @@ TMailWindow::TMailWindow(BRect rect, const char* title, TMailApp* app, } -BObjectList TMailWindow::fBitmapCache; -BLocker TMailWindow::fBitmapCacheLock; - BBitmap* TMailWindow::_RetrieveVectorIcon(int32 id) { // Lock access to the list - BAutolock lock(fBitmapCacheLock); + BAutolock lock(sBitmapCacheLock); if (!lock.IsLocked()) return NULL; // Check for the bitmap in the cache first BitmapItem* item; - for (int32 i = 0; (item = fBitmapCache.ItemAt(i)) != NULL; i++) { + for (int32 i = 0; (item = sBitmapCache.ItemAt(i)) != NULL; i++) { if (item->id == id) return item->bm; } @@ -588,7 +603,7 @@ TMailWindow::_RetrieveVectorIcon(int32 id) item = (BitmapItem*)malloc(sizeof(BitmapItem)); item->bm = bitmap; item->id = id; - fBitmapCache.AddItem(item); + sBitmapCache.AddItem(item); return bitmap; } @@ -599,7 +614,7 @@ TMailWindow::_RetrieveVectorIcon(int32 id) void TMailWindow::BuildToolBar() { - fToolBar = new BToolBar(BRect(0, 0, 100, 50)); + fToolBar = new BToolBar(); fToolBar->AddAction(M_NEW, this, _RetrieveVectorIcon(11), NULL, B_TRANSLATE("New")); fToolBar->AddSeparator(); @@ -720,7 +735,7 @@ TMailWindow::~TMailWindow() status_t -TMailWindow::GetMailNodeRef(node_ref &nodeRef) const +TMailWindow::GetMailNodeRef(node_ref& nodeRef) const { if (fRef == NULL) return B_ERROR; @@ -731,7 +746,7 @@ TMailWindow::GetMailNodeRef(node_ref &nodeRef) const bool -TMailWindow::GetTrackerWindowFile(entry_ref *ref, bool next) const +TMailWindow::GetTrackerWindowFile(entry_ref* ref, bool next) const { // Position was already saved if (next && fNextTrackerPositionSaved) { @@ -789,7 +804,7 @@ TMailWindow::GetTrackerWindowFile(entry_ref *ref, bool next) const void -TMailWindow::SaveTrackerPosition(entry_ref *ref) +TMailWindow::SaveTrackerPosition(entry_ref* ref) { // if only one of them is saved, we're not going to do it again if (fNextTrackerPositionSaved || fPrevTrackerPositionSaved) @@ -803,7 +818,7 @@ TMailWindow::SaveTrackerPosition(entry_ref *ref) void -TMailWindow::SetOriginatingWindow(BWindow *window) +TMailWindow::SetOriginatingWindow(BWindow* window) { delete fOriginatingWindow; fOriginatingWindow = new BMessenger(window); @@ -824,7 +839,7 @@ TMailWindow::SetTrackerSelectionToCurrent() void TMailWindow::PreserveReadingPos(bool save) { - BScrollBar *scroll = fContentView->fTextView->ScrollBar(B_VERTICAL); + BScrollBar* scroll = fContentView->fTextView->ScrollBar(B_VERTICAL); if (scroll == NULL || fRef == NULL) return; @@ -881,7 +896,7 @@ TMailWindow::MenusBeginning() bool enable; int32 finish = 0; int32 start = 0; - BTextView *textView; + BTextView* textView; if (!fIncoming) { bool gotToField = fHeaderView->fTo->Text()[0] != 0; @@ -937,9 +952,9 @@ TMailWindow::MenusBeginning() fPrint->SetEnabled(fContentView->fTextView->TextLength()); - textView = dynamic_cast(CurrentFocus()); + textView = dynamic_cast(CurrentFocus()); if (textView != NULL - && dynamic_cast(textView->Parent()) != NULL) { + && dynamic_cast(textView->Parent()) != NULL) { // one of To:, Subject:, Account:, Cc:, Bcc: textView->GetSelection(&start, &finish); } else if (fContentView->fTextView->IsFocus()) { @@ -958,7 +973,7 @@ TMailWindow::MenusBeginning() bool isRedo = false; undo_state undoState = B_UNDO_UNAVAILABLE; - BTextView *focusTextView = dynamic_cast(CurrentFocus()); + BTextView* focusTextView = dynamic_cast(CurrentFocus()); if (focusTextView != NULL) undoState = focusTextView->UndoState(&isRedo); @@ -985,7 +1000,7 @@ TMailWindow::MenusBeginning() void -TMailWindow::MessageReceived(BMessage *msg) +TMailWindow::MessageReceived(BMessage* msg) { bool wasReadMsg = false; switch (msg->what) { @@ -1012,15 +1027,15 @@ TMailWindow::MessageReceived(BMessage *msg) { int32 prevState = fFieldState; int32 fieldMask = msg->FindInt32("bitmask"); - void *source; + void* source; if (msg->FindPointer("source", &source) == B_OK) { int32 length; if (fieldMask == FIELD_BODY) - length = ((TTextView *)source)->TextLength(); + length = ((TTextView*)source)->TextLength(); else - length = ((BComboBox *)source)->TextView()->TextLength(); + length = ((BComboBox*)source)->TextView()->TextLength(); if (length) fFieldState |= fieldMask; @@ -1039,7 +1054,7 @@ TMailWindow::MessageReceived(BMessage *msg) fChanged = true; // Update title bar if "subject" has changed - if (!fIncoming && fieldMask & FIELD_SUBJECT) { + if (!fIncoming && (fieldMask & FIELD_SUBJECT) != 0) { // If no subject, set to "Mail" if (!fHeaderView->fSubject->TextView()->TextLength()) SetTitle(B_TRANSLATE_SYSTEM_NAME("Mail")); @@ -1077,7 +1092,7 @@ TMailWindow::MessageReceived(BMessage *msg) TODO: Replace this code with a split toolbar button */ uint32 buttons; - if (msg->FindInt32("buttons", (int32 *)&buttons) == B_OK + if (msg->FindInt32("buttons", (int32*)&buttons) == B_OK && buttons == B_SECONDARY_MOUSE_BUTTON) { BPopUpMenu menu("Spam Actions", false, false); for (int i = 0; i < 4; i++) @@ -1086,7 +1101,7 @@ TMailWindow::MessageReceived(BMessage *msg) BPoint where; msg->FindPoint("where", &where); - BMenuItem *item; + BMenuItem* item; if ((item = menu.Go(where, false, false)) != NULL) PostMessage(item->Message()); break; @@ -1116,7 +1131,7 @@ TMailWindow::MessageReceived(BMessage *msg) // TODO: This needs removed in favor of a split toolbar button. // See comments for Spam button uint32 buttons; - if (msg->FindInt32("buttons", (int32 *)&buttons) == B_OK + if (msg->FindInt32("buttons", (int32*)&buttons) == B_OK && buttons == B_SECONDARY_MOUSE_BUTTON) { BPopUpMenu menu("Reply To", false, false); menu.AddItem(new BMenuItem(B_TRANSLATE("Reply"), @@ -1129,7 +1144,7 @@ TMailWindow::MessageReceived(BMessage *msg) BPoint where; msg->FindPoint("where", &where); - BMenuItem *item; + BMenuItem* item; if ((item = menu.Go(where, false, false)) != NULL) { item->SetTarget(this); PostMessage(item->Message()); @@ -1143,7 +1158,7 @@ TMailWindow::MessageReceived(BMessage *msg) // TODO: This needs removed in favor of a split toolbar button. // See comments for Spam button uint32 buttons; - if (msg->FindInt32("buttons", (int32 *)&buttons) == B_OK + if (msg->FindInt32("buttons", (int32*)&buttons) == B_OK && buttons == B_SECONDARY_MOUSE_BUTTON) { BPopUpMenu menu("Forward", false, false); menu.AddItem(new BMenuItem(B_TRANSLATE("Forward"), @@ -1155,7 +1170,7 @@ TMailWindow::MessageReceived(BMessage *msg) BPoint where; msg->FindPoint("where", &where); - BMenuItem *item; + BMenuItem* item; if ((item = menu.Go(where, false, false)) != NULL) { item->SetTarget(this); PostMessage(item->Message()); @@ -1182,7 +1197,7 @@ TMailWindow::MessageReceived(BMessage *msg) case M_DELETE_PREV: case M_DELETE_NEXT: { - if (msg->what == M_DELETE_NEXT && (modifiers() & B_SHIFT_KEY)) + if (msg->what == M_DELETE_NEXT && (modifiers() & B_SHIFT_KEY) != 0) msg->what = M_DELETE_PREV; bool foundRef = false; @@ -1233,8 +1248,8 @@ TMailWindow::MessageReceived(BMessage *msg) // If the next file was found, open it. If it was not, // we have no choice but to close this window. if (foundRef) { - TMailWindow *window - = static_cast(be_app)->FindWindow(nextRef); + TMailWindow* window + = static_cast(be_app)->FindWindow(nextRef); if (window == NULL) OpenMessage(&nextRef, fHeaderView->fCharacterSetUserSees); else @@ -1272,10 +1287,8 @@ TMailWindow::MessageReceived(BMessage *msg) break; case M_CLOSE_CUSTOM: if (msg->HasString("status")) { - const char *str; - msg->FindString("status", (const char**) &str); BMessage message(B_CLOSE_REQUESTED); - message.AddString("status", str); + message.AddString("status", msg->GetString("status")); PostMessage(&message); } else { BRect r = Frame(); @@ -1331,7 +1344,7 @@ TMailWindow::MessageReceived(BMessage *msg) case M_SAVE: { const char* address; - if (msg->FindString("address", (const char**)&address) != B_NO_ERROR) + if (msg->FindString("address", (const char**)&address) != B_OK) break; BVolumeRoster volumeRoster; @@ -1448,10 +1461,10 @@ TMailWindow::MessageReceived(BMessage *msg) } if (sigList.CountItems() > 0) { srand(time(0)); - PostMessage((BMessage *)sigList.ItemAt(rand() + PostMessage((BMessage*)sigList.ItemAt(rand() % sigList.CountItems())); - for (int32 i = 0; (message = (BMessage *)sigList.ItemAt(i)) + for (int32 i = 0; (message = (BMessage*)sigList.ItemAt(i)) != NULL; i++) delete message; } @@ -1466,8 +1479,8 @@ TMailWindow::MessageReceived(BMessage *msg) } case M_SIG_MENU: { - TMenu *menu; - BMenuItem *item; + TMenu* menu; + BMenuItem* item; menu = new TMenu("Add Signature", INDEX_SIGNATURE, M_SIGNATURE, true); @@ -1481,7 +1494,7 @@ TMailWindow::MessageReceived(BMessage *msg) if ((item = menu->Go(where, false, true)) != NULL) { item->SetTarget(this); - (dynamic_cast(item))->Invoke(); + (dynamic_cast(item))->Invoke(); } delete menu; break; @@ -1544,7 +1557,7 @@ TMailWindow::MessageReceived(BMessage *msg) entry_ref orgRef = *fRef; entry_ref nextRef = *fRef; if (GetTrackerWindowFile(&nextRef, (msg->what == M_NEXTMSG))) { - TMailWindow *window = static_cast(be_app) + TMailWindow* window = static_cast(be_app) ->FindWindow(nextRef); if (window == NULL) { BNode node(fRef); @@ -1672,7 +1685,7 @@ TMailWindow::MessageReceived(BMessage *msg) void -TMailWindow::AddEnclosure(BMessage *msg) +TMailWindow::AddEnclosure(BMessage* msg) { if (fEnclosuresView == NULL && !fIncoming) { BRect r; @@ -1720,7 +1733,7 @@ TMailWindow::QuitRequested() || (fEnclosuresView != NULL && fEnclosuresView->fList->CountItems()))) { if (fResending) { - BAlert *alert = new BAlert("", B_TRANSLATE( + BAlert* alert = new BAlert("", B_TRANSLATE( "Send this message before closing?"), B_TRANSLATE("Cancel"), B_TRANSLATE("Don't send"), @@ -1741,7 +1754,7 @@ TMailWindow::QuitRequested() break; } } else { - BAlert *alert = new BAlert("", + BAlert* alert = new BAlert("", B_TRANSLATE("Save this message as a draft before closing?"), B_TRANSLATE("Cancel"), B_TRANSLATE("Don't save"), @@ -1771,7 +1784,7 @@ TMailWindow::QuitRequested() if (CurrentMessage() && CurrentMessage()->HasString("status")) { // User explicitly requests a status to set this message to. if (!CurrentMessage()->HasString("same")) { - const char *status = CurrentMessage()->FindString("status"); + const char* status = CurrentMessage()->FindString("status"); if (status != NULL) { BNode node(fRef); if (node.InitCheck() == B_NO_ERROR) { @@ -1807,7 +1820,7 @@ TMailWindow::Show() if (!fResending && (fIncoming || fReplying)) { fContentView->fTextView->MakeFocus(true); } else { - BTextView *textView = fHeaderView->fTo->TextView(); + BTextView* textView = fHeaderView->fTo->TextView(); fHeaderView->fTo->MakeFocus(true); textView->Select(0, textView->TextLength()); } @@ -1822,61 +1835,57 @@ TMailWindow::Zoom(BPoint /*pos*/, float /*x*/, float /*y*/) { float height; float width; - BScreen screen(this); - BRect r; - BRect s_frame = screen.Frame(); - r = Frame(); + BRect rect = Frame(); width = 80 * fApp->ContentFont().StringWidth("M") - + (r.Width() - fContentView->fTextView->Bounds().Width() + 6); - if (width > (s_frame.Width() - 8)) - width = s_frame.Width() - 8; + + (rect.Width() - fContentView->fTextView->Bounds().Width() + 6); + + BScreen screen(this); + BRect screenFrame = screen.Frame(); + if (width > (screenFrame.Width() - 8)) + width = screenFrame.Width() - 8; height = max_c(fContentView->fTextView->CountLines(), 20) * fContentView->fTextView->LineHeight(0) - + (r.Height() - fContentView->fTextView->Bounds().Height()); - if (height > (s_frame.Height() - 29)) - height = s_frame.Height() - 29; + + (rect.Height() - fContentView->fTextView->Bounds().Height()); + if (height > (screenFrame.Height() - 29)) + height = screenFrame.Height() - 29; - r.right = r.left + width; - r.bottom = r.top + height; + rect.right = rect.left + width; + rect.bottom = rect.top + height; - if (abs((int)(Frame().Width() - r.Width())) < 5 - && abs((int)(Frame().Height() - r.Height())) < 5) { - r = fZoom; + if (abs((int)(Frame().Width() - rect.Width())) < 5 + && abs((int)(Frame().Height() - rect.Height())) < 5) { + rect = fZoom; } else { fZoom = Frame(); - s_frame.InsetBy(6, 6); + screenFrame.InsetBy(6, 6); - if (r.Width() > s_frame.Width()) - r.right = r.left + s_frame.Width(); - if (r.Height() > s_frame.Height()) - r.bottom = r.top + s_frame.Height(); + if (rect.Width() > screenFrame.Width()) + rect.right = rect.left + screenFrame.Width(); + if (rect.Height() > screenFrame.Height()) + rect.bottom = rect.top + screenFrame.Height(); - if (r.right > s_frame.right) - { - r.left -= r.right - s_frame.right; - r.right = s_frame.right; + if (rect.right > screenFrame.right) { + rect.left -= rect.right - screenFrame.right; + rect.right = screenFrame.right; } - if (r.bottom > s_frame.bottom) - { - r.top -= r.bottom - s_frame.bottom; - r.bottom = s_frame.bottom; + if (rect.bottom > screenFrame.bottom) { + rect.top -= rect.bottom - screenFrame.bottom; + rect.bottom = screenFrame.bottom; } - if (r.left < s_frame.left) - { - r.right += s_frame.left - r.left; - r.left = s_frame.left; + if (rect.left < screenFrame.left) { + rect.right += screenFrame.left - rect.left; + rect.left = screenFrame.left; } - if (r.top < s_frame.top) - { - r.bottom += s_frame.top - r.top; - r.top = s_frame.top; + if (rect.top < screenFrame.top) { + rect.bottom += screenFrame.top - rect.top; + rect.top = screenFrame.top; } } - ResizeTo(r.Width(), r.Height()); - MoveTo(r.LeftTop()); + ResizeTo(rect.Width(), rect.Height()); + MoveTo(rect.LeftTop()); } @@ -1892,10 +1901,10 @@ TMailWindow::WindowActivated(bool status) void -TMailWindow::Forward(entry_ref *ref, TMailWindow *window, +TMailWindow::Forward(entry_ref* ref, TMailWindow* window, bool includeAttachments) { - BEmailMessage *mail = window->Mail(); + BEmailMessage* mail = window->Mail(); if (mail == NULL) return; @@ -1915,10 +1924,10 @@ TMailWindow::Forward(entry_ref *ref, TMailWindow *window, if (useAccountFrom == ACCOUNT_FROM_MAIL) { fHeaderView->fAccountID = fMail->Account(); - BMenu *menu = fHeaderView->fAccountMenu; + BMenu* menu = fHeaderView->fAccountMenu; for (int32 i = menu->CountItems(); i-- > 0;) { - BMenuItem *item = menu->ItemAt(i); - BMessage *msg; + BMenuItem* item = menu->ItemAt(i); + BMessage* msg; if (item && (msg = item->Message()) != NULL && msg->FindInt32("id") == fHeaderView->fAccountID) item->SetMarked(true); @@ -1939,19 +1948,6 @@ TMailWindow::Forward(entry_ref *ref, TMailWindow *window, } -class HorizontalLine : public BView { - public: - HorizontalLine(BRect rect) - : - BView (rect, NULL, B_FOLLOW_ALL, B_WILL_DRAW) {} - - virtual void Draw(BRect rect) - { - FillRect(rect, B_SOLID_HIGH); - } -}; - - void TMailWindow::Print() { @@ -1989,8 +1985,7 @@ TMailWindow::Print() add_header_field(fSubject); add_header_field(fTo); - if ((fHeaderView->fCc != NULL) - && (strcmp(fHeaderView->fCc->Text(),"") != 0)) + if (fHeaderView->fCc != NULL && fHeaderView->fCc->TextLength() != 0) add_header_field(fCc); if (fHeaderView->fDate != NULL) @@ -2025,21 +2020,18 @@ TMailWindow::Print() BPoint(0.0, curPageRect.bottom - ((curPage == 1) ? header_height : 0))); - float curPageHeight = fContentView->fTextView-> - TextHeight(fromLine, lastLine) + ((curPage == 1) - ? header_height : 0); + float curPageHeight = fContentView->fTextView->TextHeight( + fromLine, lastLine) + (curPage == 1 ? header_height : 0); if (curPageHeight > pageRect.Height()) { curPageHeight = fContentView->fTextView->TextHeight( - fromLine, --lastLine) + ((curPage == 1) - ? header_height : 0); + fromLine, --lastLine) + (curPage == 1 ? header_height : 0); } curPageRect.bottom = curPageRect.top + curPageHeight - 1.0; - if ((curPage >= print.FirstPage()) - && (curPage <= print.LastPage())) { + if (curPage >= print.FirstPage() && curPage <= print.LastPage()) { print.DrawView(fContentView->fTextView, curPageRect, - BPoint(0.0, (curPage == 1) ? header_height : 0.0)); + BPoint(0.0, curPage == 1 ? header_height : 0.0)); print.SpoolPage(); } @@ -2072,8 +2064,8 @@ TMailWindow::PrintSetup() void -TMailWindow::SetTo(const char *mailTo, const char *subject, const char *ccTo, - const char *bccTo, const BString *body, BMessage *enclosures) +TMailWindow::SetTo(const char* mailTo, const char* subject, const char* ccTo, + const char* bccTo, const BString* body, BMessage* enclosures) { Lock(); @@ -2099,7 +2091,7 @@ TMailWindow::SetTo(const char *mailTo, const char *subject, const char *ccTo, void -TMailWindow::CopyMessage(entry_ref *ref, TMailWindow *src) +TMailWindow::CopyMessage(entry_ref* ref, TMailWindow* src) { BNode file(ref); if (file.InitCheck() == B_OK) { @@ -2117,8 +2109,8 @@ TMailWindow::CopyMessage(entry_ref *ref, TMailWindow *src) fHeaderView->fCc->SetText(string.String()); } - TTextView *text = src->fContentView->fTextView; - text_run_array *style = text->RunArray(0, text->TextLength()); + TTextView* text = src->fContentView->fTextView; + text_run_array* style = text->RunArray(0, text->TextLength()); fContentView->fTextView->SetText(text->Text(), text->TextLength(), style); @@ -2127,12 +2119,12 @@ TMailWindow::CopyMessage(entry_ref *ref, TMailWindow *src) void -TMailWindow::Reply(entry_ref *ref, TMailWindow *window, uint32 type) +TMailWindow::Reply(entry_ref* ref, TMailWindow* window, uint32 type) { fRepliedMail = *ref; SetOriginatingWindow(window); - BEmailMessage *mail = window->Mail(); + BEmailMessage* mail = window->Mail(); if (mail == NULL) return; @@ -2167,10 +2159,10 @@ TMailWindow::Reply(entry_ref *ref, TMailWindow *window, uint32 type) else fHeaderView->fAccountID = accountID; - BMenu *menu = fHeaderView->fAccountMenu; + BMenu* menu = fHeaderView->fAccountMenu; for (int32 i = menu->CountItems(); i-- > 0;) { - BMenuItem *item = menu->ItemAt(i); - BMessage *msg; + BMenuItem* item = menu->ItemAt(i); + BMessage* msg; if (item && (msg = item->Message()) != NULL && msg->FindInt32("id") == fHeaderView->fAccountID) item->SetMarked(true); @@ -2204,7 +2196,7 @@ TMailWindow::Reply(entry_ref *ref, TMailWindow *window, uint32 type) int32 finish, start; window->fContentView->fTextView->GetSelection(&start, &finish); if (start != finish) { - char *text = (char *)malloc(finish - start + 1); + char* text = (char*)malloc(finish - start + 1); if (text == NULL) return; @@ -2219,11 +2211,11 @@ TMailWindow::Reply(entry_ref *ref, TMailWindow *window, uint32 type) finish = fContentView->fTextView->CountLines(); for (int32 loop = 0; loop < finish; loop++) { fContentView->fTextView->GoToLine(loop); - fContentView->fTextView->Insert((const char *)QUOTE); + fContentView->fTextView->Insert((const char*)QUOTE); } if (fApp->ColoredQuotes()) { - const BFont *font = fContentView->fTextView->Font(); + const BFont* font = fContentView->fTextView->Font(); int32 length = fContentView->fTextView->TextLength(); TextRunArray style(length / 8 + 8); @@ -2433,9 +2425,9 @@ TMailWindow::Send(bool now) characterSetToUse, encodingForBody); if (fEnclosuresView != NULL) { - TListItem *item; + TListItem* item; int32 index = 0; - while ((item = (TListItem *)fEnclosuresView->fList->ItemAt(index++)) + while ((item = (TListItem*)fEnclosuresView->fList->ItemAt(index++)) != NULL) { if (item->Component()) continue; @@ -2489,7 +2481,7 @@ TMailWindow::Send(bool now) BAlert* alert = new BAlert("no daemon", B_TRANSLATE("The mail_daemon is not running. The message is " - "queued and will be sent when the mail_daemon is started."), + "queued and will be sent when the mail_daemon is started."), B_TRANSLATE("Start now"), B_TRANSLATE("OK")); alert->SetShortcut(1, B_ESCAPE); int32 start = alert->Go(); @@ -2529,7 +2521,8 @@ TMailWindow::Send(bool now) if (result != B_NO_ERROR && result != B_MAIL_NO_DAEMON) { beep(); - BAlert* alert = new BAlert("", errorMessage.String(), B_TRANSLATE("OK")); + BAlert* alert = new BAlert("", errorMessage.String(), + B_TRANSLATE("OK")); alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); alert->Go(); } @@ -2547,20 +2540,20 @@ TMailWindow::Send(bool now) status_t TMailWindow::SaveAsDraft() { - status_t status; - BPath draftPath; - BDirectory dir; - BFile draft; - uint32 flags = 0; + BPath draftPath; + BDirectory dir; + BFile draft; + uint32 flags = 0; if (fDraft) { - if ((status = draft.SetTo(fRef, - B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE)) != B_OK) { + status_t status = draft.SetTo(fRef, + B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE); + if (status != B_OK) return status; - } } else { // Get the user home directory - if ((status = find_directory(B_USER_DIRECTORY, &draftPath)) != B_OK) + status_t status = find_directory(B_USER_DIRECTORY, &draftPath); + if (status != B_OK) return status; // Append the relative path of the draft directory @@ -2588,12 +2581,18 @@ TMailWindow::SaveAsDraft() uint32 originalLength = strlen(fileName); // convert /, \ and : to - - for (char *bad = fileName; (bad = strchr(bad, '/')) != NULL; - ++bad) *bad = '-'; - for (char *bad = fileName; (bad = strchr(bad, '\\')) != NULL; - ++bad) *bad = '-'; - for (char *bad = fileName; (bad = strchr(bad, ':')) != NULL; - ++bad) *bad = '-'; + for (char* bad = fileName; (bad = strchr(bad, '/')) != NULL; + ++bad) { + *bad = '-'; + } + for (char* bad = fileName; (bad = strchr(bad, '\\')) != NULL; + ++bad) { + *bad = '-'; + } + for (char* bad = fileName; (bad = strchr(bad, ':')) != NULL; + ++bad) { + *bad = '-'; + } // Create the file; if the name exists, find a unique name flags = B_WRITE_ONLY | B_CREATE_FILE | B_FAIL_IF_EXISTS; @@ -2627,9 +2626,7 @@ TMailWindow::SaveAsDraft() draft.Write(fContentView->fTextView->Text(), fContentView->fTextView->TextLength()); - // // Add the header stuff as attributes - // WriteAttrString(&draft, B_MAIL_ATTR_NAME, fHeaderView->fTo->Text()); WriteAttrString(&draft, B_MAIL_ATTR_TO, fHeaderView->fTo->Text()); WriteAttrString(&draft, B_MAIL_ATTR_SUBJECT, fHeaderView->fSubject->Text()); @@ -2654,12 +2651,11 @@ TMailWindow::SaveAsDraft() // Add Attachment paths in attribute if (fEnclosuresView != NULL) { - TListItem *item; - BPath path; + TListItem* item; BString pathStr; - for (int32 i = 0; (item = (TListItem *) - fEnclosuresView->fList->ItemAt(i)) != NULL; i++) { + for (int32 i = 0; (item = (TListItem*)fEnclosuresView->fList->ItemAt(i)) + != NULL; i++) { if (i > 0) pathStr.Append(":"); @@ -2667,6 +2663,7 @@ TMailWindow::SaveAsDraft() if (!entry.Exists()) continue; + BPath path; entry.GetPath(&path); pathStr.Append(path.Path()); } @@ -2688,10 +2685,9 @@ TMailWindow::SaveAsDraft() status_t -TMailWindow::TrainMessageAs(const char *CommandWord) +TMailWindow::TrainMessageAs(const char* commandWord) { status_t errorCode = -1; - char errorString[1500]; BEntry fileEntry; BPath filePath; BMessage replyMessage; @@ -2700,7 +2696,7 @@ TMailWindow::TrainMessageAs(const char *CommandWord) if (fRef == NULL) goto ErrorExit; // Need to have a real file and name. - errorCode = fileEntry.SetTo(fRef, true /* traverse */); + errorCode = fileEntry.SetTo(fRef, true); if (errorCode != B_OK) goto ErrorExit; errorCode = fileEntry.GetPath(&filePath); @@ -2717,15 +2713,17 @@ TMailWindow::TrainMessageAs(const char *CommandWord) if (errorCode != B_OK) { BPath path; entry_ref ref; - directory_which places[] - = {B_SYSTEM_NONPACKAGED_BIN_DIRECTORY, B_SYSTEM_BIN_DIRECTORY}; + directory_which places[] = {B_SYSTEM_NONPACKAGED_BIN_DIRECTORY, + B_SYSTEM_BIN_DIRECTORY}; for (int32 i = 0; i < 2; i++) { find_directory(places[i],&path); path.Append("spamdbm"); if (!BEntry(path.Path()).Exists()) continue; get_ref_for_path(path.Path(),&ref); - if ((errorCode = be_roster->Launch (&ref)) == B_OK) + + errorCode = be_roster->Launch(&ref); + if (errorCode == B_OK) break; } if (errorCode != B_OK) @@ -2751,9 +2749,9 @@ TMailWindow::TrainMessageAs(const char *CommandWord) scriptingMessage.MakeEmpty(); scriptingMessage.what = B_SET_PROPERTY; - scriptingMessage.AddSpecifier(CommandWord); + scriptingMessage.AddSpecifier(commandWord); errorCode = scriptingMessage.AddData("data", B_STRING_TYPE, - filePath.Path(), strlen(filePath.Path()) + 1, false /* fixed size */); + filePath.Path(), strlen(filePath.Path()) + 1, false); if (errorCode != B_OK) goto ErrorExit; replyMessage.MakeEmpty(); @@ -2770,9 +2768,10 @@ TMailWindow::TrainMessageAs(const char *CommandWord) ErrorExit: beep(); - sprintf(errorString, "Unable to train the message file \"%s\" as %s. " - "Possibly useful error code: %s (%" B_PRId32 ").", - filePath.Path(), CommandWord, strerror(errorCode), errorCode); + char errorString[1500]; + snprintf(errorString, sizeof(errorString), "Unable to train the message " + "file \"%s\" as %s. Possibly useful error code: %s (%" B_PRId32 ").", + filePath.Path(), commandWord, strerror(errorCode), errorCode); BAlert* alert = new BAlert("", errorString, B_TRANSLATE("OK")); alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); alert->Go(); @@ -2784,9 +2783,7 @@ ErrorExit: void TMailWindow::SetTitleForMessage() { - // - // Figure out the title of this message and set the title bar - // + // Figure out the title of this message and set the title bar BString title = B_TRANSLATE_SYSTEM_NAME("Mail"); if (fIncoming) { @@ -2800,19 +2797,19 @@ TMailWindow::SetTitleForMessage() if (fApp->ShowSpamGUI() && fRef != NULL) { BString classification; - BNode node (fRef); - char numberString [30]; - BString oldTitle (title); - float spamRatio; - if (node.InitCheck() != B_OK || node.ReadAttrString - ("MAIL:classification", &classification) != B_OK) + BNode node(fRef); + char numberString[30]; + BString oldTitle(title); + float spamRatio; + if (node.InitCheck() != B_OK || node.ReadAttrString( + "MAIL:classification", &classification) != B_OK) classification = "Unrated"; if (classification != "Spam" && classification != "Genuine") { // Uncertain, Unrated and other unknown classes, show the ratio. - if (node.InitCheck() == B_OK && sizeof (spamRatio) == - node.ReadAttr("MAIL:ratio_spam", B_FLOAT_TYPE, 0, - &spamRatio, sizeof (spamRatio))) { - sprintf (numberString, "%.4f", spamRatio); + if (node.InitCheck() == B_OK && node.ReadAttr("MAIL:ratio_spam", + B_FLOAT_TYPE, 0, &spamRatio, sizeof(spamRatio)) + == sizeof(spamRatio)) { + sprintf(numberString, "%.4f", spamRatio); classification << " " << numberString; } } @@ -2824,20 +2821,17 @@ TMailWindow::SetTitleForMessage() } -// -// Open *another* message in the existing mail window. Some code here is -// duplicated from various constructors. -// The duplicated code should be in a private initializer method -- axeld. -// - +/*! Open *another* message in the existing mail window. Some code here is + duplicated from various constructors. + TODO: The duplicated code should be moved to a private initializer method +*/ status_t -TMailWindow::OpenMessage(const entry_ref *ref, uint32 characterSetForDecoding) +TMailWindow::OpenMessage(const entry_ref* ref, uint32 characterSetForDecoding) { if (ref == NULL) return B_ERROR; - // - // Set some references to the email file - // + + // Set some references to the email file delete fRef; fRef = new entry_ref(*ref); @@ -2907,8 +2901,8 @@ TMailWindow::OpenMessage(const entry_ref *ref, uint32 characterSetForDecoding) BMessage msg(REFS_RECEIVED); entry_ref enc_ref; - char *s = strtok((char *)string.String(), ":"); - while (s) { + char* s = strtok((char*)string.String(), ":"); + while (s != NULL) { BEntry entry(s, true); if (entry.Exists()) { entry.GetRef(&enc_ref); @@ -2942,10 +2936,8 @@ TMailWindow::OpenMessage(const entry_ref *ref, uint32 characterSetForDecoding) SetTitleForMessage(); if (fIncoming) { - // // Put the addresses in the 'Save Address' Menu - // - BMenuItem *item; + BMenuItem* item; while ((item = fSaveAddrMenu->RemoveItem((int32)0)) != NULL) delete item; @@ -2957,10 +2949,10 @@ TMailWindow::OpenMessage(const entry_ref *ref, uint32 characterSetForDecoding) get_address_list(addressList, fMail->From(), extract_address); get_address_list(addressList, fMail->ReplyTo(), extract_address); - BMessage *msg; + BMessage* msg; for (int32 i = addressList.CountItems(); i-- > 0;) { - char *address = (char *)addressList.RemoveItem((int32)0); + char* address = (char*)addressList.RemoveItem((int32)0); // insert the new address in alphabetical order int32 index = 0; @@ -2984,9 +2976,7 @@ TMailWindow::OpenMessage(const entry_ref *ref, uint32 characterSetForDecoding) free(address); } - // // Clear out existing contents of text view. - // fContentView->fTextView->SetText("", (int32)0); fContentView->fTextView->LoadMessage(fMail, false, NULL); @@ -2999,50 +2989,17 @@ TMailWindow::OpenMessage(const entry_ref *ref, uint32 characterSetForDecoding) } -TMailWindow * +TMailWindow* TMailWindow::FrontmostWindow() { BAutolock locker(sWindowListLock); if (sWindowList.CountItems() > 0) - return (TMailWindow *)sWindowList.ItemAt(0); + return (TMailWindow*)sWindowList.ItemAt(0); return NULL; } -/* -// Copied from src/kits/tracker/FindPanel.cpp. -uint32 -TMailWindow::InitialMode(const BNode *node) -{ - if (!node || node->InitCheck() != B_OK) - return kByNameItem; - - uint32 result; - if (node->ReadAttr(kAttrQueryInitialMode, B_INT32_TYPE, 0, - (int32 *)&result, sizeof(int32)) <= 0) - return kByNameItem; - - return result; -} - - -// Copied from src/kits/tracker/FindPanel.cpp. -int32 -TMailWindow::InitialAttrCount(const BNode *node) -{ - if (!node || node->InitCheck() != B_OK) - return 1; - - int32 result; - if (node->ReadAttr(kAttrQueryInitialNumAttrs, B_INT32_TYPE, 0, - &result, sizeof(int32)) <= 0) - return 1; - - return result; -}*/ - - // #pragma mark - @@ -3168,7 +3125,7 @@ TMailWindow::_BuildQueryString(BEntry* entry) const { int32 count = 1; if (node.ReadAttr(kAttrQueryInitialNumAttrs, B_INT32_TYPE, 0, - (int32 *)&count, sizeof(int32)) <= 0) { + (int32*)&count, sizeof(int32)) <= 0) { count = 1; } @@ -3179,14 +3136,14 @@ TMailWindow::_BuildQueryString(BEntry* entry) const if (count > 1) queryString << "("; - char *buffer = new char[info.size]; + char* buffer = new char[info.size]; if (node.ReadAttr(kAttrQueryInitialAttrs, B_MESSAGE_TYPE, 0, buffer, (size_t)info.size) == info.size) { BMessage message; if (message.Unflatten(buffer) == B_OK) { for (int32 index = 0; /*index < count*/; index++) { - const char *field; - const char *value; + const char* field; + const char* value; if (message.FindString("menuSelection", index, &field) != B_OK || message.FindString("attrViewText", index, &value) diff --git a/src/apps/mail/MailWindow.h b/src/apps/mail/MailWindow.h index 8b2294b3fb..6713f6eb85 100644 --- a/src/apps/mail/MailWindow.h +++ b/src/apps/mail/MailWindow.h @@ -65,153 +65,156 @@ class BMenuBar; class BMenuItem; class Words; + class TMailWindow : public BWindow { - public: +public: TMailWindow(BRect frame, const char* title, TMailApp* app, const entry_ref* ref, const char* to, const BFont *font, bool resending, BMessenger* trackerMessenger); - virtual ~TMailWindow(); + virtual ~TMailWindow(); - virtual void FrameResized(float width, float height); - virtual void MenusBeginning(); - virtual void MessageReceived(BMessage*); - virtual bool QuitRequested(); - virtual void Show(); - virtual void Zoom(BPoint, float, float); - virtual void WindowActivated(bool state); + virtual void FrameResized(float width, float height); + virtual void MenusBeginning(); + virtual void MessageReceived(BMessage*); + virtual bool QuitRequested(); + virtual void Show(); + virtual void Zoom(BPoint, float, float); + virtual void WindowActivated(bool state); - void SetTo(const char* mailTo, const char* subject, + void SetTo(const char* mailTo, const char* subject, const char* ccTo = NULL, const char* bccTo = NULL, const BString* body = NULL, BMessage* enclosures = NULL); - void AddSignature(BMailMessage*); - void Forward(entry_ref*, TMailWindow*, + void AddSignature(BMailMessage*); + void Forward(entry_ref*, TMailWindow*, bool includeAttachments); - void Print(); - void PrintSetup(); - void Reply(entry_ref*, TMailWindow*, uint32); - void CopyMessage(entry_ref* ref, TMailWindow* src); - status_t Send(bool); - status_t SaveAsDraft(); - status_t OpenMessage(const entry_ref* ref, + void Print(); + void PrintSetup(); + void Reply(entry_ref*, TMailWindow*, uint32); + void CopyMessage(entry_ref* ref, TMailWindow* src); + status_t Send(bool now); + status_t SaveAsDraft(); + status_t OpenMessage(const entry_ref* ref, uint32 characterSetForDecoding = B_MAIL_NULL_CONVERSION); - status_t GetMailNodeRef(node_ref &nodeRef) const; - BEmailMessage* Mail() const { return fMail; } + status_t GetMailNodeRef(node_ref &nodeRef) const; + BEmailMessage* Mail() const { return fMail; } - bool GetTrackerWindowFile(entry_ref*, + bool GetTrackerWindowFile(entry_ref*, bool dir) const; - void SaveTrackerPosition(entry_ref*); - void SetOriginatingWindow(BWindow* window); + void SaveTrackerPosition(entry_ref*); + void SetOriginatingWindow(BWindow* window); - void PreserveReadingPos(bool save); - void MarkMessageRead(entry_ref* message, + void PreserveReadingPos(bool save); + void MarkMessageRead(entry_ref* message, read_flags flag); - void SetTrackerSelectionToCurrent(); - TMailWindow* FrontmostWindow(); - void UpdateViews(); - void UpdatePreferences(); + void SetTrackerSelectionToCurrent(); + TMailWindow* FrontmostWindow(); + void UpdateViews(); + void UpdatePreferences(); - protected: - void SetTitleForMessage(); - void AddEnclosure(BMessage* msg); - void BuildToolBar(); - status_t TrainMessageAs(const char* commandWord); +protected: + void SetTitleForMessage(); + void AddEnclosure(BMessage* msg); + void BuildToolBar(); + status_t TrainMessageAs(const char* commandWord); - private: - void _UpdateSizeLimits(); +private: + void _UpdateSizeLimits(); - status_t _GetQueryPath(BPath* path) const; - void _RebuildQueryMenu(bool firstTime = false); - char* _BuildQueryString(BEntry* entry) const; + status_t _GetQueryPath(BPath* path) const; + void _RebuildQueryMenu(bool firstTime = false); + char* _BuildQueryString(BEntry* entry) const; - void _AddReadButton(); - void _UpdateReadButton(); + void _AddReadButton(); + void _UpdateReadButton(); - void _SetDownloading(bool downloading); + void _SetDownloading(bool downloading); - TMailApp* fApp; + static BBitmap* _RetrieveVectorIcon(int32 id); - BEmailMessage* fMail; - entry_ref* fRef; - // Reference to currently displayed file - int32 fFieldState; - BFilePanel* fPanel; - BMenuBar* fMenuBar; - BMenuItem* fAdd; - BMenuItem* fCut; - BMenuItem* fCopy; - BMenuItem* fHeader; - BMenuItem* fPaste; - BMenuItem* fPrint; - BMenuItem* fPrintSetup; - BMenuItem* fQuote; - BMenuItem* fRaw; - BMenuItem* fRemove; - BMenuItem* fRemoveQuote; - BMenuItem* fSendNow; - BMenuItem* fSendLater; - BMenuItem* fUndo; - BMenuItem* fRedo; - BMenuItem* fNextMsg; - BMenuItem* fPrevMsg; - BMenuItem* fDeleteNext; - BMenuItem* fSpelling; - BMenu* fSaveAddrMenu; +private: + TMailApp* fApp; - BMenu* fQueryMenu; - BMenu* fLeaveStatusMenu; + BEmailMessage* fMail; + entry_ref* fRef; + // Reference to currently displayed file + int32 fFieldState; + BFilePanel* fPanel; + BMenuBar* fMenuBar; + BMenuItem* fAdd; + BMenuItem* fCut; + BMenuItem* fCopy; + BMenuItem* fHeader; + BMenuItem* fPaste; + BMenuItem* fPrint; + BMenuItem* fPrintSetup; + BMenuItem* fQuote; + BMenuItem* fRaw; + BMenuItem* fRemove; + BMenuItem* fRemoveQuote; + BMenuItem* fSendNow; + BMenuItem* fSendLater; + BMenuItem* fUndo; + BMenuItem* fRedo; + BMenuItem* fNextMsg; + BMenuItem* fPrevMsg; + BMenuItem* fDeleteNext; + BMenuItem* fSpelling; + BMenu* fSaveAddrMenu; - static BBitmap* _RetrieveVectorIcon(int32 id); - struct BitmapItem { - BBitmap* bm; - int32 id; - }; - static BObjectList fBitmapCache; - static BLocker fBitmapCacheLock; + BMenu* fQueryMenu; + BMenu* fLeaveStatusMenu; - BToolBar* fToolBar; + struct BitmapItem { + BBitmap* bm; + int32 id; + }; + static BObjectList sBitmapCache; + static BLocker sBitmapCacheLock; - BRect fZoom; - TContentView* fContentView; - THeaderView* fHeaderView; - TEnclosuresView* fEnclosuresView; - TMenu* fSignature; + BToolBar* fToolBar; - BMessenger fTrackerMessenger; - // Talks to tracker window that this was launched from. - BMessenger fMessengerToSpamServer; + BRect fZoom; + TContentView* fContentView; + THeaderView* fHeaderView; + TEnclosuresView* fEnclosuresView; + TMenu* fSignature; - entry_ref fPrevRef; - entry_ref fNextRef; - bool fPrevTrackerPositionSaved : 1; - bool fNextTrackerPositionSaved : 1; + BMessenger fTrackerMessenger; + // Talks to tracker window that this was launched from. + BMessenger fMessengerToSpamServer; - entry_ref fOpenFolder; + entry_ref fPrevRef; + entry_ref fNextRef; + bool fPrevTrackerPositionSaved : 1; + bool fNextTrackerPositionSaved : 1; - bool fSigAdded : 1; - bool fIncoming : 1; - bool fReplying : 1; - bool fResending : 1; - bool fSent : 1; - bool fDraft : 1; - bool fChanged : 1; + entry_ref fOpenFolder; - static BList sWindowList; - static BLocker sWindowListLock; + bool fSigAdded : 1; + bool fIncoming : 1; + bool fReplying : 1; + bool fResending : 1; + bool fSent : 1; + bool fDraft : 1; + bool fChanged : 1; - entry_ref fRepliedMail; - BMessenger* fOriginatingWindow; + static BList sWindowList; + static BLocker sWindowListLock; - bool fAutoMarkRead : 1; - bool fKeepStatusOnQuit; + entry_ref fRepliedMail; + BMessenger* fOriginatingWindow; - bool fDownloading; + bool fAutoMarkRead : 1; + bool fKeepStatusOnQuit; + + bool fDownloading; }; -#endif // _MAIL_WINDOW_H +#endif // _MAIL_WINDOW_H diff --git a/src/apps/powerstatus/PowerStatusView.cpp b/src/apps/powerstatus/PowerStatusView.cpp index 3b9d26c64c..2b7cc98aff 100644 --- a/src/apps/powerstatus/PowerStatusView.cpp +++ b/src/apps/powerstatus/PowerStatusView.cpp @@ -11,6 +11,7 @@ #include "PowerStatusView.h" +#include #include #include #include @@ -222,6 +223,26 @@ PowerStatusView::_DrawBattery(BRect rect) } } + if (fOnline) { + // When charging, draw a lightning symbol over the battery. + SetHighColor(255, 255, 0, 180); + SetDrawingMode(B_OP_ALPHA); + SetScale(std::min(Bounds().Width(), Bounds().Height()) / 16); + + static const BPoint points[] = { + BPoint(2, 13), + BPoint(9, 5), + BPoint(9, 7), + BPoint(16, 2), + BPoint(8, 11), + BPoint(8, 9) + }; + FillPolygon(points, 6); + + SetScale(1); + SetDrawingMode(B_OP_OVER); + } + SetHighColor(0, 0, 0); } diff --git a/src/apps/webpositive/SettingsWindow.cpp b/src/apps/webpositive/SettingsWindow.cpp index 70bdf84cf7..ae71aee8f2 100644 --- a/src/apps/webpositive/SettingsWindow.cpp +++ b/src/apps/webpositive/SettingsWindow.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -303,18 +304,12 @@ SettingsWindow::_CreateGeneralPage(float spacing) 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:"), "", + fDaysInHistory = new BSpinner("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); + fDaysInHistory->SetRange(1, 35); + fDaysInHistory->SetValue( + BrowsingHistory::DefaultInstance()->MaxHistoryItemAge()); fShowTabsIfOnlyOnePage = new BCheckBox("show tabs if only one page", B_TRANSLATE("Show tabs if only one page is open"), @@ -360,7 +355,7 @@ SettingsWindow::_CreateGeneralPage(float spacing) .Add(fAutoHideInterfaceInFullscreenMode) .Add(fAutoHidePointer) .Add(fShowHomeButton) - .Add(fDaysInHistoryMenuControl) + .Add(fDaysInHistory) .Add(BSpaceLayoutItem::CreateHorizontalStrut(spacing)) .SetInsets(spacing, spacing, spacing, spacing) @@ -580,7 +575,7 @@ SettingsWindow::_CanApplySettings() const canApply = canApply || ((fShowHomeButton->Value() == B_CONTROL_ON) != fSettings->GetValue(kSettingsKeyShowHomeButton, true)); - canApply = canApply || (_MaxHistoryAge() + canApply = canApply || (fDaysInHistory->Value() != BrowsingHistory::DefaultInstance()->MaxHistoryItemAge()); // New window policy @@ -639,12 +634,8 @@ void SettingsWindow::_ApplySettings() { // Store general settings - int32 maxHistoryAge = _MaxHistoryAge(); - BString text; - text << maxHistoryAge; - fDaysInHistoryMenuControl->SetText(text.String()); - BrowsingHistory::DefaultInstance()->SetMaxHistoryItemAge(maxHistoryAge); - + BrowsingHistory::DefaultInstance()->SetMaxHistoryItemAge( + (uint32)fDaysInHistory->Value()); fSettings->SetValue(kSettingsKeyStartPageURL, fStartPageControl->Text()); fSettings->SetValue(kSettingsKeySearchPageURL, fSearchPageControl->Text()); fSettings->SetValue(kSettingsKeyDownloadPath, fDownloadFolderControl->Text()); @@ -712,7 +703,6 @@ SettingsWindow::_ApplySettings() // the default values, unless the page settings have local overrides. BWebSettings::Default()->Apply(); - _ValidateControlsEnabledStatus(); } @@ -738,9 +728,8 @@ SettingsWindow::_RevertSettings() fShowHomeButton->SetValue( fSettings->GetValue(kSettingsKeyShowHomeButton, true)); - BString text; - text << BrowsingHistory::DefaultInstance()->MaxHistoryItemAge(); - fDaysInHistoryMenuControl->SetText(text.String()); + fDaysInHistory->SetValue( + BrowsingHistory::DefaultInstance()->MaxHistoryItemAge()); // New window policy uint32 newWindowPolicy = fSettings->GetValue(kSettingsKeyNewWindowPolicy, @@ -800,9 +789,9 @@ SettingsWindow::_RevertSettings() false)); fProxyAddressControl->SetText(fSettings->GetValue(kSettingsKeyProxyAddress, "")); - text = ""; - text << fSettings->GetValue(kSettingsKeyProxyPort, (uint32)0); - fProxyPortControl->SetText(text.String()); + BString keyProxyPort; + keyProxyPort << fSettings->GetValue(kSettingsKeyProxyPort, (uint32)0); + fProxyPortControl->SetText(keyProxyPort.String()); fUseProxyAuthCheckBox->SetValue(fSettings->GetValue(kSettingsKeyUseProxyAuth, false)); fProxyUsernameControl->SetText(fSettings->GetValue(kSettingsKeyProxyUsername, @@ -865,18 +854,6 @@ SettingsWindow::_NewTabPolicy() const } -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) { diff --git a/src/apps/webpositive/SettingsWindow.h b/src/apps/webpositive/SettingsWindow.h index eabfc5a460..4511c5a33e 100644 --- a/src/apps/webpositive/SettingsWindow.h +++ b/src/apps/webpositive/SettingsWindow.h @@ -13,6 +13,7 @@ class BCheckBox; class BMenu; class BMenuField; class BMenuItem; +class BSpinner; class BTextControl; class FontSelectionView; class SettingsMessage; @@ -46,7 +47,6 @@ private: uint32 _NewWindowPolicy() const; uint32 _NewTabPolicy() const; - int32 _MaxHistoryAge() const; void _SetSizesMenuValue(BMenu* menu, int32 value); int32 _SizesMenuValue(BMenu* menu) const; @@ -73,7 +73,7 @@ private: BMenuItem* fNewTabBehaviorOpenSearchItem; BMenuItem* fNewTabBehaviorOpenBlankItem; - BTextControl* fDaysInHistoryMenuControl; + BSpinner* fDaysInHistory; BCheckBox* fShowTabsIfOnlyOnePage; BCheckBox* fAutoHideInterfaceInFullscreenMode; BCheckBox* fAutoHidePointer; diff --git a/src/bin/Jamfile b/src/bin/Jamfile index e9d29fb28e..3768ac2fb6 100644 --- a/src/bin/Jamfile +++ b/src/bin/Jamfile @@ -48,6 +48,7 @@ StdBinCommands release.c renice.c rescan.c + system_time.cpp unchop.c uptime.cpp vmstat.cpp diff --git a/src/bin/desklink/MixerControl.cpp b/src/bin/desklink/MixerControl.cpp index dea3fa52e6..81cb36cbd3 100644 --- a/src/bin/desklink/MixerControl.cpp +++ b/src/bin/desklink/MixerControl.cpp @@ -28,8 +28,10 @@ MixerControl::MixerControl(int32 volumeWhich) fMuteParameter(NULL), fMin(0.0f), fMax(0.0f), - fStep(0.0f) + fStep(0.0f), + fRoster(NULL) { + fRoster = BMediaRoster::Roster(); } @@ -47,22 +49,22 @@ MixerControl::Connect(int32 volumeWhich, float* _value, const char** _error) _Disconnect(); status_t status = B_OK; - // BMediaRoster::Roster() doesn't set it if all is ok const char* errorString = NULL; - BMediaRoster* roster = BMediaRoster::Roster(&status); + if (fRoster == NULL) + fRoster = BMediaRoster::Roster(&status); - if (BMediaRoster::IsRunning() && roster != NULL + if (BMediaRoster::IsRunning() && fRoster != NULL && status == B_OK) { switch (volumeWhich) { case VOLUME_USE_MIXER: - status = roster->GetAudioMixer(&fGainMediaNode); + status = fRoster->GetAudioMixer(&fGainMediaNode); break; case VOLUME_USE_PHYS_OUTPUT: - status = roster->GetAudioOutput(&fGainMediaNode); + status = fRoster->GetAudioOutput(&fGainMediaNode); break; } if (status == B_OK) { - status = roster->GetParameterWebFor(fGainMediaNode, &fParameterWeb); + status = fRoster->GetParameterWebFor(fGainMediaNode, &fParameterWeb); if (status == B_OK) { // Finding the Mixer slider in the audio output ParameterWeb int32 numParams = fParameterWeb->CountParameters(); @@ -252,9 +254,11 @@ MixerControl::_Disconnect() fParameterWeb = NULL; fMixerParameter = NULL; - BMediaRoster* roster = BMediaRoster::CurrentRoster(); - if (roster != NULL && fGainMediaNode != media_node::null) - roster->ReleaseNode(fGainMediaNode); + if (fRoster == NULL) + fRoster = BMediaRoster::Roster(); + + if (fRoster != NULL && fGainMediaNode != media_node::null) + fRoster->ReleaseNode(fGainMediaNode); fGainMediaNode = media_node::null; } diff --git a/src/bin/desklink/MixerControl.h b/src/bin/desklink/MixerControl.h index 62d2dca621..68fd1254e6 100644 --- a/src/bin/desklink/MixerControl.h +++ b/src/bin/desklink/MixerControl.h @@ -56,6 +56,7 @@ private: float fMin; float fMax; float fStep; + BMediaRoster* fRoster; }; #endif // MIXER_CONTROL_H diff --git a/src/bin/leak_analyser.sh b/src/bin/leak_analyser.sh index 222388ee02..2532e2af52 100755 --- a/src/bin/leak_analyser.sh +++ b/src/bin/leak_analyser.sh @@ -14,7 +14,7 @@ then To generate such a file run a program with the following environment variables prefixed and pipe the output to a file: - LD_PRELOAD=libroot_guarded.so MALLOC_DEBUG=es50 program > file + LD_PRELOAD=libroot_debug.so MALLOC_DEBUG=ges50 program > file The number after the "s" is the stack trace depth. Note that there is an implementation defined maximum. @@ -94,6 +94,7 @@ EXCLUDE_PATTERN="" if [ -z "$NO_DEFAULTS" ] then declare -a DEFAULT_EXCLUDE_LIST=( \ + " initialize_before " \ " __cxa_atexit " \ " BPrivate::Libroot::LocaleBackend::LoadBackend" \ " initialize_before " \ @@ -108,8 +109,7 @@ then " _init " \ " BTranslatorRoster::Default" \ "Translator> " \ - " icu::" \ - " icu::" \ + " icu(_[0-9]+)?::" \ ) for EXCLUDE in "${DEFAULT_EXCLUDE_LIST[@]}" diff --git a/src/bin/network/ftp/Jamfile b/src/bin/network/ftp/Jamfile index 097fa70772..2c7c6396c6 100644 --- a/src/bin/network/ftp/Jamfile +++ b/src/bin/network/ftp/Jamfile @@ -13,7 +13,7 @@ SubDirCcFlags [ FDefines _BSD_SOURCE=1 ] ; UseBuildFeatureHeaders libedit ; -BinCommand ftp : +local ftp_src = cmds.c cmdtab.c complete.c @@ -24,6 +24,13 @@ BinCommand ftp : progressbar.c ruserpass.c util.c +; +Includes [ FGristFiles $(ftp_src) ] + : [ BuildFeatureAttribute libedit : headers ] ; + + +BinCommand ftp : + $(ftp_src) : [ BuildFeatureAttribute libedit : library ] [ BuildFeatureAttribute ncurses : library ] diff --git a/src/bin/system_time.cpp b/src/bin/system_time.cpp new file mode 100644 index 0000000000..128df6b754 --- /dev/null +++ b/src/bin/system_time.cpp @@ -0,0 +1,19 @@ +/* + * Copyright 2015 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Michael Lotz, mmlr@mlotz.ch + */ + +#include + +#include + + +int +main(int argc, char* argv[]) +{ + printf("%" B_PRIdBIGTIME "\n", system_time()); + return 0; +} diff --git a/src/kits/app/Application.cpp b/src/kits/app/Application.cpp index cf83e1df88..cda2c6d891 100644 --- a/src/kits/app/Application.cpp +++ b/src/kits/app/Application.cpp @@ -509,7 +509,7 @@ BApplication::_InitData(const char* signature, bool initGUI, status_t* _error) // create meta MIME BPath path; - if (path.SetTo(&ref) == B_OK) + if (registerApp && path.SetTo(&ref) == B_OK) create_app_meta_mime(path.Path(), false, true, false); #ifndef RUN_WITHOUT_APP_SERVER diff --git a/src/kits/app/Message.cpp b/src/kits/app/Message.cpp index aa7729cff7..d1824937e7 100644 --- a/src/kits/app/Message.cpp +++ b/src/kits/app/Message.cpp @@ -2132,6 +2132,13 @@ BMessage::_SendMessage(port_id port, team_id portOwner, int32 token, return B_NO_MEMORY; } #ifndef HAIKU_TARGET_PLATFORM_LIBBE_TEST + } else if ((fHeader->flags & MESSAGE_FLAG_REPLY_AS_KMESSAGE) != 0) { + KMessage toMessage; + result = BPrivate::MessageAdapter::ConvertToKMessage(this, toMessage); + if (result != B_OK) + return result; + + return toMessage.SendTo(port, token); } else if (fHeader->data_size > B_PAGE_SIZE * 10) { // ToDo: bind the above size to the max port message size // use message passing by area for such a large message @@ -2166,13 +2173,6 @@ BMessage::_SendMessage(port_id port, team_id portOwner, int32 token, header->message_area = transfered; } #endif - } else if ((fHeader->flags & MESSAGE_FLAG_REPLY_AS_KMESSAGE) != 0) { - KMessage toMessage; - result = BPrivate::MessageAdapter::ConvertToKMessage(this, toMessage); - if (result != B_OK) - return result; - - return toMessage.SendTo(port, token); } else { size = FlattenedSize(); buffer = (char*)malloc(size); diff --git a/src/kits/app/Roster.cpp b/src/kits/app/Roster.cpp index 46433d1827..a268796126 100644 --- a/src/kits/app/Roster.cpp +++ b/src/kits/app/Roster.cpp @@ -923,7 +923,7 @@ BRoster::Launch(const char* mimeType, BMessage* initialMessage, messageList.AddItem(initialMessage); return _LaunchApp(mimeType, NULL, &messageList, 0, NULL, - (const char**)environ, _appTeam); + (const char**)environ, _appTeam, NULL, false); } @@ -935,7 +935,7 @@ BRoster::Launch(const char* mimeType, BList* messageList, return B_BAD_VALUE; return _LaunchApp(mimeType, NULL, messageList, 0, NULL, - (const char**)environ, _appTeam); + (const char**)environ, _appTeam, NULL, false); } @@ -947,7 +947,7 @@ BRoster::Launch(const char* mimeType, int argc, const char* const* args, return B_BAD_VALUE; return _LaunchApp(mimeType, NULL, NULL, argc, args, (const char**)environ, - _appTeam); + _appTeam, NULL, false); } @@ -963,7 +963,7 @@ BRoster::Launch(const entry_ref* ref, const BMessage* initialMessage, messageList.AddItem(const_cast(initialMessage)); return _LaunchApp(NULL, ref, &messageList, 0, NULL, (const char**)environ, - _appTeam); + _appTeam, NULL, false); } @@ -975,7 +975,7 @@ BRoster::Launch(const entry_ref* ref, const BList* messageList, return B_BAD_VALUE; return _LaunchApp(NULL, ref, messageList, 0, NULL, (const char**)environ, - appTeam); + appTeam, NULL, false); } @@ -987,7 +987,7 @@ BRoster::Launch(const entry_ref* ref, int argc, const char* const* args, return B_BAD_VALUE; return _LaunchApp(NULL, ref, NULL, argc, args, (const char**)environ, - appTeam); + appTeam, NULL, false); } @@ -1800,6 +1800,10 @@ BRoster::_UpdateActiveApp(team_id team) const \c B_REFS_RECEIVED message, if no arguments are supplied via \a argc and \args. + If \a launchSuspended is set to true, the main thread of the loaded app + (returned in \a appThread) is kept in the suspended state and not + automatically resumed. + \param mimeType MIME type for which the application shall be launched. May be \c NULL. \param ref entry_ref referring to the file for which an application shall @@ -1811,6 +1815,10 @@ BRoster::_UpdateActiveApp(team_id team) const to the launched application. \param appTeam Pointer to a pre-allocated team_id variable to be set to the team ID of the launched application. + \param appThread Pointer to a pre-allocated thread_id variable to + be set to the thread ID of the launched main thread. + \param launchSuspended Indicates whether to keep the app thread in the + suspended state or resume it. \return A status code. \retval B_OK Everything went fine. @@ -1828,7 +1836,8 @@ BRoster::_UpdateActiveApp(team_id team) const status_t BRoster::_LaunchApp(const char* mimeType, const entry_ref* ref, const BList* messageList, int argc, const char* const* args, - const char** environment, team_id* _appTeam) const + const char** environment, team_id* _appTeam, + thread_id* _appThread, bool launchSuspended) const { DBG(OUT("BRoster::_LaunchApp()")); @@ -1856,6 +1865,7 @@ BRoster::_LaunchApp(const char* mimeType, const entry_ref* ref, status_t error = B_OK; ArgVector argVector; team_id team = -1; + thread_id appThread = -1; do { // find the app @@ -1900,7 +1910,7 @@ BRoster::_LaunchApp(const char* mimeType, const entry_ref* ref, if (error == B_OK && !alreadyRunning) { DBG(OUT(" token: %lu\n", appToken)); // load the app image - thread_id appThread = load_image(argVector.Count(), + appThread = load_image(argVector.Count(), const_cast(argVector.Args()), environment); // get the app team @@ -1922,7 +1932,7 @@ BRoster::_LaunchApp(const char* mimeType, const entry_ref* ref, DBG(OUT(" set thread and team: %s (%lx)\n", strerror(error), error)); // resume the launched team - if (error == B_OK) + if (error == B_OK && !launchSuspended) error = resume_thread(appThread); DBG(OUT(" resume thread: %s (%lx)\n", strerror(error), error)); @@ -1983,6 +1993,9 @@ BRoster::_LaunchApp(const char* mimeType, const entry_ref* ref, error = B_ALREADY_RUNNING; else if (_appTeam) *_appTeam = team; + + if (_appThread != NULL) + *_appThread = appThread; } DBG(OUT("BRoster::_LaunchApp() done: %s (%lx)\n", @@ -2068,7 +2081,7 @@ BRoster::_ResolveApp(const char* inType, entry_ref* ref, } // create meta mime - if (error == B_OK) { + if (!fNoRegistrar && error == B_OK) { BPath path; if (path.SetTo(&appRef) == B_OK) create_app_meta_mime(path.Path(), false, true, false); @@ -2077,7 +2090,7 @@ BRoster::_ResolveApp(const char* inType, entry_ref* ref, // set the app hint on the type -- but only if the file has the // respective signature, otherwise unset the app hint BAppFileInfo appFileInfo; - if (error == B_OK) { + if (!fNoRegistrar && error == B_OK) { char signature[B_MIME_TYPE_LENGTH]; if (appFileInfo.SetTo(&appFile) == B_OK && appFileInfo.GetSignature(signature) == B_OK) { @@ -2482,6 +2495,9 @@ BRoster::_GetFileType(const entry_ref* file, BNodeInfo* nodeInfo, if (nodeInfo->GetType(mimeType) == B_OK) return B_OK; + if (fNoRegistrar) + return B_NO_INIT; + // Try to update the file's MIME info and just read the updated type. // If that fails, sniff manually. BPath path; @@ -2610,7 +2626,10 @@ BRoster::_InitMessenger() if (BLaunchRoster().GetData(B_REGISTRAR_SIGNATURE, data) == B_OK) { port_id port = data.GetInt32("port", -1); team_id team = data.GetInt32("team", -1); - if (port >= 0) { + + if (port >= 0 && team != current_team()) { + // Make sure we aren't the registrar ourselves. + DBG(OUT(" found roster port\n")); BMessenger::Private(fMessenger).SetTo(team, port, diff --git a/src/kits/interface/AbstractSpinner.cpp b/src/kits/interface/AbstractSpinner.cpp new file mode 100644 index 0000000000..576697a835 --- /dev/null +++ b/src/kits/interface/AbstractSpinner.cpp @@ -0,0 +1,1693 @@ +/* + * Copyright 2004 DarkWyrm + * Copyright 2013 FeemanLou + * Copyright 2014-2015 Haiku, Inc. All rights reserved. + * + * Distributed under the terms of the MIT license. + * + * Originally written by DarkWyrm + * Updated by FreemanLou as part of Google GCI 2013 + * + * Authors: + * DarkWyrm, darkwyrm@earthlink.net + * FeemanLou + * John Scipione, jscipione@gmail.com + */ + + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Thread.h" + + +static const float kFrameMargin = 2.0f; + +const char* const kFrameField = "BAbstractSpinner:layoutItem:frame"; +const char* const kLabelItemField = "BAbstractSpinner:labelItem"; +const char* const kTextViewItemField = "BAbstractSpinner:textViewItem"; + + +static property_info sProperties[] = { + { + "Align", + { B_GET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns the alignment of the spinner label.", + 0, + { B_INT32_TYPE } + }, + { + "Align", + { B_SET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0}, + "Sets the alignment of the spinner label.", + 0, + { B_INT32_TYPE } + }, + + { + "ButtonStyle", + { B_GET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns the style of the spinner buttons.", + 0, + { B_INT32_TYPE } + }, + { + "ButtonStyle", + { B_SET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0}, + "Sets the style of the spinner buttons.", + 0, + { B_INT32_TYPE } + }, + + { + "Divider", + { B_GET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns the divider position of the spinner.", + 0, + { B_FLOAT_TYPE } + }, + { + "Divider", + { B_SET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0}, + "Sets the divider position of the spinner.", + 0, + { B_FLOAT_TYPE } + }, + + { + "Enabled", + { B_GET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns whether or not the spinner is enabled.", + 0, + { B_BOOL_TYPE } + }, + { + "Enabled", + { B_SET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0}, + "Sets whether or not the spinner is enabled.", + 0, + { B_BOOL_TYPE } + }, + + { + "Label", + { B_GET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns the spinner label.", + 0, + { B_STRING_TYPE } + }, + { + "Label", + { B_SET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0}, + "Sets the spinner label.", + 0, + { B_STRING_TYPE } + }, + + { + "Message", + { B_GET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns the spinner invocation message.", + 0, + { B_MESSAGE_TYPE } + }, + { + "Message", + { B_SET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0}, + "Sets the spinner invocation message.", + 0, + { B_MESSAGE_TYPE } + }, + + { 0 } +}; + + +typedef enum { + SPINNER_INCREMENT, + SPINNER_DECREMENT +} spinner_direction; + + +class SpinnerButton : public BView { +public: + SpinnerButton(BRect frame, const char* name, + spinner_direction direction); + virtual ~SpinnerButton(); + + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + virtual void Draw(BRect updateRect); + virtual void MouseDown(BPoint where); + virtual void MouseUp(BPoint where); + virtual void MouseMoved(BPoint where, uint32 transit, + const BMessage* message); + + bool IsEnabled() const { return fIsEnabled; } + virtual void SetEnabled(bool enable) { fIsEnabled = enable; }; + +private: + void _DoneTracking(BPoint where); + void _Track(BPoint where, uint32); + + spinner_direction fSpinnerDirection; + BAbstractSpinner* fParent; + bool fIsEnabled; + bool fIsMouseDown; + bool fIsMouseOver; + bigtime_t fRepeatDelay; +}; + + +class SpinnerTextView : public BTextView { +public: + SpinnerTextView(BRect rect, BRect textRect); + virtual ~SpinnerTextView(); + + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + virtual void KeyDown(const char* bytes, int32 numBytes); + virtual void MakeFocus(bool focus); + +private: + BAbstractSpinner* fParent; +}; + + +class BAbstractSpinner::LabelLayoutItem : public BAbstractLayoutItem { +public: + LabelLayoutItem(BAbstractSpinner* parent); + LabelLayoutItem(BMessage* archive); + + virtual bool IsVisible(); + virtual void SetVisible(bool visible); + + virtual BRect Frame(); + virtual void SetFrame(BRect frame); + + void SetParent(BAbstractSpinner* parent); + virtual BView* View(); + + virtual BSize BaseMinSize(); + virtual BSize BaseMaxSize(); + virtual BSize BasePreferredSize(); + virtual BAlignment BaseAlignment(); + + BRect FrameInParent() const; + + virtual status_t Archive(BMessage* into, bool deep = true) const; + static BArchivable* Instantiate(BMessage* from); + +private: + BAbstractSpinner* fParent; + BRect fFrame; +}; + + +class BAbstractSpinner::TextViewLayoutItem : public BAbstractLayoutItem { +public: + TextViewLayoutItem(BAbstractSpinner* parent); + TextViewLayoutItem(BMessage* archive); + + virtual bool IsVisible(); + virtual void SetVisible(bool visible); + + virtual BRect Frame(); + virtual void SetFrame(BRect frame); + + void SetParent(BAbstractSpinner* parent); + virtual BView* View(); + + virtual BSize BaseMinSize(); + virtual BSize BaseMaxSize(); + virtual BSize BasePreferredSize(); + virtual BAlignment BaseAlignment(); + + BRect FrameInParent() const; + + virtual status_t Archive(BMessage* into, bool deep = true) const; + static BArchivable* Instantiate(BMessage* from); + +private: + BAbstractSpinner* fParent; + BRect fFrame; +}; + + +struct BAbstractSpinner::LayoutData { + LayoutData(float width, float height) + : + label_layout_item(NULL), + text_view_layout_item(NULL), + label_width(0), + label_height(0), + text_view_width(0), + text_view_height(0), + previous_width(width), + previous_height(height), + valid(false) + { + } + + LabelLayoutItem* label_layout_item; + TextViewLayoutItem* text_view_layout_item; + + font_height font_info; + + float label_width; + float label_height; + float text_view_width; + float text_view_height; + + float previous_width; + float previous_height; + + BSize min; + BAlignment alignment; + + bool valid; +}; + + +// #pragma mark - SpinnerButton + + +SpinnerButton::SpinnerButton(BRect frame, const char* name, + spinner_direction direction) + : + BView(frame, name, B_FOLLOW_RIGHT | B_FOLLOW_TOP, B_WILL_DRAW), + fSpinnerDirection(direction), + fParent(NULL), + fIsEnabled(true), + fIsMouseDown(false), + fIsMouseOver(false), + fRepeatDelay(100000) +{ + rgb_color bgColor = ui_color(B_PANEL_BACKGROUND_COLOR); + SetViewColor(bgColor); + SetLowColor(bgColor); +} + + +SpinnerButton::~SpinnerButton() +{ +} + + +void +SpinnerButton::AttachedToWindow() +{ + fParent = static_cast(Parent()); + + BView::AttachedToWindow(); +} + + +void +SpinnerButton::DetachedFromWindow() +{ + fParent = NULL; + + BView::DetachedFromWindow(); +} + + +void +SpinnerButton::Draw(BRect updateRect) +{ + BRect rect(Bounds()); + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + BView::Draw(updateRect); + + float frameTint = B_DARKEN_1_TINT; + + float fgTint; + if (!fIsEnabled) + fgTint = B_DARKEN_1_TINT; + else if (fIsMouseDown) + fgTint = B_DARKEN_MAX_TINT; + else + fgTint = 1.777f; // 216 --> 48.2 (48) + + float bgTint; + if (fIsEnabled && fIsMouseOver) + bgTint = B_DARKEN_1_TINT; + else + bgTint = B_NO_TINT; + + rgb_color bgColor = ui_color(B_PANEL_BACKGROUND_COLOR); + if (bgColor.red + bgColor.green + bgColor.blue <= 128 * 3) { + // if dark background make the tint lighter + frameTint = 2.0f - frameTint; + fgTint = 2.0f - fgTint; + bgTint = 2.0f - bgTint; + } + + uint32 borders = be_control_look->B_TOP_BORDER + | be_control_look->B_BOTTOM_BORDER; + + if (fSpinnerDirection == SPINNER_INCREMENT) + borders |= be_control_look->B_RIGHT_BORDER; + else + borders |= be_control_look->B_LEFT_BORDER; + + // draw the button + be_control_look->DrawButtonFrame(this, rect, updateRect, + tint_color(bgColor, frameTint), bgColor, 0, borders); + be_control_look->DrawButtonBackground(this, rect, updateRect, + tint_color(bgColor, bgTint), 0, borders); + + switch (fParent->ButtonStyle()) { + case SPINNER_BUTTON_HORIZONTAL_ARROWS: + { + int32 arrowDirection = fSpinnerDirection == SPINNER_INCREMENT + ? be_control_look->B_RIGHT_ARROW + : be_control_look->B_LEFT_ARROW; + + rect.InsetBy(0.0f, 1.0f); + be_control_look->DrawArrowShape(this, rect, updateRect, bgColor, + arrowDirection, 0, fgTint); + break; + } + + case SPINNER_BUTTON_VERTICAL_ARROWS: + { + int32 arrowDirection = fSpinnerDirection == SPINNER_INCREMENT + ? be_control_look->B_UP_ARROW + : be_control_look->B_DOWN_ARROW; + + rect.InsetBy(0.0f, 1.0f); + be_control_look->DrawArrowShape(this, rect, updateRect, bgColor, + arrowDirection, 0, fgTint); + break; + } + + default: + case SPINNER_BUTTON_PLUS_MINUS: + { + BFont font; + fParent->GetFont(&font); + float inset = floorf(font.Size() / 4); + rect.InsetBy(inset, inset); + + if (rect.IntegerWidth() % 2 != 0) + rect.right -= 1; + + if (rect.IntegerHeight() % 2 != 0) + rect.bottom -= 1; + + SetHighColor(tint_color(bgColor, fgTint)); + + // draw the +/- + float halfHeight = floorf(rect.Height() / 2); + StrokeLine(BPoint(rect.left, rect.top + halfHeight), + BPoint(rect.right, rect.top + halfHeight)); + if (fSpinnerDirection == SPINNER_INCREMENT) { + float halfWidth = floorf(rect.Width() / 2); + StrokeLine(BPoint(rect.left + halfWidth, rect.top), + BPoint(rect.left + halfWidth, rect.bottom)); + } + } + } +} + + +void +SpinnerButton::MouseDown(BPoint where) +{ + if (fIsEnabled) { + fIsMouseDown = true; + Invalidate(); + fRepeatDelay = 100000; + MouseDownThread::TrackMouse(this, + &SpinnerButton::_DoneTracking, &SpinnerButton::_Track); + } + + BView::MouseDown(where); +} + + +void +SpinnerButton::MouseMoved(BPoint where, uint32 transit, + const BMessage* message) +{ + switch (transit) { + case B_ENTERED_VIEW: + case B_INSIDE_VIEW: + { + BPoint where; + uint32 buttons; + GetMouse(&where, &buttons); + fIsMouseOver = Bounds().Contains(where) && buttons == 0; + if (!fIsMouseDown) + Invalidate(); + + break; + } + + case B_EXITED_VIEW: + case B_OUTSIDE_VIEW: + fIsMouseOver = false; + MouseUp(Bounds().LeftTop()); + break; + } + + BView::MouseMoved(where, transit, message); +} + + +void +SpinnerButton::MouseUp(BPoint where) +{ + fIsMouseDown = false; + Invalidate(); + + BView::MouseUp(where); +} + + +// #pragma mark - SpinnerButton private methods + + +void +SpinnerButton::_DoneTracking(BPoint where) +{ + if (fIsMouseDown || !Bounds().Contains(where)) + fIsMouseDown = false; +} + + +void +SpinnerButton::_Track(BPoint where, uint32) +{ + if (fParent == NULL || !Bounds().Contains(where)) { + fIsMouseDown = false; + return; + } + fIsMouseDown = true; + + fSpinnerDirection == SPINNER_INCREMENT + ? fParent->Increment() + : fParent->Decrement(); + + snooze(fRepeatDelay); + fRepeatDelay = 10000; +} + + +// #pragma mark - SpinnerTextView + + +SpinnerTextView::SpinnerTextView(BRect rect, BRect textRect) + : + BTextView(rect, "textview", textRect, B_FOLLOW_ALL, + B_WILL_DRAW | B_NAVIGABLE), + fParent(NULL) +{ + rgb_color bgColor = ui_color(B_PANEL_BACKGROUND_COLOR); + SetViewColor(bgColor); + SetLowColor(bgColor); +} + + +SpinnerTextView::~SpinnerTextView() +{ +} + + +void +SpinnerTextView::AttachedToWindow() +{ + fParent = static_cast(Parent()); + + BTextView::AttachedToWindow(); +} + + +void +SpinnerTextView::DetachedFromWindow() +{ + fParent = NULL; + + BTextView::DetachedFromWindow(); +} + + +void +SpinnerTextView::KeyDown(const char* bytes, int32 numBytes) +{ + if (fParent == NULL) { + BTextView::KeyDown(bytes, numBytes); + return; + } + + switch (bytes[0]) { + case B_ENTER: + case B_SPACE: + fParent->SetValueFromText(); + break; + + case B_TAB: + fParent->KeyDown(bytes, numBytes); + break; + + case B_LEFT_ARROW: + if (fParent->ButtonStyle() == SPINNER_BUTTON_HORIZONTAL_ARROWS + && (modifiers() & B_CONTROL_KEY) != 0) { + // need to hold down control, otherwise can't move cursor + fParent->Decrement(); + } else + BTextView::KeyDown(bytes, numBytes); + break; + + case B_UP_ARROW: + if (fParent->ButtonStyle() != SPINNER_BUTTON_HORIZONTAL_ARROWS) + fParent->Increment(); + else + BTextView::KeyDown(bytes, numBytes); + break; + + case B_RIGHT_ARROW: + if (fParent->ButtonStyle() == SPINNER_BUTTON_HORIZONTAL_ARROWS + && (modifiers() & B_CONTROL_KEY) != 0) { + // need to hold down control, otherwise can't move cursor + fParent->Increment(); + } else + BTextView::KeyDown(bytes, numBytes); + break; + + case B_DOWN_ARROW: + if (fParent->ButtonStyle() != SPINNER_BUTTON_HORIZONTAL_ARROWS) + fParent->Decrement(); + else + BTextView::KeyDown(bytes, numBytes); + break; + + default: + BTextView::KeyDown(bytes, numBytes); + break; + } +} + + +void +SpinnerTextView::MakeFocus(bool focus) +{ + BTextView::MakeFocus(focus); + + if (fParent == NULL) + return; + + if (focus) + SelectAll(); + else + fParent->SetValueFromText(); + + fParent->_DrawTextView(fParent->Bounds()); +} + + +// #pragma mark - BAbstractSpinner::LabelLayoutItem + + +BAbstractSpinner::LabelLayoutItem::LabelLayoutItem(BAbstractSpinner* parent) + : + fParent(parent), + fFrame() +{ +} + + +BAbstractSpinner::LabelLayoutItem::LabelLayoutItem(BMessage* from) + : + BAbstractLayoutItem(from), + fParent(NULL), + fFrame() +{ + from->FindRect(kFrameField, &fFrame); +} + + +bool +BAbstractSpinner::LabelLayoutItem::IsVisible() +{ + return !fParent->IsHidden(fParent); +} + + +void +BAbstractSpinner::LabelLayoutItem::SetVisible(bool visible) +{ +} + + +BRect +BAbstractSpinner::LabelLayoutItem::Frame() +{ + return fFrame; +} + + +void +BAbstractSpinner::LabelLayoutItem::SetFrame(BRect frame) +{ + fFrame = frame; + fParent->_UpdateFrame(); +} + + +void +BAbstractSpinner::LabelLayoutItem::SetParent(BAbstractSpinner* parent) +{ + fParent = parent; +} + + +BView* +BAbstractSpinner::LabelLayoutItem::View() +{ + return fParent; +} + + +BSize +BAbstractSpinner::LabelLayoutItem::BaseMinSize() +{ + fParent->_ValidateLayoutData(); + + if (fParent->Label() == NULL) + return BSize(-1.0f, -1.0f); + + return BSize(fParent->fLayoutData->label_width + + be_control_look->DefaultLabelSpacing(), + fParent->fLayoutData->label_height); +} + + +BSize +BAbstractSpinner::LabelLayoutItem::BaseMaxSize() +{ + return BaseMinSize(); +} + + +BSize +BAbstractSpinner::LabelLayoutItem::BasePreferredSize() +{ + return BaseMinSize(); +} + + +BAlignment +BAbstractSpinner::LabelLayoutItem::BaseAlignment() +{ + return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT); +} + + +BRect +BAbstractSpinner::LabelLayoutItem::FrameInParent() const +{ + return fFrame.OffsetByCopy(-fParent->Frame().left, -fParent->Frame().top); +} + + +status_t +BAbstractSpinner::LabelLayoutItem::Archive(BMessage* into, bool deep) const +{ + BArchiver archiver(into); + status_t result = BAbstractLayoutItem::Archive(into, deep); + + if (result == B_OK) + result = into->AddRect(kFrameField, fFrame); + + return archiver.Finish(result); +} + + +BArchivable* +BAbstractSpinner::LabelLayoutItem::Instantiate(BMessage* from) +{ + if (validate_instantiation(from, "BAbstractSpinner::LabelLayoutItem")) + return new LabelLayoutItem(from); + + return NULL; +} + + +// #pragma mark - BAbstractSpinner::TextViewLayoutItem + + +BAbstractSpinner::TextViewLayoutItem::TextViewLayoutItem(BAbstractSpinner* parent) + : + fParent(parent), + fFrame() +{ + SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); +} + + +BAbstractSpinner::TextViewLayoutItem::TextViewLayoutItem(BMessage* from) + : + BAbstractLayoutItem(from), + fParent(NULL), + fFrame() +{ + from->FindRect(kFrameField, &fFrame); +} + + +bool +BAbstractSpinner::TextViewLayoutItem::IsVisible() +{ + return !fParent->IsHidden(fParent); +} + + +void +BAbstractSpinner::TextViewLayoutItem::SetVisible(bool visible) +{ + // not allowed +} + + +BRect +BAbstractSpinner::TextViewLayoutItem::Frame() +{ + return fFrame; +} + + +void +BAbstractSpinner::TextViewLayoutItem::SetFrame(BRect frame) +{ + fFrame = frame; + fParent->_UpdateFrame(); +} + + +void +BAbstractSpinner::TextViewLayoutItem::SetParent(BAbstractSpinner* parent) +{ + fParent = parent; +} + + +BView* +BAbstractSpinner::TextViewLayoutItem::View() +{ + return fParent; +} + + +BSize +BAbstractSpinner::TextViewLayoutItem::BaseMinSize() +{ + fParent->_ValidateLayoutData(); + + BSize size(fParent->fLayoutData->text_view_width, + fParent->fLayoutData->text_view_height); + + return size; +} + + +BSize +BAbstractSpinner::TextViewLayoutItem::BaseMaxSize() +{ + return BaseMinSize(); +} + + +BSize +BAbstractSpinner::TextViewLayoutItem::BasePreferredSize() +{ + return BaseMinSize(); +} + + +BAlignment +BAbstractSpinner::TextViewLayoutItem::BaseAlignment() +{ + return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT); +} + + +BRect +BAbstractSpinner::TextViewLayoutItem::FrameInParent() const +{ + return fFrame.OffsetByCopy(-fParent->Frame().left, -fParent->Frame().top); +} + + +status_t +BAbstractSpinner::TextViewLayoutItem::Archive(BMessage* into, bool deep) const +{ + BArchiver archiver(into); + status_t result = BAbstractLayoutItem::Archive(into, deep); + + if (result == B_OK) + result = into->AddRect(kFrameField, fFrame); + + return archiver.Finish(result); +} + + +BArchivable* +BAbstractSpinner::TextViewLayoutItem::Instantiate(BMessage* from) +{ + if (validate_instantiation(from, "BAbstractSpinner::TextViewLayoutItem")) + return new LabelLayoutItem(from); + + return NULL; +} + + +// #pragma mark - BAbstractSpinner + + +BAbstractSpinner::BAbstractSpinner(BRect frame, const char* name, const char* label, + BMessage* message, uint32 resizingMode, uint32 flags) + : + BControl(frame, name, label, message, resizingMode, + flags | B_WILL_DRAW | B_FRAME_EVENTS) +{ + _InitObject(); +} + + +BAbstractSpinner::BAbstractSpinner(const char* name, const char* label, BMessage* message, + uint32 flags) + : + BControl(name, label, message, flags | B_WILL_DRAW | B_FRAME_EVENTS) +{ + _InitObject(); +} + + +BAbstractSpinner::BAbstractSpinner(BMessage* data) + : + BControl(data), + fButtonStyle(SPINNER_BUTTON_PLUS_MINUS) +{ + _InitObject(); + + if (data->FindInt32("_align") != B_OK) + fAlignment = B_ALIGN_LEFT; + + if (data->FindInt32("_button_style") != B_OK) + fButtonStyle = SPINNER_BUTTON_PLUS_MINUS; + + if (data->FindInt32("_divider") != B_OK) + fDivider = 0.0f; +} + + +BAbstractSpinner::~BAbstractSpinner() +{ + delete fLayoutData; + fLayoutData = NULL; +} + + +BArchivable* +BAbstractSpinner::Instantiate(BMessage* data) +{ + // cannot instantiate an abstract spinner + return NULL; +} + + +status_t +BAbstractSpinner::Archive(BMessage* data, bool deep) const +{ + status_t status = BControl::Archive(data, deep); + data->AddString("class", "Spinner"); + + if (status == B_OK) + status = data->AddInt32("_align", fAlignment); + + if (status == B_OK) + data->AddInt32("_button_style", fButtonStyle); + + if (status == B_OK) + status = data->AddFloat("_divider", fDivider); + + return status; +} + + +status_t +BAbstractSpinner::GetSupportedSuites(BMessage* message) +{ + message->AddString("suites", "suite/vnd.Haiku-spinner"); + + BPropertyInfo prop_info(sProperties); + message->AddFlat("messages", &prop_info); + + return BView::GetSupportedSuites(message); +} + + +BHandler* +BAbstractSpinner::ResolveSpecifier(BMessage* message, int32 index, BMessage* specifier, + int32 form, const char* property) +{ + return BView::ResolveSpecifier(message, index, specifier, form, + property); +} + + +void +BAbstractSpinner::AttachedToWindow() +{ + if (!Messenger().IsValid()) + SetTarget(Window()); + + BControl::SetValue(Value()); + // sets the text and enables or disables the arrows + + _UpdateTextViewColors(IsEnabled()); + fTextView->MakeEditable(IsEnabled()); + + BView::AttachedToWindow(); +} + + +void +BAbstractSpinner::Draw(BRect updateRect) +{ + _DrawLabel(updateRect); + _DrawTextView(updateRect); + fIncrement->Invalidate(); + fDecrement->Invalidate(); +} + + +void +BAbstractSpinner::FrameResized(float width, float height) +{ + BView::FrameResized(width, height); + + // TODO: this causes flickering still... + + // changes in width + + BRect bounds = Bounds(); + + if (bounds.Width() > fLayoutData->previous_width) { + // invalidate the region between the old and the new right border + BRect rect = bounds; + rect.left += fLayoutData->previous_width - kFrameMargin; + rect.right--; + Invalidate(rect); + } else if (bounds.Width() < fLayoutData->previous_width) { + // invalidate the region of the new right border + BRect rect = bounds; + rect.left = rect.right - kFrameMargin; + Invalidate(rect); + } + + // changes in height + + if (bounds.Height() > fLayoutData->previous_height) { + // invalidate the region between the old and the new bottom border + BRect rect = bounds; + rect.top += fLayoutData->previous_height - kFrameMargin; + rect.bottom--; + Invalidate(rect); + // invalidate label area + rect = bounds; + rect.right = fDivider; + Invalidate(rect); + } else if (bounds.Height() < fLayoutData->previous_height) { + // invalidate the region of the new bottom border + BRect rect = bounds; + rect.top = rect.bottom - kFrameMargin; + Invalidate(rect); + // invalidate label area + rect = bounds; + rect.right = fDivider; + Invalidate(rect); + } + + fLayoutData->previous_width = bounds.Width(); + fLayoutData->previous_height = bounds.Height(); +} + + +void +BAbstractSpinner::ValueChanged() +{ + // hook method - does nothing +} + + +void +BAbstractSpinner::MakeFocus(bool focus) +{ + fTextView->MakeFocus(focus); +} + + +void +BAbstractSpinner::ResizeToPreferred() +{ + BView::ResizeToPreferred(); + + const char* label = Label(); + if (label != NULL) { + fDivider = ceilf(StringWidth(label)) + + be_control_look->DefaultLabelSpacing(); + } else + fDivider = 0.0f; + + _LayoutTextView(); +} + + +void +BAbstractSpinner::SetFlags(uint32 flags) +{ + // If the textview is navigable, set it to not navigable if needed, + // else if it is not navigable, set it to navigable if needed + if (fTextView->Flags() & B_NAVIGABLE) { + if (!(flags & B_NAVIGABLE)) + fTextView->SetFlags(fTextView->Flags() & ~B_NAVIGABLE); + } else { + if (flags & B_NAVIGABLE) + fTextView->SetFlags(fTextView->Flags() | B_NAVIGABLE); + } + + // Don't make this one navigable + flags &= ~B_NAVIGABLE; + + BView::SetFlags(flags); +} + + +void +BAbstractSpinner::WindowActivated(bool active) +{ + _DrawTextView(fTextView->Frame()); +} + + +void +BAbstractSpinner::SetAlignment(alignment align) +{ + fAlignment = align; +} + + +void +BAbstractSpinner::SetButtonStyle(spinner_button_style buttonStyle) +{ + fButtonStyle = buttonStyle; +} + + +void +BAbstractSpinner::SetDivider(float position) +{ + position = roundf(position); + + float delta = fDivider - position; + if (delta == 0.0f) + return; + + fDivider = position; + + if ((Flags() & B_SUPPORTS_LAYOUT) != 0) { + // We should never get here, since layout support means, we also + // layout the divider, and don't use this method at all. + Relayout(); + } else { + _LayoutTextView(); + Invalidate(); + } +} + + +void +BAbstractSpinner::SetEnabled(bool enable) +{ + if (IsEnabled() == enable) + return; + + BControl::SetEnabled(enable); + + fTextView->MakeEditable(enable); + if (enable) + fTextView->SetFlags(fTextView->Flags() | B_NAVIGABLE); + else + fTextView->SetFlags(fTextView->Flags() & ~B_NAVIGABLE); + + _UpdateTextViewColors(enable); + fTextView->Invalidate(); + + _LayoutTextView(); + Invalidate(); + if (Window() != NULL) + Window()->UpdateIfNeeded(); +} + + +void +BAbstractSpinner::SetLabel(const char* label) +{ + BControl::SetLabel(label); + + if (Window() != NULL) + Window()->UpdateIfNeeded(); +} + + +bool +BAbstractSpinner::IsDecrementEnabled() const +{ + return fDecrement->IsEnabled(); +} + + +void +BAbstractSpinner::SetDecrementEnabled(bool enable) +{ + if (IsDecrementEnabled() == enable) + return; + + fDecrement->SetEnabled(enable); + fDecrement->Invalidate(); +} + + +bool +BAbstractSpinner::IsIncrementEnabled() const +{ + return fIncrement->IsEnabled(); +} + + +void +BAbstractSpinner::SetIncrementEnabled(bool enable) +{ + if (IsIncrementEnabled() == enable) + return; + + fIncrement->SetEnabled(enable); + fIncrement->Invalidate(); +} + + +BSize +BAbstractSpinner::MinSize() +{ + _ValidateLayoutData(); + return BLayoutUtils::ComposeSize(ExplicitMinSize(), fLayoutData->min); +} + + +BSize +BAbstractSpinner::MaxSize() +{ + _ValidateLayoutData(); + + BSize max = fLayoutData->min; + max.width = B_SIZE_UNLIMITED; + + return BLayoutUtils::ComposeSize(ExplicitMaxSize(), max); +} + + +BSize +BAbstractSpinner::PreferredSize() +{ + _ValidateLayoutData(); + return BLayoutUtils::ComposeSize(ExplicitPreferredSize(), + fLayoutData->min); +} + + +BAlignment +BAbstractSpinner::LayoutAlignment() +{ + _ValidateLayoutData(); + return BLayoutUtils::ComposeAlignment(ExplicitAlignment(), + BAlignment(B_ALIGN_LEFT, B_ALIGN_VERTICAL_CENTER)); +} + + +BLayoutItem* +BAbstractSpinner::CreateLabelLayoutItem() +{ + if (fLayoutData->label_layout_item == NULL) + fLayoutData->label_layout_item = new LabelLayoutItem(this); + + return fLayoutData->label_layout_item; +} + + +BLayoutItem* +BAbstractSpinner::CreateTextViewLayoutItem() +{ + if (fLayoutData->text_view_layout_item == NULL) + fLayoutData->text_view_layout_item = new TextViewLayoutItem(this); + + return fLayoutData->text_view_layout_item; +} + + +BTextView* +BAbstractSpinner::TextView() const +{ + return dynamic_cast(fTextView); +} + + +// #pragma mark - BAbstractSpinner protected methods + + +status_t +BAbstractSpinner::AllArchived(BMessage* into) const +{ + status_t result; + if ((result = BControl::AllArchived(into)) != B_OK) + return result; + + BArchiver archiver(into); + + BArchivable* textViewItem = fLayoutData->text_view_layout_item; + if (archiver.IsArchived(textViewItem)) + result = archiver.AddArchivable(kTextViewItemField, textViewItem); + + if (result != B_OK) + return result; + + BArchivable* labelBarItem = fLayoutData->label_layout_item; + if (archiver.IsArchived(labelBarItem)) + result = archiver.AddArchivable(kLabelItemField, labelBarItem); + + return result; +} + + +status_t +BAbstractSpinner::AllUnarchived(const BMessage* from) +{ + BUnarchiver unarchiver(from); + + status_t result = B_OK; + if ((result = BControl::AllUnarchived(from)) != B_OK) + return result; + + if (unarchiver.IsInstantiated(kTextViewItemField)) { + TextViewLayoutItem*& textViewItem + = fLayoutData->text_view_layout_item; + result = unarchiver.FindObject(kTextViewItemField, + BUnarchiver::B_DONT_ASSUME_OWNERSHIP, textViewItem); + + if (result == B_OK) + textViewItem->SetParent(this); + else + return result; + } + + if (unarchiver.IsInstantiated(kLabelItemField)) { + LabelLayoutItem*& labelItem = fLayoutData->label_layout_item; + result = unarchiver.FindObject(kLabelItemField, + BUnarchiver::B_DONT_ASSUME_OWNERSHIP, labelItem); + + if (result == B_OK) + labelItem->SetParent(this); + } + + return result; +} + + +void +BAbstractSpinner::DoLayout() +{ + if ((Flags() & B_SUPPORTS_LAYOUT) == 0) + return; + + if (GetLayout()) { + BControl::DoLayout(); + return; + } + + _ValidateLayoutData(); + + BSize size(Bounds().Size()); + if (size.width < fLayoutData->min.width) + size.width = fLayoutData->min.width; + + if (size.height < fLayoutData->min.height) + size.height = fLayoutData->min.height; + + float divider = 0; + if (fLayoutData->label_layout_item != NULL + && fLayoutData->text_view_layout_item != NULL + && fLayoutData->label_layout_item->Frame().IsValid() + && fLayoutData->text_view_layout_item->Frame().IsValid()) { + divider = fLayoutData->text_view_layout_item->Frame().left + - fLayoutData->label_layout_item->Frame().left; + } else if (fLayoutData->label_width > 0) { + divider = fLayoutData->label_width + + be_control_look->DefaultLabelSpacing(); + } + fDivider = divider; + + BRect dirty(fTextView->Frame()); + _LayoutTextView(); + + // invalidate dirty region + dirty = dirty | fTextView->Frame(); + dirty = dirty | fIncrement->Frame(); + dirty = dirty | fDecrement->Frame(); + + Invalidate(dirty); +} + + +void +BAbstractSpinner::LayoutInvalidated(bool descendants) +{ + if (fLayoutData != NULL) + fLayoutData->valid = false; +} + + +// #pragma mark - BAbstractSpinner private methods + + +void +BAbstractSpinner::_DrawLabel(BRect updateRect) +{ + BRect rect(Bounds()); + rect.right = fDivider; + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + _ValidateLayoutData(); + + const char* label = Label(); + if (label == NULL) + return; + + // horizontal position + float x; + switch (fAlignment) { + case B_ALIGN_RIGHT: + x = fDivider - fLayoutData->label_width - 3.0f; + break; + + case B_ALIGN_CENTER: + x = fDivider - roundf(fLayoutData->label_width / 2.0f); + break; + + default: + x = 0.0f; + break; + } + + // vertical position + font_height& fontHeight = fLayoutData->font_info; + float y = rect.top + + roundf((rect.Height() + 1.0f - fontHeight.ascent + - fontHeight.descent) / 2.0f) + + fontHeight.ascent + kFrameMargin * 2; + + uint32 flags = 0; + if (!IsEnabled()) + flags |= BControlLook::B_DISABLED; + + be_control_look->DrawLabel(this, label, LowColor(), flags, BPoint(x, y)); +} + + +void +BAbstractSpinner::_DrawTextView(BRect updateRect) +{ + BRect rect = fTextView->Frame(); + rect.InsetBy(-kFrameMargin, -kFrameMargin); + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); + uint32 flags = 0; + if (!IsEnabled()) + flags |= BControlLook::B_DISABLED; + + if (fTextView->IsFocus() && Window()->IsActive()) + flags |= BControlLook::B_FOCUSED; + + be_control_look->DrawTextControlBorder(this, rect, updateRect, base, + flags); +} + + +void +BAbstractSpinner::_InitObject() +{ + rgb_color bgColor = ui_color(B_PANEL_BACKGROUND_COLOR); + SetViewColor(bgColor); + SetLowColor(bgColor); + + fAlignment = B_ALIGN_LEFT; + fButtonStyle = SPINNER_BUTTON_PLUS_MINUS; + + if (Label() != NULL) { + fDivider = StringWidth(Label()) + + be_control_look->DefaultLabelSpacing(); + } else + fDivider = 0.0f; + + BControl::SetEnabled(true); + BControl::SetValue(0); + + BRect rect(Bounds()); + fLayoutData = new LayoutData(rect.Width(), rect.Height()); + + rect.left = fDivider; + rect.InsetBy(kFrameMargin, kFrameMargin); + rect.right -= rect.Height() * 2 + kFrameMargin * 2 + 1.0f; + BRect textRect(rect.OffsetToCopy(B_ORIGIN)); + + fTextView = new SpinnerTextView(rect, textRect); + AddChild(fTextView); + + rect.InsetBy(0.0f, -kFrameMargin); + + rect.left = rect.right + kFrameMargin * 2; + rect.right = rect.left + rect.Height() - kFrameMargin * 2; + + fDecrement = new SpinnerButton(rect, "decrement", SPINNER_DECREMENT); + AddChild(fDecrement); + + rect.left = rect.right + 1.0f; + rect.right = rect.left + rect.Height() - kFrameMargin * 2; + + fIncrement = new SpinnerButton(rect, "increment", SPINNER_INCREMENT); + AddChild(fIncrement); + + uint32 navigableFlags = Flags() & B_NAVIGABLE; + if (navigableFlags != 0) + BControl::SetFlags(Flags() & ~B_NAVIGABLE); +} + + +void +BAbstractSpinner::_LayoutTextView() +{ + BRect rect; + if (fLayoutData->text_view_layout_item != NULL) { + rect = fLayoutData->text_view_layout_item->FrameInParent(); + } else { + rect = Bounds(); + rect.left = fDivider; + } + rect.InsetBy(kFrameMargin, kFrameMargin); + rect.right -= rect.Height() * 2 + kFrameMargin * 2 + 1.0f; + + fTextView->MoveTo(rect.left, rect.top); + fTextView->ResizeTo(rect.Width(), rect.Height()); + fTextView->SetTextRect(rect.OffsetToCopy(B_ORIGIN)); + + rect.InsetBy(0.0f, -kFrameMargin); + + rect.left = rect.right + kFrameMargin * 2; + rect.right = rect.left + rect.Height() - kFrameMargin * 2; + + fDecrement->ResizeTo(rect.Width(), rect.Height()); + fDecrement->MoveTo(rect.LeftTop()); + + rect.left = rect.right + 1.0f; + rect.right = rect.left + rect.Height() - kFrameMargin * 2; + + fIncrement->ResizeTo(rect.Width(), rect.Height()); + fIncrement->MoveTo(rect.LeftTop()); +} + + +void +BAbstractSpinner::_UpdateFrame() +{ + if (fLayoutData->label_layout_item == NULL + || fLayoutData->text_view_layout_item == NULL) { + return; + } + + BRect labelFrame = fLayoutData->label_layout_item->Frame(); + BRect textViewFrame = fLayoutData->text_view_layout_item->Frame(); + + if (!labelFrame.IsValid() || !textViewFrame.IsValid()) + return; + + // update divider + fDivider = textViewFrame.left - labelFrame.left; + + BRect frame = textViewFrame | labelFrame; + MoveTo(frame.left, frame.top); + BSize oldSize = Bounds().Size(); + ResizeTo(frame.Width(), frame.Height()); + BSize newSize = Bounds().Size(); + + // If the size changes, ResizeTo() will trigger a relayout, otherwise + // we need to do that explicitly. + if (newSize != oldSize) + Relayout(); +} + + +void +BAbstractSpinner::_UpdateTextViewColors(bool enable) +{ + rgb_color textColor; + rgb_color bgColor; + BFont font; + + fTextView->GetFontAndColor(0, &font); + + if (enable) + textColor = ui_color(B_DOCUMENT_TEXT_COLOR); + else { + textColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), + B_DISABLED_LABEL_TINT); + } + + fTextView->SetFontAndColor(&font, B_FONT_ALL, &textColor); + + if (enable) + bgColor = ui_color(B_DOCUMENT_BACKGROUND_COLOR); + else { + bgColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), + B_LIGHTEN_2_TINT); + } + + fTextView->SetViewColor(bgColor); + fTextView->SetLowColor(bgColor); +} + + +void +BAbstractSpinner::_ValidateLayoutData() +{ + if (fLayoutData->valid) + return; + + font_height fontHeight = fLayoutData->font_info; + GetFontHeight(&fontHeight); + + if (Label() != NULL) { + fLayoutData->label_width = StringWidth(Label()); + fLayoutData->label_height = ceilf(fontHeight.ascent + + fontHeight.descent + fontHeight.leading); + } else { + fLayoutData->label_width = 0; + fLayoutData->label_height = 0; + } + + float divider = 0; + if (fLayoutData->label_width > 0) { + divider = ceilf(fLayoutData->label_width + + be_control_look->DefaultLabelSpacing()); + } + + if ((Flags() & B_SUPPORTS_LAYOUT) == 0) + divider = std::max(divider, fDivider); + + float minTextWidth = fTextView->StringWidth("99999"); + + float textViewHeight = fTextView->LineHeight(0) + kFrameMargin * 2; + float textViewWidth = minTextWidth + textViewHeight * 2; + + fLayoutData->text_view_width = textViewWidth; + fLayoutData->text_view_height = textViewHeight; + + BSize min(textViewWidth, textViewHeight); + if (divider > 0.0f) + min.width += divider; + + if (fLayoutData->label_height > min.height) + min.height = fLayoutData->label_height; + + fLayoutData->min = min; + fLayoutData->valid = true; + + ResetLayoutInvalidation(); +} + + +// FBC padding + +void BAbstractSpinner::_ReservedAbstractSpinner20() {} +void BAbstractSpinner::_ReservedAbstractSpinner19() {} +void BAbstractSpinner::_ReservedAbstractSpinner18() {} +void BAbstractSpinner::_ReservedAbstractSpinner17() {} +void BAbstractSpinner::_ReservedAbstractSpinner16() {} +void BAbstractSpinner::_ReservedAbstractSpinner15() {} +void BAbstractSpinner::_ReservedAbstractSpinner14() {} +void BAbstractSpinner::_ReservedAbstractSpinner13() {} +void BAbstractSpinner::_ReservedAbstractSpinner12() {} +void BAbstractSpinner::_ReservedAbstractSpinner11() {} +void BAbstractSpinner::_ReservedAbstractSpinner10() {} +void BAbstractSpinner::_ReservedAbstractSpinner9() {} +void BAbstractSpinner::_ReservedAbstractSpinner8() {} +void BAbstractSpinner::_ReservedAbstractSpinner7() {} +void BAbstractSpinner::_ReservedAbstractSpinner6() {} +void BAbstractSpinner::_ReservedAbstractSpinner5() {} +void BAbstractSpinner::_ReservedAbstractSpinner4() {} +void BAbstractSpinner::_ReservedAbstractSpinner3() {} +void BAbstractSpinner::_ReservedAbstractSpinner2() {} +void BAbstractSpinner::_ReservedAbstractSpinner1() {} diff --git a/src/kits/interface/Alert.cpp b/src/kits/interface/Alert.cpp index 422692771d..411792ded1 100644 --- a/src/kits/interface/Alert.cpp +++ b/src/kits/interface/Alert.cpp @@ -264,7 +264,6 @@ BAlert::SetShortcut(int32 index, char key) char BAlert::Shortcut(int32 index) const { - if (index >= 0 && (size_t)index < fKeys.size()) return fKeys[index]; @@ -378,6 +377,7 @@ BAlert::AddButton(const char* label, char key) fButtons.push_back(button); fKeys.push_back(key); + SetDefaultButton(button); fButtonLayout->AddView(button); } @@ -520,6 +520,8 @@ BAlert::_Init(const char* text, const char* button0, const char* button1, AddButton(button0); AddButton(button1); AddButton(button2); + + AddCommonFilter(new(std::nothrow) _BAlertFilter_(this)); } @@ -644,8 +646,6 @@ BAlert::_Prepare() if (CountButtons() == 0) debugger("BAlerts must have at least one button."); - SetDefaultButton(ButtonAt(CountButtons() - 1)); - float fontFactor = be_plain_font->Size() / 11.0f; if (fIconView->Bitmap() == NULL) @@ -691,6 +691,11 @@ BAlert::_Prepare() ResizeToPreferred(); + // Return early if we've already been moved... + if (Frame().left != 0 && Frame().right != 0) + return; + + // otherwise center ourselves on-top of parent window/screen BWindow* parent = dynamic_cast(BLooper::LooperForThread( find_thread(NULL))); const BRect frame = parent != NULL ? parent->Frame() @@ -812,7 +817,7 @@ _BAlertFilter_::Filter(BMessage* msg, BHandler** target) if (msg->what == B_KEY_DOWN) { char byte; if (msg->FindInt8("byte", (int8*)&byte) == B_OK) { - for (int i = 0; i < 3; ++i) { + for (int i = 0; i < fAlert->CountButtons(); ++i) { if (byte == fAlert->Shortcut(i) && fAlert->ButtonAt(i)) { char space = ' '; fAlert->ButtonAt(i)->KeyDown(&space, 1); diff --git a/src/kits/interface/Bitmap.cpp b/src/kits/interface/Bitmap.cpp index 33f60ca16b..42da316733 100644 --- a/src/kits/interface/Bitmap.cpp +++ b/src/kits/interface/Bitmap.cpp @@ -429,16 +429,15 @@ BBitmap::Archive(BMessage* data, bool deep) const break; } } - // Note: R5 does not archive the data if B_BITMAP_IS_CONTIGUOUS is - // true and it does save all formats as B_RAW_TYPE and it does save - // the data even if B_BITMAP_ACCEPTS_VIEWS is set (as opposed to - // the BeBook) - if (ret == B_OK) { - const_cast(this)->_AssertPointer(); - ret = data->AddData("_data", B_RAW_TYPE, fBasePointer, fSize); - } } - + // Note: R5 does not archive the data if B_BITMAP_IS_CONTIGUOUS is + // true and it does save all formats as B_RAW_TYPE and it does save + // the data even if B_BITMAP_ACCEPTS_VIEWS is set (as opposed to + // the BeBook) + if (ret == B_OK) { + const_cast(this)->_AssertPointer(); + ret = data->AddData("_data", B_RAW_TYPE, fBasePointer, fSize); + } return ret; } diff --git a/src/kits/interface/DecimalSpinner.cpp b/src/kits/interface/DecimalSpinner.cpp new file mode 100644 index 0000000000..e772b53e59 --- /dev/null +++ b/src/kits/interface/DecimalSpinner.cpp @@ -0,0 +1,372 @@ +/* + * Copyright 2015 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT license. + * + * Authors: + * John Scipione, jscipione@gmail.com + */ + + +#include + +#include +#include + +#include +#include + + +static double +roundTo(double value, uint32 n) +{ + return floor(value * pow(10.0, n) + 0.5) / pow(10.0, n); +} + + +static property_info sProperties[] = { + { + "MaxValue", + { B_GET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns the maximum value of the spinner.", + 0, + { B_DOUBLE_TYPE } + }, + { + "MaxValue", + { B_SET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0}, + "Sets the maximum value of the spinner.", + 0, + { B_DOUBLE_TYPE } + }, + + { + "MinValue", + { B_GET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns the minimum value of the spinner.", + 0, + { B_DOUBLE_TYPE } + }, + { + "MinValue", + { B_SET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0}, + "Sets the minimum value of the spinner.", + 0, + { B_DOUBLE_TYPE } + }, + + { + "Precision", + { B_SET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0}, + "Sets the number of decimal places of precision of the spinner.", + 0, + { B_UINT32_TYPE } + }, + { + "Precision", + { B_GET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns the number of decimal places of precision of the spinner.", + 0, + { B_UINT32_TYPE } + }, + + { + "Step", + { B_GET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns the step size of the spinner.", + 0, + { B_DOUBLE_TYPE } + }, + { + "Step", + { B_SET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0}, + "Sets the step size of the spinner.", + 0, + { B_DOUBLE_TYPE } + }, + + { + "Value", + { B_GET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns the value of the spinner.", + 0, + { B_DOUBLE_TYPE } + }, + { + "Value", + { B_SET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0}, + "Sets the value of the spinner.", + 0, + { B_DOUBLE_TYPE } + }, + + { 0 } +}; + + +// #pragma mark - BDecimalSpinner + + +BDecimalSpinner::BDecimalSpinner(BRect frame, const char* name, + const char* label, BMessage* message, uint32 resizingMode, uint32 flags) + : + BAbstractSpinner(frame, name, label, message, resizingMode, flags) +{ + _InitObject(); +} + + +BDecimalSpinner::BDecimalSpinner(const char* name, const char* label, + BMessage* message, uint32 flags) + : + BAbstractSpinner(name, label, message, flags) +{ + _InitObject(); +} + + +BDecimalSpinner::BDecimalSpinner(BMessage* data) + : + BAbstractSpinner(data) +{ + _InitObject(); + + if (data->FindDouble("_max", &fMaxValue) != B_OK) + fMinValue = 100.0; + + if (data->FindDouble("_min", &fMinValue) != B_OK) + fMinValue = 0.0; + + if (data->FindUInt32("_precision", &fPrecision) != B_OK) + fPrecision = 2; + + if (data->FindDouble("_step", &fStep) != B_OK) + fStep = 1.0; + + if (data->FindDouble("_val", &fValue) != B_OK) + fValue = 0.0; +} + + +BDecimalSpinner::~BDecimalSpinner() +{ +} + + +BArchivable* +BDecimalSpinner::Instantiate(BMessage* data) +{ + if (validate_instantiation(data, "DecimalSpinner")) + return new BDecimalSpinner(data); + + return NULL; +} + + +status_t +BDecimalSpinner::Archive(BMessage* data, bool deep) const +{ + status_t status = BAbstractSpinner::Archive(data, deep); + data->AddString("class", "DecimalSpinner"); + + if (status == B_OK) + status = data->AddDouble("_max", fMaxValue); + + if (status == B_OK) + status = data->AddDouble("_min", fMinValue); + + if (status == B_OK) + status = data->AddUInt32("_precision", fPrecision); + + if (status == B_OK) + status = data->AddDouble("_step", fStep); + + if (status == B_OK) + status = data->AddDouble("_val", fValue); + + return status; +} + + +status_t +BDecimalSpinner::GetSupportedSuites(BMessage* message) +{ + message->AddString("suites", "suite/vnd.Haiku-decimal-spinner"); + + BPropertyInfo prop_info(sProperties); + message->AddFlat("messages", &prop_info); + + return BView::GetSupportedSuites(message); +} + + +void +BDecimalSpinner::AttachedToWindow() +{ + SetValue(fValue); + + BAbstractSpinner::AttachedToWindow(); +} + + +void +BDecimalSpinner::Decrement() +{ + SetValue(Value() - Step()); +} + + +void +BDecimalSpinner::Increment() +{ + SetValue(Value() + Step()); +} + + +void +BDecimalSpinner::SetEnabled(bool enable) +{ + if (IsEnabled() == enable) + return; + + SetIncrementEnabled(enable && Value() < fMaxValue); + SetDecrementEnabled(enable && Value() > fMinValue); + + BAbstractSpinner::SetEnabled(enable); +} + + +void +BDecimalSpinner::SetMaxValue(double max) +{ + fMaxValue = max; + if (fValue > fMaxValue) + SetValue(fMaxValue); +} + + +void +BDecimalSpinner::SetMinValue(double min) +{ + fMinValue = min; + if (fValue < fMinValue) + SetValue(fMinValue); +} + + +void +BDecimalSpinner::Range(double* min, double* max) +{ + *min = fMinValue; + *max = fMaxValue; +} + + +void +BDecimalSpinner::SetRange(double min, double max) +{ + SetMinValue(min); + SetMaxValue(max); +} + + +void +BDecimalSpinner::SetValue(int32 value) +{ + SetValue((double)value); +} + + +void +BDecimalSpinner::SetValue(double value) +{ + // clip to range + if (value < fMinValue) + value = fMinValue; + else if (value > fMaxValue) + value = fMaxValue; + + // update the text view + char* format; + asprintf(&format, "%%.%" B_PRId32 "f", fPrecision); + char* valueString; + asprintf(&valueString, format, value); + TextView()->SetText(valueString); + free(format); + free(valueString); + + // update the up and down arrows + SetIncrementEnabled(IsEnabled() && value < fMaxValue); + SetDecrementEnabled(IsEnabled() && value > fMinValue); + + if (value == fValue) + return; + + fValue = value; + ValueChanged(); + + Invoke(); + Invalidate(); +} + + +void +BDecimalSpinner::SetValueFromText() +{ + SetValue(roundTo(atof(TextView()->Text()), Precision())); +} + + +// #pragma mark - BDecimalSpinner private methods + + +void +BDecimalSpinner::_InitObject() +{ + fMaxValue = 100.0; + fMinValue = 0.0; + fPrecision = 2; + fStep = 1.0; + fValue = 0.0; + + TextView()->SetAlignment(B_ALIGN_RIGHT); + for (uint32 c = 0; c <= 42; c++) + TextView()->DisallowChar(c); + + TextView()->DisallowChar('/'); + for (uint32 c = 58; c <= 127; c++) + TextView()->DisallowChar(c); +} + + +// FBC padding + +void BDecimalSpinner::_ReservedDecimalSpinner20() {} +void BDecimalSpinner::_ReservedDecimalSpinner19() {} +void BDecimalSpinner::_ReservedDecimalSpinner18() {} +void BDecimalSpinner::_ReservedDecimalSpinner17() {} +void BDecimalSpinner::_ReservedDecimalSpinner16() {} +void BDecimalSpinner::_ReservedDecimalSpinner15() {} +void BDecimalSpinner::_ReservedDecimalSpinner14() {} +void BDecimalSpinner::_ReservedDecimalSpinner13() {} +void BDecimalSpinner::_ReservedDecimalSpinner12() {} +void BDecimalSpinner::_ReservedDecimalSpinner11() {} +void BDecimalSpinner::_ReservedDecimalSpinner10() {} +void BDecimalSpinner::_ReservedDecimalSpinner9() {} +void BDecimalSpinner::_ReservedDecimalSpinner8() {} +void BDecimalSpinner::_ReservedDecimalSpinner7() {} +void BDecimalSpinner::_ReservedDecimalSpinner6() {} +void BDecimalSpinner::_ReservedDecimalSpinner5() {} +void BDecimalSpinner::_ReservedDecimalSpinner4() {} +void BDecimalSpinner::_ReservedDecimalSpinner3() {} +void BDecimalSpinner::_ReservedDecimalSpinner2() {} +void BDecimalSpinner::_ReservedDecimalSpinner1() {} diff --git a/src/kits/interface/Jamfile b/src/kits/interface/Jamfile index af100e0bfc..cec0540f17 100644 --- a/src/kits/interface/Jamfile +++ b/src/kits/interface/Jamfile @@ -42,6 +42,7 @@ for architectureObject in [ MultiArchSubDirSetup ] { AboutWindow.cpp AbstractLayout.cpp AbstractLayoutItem.cpp + AbstractSpinner.cpp AffineTransform.cpp Alert.cpp Alignment.cpp @@ -60,6 +61,7 @@ for architectureObject in [ MultiArchSubDirSetup ] { ControlLook.cpp DecorInfo.cpp Deskbar.cpp + DecimalSpinner.cpp Dragger.cpp Font.cpp Gradient.cpp @@ -116,6 +118,7 @@ for architectureObject in [ MultiArchSubDirSetup ] { Size.cpp Slider.cpp SpaceLayoutItem.cpp + Spinner.cpp SplitLayout.cpp SplitLayoutBuilder.cpp SplitView.cpp diff --git a/src/kits/interface/MenuWindow.cpp b/src/kits/interface/MenuWindow.cpp index 9523f67178..42889a9be6 100644 --- a/src/kits/interface/MenuWindow.cpp +++ b/src/kits/interface/MenuWindow.cpp @@ -203,23 +203,18 @@ void BMenuFrame::Draw(BRect updateRect) { if (fMenu != NULL && fMenu->CountItems() == 0) { - if (be_control_look != NULL) { - BRect rect(Bounds()); - be_control_look->DrawMenuBackground(this, rect, updateRect, - ui_color(B_MENU_BACKGROUND_COLOR)); - SetDrawingMode(B_OP_OVER); - } else { - // TODO: Review this as it's a bit hacky. - // Menu has a size of 0, 0, since there are no items in it. - // So the BMenuFrame class has to fake it and draw an empty item. - // Note that we can't add a real "empty" item because then we - // couldn't tell if the item was added by us or not. - // See also BMenu::UpdateWindowViewSize() - SetHighColor(ui_color(B_MENU_BACKGROUND_COLOR)); - SetLowColor(HighColor()); - FillRect(updateRect); - } + BRect rect(Bounds()); + be_control_look->DrawMenuBackground(this, rect, updateRect, + ui_color(B_MENU_BACKGROUND_COLOR)); + SetDrawingMode(B_OP_OVER); + // TODO: Review this as it's a bit hacky. + // Since there are no items in this menu, its size is 0x0. + // To show an empty BMenu, we use BMenuFrame to draw an empty item. + // It would be nice to simply add a real "empty" item, but in that case + // we couldn't tell if the item was added by us or not, and applications + // could break (because CountItems() would return 1 for an empty BMenu). + // See also BMenu::UpdateWindowViewSize() font_height height; GetFontHeight(&height); SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR), @@ -229,18 +224,6 @@ BMenuFrame::Draw(BRect updateRect) ceilf(height.ascent + 1)); DrawString(kEmptyMenuLabel, where); } - - if (be_control_look != NULL) - return; - - SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR), - B_DARKEN_2_TINT)); - BRect bounds(Bounds()); - - StrokeLine(BPoint(bounds.right, bounds.top), - BPoint(bounds.right, bounds.bottom - 1)); - StrokeLine(BPoint(bounds.left + 1, bounds.bottom), - BPoint(bounds.right, bounds.bottom)); } diff --git a/src/kits/interface/Spinner.cpp b/src/kits/interface/Spinner.cpp new file mode 100644 index 0000000000..e6d6a63b71 --- /dev/null +++ b/src/kits/interface/Spinner.cpp @@ -0,0 +1,311 @@ +/* + * Copyright 2015 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT license. + * + * Authors: + * John Scipione, jscipione@gmail.com + */ + + +#include + +#include +#include + +#include +#include +#include + + +static property_info sProperties[] = { + { + "MaxValue", + { B_GET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns the maximum value of the spinner.", + 0, + { B_INT32_TYPE } + }, + { + "MaxValue", + { B_SET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0}, + "Sets the maximum value of the spinner.", + 0, + { B_INT32_TYPE } + }, + + { + "MinValue", + { B_GET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns the minimum value of the spinner.", + 0, + { B_INT32_TYPE } + }, + { + "MinValue", + { B_SET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0}, + "Sets the minimum value of the spinner.", + 0, + { B_INT32_TYPE } + }, + + { + "Value", + { B_GET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns the value of the spinner.", + 0, + { B_INT32_TYPE } + }, + { + "Value", + { B_SET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0}, + "Sets the value of the spinner.", + 0, + { B_INT32_TYPE } + }, + + { 0 } +}; + + +// #pragma mark - BSpinner + + +BSpinner::BSpinner(BRect frame, const char* name, const char* label, + BMessage* message, uint32 resizingMode, uint32 flags) + : + BAbstractSpinner(frame, name, label, message, resizingMode, flags) +{ + _InitObject(); +} + + +BSpinner::BSpinner(const char* name, const char* label, + BMessage* message, uint32 flags) + : + BAbstractSpinner(name, label, message, flags) +{ + _InitObject(); +} + + +BSpinner::BSpinner(BMessage* data) + : + BAbstractSpinner(data) +{ + _InitObject(); + + if (data->FindInt32("_max", &fMaxValue) != B_OK) + fMinValue = INT32_MAX; + + if (data->FindInt32("_min", &fMinValue) != B_OK) + fMinValue = INT32_MIN; + + if (data->FindInt32("_val", &fValue) != B_OK) + fValue = 0; +} + + +BSpinner::~BSpinner() +{ +} + + +BArchivable* +BSpinner::Instantiate(BMessage* data) +{ + if (validate_instantiation(data, "Spinner")) + return new BSpinner(data); + + return NULL; +} + + +status_t +BSpinner::Archive(BMessage* data, bool deep) const +{ + status_t status = BAbstractSpinner::Archive(data, deep); + data->AddString("class", "Spinner"); + + if (status == B_OK) + status = data->AddInt32("_max", fMaxValue); + + if (status == B_OK) + status = data->AddInt32("_min", fMinValue); + + if (status == B_OK) + status = data->AddInt32("_val", fValue); + + return status; +} + + +status_t +BSpinner::GetSupportedSuites(BMessage* message) +{ + message->AddString("suites", "suite/vnd.Haiku-intenger-spinner"); + + BPropertyInfo prop_info(sProperties); + message->AddFlat("messages", &prop_info); + + return BView::GetSupportedSuites(message); +} + + +void +BSpinner::AttachedToWindow() +{ + SetValue(fValue); + + BAbstractSpinner::AttachedToWindow(); +} + + +void +BSpinner::Decrement() +{ + SetValue(Value() - 1); +} + + +void +BSpinner::Increment() +{ + SetValue(Value() + 1); +} + + +void +BSpinner::SetEnabled(bool enable) +{ + if (IsEnabled() == enable) + return; + + SetIncrementEnabled(enable && Value() < fMaxValue); + SetDecrementEnabled(enable && Value() > fMinValue); + + BAbstractSpinner::SetEnabled(enable); +} + + +void +BSpinner::SetMaxValue(int32 max) +{ + fMaxValue = max; + if (fValue > fMaxValue) + SetValue(fMaxValue); +} + + +void +BSpinner::SetMinValue(int32 min) +{ + fMinValue = min; + if (fValue < fMinValue) + SetValue(fMinValue); +} + + +void +BSpinner::Range(int32* min, int32* max) +{ + *min = fMinValue; + *max = fMaxValue; +} + + +void +BSpinner::SetRange(int32 min, int32 max) +{ + SetMinValue(min); + SetMaxValue(max); +} + + +void +BSpinner::SetValue(int32 value) +{ + // clip to range + if (value < fMinValue) + value = fMinValue; + else if (value > fMaxValue) + value = fMaxValue; + + // update the text view + BString valueString; + valueString << value; + TextView()->SetText(valueString.String()); + + // update the up and down arrows + SetIncrementEnabled(IsEnabled() && value < fMaxValue); + SetDecrementEnabled(IsEnabled() && value > fMinValue); + + if (value == fValue) + return; + + fValue = value; + ValueChanged(); + + Invoke(); + Invalidate(); +} + + +void +BSpinner::SetValueFromText() +{ + SetValue(atol(TextView()->Text())); +} + + +// #pragma mark - BSpinner private methods + + +void +BSpinner::_InitObject() +{ + fMaxValue = INT32_MIN; + fMinValue = INT32_MAX; + fValue = 0; + + TextView()->SetAlignment(B_ALIGN_RIGHT); + for (uint32 c = 0; c <= 42; c++) + TextView()->DisallowChar(c); + + TextView()->DisallowChar(','); + + for (uint32 c = 46; c <= 47; c++) + TextView()->DisallowChar(c); + + for (uint32 c = 58; c <= 127; c++) + TextView()->DisallowChar(c); +} + + +// FBC padding + +void BSpinner::_ReservedSpinner20() {} +void BSpinner::_ReservedSpinner19() {} +void BSpinner::_ReservedSpinner18() {} +void BSpinner::_ReservedSpinner17() {} +void BSpinner::_ReservedSpinner16() {} +void BSpinner::_ReservedSpinner15() {} +void BSpinner::_ReservedSpinner14() {} +void BSpinner::_ReservedSpinner13() {} +void BSpinner::_ReservedSpinner12() {} +void BSpinner::_ReservedSpinner11() {} +void BSpinner::_ReservedSpinner10() {} +void BSpinner::_ReservedSpinner9() {} +void BSpinner::_ReservedSpinner8() {} +void BSpinner::_ReservedSpinner7() {} +void BSpinner::_ReservedSpinner6() {} +void BSpinner::_ReservedSpinner5() {} +void BSpinner::_ReservedSpinner4() {} +void BSpinner::_ReservedSpinner3() {} +void BSpinner::_ReservedSpinner2() {} +void BSpinner::_ReservedSpinner1() {} diff --git a/src/kits/interface/TextView.cpp b/src/kits/interface/TextView.cpp index f5625d90a5..d9091683e7 100644 --- a/src/kits/interface/TextView.cpp +++ b/src/kits/interface/TextView.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2001-2014 Haiku, Inc. All rights reserved. + * Copyright 2001-2015 Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -2601,7 +2601,7 @@ BTextView::GetHeightForWidth(float width, float* min, float* max, if (min != NULL) *min = fTextRect.Height(); if (max != NULL) - *max = fTextRect.Height(); + *max = B_SIZE_UNLIMITED; if (preferred != NULL) *preferred = fTextRect.Height(); } diff --git a/src/kits/media/MediaEventLooper.cpp b/src/kits/media/MediaEventLooper.cpp index bf3c8d0012..c9c006d287 100644 --- a/src/kits/media/MediaEventLooper.cpp +++ b/src/kits/media/MediaEventLooper.cpp @@ -215,7 +215,6 @@ BMediaEventLooper::ControlLoop() status_t err; bigtime_t waitUntil = B_INFINITE_TIMEOUT; - bigtime_t tempLateness = 0; bool hasRealtime = false; bool hasEvent = false; @@ -229,19 +228,20 @@ BMediaEventLooper::ControlLoop() return; err = WaitForMessage(waitUntil); - if (err == B_TIMED_OUT) { + if (err == B_TIMED_OUT + || err == B_WOULD_BLOCK) { media_timed_event event; if (hasEvent) err = fEventQueue.RemoveFirstEvent(&event); - else + else if (hasRealtime) err = fRealTimeQueue.RemoveFirstEvent(&event); if (err == B_OK) { - tempLateness -= TimeSource()->RealTime(); - if (tempLateness < 0) - tempLateness = 0; + bigtime_t lateness = waitUntil - TimeSource()->RealTime(); + if (lateness < 0) + lateness = 0; - DispatchEvent(&event, tempLateness, hasRealtime); + DispatchEvent(&event, lateness, hasRealtime); } } else if (err != B_OK) return; @@ -255,29 +255,23 @@ BMediaEventLooper::ControlLoop() if (hasEvent) { waitUntil = TimeSource()->RealTimeFor( - fEventQueue.FirstEvent()->event_time, + fEventQueue.FirstEventTime(), fEventLatency + fSchedulingLatency); } else if (!hasRealtime) { waitUntil = B_INFINITE_TIMEOUT; continue; } - if (hasEvent && hasRealtime) { - if (fRealTimeQueue.FirstEventTime() - - fSchedulingLatency <= waitUntil) { + if (hasRealtime) { + bigtime_t realtimeWait = fRealTimeQueue.FirstEventTime() + - fSchedulingLatency; + + if (!hasEvent || realtimeWait <= waitUntil) { + waitUntil = realtimeWait; hasEvent = false; } else hasRealtime = false; } - - if (hasRealtime) { - waitUntil = fRealTimeQueue.FirstEventTime() - - fSchedulingLatency; - } - - tempLateness = waitUntil; - if (waitUntil < TimeSource()->RealTime()) - waitUntil = 0; } } diff --git a/src/kits/media/MediaNode.cpp b/src/kits/media/MediaNode.cpp index bece94a000..c7b5f21f16 100644 --- a/src/kits/media/MediaNode.cpp +++ b/src/kits/media/MediaNode.cpp @@ -343,6 +343,13 @@ BMediaNode::WaitForMessage(bigtime_t waitUntil, uint32 flags, char data[B_MEDIA_MESSAGE_SIZE]; int32 message; ssize_t size; + + // TODO: Investigate on this issue + if (waitUntil < 0) { + TRACE("BMediaNode::WaitForMessage: Negative timeout!\n"); + waitUntil = 0; + } + while (true) { size = read_port_etc(ControlPort(), &message, data, sizeof(data), B_ABSOLUTE_TIMEOUT, waitUntil); diff --git a/src/kits/media/MediaRoster.cpp b/src/kits/media/MediaRoster.cpp index 6799b01d7a..6351302baf 100644 --- a/src/kits/media/MediaRoster.cpp +++ b/src/kits/media/MediaRoster.cpp @@ -44,6 +44,7 @@ char __dont_remove_copyright_from_binary[] = "Copyright (c) 2002-2006 Marcus " #include +#include #include #include #include @@ -83,6 +84,23 @@ struct RosterNotification { static bool sServerIsUp = false; static List sNotificationList; +static BLocker sInitLocker("BMediaRoster::Roster locker"); + + +class MediaRosterUndertaker { +public: + ~MediaRosterUndertaker() + { + BAutolock _(sInitLocker); + if (BMediaRoster::CurrentRoster() != NULL + && BMediaRoster::CurrentRoster()->Lock()) { + BMediaRoster::CurrentRoster()->Quit(); + } + } +}; + + +static MediaRosterUndertaker sMediaRosterUndertaker; } // namespace media } // namespace BPrivate @@ -94,8 +112,8 @@ BMediaRosterEx::BMediaRosterEx(status_t* _error) : BMediaRoster() { - gDormantNodeManager = new DormantNodeManager; - gTimeSourceObjectManager = new TimeSourceObjectManager; + gDormantNodeManager = new DormantNodeManager(); + gTimeSourceObjectManager = new TimeSourceObjectManager(); *_error = BuildConnections(); @@ -109,6 +127,19 @@ BMediaRosterEx::BMediaRosterEx(status_t* _error) } +void +BMediaRosterEx::Quit() +{ + if (be_roster->StopWatching(BMessenger(this, this)) != B_OK) + TRACE("Can't unregister roster notifications"); + + if (sNotificationList.CountItems() != 0) + sNotificationList.MakeEmpty(); + + BMediaRoster::Quit(); +} + + status_t BMediaRosterEx::BuildConnections() { @@ -2188,10 +2219,14 @@ BMediaRoster::UnregisterNode(BMediaNode* node) /*static*/ BMediaRoster* BMediaRoster::Roster(status_t* out_error) { - static BLocker locker("BMediaRoster::Roster locker"); - locker.Lock(); + BAutolock lock(sInitLocker); + + if (!lock.IsLocked()) + return NULL; + if (out_error) *out_error = B_OK; + if (sDefaultInstance == NULL) { status_t err; sDefaultInstance = new (std::nothrow) BMediaRosterEx(&err); @@ -2207,7 +2242,6 @@ BMediaRoster::Roster(status_t* out_error) *out_error = err; } } - locker.Unlock(); return sDefaultInstance; } @@ -3455,9 +3489,11 @@ BMediaRoster::MessageReceived(BMessage* message) node->DeleteHook(node); // we don't call Release(), see above! return; } + + default: + BLooper::MessageReceived(message); + break; } - printf("BMediaRoster::MessageReceived: unknown message!\n"); - message->PrintToStream(); } @@ -3465,13 +3501,6 @@ bool BMediaRoster::QuitRequested() { CALLED(); - - if (be_roster->StopWatching(BMessenger(this, this)) != B_OK) - TRACE("Can't unregister roster notifications"); - - if (sNotificationList.CountItems() != 0) - sNotificationList.MakeEmpty(); - return true; } diff --git a/src/kits/midi/Jamfile b/src/kits/midi/Jamfile index 85d4e72a82..d6bb5c2a1c 100644 --- a/src/kits/midi/Jamfile +++ b/src/kits/midi/Jamfile @@ -18,6 +18,7 @@ for architectureObject in [ MultiArchSubDirSetup ] { Midi.cpp MidiGlue.cpp MidiPort.cpp + MidiSettings.cpp MidiStore.cpp MidiSynth.cpp MidiSynthFile.cpp diff --git a/src/kits/midi/MidiSettings.cpp b/src/kits/midi/MidiSettings.cpp new file mode 100644 index 0000000000..be1cd00be6 --- /dev/null +++ b/src/kits/midi/MidiSettings.cpp @@ -0,0 +1,68 @@ +/* + * Copyright 2015 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#include + +#include +#include +#include + +#include +#include +#include + +#define SETTINGS_FILE "midi" + +namespace BPrivate { + +status_t +read_midi_settings(struct midi_settings* settings) +{ + if (settings == NULL) + return B_ERROR; + + char buffer[B_FILE_NAME_LENGTH + 128]; + BPath path; + status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path); + if (status != B_OK) + return status; + + path.Append("midi"); + BFile file(path.Path(), B_READ_ONLY); + if (file.InitCheck() != B_OK + || file.Read(buffer, sizeof(buffer)) <= 0) + return B_ERROR; + + sscanf(buffer, "# Midi Settings\n soundfont = %s\n", + settings->soundfont_file); + + return B_OK; +} + + +status_t +write_midi_settings(struct midi_settings settings) +{ + char buffer[B_FILE_NAME_LENGTH + 128]; + snprintf(buffer, sizeof(buffer), "# Midi Settings\n soundfont = %s\n", + settings.soundfont_file); + + BPath path; + status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path); + if (status != B_OK) + return status; + + path.Append(SETTINGS_FILE); + BFile file(path.Path(), B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE); + + size_t bufferSize = strlen(buffer); + if (file.InitCheck() != B_OK + || file.Write(buffer, bufferSize) != (ssize_t)bufferSize) + return B_ERROR; + + return B_OK; +} + +} diff --git a/src/kits/midi/SoftSynth.cpp b/src/kits/midi/SoftSynth.cpp index 905aa3dd2f..a7c003cc4b 100644 --- a/src/kits/midi/SoftSynth.cpp +++ b/src/kits/midi/SoftSynth.cpp @@ -14,12 +14,19 @@ #include #include +#include #include #include +#include +#include #include +#include + #include #include +#include + #include "debug.h" #include "MidiGlue.h" // for MAKE_BIGTIME #include "SoftSynth.h" @@ -100,30 +107,55 @@ BSoftSynth::IsLoaded(void) const status_t BSoftSynth::SetDefaultInstrumentsFile() { + // TODO: Duplicated code, check MidiSettingsView::_LoadSettings() and + // MidiSettingsView::_RetrieveSoftSynthList() // We first search for a setting file (or symlink to it) // in the user settings directory - char buffer[512]; + + struct BPrivate::midi_settings settings; + if (BPrivate::read_midi_settings(&settings) == B_OK) { + if (SetInstrumentsFile(settings.soundfont_file) == B_OK) + return B_OK; + } + + // Try a well-known (and usually present on a default install) soft synth BPath path; - if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) { - path.Append("midi"); - BFile file(path.Path(), B_READ_ONLY); - if (file.InitCheck() == B_OK - && file.Read(buffer, sizeof(buffer)) > 0) { - char soundFont[512]; - sscanf(buffer, "# Midi Settings\n soundfont = %s\n", - soundFont); - return SetInstrumentsFile(soundFont); + if (find_directory(B_SYNTH_DIRECTORY, &path, false, NULL) == B_OK) { + path.Append("synth/TimGM6mb.sf2"); + if (SetInstrumentsFile(path.Path()) == B_OK) + return B_OK; + } + + // Just use the first soundfont we find + BStringList paths; + status_t status = BPathFinder::FindPaths(B_FIND_PATH_DATA_DIRECTORY, + "synth", paths); + + if (status != B_OK) + return B_ERROR; + + for (int32 i = 0; i < paths.CountStrings(); i++) { + BDirectory directory(paths.StringAt(i).String()); + BEntry entry; + if (directory.InitCheck() != B_OK) + continue; + while (directory.GetNextEntry(&entry) == B_OK) { + BNode node(&entry); + BNodeInfo nodeInfo(&node); + char mimeType[B_MIME_TYPE_LENGTH]; + // TODO: For some reason the mimetype check fails. + // maybe because the file hasn't yet been sniffed and recognized? + if (nodeInfo.GetType(mimeType) == B_OK + /*&& !strcmp(mimeType, "audio/x-soundfont")*/) { + BPath fullPath = paths.StringAt(i).String(); + fullPath.Append(entry.Name()); + if (SetInstrumentsFile(fullPath.Path()) == B_OK) + return B_OK; + } } } - // TODO: Use the first soundfont found in the synth directory - // instead of hardcoding - if (find_directory(B_SYNTH_DIRECTORY, &path, false, NULL) == B_OK) { - path.Append("TimGM6mb.sf2"); - return SetInstrumentsFile(path.Path()); - } - - // TODO: Write the settings file + // TODO: Write the settings file ? return B_ERROR; } diff --git a/src/kits/tracker/FSUtils.cpp b/src/kits/tracker/FSUtils.cpp index a17a074be6..aaca5fc1ff 100644 --- a/src/kits/tracker/FSUtils.cpp +++ b/src/kits/tracker/FSUtils.cpp @@ -101,6 +101,7 @@ enum { enum ConflictCheckResult { kCanceled = kUserCanceled, kPrompt, + kSkipAll, kReplace, kReplaceAll, kNoConflicts @@ -1024,7 +1025,7 @@ MoveTask(BObjectList* srcList, BEntry* destEntry, BList* pointList, // resolve name collisions and hierarchy problems if (CheckName(moveMode, &sourceEntry, &destDir, - collisionCount > 1, conflictCheckResult) != B_OK) { + collisionCount > 1, conflictCheckResult) != B_OK) { // we will skip the current item, because we got a conflict // and were asked to or because there was some conflict @@ -1152,7 +1153,7 @@ CopyFile(BEntry* srcFile, StatStruct* srcStat, BDirectory* destDir, BEntry conflictingEntry; if (destDir->FindEntry(destName, &conflictingEntry) == B_OK) { switch (loopControl->OverwriteOnConflict(srcFile, destName, destDir, - false, false)) { + false, false)) { case TrackerCopyLoopControl::kSkip: // we are about to ignore this entire directory return; @@ -1573,36 +1574,35 @@ status_t RecursiveMove(BEntry* entry, BDirectory* destDir, CopyLoopControl* loopControl) { - char name[B_FILE_NAME_LENGTH]; - if (entry->GetName(name) == B_OK) { - if (destDir->Contains(name)) { - BPath path (destDir, name); - BDirectory subDir (path.Path()); - entry_ref ref; - entry->GetRef(&ref); - BDirectory source(&ref); - if (source.InitCheck() == B_OK) { - source.Rewind(); - BEntry current; - while (source.GetNextEntry(¤t) == B_OK) { - if (current.IsDirectory()) { - RecursiveMove(¤t, &subDir, loopControl); - current.Remove(); - } else { - current.GetName(name); - if (loopControl->OverwriteOnConflict(¤t, name, + const char* name = entry->Name(); + + if (destDir->Contains(name)) { + BPath path (destDir, name); + BDirectory subDir (path.Path()); + entry_ref ref; + entry->GetRef(&ref); + BDirectory source(&ref); + if (source.InitCheck() == B_OK) { + source.Rewind(); + BEntry current; + while (source.GetNextEntry(¤t) == B_OK) { + if (current.IsDirectory()) { + RecursiveMove(¤t, &subDir, loopControl); + current.Remove(); + } else { + name = current.Name(); + if (loopControl->OverwriteOnConflict(¤t, name, &subDir, true, false) != TrackerCopyLoopControl::kSkip) { - MoveError::FailOnError(current.MoveTo(&subDir, - NULL, true)); - } + MoveError::FailOnError(current.MoveTo(&subDir, + NULL, true)); } } } - entry->Remove(); - } else - MoveError::FailOnError(entry->MoveTo(destDir)); - } + } + entry->Remove(); + } else + MoveError::FailOnError(entry->MoveTo(destDir)); return B_OK; } @@ -1998,7 +1998,6 @@ ConflictCheckResult PreFlightNameCheck(BObjectList* srcList, const BDirectory* destDir, int32* collisionCount, uint32 moveMode) { - // count the number of name collisions in dest folder *collisionCount = 0; @@ -2009,10 +2008,8 @@ PreFlightNameCheck(BObjectList* srcList, const BDirectory* destDir, BDirectory parent; entry.GetParent(&parent); - if (parent != *destDir) { - if (destDir->Contains(srcRef->name)) - (*collisionCount)++; - } + if (parent != *destDir && destDir->Contains(srcRef->name)) + (*collisionCount)++; } // prompt user only if there is more than one collision, otherwise the @@ -2023,9 +2020,12 @@ PreFlightNameCheck(BObjectList* srcList, const BDirectory* destDir, BString replaceMsg(B_TRANSLATE_NOCOLLECT(kReplaceManyStr)); replaceMsg.ReplaceAll("%verb", verb); - BAlert* alert = new BAlert("", replaceMsg.String(), - B_TRANSLATE("Cancel"), B_TRANSLATE("Prompt"), - B_TRANSLATE("Replace all")); + BAlert* alert = new BAlert(); + alert->SetText(replaceMsg.String()); + alert->AddButton(B_TRANSLATE("Cancel")); + alert->AddButton(B_TRANSLATE("Prompt")); + alert->AddButton(B_TRANSLATE("Skip all")); + alert->AddButton(B_TRANSLATE("Replace all")); alert->SetShortcut(0, B_ESCAPE); switch (alert->Go()) { case 0: @@ -2036,7 +2036,11 @@ PreFlightNameCheck(BObjectList* srcList, const BDirectory* destDir, return kPrompt; case 2: - // user selected "Replace All" + // user selected "Skip all" + return kSkipAll; + + case 3: + // user selected "Replace all" return kReplaceAll; } } @@ -2064,16 +2068,15 @@ FileStatToString(StatStruct* stat, char* buffer, int32 length) status_t CheckName(uint32 moveMode, const BEntry* sourceEntry, const BDirectory* destDir, bool multipleCollisions, - ConflictCheckResult &replaceAll) + ConflictCheckResult& conflictResolution) { - if (moveMode == kDuplicateSelection) + if (moveMode == kDuplicateSelection) { // when duplicating, we will never have a conflict return B_OK; + } // see if item already exists in destination dir - status_t err = B_OK; - char name[B_FILE_NAME_LENGTH]; - sourceEntry->GetName(name); + const char* name = sourceEntry->Name(); bool sourceIsDirectory = sourceEntry->IsDirectory(); BDirectory srcDirectory; @@ -2082,8 +2085,7 @@ CheckName(uint32 moveMode, const BEntry* sourceEntry, BEntry destEntry; destDir->GetEntry(&destEntry); - if (moveMode != kCreateLink - && moveMode != kCreateRelativeLink + if (moveMode != kCreateLink && moveMode != kCreateRelativeLink && (srcDirectory == *destDir || srcDirectory.Contains(&destEntry))) { BAlert* alert = new BAlert("", @@ -2108,9 +2110,10 @@ CheckName(uint32 moveMode, const BEntry* sourceEntry, } BEntry entry; - if (destDir->FindEntry(name, &entry) != B_OK) + if (destDir->FindEntry(name, &entry) != B_OK) { // no conflict, return return B_OK; + } if (moveMode == kCreateLink || moveMode == kCreateRelativeLink) { // if we are creating link in the same directory, the conflict will @@ -2124,8 +2127,8 @@ CheckName(uint32 moveMode, const BEntry* sourceEntry, bool destIsDir = entry.IsDirectory(); // be sure not to replace the parent directory of the item being moved if (destIsDir) { - BDirectory test_dir(&entry); - if (test_dir.Contains(sourceEntry)) { + BDirectory targetDir(&entry); + if (targetDir.Contains(sourceEntry)) { BAlert* alert = new BAlert("", B_TRANSLATE("You can't replace a folder " "with one of its sub-folders."), @@ -2141,18 +2144,21 @@ CheckName(uint32 moveMode, const BEntry* sourceEntry, if (moveMode != kCreateLink && moveMode != kCreateRelativeLink && destIsDir != sourceIsDirectory) { - BAlert* alert = new BAlert("", sourceIsDirectory - ? B_TRANSLATE("You cannot replace a file with a folder or a " + BAlert* alert = new BAlert("", sourceIsDirectory + ? B_TRANSLATE("You cannot replace a file with a folder or a " "symbolic link.") - : B_TRANSLATE("You cannot replace a folder or a symbolic link " + : B_TRANSLATE("You cannot replace a folder or a symbolic link " "with a file."), B_TRANSLATE("OK"), 0, 0, B_WIDTH_AS_USUAL, - B_WARNING_ALERT); - alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); - alert->Go(); - return B_ERROR; - } + B_WARNING_ALERT); + alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); + alert->Go(); + return B_ERROR; + } - if (replaceAll != kReplaceAll) { + if (conflictResolution == kSkipAll) + return B_ERROR; + + if (conflictResolution != kReplaceAll) { // prompt user to determine whether to replace or not BString replaceMsg; @@ -2170,8 +2176,8 @@ CheckName(uint32 moveMode, const BEntry* sourceEntry, char sourceBuffer[96], destBuffer[96]; StatStruct statBuffer; - if (!sourceEntry->IsDirectory() && sourceEntry->GetStat( - &statBuffer) == B_OK) { + if (!sourceEntry->IsDirectory() + && sourceEntry->GetStat(&statBuffer) == B_OK) { FileStatToString(&statBuffer, sourceBuffer, 96); } else sourceBuffer[0] = '\0'; @@ -2185,53 +2191,64 @@ CheckName(uint32 moveMode, const BEntry* sourceEntry, replaceMsg.ReplaceAll("%name", name); replaceMsg.ReplaceFirst("%dest", destBuffer); replaceMsg.ReplaceFirst("%src", sourceBuffer); - replaceMsg.ReplaceFirst("%movemode", - moveMode == kMoveSelectionTo - ? B_TRANSLATE("moving") - : B_TRANSLATE("copying")); + replaceMsg.ReplaceFirst("%movemode", moveMode == kMoveSelectionTo + ? B_TRANSLATE("moving") : B_TRANSLATE("copying")); } // special case single collision (don't need Replace All shortcut) BAlert* alert; if (multipleCollisions || sourceIsDirectory) { - alert = new BAlert("", replaceMsg.String(), - B_TRANSLATE("Skip"), B_TRANSLATE("Replace all")); + alert = new BAlert(); + alert->SetText(replaceMsg.String()); + alert->AddButton(B_TRANSLATE("Skip")); + alert->AddButton(B_TRANSLATE("Skip all")); + alert->AddButton(B_TRANSLATE("Replace")); + alert->AddButton(B_TRANSLATE("Replace all")); + switch (alert->Go()) { + case 0: + conflictResolution = kCanceled; + return B_ERROR; + case 1: + conflictResolution = kSkipAll; + return B_ERROR; + case 2: + conflictResolution = kReplace; + break; + case 3: + conflictResolution = kReplaceAll; + break; + } } else { alert = new BAlert("", replaceMsg.String(), B_TRANSLATE("Cancel"), B_TRANSLATE("Replace")); alert->SetShortcut(0, B_ESCAPE); - } - switch (alert->Go()) { - case 0: // user selected "Cancel" or "Skip" - replaceAll = kCanceled; - return B_ERROR; - - case 1: // user selected "Replace" or "Replace All" - replaceAll = kReplaceAll; - // doesn't matter which since a single - // collision "Replace" is equivalent to a - // "Replace All" - break; + switch (alert->Go()) { + case 0: + conflictResolution = kCanceled; + return B_ERROR; + case 1: + conflictResolution = kReplace; + break; + } } } // delete destination item - if (!destIsDir) - err = entry.Remove(); - else + if (destIsDir) return B_OK; - if (err != B_OK) { + status_t status = entry.Remove(); + if (status != B_OK) { BString error(B_TRANSLATE("There was a problem trying to replace " "\"%name\". The item might be open or busy.")); - error.ReplaceFirst("%name", name);; + error.ReplaceFirst("%name", name); BAlert* alert = new BAlert("", error.String(), B_TRANSLATE("Cancel"), 0, 0, B_WIDTH_AS_USUAL, B_WARNING_ALERT); alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); alert->Go(); } - return err; + return status; } @@ -2962,14 +2979,10 @@ FSRecursiveCreateFolder(BPath path) entry.SetTo(path.Path()); if (entry.Exists()) return B_FILE_EXISTS; - else { - char name[B_FILE_NAME_LENGTH]; - BDirectory parent; - entry.GetParent(&parent); - entry.GetName(name); - parent.CreateDirectory(name, NULL); - } + BDirectory parent; + entry.GetParent(&parent); + parent.CreateDirectory(entry.Name(), NULL); return B_OK; } @@ -3017,8 +3030,7 @@ _RestoreTask(BObjectList* list) if (!originalEntry.Exists()) { BDirectory dir(parentPath.Path()); if (dir.InitCheck() == B_OK) { - char leafName[B_FILE_NAME_LENGTH]; - originalEntry.GetName(leafName); + const char* leafName = originalEntry.Name(); if (entry.MoveTo(&dir, leafName) == B_OK) { BNode node(&entry); if (node.InitCheck() == B_OK) diff --git a/src/preferences/media/Jamfile b/src/preferences/media/Jamfile index f4f9fffe49..9bff322326 100644 --- a/src/preferences/media/Jamfile +++ b/src/preferences/media/Jamfile @@ -6,7 +6,7 @@ if ! $(TARGET_PLATFORM_HAIKU_COMPATIBLE) { SubDirC++Flags -fmultiple-symbol-spaces ; } -UsePrivateHeaders media shared ; +UsePrivateHeaders media midi shared ; Preference Media : Media.cpp @@ -15,7 +15,7 @@ Preference Media : MediaViews.cpp MediaWindow.cpp MidiSettingsView.cpp - : media be localestub [ TargetLibsupc++ ] + : media midi be localestub [ TargetLibsupc++ ] : media.rdef ; diff --git a/src/preferences/media/MediaViews.cpp b/src/preferences/media/MediaViews.cpp index 87e869679e..f8bb697ef8 100644 --- a/src/preferences/media/MediaViews.cpp +++ b/src/preferences/media/MediaViews.cpp @@ -284,6 +284,7 @@ AudioSettingsView::AudioSettingsView() .Add(defaultsBox) .AddGroup(B_HORIZONTAL) .Add(_MakeVolumeCheckBox()) + .AddGlue() .Add(MakeRestartButton()) .End() .AddGlue(); diff --git a/src/preferences/media/MediaWindow.cpp b/src/preferences/media/MediaWindow.cpp index 30ab05126e..1275a6a502 100644 --- a/src/preferences/media/MediaWindow.cpp +++ b/src/preferences/media/MediaWindow.cpp @@ -12,7 +12,6 @@ #include -#include #include #include #include @@ -185,7 +184,8 @@ MediaWindow::MediaWindow(BRect frame) fVideoInputs(5, true), fVideoOutputs(5, true), fInitCheck(B_OK), - fRestartThread(-1) + fRestartThread(-1), + fRestartAlert(NULL) { _InitWindow(); @@ -307,13 +307,16 @@ MediaWindow::UpdateOutputListItem(MediaListItem::media_type type, bool MediaWindow::QuitRequested() { - status_t exit = B_OK; if (fRestartThread > 0) { - wait_for_thread(fRestartThread, &exit); - if (exit != B_OK) { - fprintf(stderr, "MediaWindow::QuitRequested wait_for_thread" - " returned with an error: %s\n", strerror(exit)); - } + BString text(B_TRANSLATE("Quitting Media now will stop the " + "restarting of the media services. Flaky or unavailable media " + "functionality is the likely result.")); + + fRestartAlert = new BAlert(B_TRANSLATE("Warning!"), text, + B_TRANSLATE("Quit anyway"), NULL, NULL, + B_WIDTH_AS_USUAL, B_OFFSET_SPACING, B_WARNING_ALERT); + + fRestartAlert->Go(); } // Stop watching the MediaRoster fCurrentNode.SetTo(NULL); @@ -658,6 +661,11 @@ MediaWindow::_RestartMediaServices(void* data) shutdown_media_server(); launch_media_server(); + if (window->fRestartAlert != NULL + && window->fRestartAlert->Lock()) { + window->fRestartAlert->Quit(); + } + return window->PostMessage(ML_RESTART_THREAD_FINISHED); } diff --git a/src/preferences/media/MediaWindow.h b/src/preferences/media/MediaWindow.h index 5d75867de9..a9390bf080 100644 --- a/src/preferences/media/MediaWindow.h +++ b/src/preferences/media/MediaWindow.h @@ -10,6 +10,7 @@ #define MEDIA_WINDOW_H +#include #include #include #include @@ -109,6 +110,7 @@ private: status_t fInitCheck; thread_id fRestartThread; + BAlert* fRestartAlert; }; diff --git a/src/preferences/media/MidiSettingsView.cpp b/src/preferences/media/MidiSettingsView.cpp index 5310a4d9ca..cdf0fbb662 100644 --- a/src/preferences/media/MidiSettingsView.cpp +++ b/src/preferences/media/MidiSettingsView.cpp @@ -5,6 +5,8 @@ #include "MidiSettingsView.h" +#include + #include #include #include @@ -27,8 +29,6 @@ #undef B_TRANSLATION_CONTEXT #define B_TRANSLATION_CONTEXT "Midi View" -#define SETTINGS_FILE "midi" - const static uint32 kSelectSoundFont = 'SeSf'; @@ -37,7 +37,7 @@ MidiSettingsView::MidiSettingsView() SettingsView() { BBox* defaultsBox = new BBox("SoundFont"); - defaultsBox->SetLabel(B_TRANSLATE("SoundFont")); + defaultsBox->SetLabel(B_TRANSLATE("Available SoundFonts")); BGridView* defaultsGridView = new BGridView(); fListView = new BListView(B_SINGLE_SELECTION_LIST); @@ -91,6 +91,8 @@ MidiSettingsView::MessageReceived(BMessage* message) void MidiSettingsView::_RetrieveSoftSynthList() { + // TODO: Duplicated code between here + // and BSoftSynth::SetDefaultInstrumentsFile BStringList paths; status_t status = BPathFinder::FindPaths(B_FIND_PATH_DATA_DIRECTORY, "synth", paths); @@ -108,9 +110,10 @@ MidiSettingsView::_RetrieveSoftSynthList() BNode node(&entry); BNodeInfo nodeInfo(&node); char mimeType[B_MIME_TYPE_LENGTH]; - // TODO: For some reason this doesn't work + // TODO: For some reason the mimetype check fails. + // maybe because the file hasn't yet been sniffed and recognized? if (nodeInfo.GetType(mimeType) == B_OK - /*&& !strcmp(mimeType, "audio/x-soundfont")*/) { + /*&& !strcmp(mimeType, "audio/x-soundfont")*/) { BPath fullPath = paths.StringAt(i).String(); fullPath.Append(entry.Name()); fListView->AddItem(new BStringItem(fullPath.Path())); @@ -123,25 +126,13 @@ MidiSettingsView::_RetrieveSoftSynthList() void MidiSettingsView::_LoadSettings() { - // TODO: Duplicated code between here - // and BSoftSynth::SetDefaultInstrumentsFile - char buffer[512]; - BPath path; - if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) { - path.Append(SETTINGS_FILE); - BFile file(path.Path(), B_READ_ONLY); - if (file.InitCheck() == B_OK) { - file.Read(buffer, sizeof(buffer)); - char soundFont[512]; - sscanf(buffer, "# Midi Settings\n soundfont = %s\n", - soundFont); - - for (int32 i = 0; i < fListView->CountItems(); i++) { - BStringItem* item = (BStringItem*)fListView->ItemAt(i); - if (!strcmp(item->Text(), soundFont)) { - fListView->Select(i); - break; - } + struct BPrivate::midi_settings settings; + if (BPrivate::read_midi_settings(&settings) == B_OK) { + for (int32 i = 0; i < fListView->CountItems(); i++) { + BStringItem* item = (BStringItem*)fListView->ItemAt(i); + if (!strcmp(item->Text(), settings.soundfont_file)) { + fListView->Select(i); + break; } } } @@ -159,16 +150,8 @@ MidiSettingsView::_SaveSettings() if (item == NULL) return; - char buffer[512]; - snprintf(buffer, 512, "# Midi Settings\n soundfont = %s\n", - item->Text()); - - BPath path; - if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) { - path.Append(SETTINGS_FILE); - BFile file(path.Path(), B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE); - if (file.InitCheck() == B_OK) - file.Write(buffer, strlen(buffer)); - } + struct BPrivate::midi_settings settings; + strlcpy(settings.soundfont_file, item->Text(), sizeof(settings.soundfont_file)); + BPrivate::write_midi_settings(settings); } diff --git a/src/preferences/screen/AlertView.cpp b/src/preferences/screen/AlertView.cpp deleted file mode 100644 index 7d50749b85..0000000000 --- a/src/preferences/screen/AlertView.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright 2001-2008, Haiku. - * Distributed under the terms of the MIT License. - * - * Authors: - * Rafael Romo - * Stefano Ceccherini (burton666@libero.it) - * Axel Dörfler, axeld@pinc-software.de - */ - - -#include "AlertView.h" -#include "Constants.h" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - - -#undef B_TRANSLATION_CONTEXT -#define B_TRANSLATION_CONTEXT "Screen" - - -AlertView::AlertView(BRect frame, const char *name) - : BView(frame, name, B_FOLLOW_ALL, B_WILL_DRAW | B_PULSE_NEEDED), - // we will wait 12 seconds until we send a message - fSeconds(12) -{ - SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); - fBitmap = InitIcon(); - - BRect rect(60, 8, 400, 36); - BStringView *stringView = new BStringView(rect, NULL, - B_TRANSLATE("Do you wish to keep these settings?")); - stringView->SetFont(be_bold_font); - stringView->ResizeToPreferred(); - AddChild(stringView); - - rect = stringView->Frame(); - rect.OffsetBy(0, rect.Height()); - fCountdownView = new BStringView(rect, "countdown", NULL); - UpdateCountdownView(); - fCountdownView->ResizeToPreferred(); - AddChild(fCountdownView); - - BButton* keepButton = new BButton(rect, "keep", B_TRANSLATE("Keep"), - new BMessage(BUTTON_KEEP_MSG), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); - keepButton->ResizeToPreferred(); - AddChild(keepButton); - - BButton* button = new BButton(rect, "undo", B_TRANSLATE("Undo"), - new BMessage(BUTTON_UNDO_MSG), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); - button->ResizeToPreferred(); - AddChild(button); - - // we're resizing ourselves to the right size - // (but we're not implementing GetPreferredSize(), bad style!) - float width = stringView->Frame().right; - if (fCountdownView->Frame().right > width) - width = fCountdownView->Frame().right; - if (width < Bounds().Width()) - width = Bounds().Width(); - - float height - = fCountdownView->Frame().bottom + 24 + button->Bounds().Height(); - ResizeTo(width, height); - - keepButton->MoveTo(Bounds().Width() - 8 - keepButton->Bounds().Width(), - Bounds().Height() - 8 - keepButton->Bounds().Height()); - button->MoveTo(keepButton->Frame().left - button->Bounds().Width() - 8, - keepButton->Frame().top); - - keepButton->MakeDefault(true); -} - - -void -AlertView::AttachedToWindow() -{ - // the view displays a decrementing counter - // (until the user must take action) - Window()->SetPulseRate(1000000); - // every second - - SetEventMask(B_KEYBOARD_EVENTS); -} - - -void -AlertView::Draw(BRect updateRect) -{ - rgb_color dark = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), - B_DARKEN_1_TINT); - SetHighColor(dark); - - FillRect(BRect(0.0, 0.0, 30.0, Bounds().bottom)); - - if (fBitmap != NULL) { - SetDrawingMode(B_OP_ALPHA); - DrawBitmap(fBitmap, BPoint(18.0, 6.0)); - SetDrawingMode(B_OP_COPY); - } -} - - -void -AlertView::Pulse() -{ - if (--fSeconds == 0) - Window()->PostMessage(BUTTON_UNDO_MSG); - else - UpdateCountdownView(); -} - - -void -AlertView::KeyDown(const char* bytes, int32 numBytes) -{ - if (numBytes == 1 && bytes[0] == B_ESCAPE) - Window()->PostMessage(BUTTON_UNDO_MSG); -} - - -void -AlertView::UpdateCountdownView() -{ - BString string; - string = B_TRANSLATE("Settings will revert in %seconds."); - - BTimeUnitFormat format; - BString tmp; - format.Format(tmp, fSeconds, B_TIME_UNIT_SECOND); - - string.ReplaceFirst("%seconds", tmp); - fCountdownView->SetText(string.String()); -} - - -BBitmap* -AlertView::InitIcon() -{ - // This is how BAlert gets to its icon - BBitmap* icon = NULL; - BPath path; - if (find_directory(B_BEOS_SERVERS_DIRECTORY, &path) == B_OK) { - path.Append("app_server"); - BResources resources; - BFile file; - if (file.SetTo(path.Path(), B_READ_ONLY) == B_OK - && resources.SetTo(&file) == B_OK) { - size_t size; - const void* data = resources.LoadResource(B_VECTOR_ICON_TYPE, - "warn", &size); - if (data) { - icon = new BBitmap(BRect(0, 0, 31, 31), 0, B_RGBA32); - if (BIconUtils::GetVectorIcon((const uint8*)data, size, icon) - != B_OK) { - delete icon; - icon = NULL; - } - } - } - } - - return icon; -} diff --git a/src/preferences/screen/AlertView.h b/src/preferences/screen/AlertView.h deleted file mode 100644 index 66432b3c42..0000000000 --- a/src/preferences/screen/AlertView.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2001-2005, Haiku. - * Distributed under the terms of the MIT License. - * - * Authors: - * Rafael Romo - * Stefano Ceccherini (burton666@libero.it) - * Axel Dörfler, axeld@pinc-software.de - */ -#ifndef ALERT_VIEW_H -#define ALERT_VIEW_H - - -#include -#include - -class BBitmap; -class BStringView; - - -class AlertView : public BView { - public: - AlertView(BRect frame, const char* name); - - virtual void AttachedToWindow(); - virtual void Draw(BRect updateRect); - virtual void Pulse(); - virtual void KeyDown(const char* bytes, int32 numBytes); - - private: - void UpdateCountdownView(); - BBitmap* InitIcon(); - - BStringView* fCountdownView; - BBitmap* fBitmap; - int32 fSeconds; -}; - -#endif /* ALERT_VIEW_H */ diff --git a/src/preferences/screen/AlertWindow.cpp b/src/preferences/screen/AlertWindow.cpp index 51943fd429..8d9ec10469 100644 --- a/src/preferences/screen/AlertWindow.cpp +++ b/src/preferences/screen/AlertWindow.cpp @@ -1,60 +1,117 @@ /* - * Copyright 2001-2006, Haiku. + * Copyright 2001-2015, Haiku. * Distributed under the terms of the MIT License. * * Authors: * Rafael Romo * Stefano Ceccherini (burton666@libero.it) * Axel Dörfler, axeld@pinc-software.de + * Augustin Cavalier */ + #include "AlertWindow.h" -#include "AlertView.h" #include "Constants.h" +#include #include +#include +#include #include -#include +#include #undef B_TRANSLATION_CONTEXT #define B_TRANSLATION_CONTEXT "Screen" -AlertWindow::AlertWindow(BMessenger target) - : BWindow(BRect(100.0, 100.0, 400.0, 193.0), B_TRANSLATE("Undo"), - B_MODAL_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL, - B_NOT_RESIZABLE | B_NOT_ZOOMABLE, B_ALL_WORKSPACES), - fTarget(target) +AlertWindow::AlertWindow(BMessenger handler) + : BAlert(B_TRANSLATE("Confirm changes"), + "", B_TRANSLATE("Undo"), B_TRANSLATE("Keep")), + // we will wait 12 seconds until we send a message + fSeconds(12), + fHandler(handler) { - fAlertView = new AlertView(Bounds(), "AlertView"); - - ResizeTo(fAlertView->Bounds().Width(), fAlertView->Bounds().Height()); - AddChild(fAlertView); - - // center window on screen - BScreen screen(this); - MoveTo(screen.Frame().left + (screen.Frame().Width() - Frame().Width()) / 2, - screen.Frame().top + (screen.Frame().Height() - Frame().Height()) / 2); + SetType(B_WARNING_ALERT); + SetPulseRate(1000000); + TextView()->SetStylable(true); + TextView()->GetFontAndColor(0, &fOriginalFont); + fFont = fOriginalFont; + fFont.SetFace(B_BOLD_FACE); + UpdateCountdownView(); } void -AlertWindow::MessageReceived(BMessage *message) +AlertWindow::DispatchMessage(BMessage* message, BHandler* handler) +{ + if (message->what == B_PULSE) { + if (--fSeconds == 0) { + fHandler.SendMessage(BUTTON_UNDO_MSG); + PostMessage(B_QUIT_REQUESTED); + Hide(); + } else + UpdateCountdownView(); + } + + BAlert::DispatchMessage(message, handler); +} + + +void +AlertWindow::MessageReceived(BMessage* message) { switch (message->what) { - case BUTTON_KEEP_MSG: - fTarget.SendMessage(MAKE_INITIAL_MSG); - PostMessage(B_QUIT_REQUESTED); + case 'ALTB': // alert button message + { + int32 which; + if (message->FindInt32("which", &which) == B_OK) { + if (which == 1) + fHandler.SendMessage(MAKE_INITIAL_MSG); + else if (which == 0) + fHandler.SendMessage(BUTTON_UNDO_MSG); + PostMessage(B_QUIT_REQUESTED); + Hide(); + } break; + } - case BUTTON_UNDO_MSG: - fTarget.SendMessage(BUTTON_UNDO_MSG); - PostMessage(B_QUIT_REQUESTED); - break; + case B_KEY_DOWN: + { + int8 val; + if (message->FindInt8("byte", &val) == B_OK && val == B_ESCAPE) { + fHandler.SendMessage(BUTTON_UNDO_MSG); + PostMessage(B_QUIT_REQUESTED); + Hide(); + break; + } + // fall through + } default: - BWindow::MessageReceived(message); + BAlert::MessageReceived(message); break; } } + + +void +AlertWindow::UpdateCountdownView() +{ + BString str1 = B_TRANSLATE("Do you wish to keep these settings?"); + BString string = str1; + string += "\n"; + string += B_TRANSLATE("Settings will revert in %seconds."); + + BTimeUnitFormat format; + BString tmp; + format.Format(tmp, fSeconds, B_TIME_UNIT_SECOND); + + string.ReplaceFirst("%seconds", tmp); + // The below is black magic, do not touch. We really need to refactor + // BTextView sometime... + TextView()->SetFontAndColor(0, str1.Length() + 1, &fOriginalFont, + B_FONT_ALL); + TextView()->SetText(string.String()); + TextView()->SetFontAndColor(0, str1.Length(), &fFont, B_FONT_ALL); +} diff --git a/src/preferences/screen/AlertWindow.h b/src/preferences/screen/AlertWindow.h index d216757073..48a4d00282 100644 --- a/src/preferences/screen/AlertWindow.h +++ b/src/preferences/screen/AlertWindow.h @@ -1,34 +1,39 @@ /* - * Copyright 2001-2005, Haiku. + * Copyright 2001-2015, Haiku. * Distributed under the terms of the MIT License. * * Authors: * Rafael Romo * Stefano Ceccherini (burton666@libero.it) * Axel Dörfler, axeld@pinc-software.de + * Augustin Cavalier */ #ifndef ALERT_WINDOW_H #define ALERT_WINDOW_H -#include +#include +#include #include +#include + +class BWindow; -class BMessageRunner; -class BButton; -class AlertView; - - -class AlertWindow : public BWindow { +class AlertWindow : public BAlert { public: - AlertWindow(BMessenger target); + AlertWindow(BMessenger handler); - virtual void MessageReceived(BMessage *message); + virtual void MessageReceived(BMessage* message); + virtual void DispatchMessage(BMessage* message, BHandler* handler); private: - BMessenger fTarget; - AlertView* fAlertView; + void UpdateCountdownView(); + + int32 fSeconds; + BMessenger fHandler; + BFont fOriginalFont; + BFont fFont; }; #endif /* ALERT_WINDOW_H */ diff --git a/src/preferences/screen/Jamfile b/src/preferences/screen/Jamfile index d2370cd486..116d9f2606 100644 --- a/src/preferences/screen/Jamfile +++ b/src/preferences/screen/Jamfile @@ -1,6 +1,5 @@ SubDir HAIKU_TOP src preferences screen ; -SetSubDirSupportedPlatformsBeOSCompatible ; AddSubDirSupportedPlatforms libbe_test ; UsePrivateHeaders [ FDirName graphics common ] ; @@ -8,7 +7,6 @@ UsePrivateHeaders [ FDirName graphics radeon ] ; UsePrivateHeaders interface ; Preference Screen : - AlertView.cpp AlertWindow.cpp MonitorView.cpp multimon.cpp @@ -31,7 +29,6 @@ if $(TARGET_PLATFORM) = libbe_test { DoCatalogs Screen : x-vnd.Haiku-Screen : - AlertView.cpp AlertWindow.cpp RefreshSlider.cpp RefreshWindow.cpp diff --git a/src/preferences/screen/ScreenWindow.cpp b/src/preferences/screen/ScreenWindow.cpp index c3bfb28696..29f38ddb39 100644 --- a/src/preferences/screen/ScreenWindow.cpp +++ b/src/preferences/screen/ScreenWindow.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2001-2013, Haiku, Inc. + * Copyright 2001-2014 Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -164,14 +165,14 @@ screen_errors(status_t status) } -// #pragma mark - +// #pragma mark - ScreenWindow ScreenWindow::ScreenWindow(ScreenSettings* settings) : BWindow(settings->WindowFrame(), B_TRANSLATE_SYSTEM_NAME("Screen"), B_TITLED_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE - | B_AUTO_UPDATE_SIZE_LIMITS, B_ALL_WORKSPACES), + | B_AUTO_UPDATE_SIZE_LIMITS, B_ALL_WORKSPACES), fIsVesa(false), fBootWorkspaceApplied(false), fOtherRefresh(NULL), @@ -194,7 +195,7 @@ ScreenWindow::ScreenWindow(ScreenSettings* settings) // we need the "Current Workspace" first to get its height - BPopUpMenu *popUpMenu = new BPopUpMenu(B_TRANSLATE("Current workspace"), + BPopUpMenu* popUpMenu = new BPopUpMenu(B_TRANSLATE("Current workspace"), true, true); fAllWorkspacesItem = new BMenuItem(B_TRANSLATE("All workspaces"), new BMessage(WORKSPACE_CHECK_MSG)); @@ -234,34 +235,32 @@ ScreenWindow::ScreenWindow(ScreenSettings* settings) B_TRANSLATE("Workspaces")); workspaces->SetAlignment(B_ALIGN_CENTER); - fColumnsControl = new BTextControl(B_TRANSLATE("Columns:"), "0", + fColumnsControl = new BSpinner("columns", B_TRANSLATE("Columns:"), new BMessage(kMsgWorkspaceColumnsChanged)); - fColumnsControl->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT); - fRowsControl = new BTextControl(B_TRANSLATE("Rows:"), "0", - new BMessage(kMsgWorkspaceRowsChanged)); - fRowsControl->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT); + fColumnsControl->SetAlignment(B_ALIGN_RIGHT); + fColumnsControl->SetRange(1, 32); + + fRowsControl = new BSpinner("rows", B_TRANSLATE("Rows:"), + new BMessage(kMsgWorkspaceRowsChanged)); + fRowsControl->SetAlignment(B_ALIGN_RIGHT); + fRowsControl->SetRange(1, 32); + + uint32 columns; + uint32 rows; + BPrivate::get_workspaces_layout(&columns, &rows); + fColumnsControl->SetValue(columns); + fRowsControl->SetValue(rows); - float tiny = be_control_look->DefaultItemSpacing() / 4; screenBox->AddChild(BLayoutBuilder::Group<>() .AddGroup(B_VERTICAL, B_USE_SMALL_SPACING) .Add(workspaces) - .AddGrid(0.0, tiny) + .AddGrid(B_USE_DEFAULT_SPACING, B_USE_SMALL_SPACING) // columns .Add(fColumnsControl->CreateLabelLayoutItem(), 0, 0) - .Add(BSpaceLayoutItem::CreateHorizontalStrut( - B_USE_SMALL_SPACING), 1, 0) - .Add(fColumnsControl->CreateTextViewLayoutItem(), 2, 0) - .Add(BSpaceLayoutItem::CreateHorizontalStrut(tiny), 3, 0) - .Add(_CreateColumnRowButton(true, false), 4, 0) - .Add(_CreateColumnRowButton(true, true), 5, 0) + .Add(fColumnsControl->CreateTextViewLayoutItem(), 1, 0) // rows .Add(fRowsControl->CreateLabelLayoutItem(), 0, 1) - .Add(BSpaceLayoutItem::CreateHorizontalStrut( - B_USE_SMALL_SPACING), 1, 1) - .Add(fRowsControl->CreateTextViewLayoutItem(), 2, 1) - .Add(BSpaceLayoutItem::CreateHorizontalStrut(tiny), 3, 1) - .Add(_CreateColumnRowButton(false, false), 4, 1) - .Add(_CreateColumnRowButton(false, true), 5, 1) + .Add(fRowsControl->CreateTextViewLayoutItem(), 1, 1) .End() .End() .View()); @@ -872,17 +871,33 @@ ScreenWindow::_UpdateWorkspaceButtons() uint32 rows; BPrivate::get_workspaces_layout(&columns, &rows); - char text[32]; - snprintf(text, sizeof(text), "%" B_PRId32, columns); - fColumnsControl->SetText(text); + // Set the max values enabling/disabling the up/down arrows - snprintf(text, sizeof(text), "%" B_PRId32, rows); - fRowsControl->SetText(text); + if (rows == 1) + fColumnsControl->SetMaxValue(32); + else if (rows == 2) + fColumnsControl->SetMaxValue(16); + else if (rows <= 4) + fColumnsControl->SetMaxValue(8); + else if (rows <= 8) + fColumnsControl->SetMaxValue(4); + else if (rows <= 16) + fColumnsControl->SetMaxValue(2); + else if (rows <= 32) + fColumnsControl->SetMaxValue(1); - _GetColumnRowButton(true, false)->SetEnabled(columns != 1 && rows != 32); - _GetColumnRowButton(true, true)->SetEnabled((columns + 1) * rows < 32); - _GetColumnRowButton(false, false)->SetEnabled(rows != 1 && columns != 32); - _GetColumnRowButton(false, true)->SetEnabled(columns * (rows + 1) < 32); + if (columns == 1) + fRowsControl->SetMaxValue(32); + else if (columns == 2) + fRowsControl->SetMaxValue(16); + else if (columns <= 4) + fRowsControl->SetMaxValue(8); + else if (columns <= 8) + fRowsControl->SetMaxValue(4); + else if (columns <= 16) + fRowsControl->SetMaxValue(2); + else if (columns <= 32) + fRowsControl->SetMaxValue(1); } @@ -918,51 +933,33 @@ ScreenWindow::MessageReceived(BMessage* message) _CheckApplyEnabled(); break; - case kMsgWorkspaceLayoutChanged: - { - int32 deltaX = 0; - int32 deltaY = 0; - message->FindInt32("delta_x", &deltaX); - message->FindInt32("delta_y", &deltaY); - - if (deltaX == 0 && deltaY == 0) - break; - - uint32 newColumns; - uint32 newRows; - BPrivate::get_workspaces_layout(&newColumns, &newRows); - - newColumns += deltaX; - newRows += deltaY; - BPrivate::set_workspaces_layout(newColumns, newRows); - - _UpdateWorkspaceButtons(); - _CheckApplyEnabled(); - break; - } - case kMsgWorkspaceColumnsChanged: { - uint32 newColumns = strtoul(fColumnsControl->Text(), NULL, 10); + uint32 newColumns = (uint32)fColumnsControl->Value(); uint32 rows; BPrivate::get_workspaces_layout(NULL, &rows); BPrivate::set_workspaces_layout(newColumns, rows); _UpdateWorkspaceButtons(); + fRowsControl->SetValue(rows); + // enables/disables up/down arrows _CheckApplyEnabled(); + break; } case kMsgWorkspaceRowsChanged: { - uint32 newRows = strtoul(fRowsControl->Text(), NULL, 10); + uint32 newRows = (uint32)fRowsControl->Value(); uint32 columns; BPrivate::get_workspaces_layout(&columns, NULL); BPrivate::set_workspaces_layout(columns, newRows); _UpdateWorkspaceButtons(); + fColumnsControl->SetValue(columns); + // enables/disables up/down arrows _CheckApplyEnabled(); break; } @@ -1133,7 +1130,6 @@ ScreenWindow::MessageReceived(BMessage* message) default: BWindow::MessageReceived(message); - break; } } @@ -1169,33 +1165,6 @@ ScreenWindow::_WriteVesaModeFile(const screen_mode& mode) const } -BButton* -ScreenWindow::_CreateColumnRowButton(bool columns, bool plus) -{ - BMessage* message = new BMessage(kMsgWorkspaceLayoutChanged); - message->AddInt32("delta_x", columns ? (plus ? 1 : -1) : 0); - message->AddInt32("delta_y", !columns ? (plus ? 1 : -1) : 0); - - BButton* button = new BButton(plus ? "+" : "\xe2\x88\x92", message); - button->SetFontSize(be_plain_font->Size() * 0.9); - - BSize size = button->MinSize(); - size.width = button->StringWidth("+") + 16; - button->SetExplicitMinSize(size); - button->SetExplicitMaxSize(size); - - fWorkspacesButtons[(columns ? 0 : 2) + (plus ? 1 : 0)] = button; - return button; -} - - -BButton* -ScreenWindow::_GetColumnRowButton(bool columns, bool plus) -{ - return fWorkspacesButtons[(columns ? 0 : 2) + (plus ? 1 : 0)]; -} - - void ScreenWindow::_BuildSupportedColorSpaces() { @@ -1216,7 +1185,7 @@ void ScreenWindow::_CheckApplyEnabled() { bool applyEnabled = true; - + if (fSelected == fActive) { applyEnabled = false; if (fAllWorkspacesItem->IsMarked()) { @@ -1231,7 +1200,7 @@ ScreenWindow::_CheckApplyEnabled() } } } - + fApplyButton->SetEnabled(applyEnabled); uint32 columns; @@ -1367,8 +1336,8 @@ ScreenWindow::_Apply() fActive = fSelected; // TODO: only show alert when this is an unknown mode - BWindow* window = new AlertWindow(this); - window->Show(); + BAlert* window = new AlertWindow(this); + window->Go(NULL); } else { char message[256]; snprintf(message, sizeof(message), diff --git a/src/preferences/screen/ScreenWindow.h b/src/preferences/screen/ScreenWindow.h index 1d24134b1e..1b8b14b232 100644 --- a/src/preferences/screen/ScreenWindow.h +++ b/src/preferences/screen/ScreenWindow.h @@ -1,12 +1,13 @@ /* - * Copyright 2001-2009, Haiku. + * Copyright 2001-2014 Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: - * Rafael Romo - * Stefano Ceccherini (burton666@libero.it) - * Thomas Kurschel + * Stefano Ceccherini, burton666@libero.it * Axel Dörfler, axeld@pinc-software.de + * Thomas Kurschel + * Rafael Romo + * John Scipione, jscipione@gmail.com */ #ifndef SCREEN_WINDOW_H #define SCREEN_WINDOW_H @@ -20,8 +21,8 @@ class BBox; class BPopUpMenu; class BMenuField; +class BSpinner; class BStringView; -class BTextControl; class RefreshWindow; class MonitorView; @@ -39,9 +40,6 @@ public: virtual void ScreenChanged(BRect frame, color_space mode); private: - BButton* _CreateColumnRowButton(bool columns, bool plus); - BButton* _GetColumnRowButton(bool columns, bool plus); - void _BuildSupportedColorSpaces(); void _CheckApplyEnabled(); @@ -74,9 +72,8 @@ private: MonitorView* fMonitorView; BMenuItem* fAllWorkspacesItem; - BTextControl* fColumnsControl; - BTextControl* fRowsControl; - BButton* fWorkspacesButtons[4]; + BSpinner* fColumnsControl; + BSpinner* fRowsControl; uint32 fSupportedColorSpaces; BMenuItem* fUserSelectedColorSpace; diff --git a/src/servers/app/EventDispatcher.cpp b/src/servers/app/EventDispatcher.cpp index b45f3c9298..9c8fb902f6 100644 --- a/src/servers/app/EventDispatcher.cpp +++ b/src/servers/app/EventDispatcher.cpp @@ -612,7 +612,8 @@ EventDispatcher::SetDragMessage(BMessage& message, if (fLastButtons == 0) { // mouse buttons has already been released or was never pressed - bitmap->ReleaseReference(); + if (bitmap != NULL) + bitmap->ReleaseReference(); return; } diff --git a/src/servers/app/ServerWindow.cpp b/src/servers/app/ServerWindow.cpp index 7322cd8adc..b65321636c 100644 --- a/src/servers/app/ServerWindow.cpp +++ b/src/servers/app/ServerWindow.cpp @@ -2078,7 +2078,8 @@ fDesktop->UnlockSingleWindow(); fDesktop->EventDispatcher().SetDragMessage(dragMessage, bitmap, offset); fDesktop->LockSingleWindow(); - bitmap->ReleaseReference(); + if (bitmap != NULL) + bitmap->ReleaseReference(); } delete[] buffer; } diff --git a/src/servers/keystore/AppAccessRequestWindow.cpp b/src/servers/keystore/AppAccessRequestWindow.cpp index 1a0292afc9..dc77e4ce0a 100644 --- a/src/servers/keystore/AppAccessRequestWindow.cpp +++ b/src/servers/keystore/AppAccessRequestWindow.cpp @@ -142,9 +142,10 @@ AppAccessRequestWindow::AppAccessRequestWindow(const char* keyringName, const char* signature, const char* path, const char* accessString, bool appIsNew, bool appWasUpdated) : - BWindow(BRect(50, 50, 269, 302), B_TRANSLATE("Application keyring access"), + BWindow(BRect(50, 50, 100, 100), B_TRANSLATE("Application keyring access"), B_TITLED_WINDOW, B_NOT_RESIZABLE | B_ASYNCHRONOUS_CONTROLS - | B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE | B_AUTO_UPDATE_SIZE_LIMITS), + | B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE | B_AUTO_UPDATE_SIZE_LIMITS + | B_CLOSE_ON_ESCAPE), fRequestView(NULL), fDoneSem(-1), fResult(kMessageDisallow) @@ -175,17 +176,12 @@ AppAccessRequestWindow::~AppAccessRequestWindow() } -void -AppAccessRequestWindow::DispatchMessage(BMessage* message, BHandler* handler) +bool +AppAccessRequestWindow::QuitRequested() { - int8 key; - if (message->what == B_KEY_DOWN - && message->FindInt8("byte", 0, &key) == B_OK - && key == B_ESCAPE) { - PostMessage(kMessageDisallow); - } - - BWindow::DispatchMessage(message, handler); + fResult = kMessageDisallow; + release_sem(fDoneSem); + return false; } @@ -208,6 +204,7 @@ AppAccessRequestWindow::MessageReceived(BMessage* message) status_t AppAccessRequestWindow::RequestAppAccess(bool& allowAlways) { + ResizeToPreferred(); CenterOnScreen(); Show(); diff --git a/src/servers/keystore/AppAccessRequestWindow.h b/src/servers/keystore/AppAccessRequestWindow.h index e8fbee8a5b..b1b8b1a030 100644 --- a/src/servers/keystore/AppAccessRequestWindow.h +++ b/src/servers/keystore/AppAccessRequestWindow.h @@ -23,8 +23,7 @@ public: bool appWasUpdated); virtual ~AppAccessRequestWindow(); -virtual void DispatchMessage(BMessage* message, - BHandler* handler); +virtual bool QuitRequested(); virtual void MessageReceived(BMessage* message); status_t RequestAppAccess(bool& allowAlways); diff --git a/src/servers/keystore/KeyRequestWindow.cpp b/src/servers/keystore/KeyRequestWindow.cpp index 76466577da..6d93408d58 100644 --- a/src/servers/keystore/KeyRequestWindow.cpp +++ b/src/servers/keystore/KeyRequestWindow.cpp @@ -152,9 +152,10 @@ private: KeyRequestWindow::KeyRequestWindow() : - BWindow(BRect(50, 50, 269, 302), B_TRANSLATE("Unlock keyring"), + BWindow(BRect(50, 50, 100, 100), B_TRANSLATE("Unlock keyring"), B_TITLED_WINDOW, B_NOT_RESIZABLE | B_ASYNCHRONOUS_CONTROLS - | B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE | B_AUTO_UPDATE_SIZE_LIMITS), + | B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE | B_AUTO_UPDATE_SIZE_LIMITS + | B_CLOSE_ON_ESCAPE), fRequestView(NULL), fDoneSem(-1), fResult(B_ERROR) @@ -184,17 +185,12 @@ KeyRequestWindow::~KeyRequestWindow() } -void -KeyRequestWindow::DispatchMessage(BMessage* message, BHandler* handler) +bool +KeyRequestWindow::QuitRequested() { - int8 key; - if (message->what == B_KEY_DOWN - && message->FindInt8("byte", 0, &key) == B_OK - && key == B_ESCAPE) { - PostMessage(kMessageCancel); - } - - BWindow::DispatchMessage(message, handler); + fResult = B_CANCELED; + release_sem(fDoneSem); + return false; } @@ -218,6 +214,7 @@ KeyRequestWindow::RequestKey(const BString& keyringName, BMessage& keyMessage) { fRequestView->SetUp(keyringName); + ResizeToPreferred(); CenterOnScreen(); Show(); diff --git a/src/servers/keystore/KeyRequestWindow.h b/src/servers/keystore/KeyRequestWindow.h index 8c535d6e78..2301aaa06b 100644 --- a/src/servers/keystore/KeyRequestWindow.h +++ b/src/servers/keystore/KeyRequestWindow.h @@ -18,8 +18,7 @@ public: KeyRequestWindow(); virtual ~KeyRequestWindow(); -virtual void DispatchMessage(BMessage* message, - BHandler* handler); +virtual bool QuitRequested(); virtual void MessageReceived(BMessage* message); status_t RequestKey(const BString& keyringName, diff --git a/src/servers/launch/BaseJob.cpp b/src/servers/launch/BaseJob.cpp index 555375e3a9..ef27fa134d 100644 --- a/src/servers/launch/BaseJob.cpp +++ b/src/servers/launch/BaseJob.cpp @@ -151,7 +151,7 @@ BaseJob::SetEnvironment(const BMessage& message) } BString variable = name; - variable << "='"; + variable << "="; const char* argument; for (int32 argumentIndex = 0; message.FindString(name, argumentIndex, @@ -160,7 +160,6 @@ BaseJob::SetEnvironment(const BMessage& message) variable << " "; variable += argument; } - variable << "'"; fEnvironment.Add(variable); } @@ -172,7 +171,7 @@ BaseJob::GetSourceFilesEnvironment(BStringList& environment) { int32 count = fSourceFiles.CountStrings(); for (int32 index = 0; index < count; index++) { - _GetSourceFileEnvironment(fSourceFiles.StringAt(index), fEnvironment); + _GetSourceFileEnvironment(fSourceFiles.StringAt(index), environment); } } diff --git a/src/servers/launch/Job.cpp b/src/servers/launch/Job.cpp index 7432921aaf..13ccd9cec1 100644 --- a/src/servers/launch/Job.cpp +++ b/src/servers/launch/Job.cpp @@ -27,8 +27,11 @@ Job::Job(const char* name) fCreateDefaultPort(false), fInitStatus(B_NO_INIT), fTeam(-1), - fTarget(NULL) + fLaunchStatus(B_NO_INIT), + fTarget(NULL), + fPendingLaunchDataReplies(0, false) { + mutex_init(&fLaunchStatusLock, "launch status lock"); } @@ -40,8 +43,12 @@ Job::Job(const Job& other) fCreateDefaultPort(other.CreateDefaultPort()), fInitStatus(B_NO_INIT), fTeam(-1), - fTarget(other.Target()) + fLaunchStatus(B_NO_INIT), + fTarget(other.Target()), + fPendingLaunchDataReplies(0, false) { + mutex_init(&fLaunchStatusLock, "launch status lock"); + fCondition = other.fCondition; // TODO: copy events //fEvent = other.fEvent; @@ -237,50 +244,6 @@ Job::Init(const Finder& finder, std::set& dependencies) } } - // Create ports - // TODO: prefix system ports with "system:" - - bool defaultPort = false; - - for (PortMap::iterator iterator = fPortMap.begin(); - iterator != fPortMap.end(); iterator++) { - BString name(Name()); - const char* suffix = iterator->second.GetString("name"); - if (suffix != NULL) - name << ':' << suffix; - else - defaultPort = true; - - const int32 capacity = iterator->second.GetInt32("capacity", - B_LOOPER_PORT_DEFAULT_CAPACITY); - - port_id port = create_port(capacity, name.String()); - if (port < 0) { - fInitStatus = port; - break; - } - iterator->second.SetInt32("port", port); - - if (name == "x-vnd.haiku-registrar:auth") { - // Allow the launch_daemon to access the registrar authentication - BPrivate::set_registrar_authentication_port(port); - } - } - - if (fInitStatus == B_OK && fCreateDefaultPort && !defaultPort) { - BMessage data; - data.AddInt32("capacity", B_LOOPER_PORT_DEFAULT_CAPACITY); - - port_id port = create_port(B_LOOPER_PORT_DEFAULT_CAPACITY, Name()); - if (port < 0) { - // TODO: log error - fInitStatus = port; - } else { - data.SetInt32("port", port); - AddPort(data); - } - } - return fInitStatus; } @@ -343,16 +306,18 @@ Job::Launch() // Launch by signature BString signature("application/"); signature << Name(); - return BRoster::Private().Launch(signature.String(), NULL, NULL, - 0, NULL, &environment[0], &fTeam); + + return _Launch(signature.String(), NULL, 0, NULL, &environment[0]); } // Build argument vector entry_ref ref; status_t status = get_ref_for_path(fArguments.StringAt(0).String(), &ref); - if (status != B_OK) + if (status != B_OK) { + _SetLaunchStatus(status); return status; + } std::vector args; @@ -365,15 +330,25 @@ Job::Launch() } // Launch via entry_ref - return BRoster::Private().Launch(NULL, &ref, NULL, count, &args[0], - &environment[0], &fTeam); + return _Launch(NULL, &ref, count, &args[0], &environment[0]); } bool Job::IsLaunched() const { - return fTeam >= 0; + return fLaunchStatus != B_NO_INIT; +} + + +status_t +Job::HandleGetLaunchData(BMessage* message) +{ + MutexLocker launchLocker(fLaunchStatusLock); + if (IsLaunched()) + return _SendLaunchDataReply(message); + + return fPendingLaunchDataReplies.AddItem(message) ? B_OK : B_NO_MEMORY; } @@ -434,3 +409,126 @@ Job::_AddStringList(std::vector& array, const BStringList& list) array.push_back(list.StringAt(index).String()); } } + + +void +Job::_SetLaunchStatus(status_t launchStatus) +{ + MutexLocker launchLocker(fLaunchStatusLock); + fLaunchStatus = launchStatus != B_NO_INIT ? launchStatus : B_ERROR; + launchLocker.Unlock(); + + _SendPendingLaunchDataReplies(); +} + + +status_t +Job::_SendLaunchDataReply(BMessage* message) +{ + BMessage reply(fTeam < 0 ? fTeam : (uint32)B_OK); + if (reply.what == B_OK) { + reply.AddInt32("team", fTeam); + + PortMap::const_iterator iterator = fPortMap.begin(); + for (; iterator != fPortMap.end(); iterator++) { + BString name; + if (iterator->second.HasString("name")) + name << iterator->second.GetString("name") << "_"; + name << "port"; + + reply.AddInt32(name.String(), + iterator->second.GetInt32("port", -1)); + } + } + + message->SendReply(&reply); + delete message; + return B_OK; +} + + +void +Job::_SendPendingLaunchDataReplies() +{ + for (int32 i = 0; i < fPendingLaunchDataReplies.CountItems(); i++) + _SendLaunchDataReply(fPendingLaunchDataReplies.ItemAt(i)); + + fPendingLaunchDataReplies.MakeEmpty(); +} + + +status_t +Job::_CreateAndTransferPorts() +{ + // TODO: prefix system ports with "system:" + + bool defaultPort = false; + + for (PortMap::iterator iterator = fPortMap.begin(); + iterator != fPortMap.end(); iterator++) { + BString name(Name()); + const char* suffix = iterator->second.GetString("name"); + if (suffix != NULL) + name << ':' << suffix; + else + defaultPort = true; + + const int32 capacity = iterator->second.GetInt32("capacity", + B_LOOPER_PORT_DEFAULT_CAPACITY); + + port_id port = create_port(capacity, name.String()); + if (port < 0) + return port; + + status_t result = set_port_owner(port, fTeam); + if (result != B_OK) + return result; + + iterator->second.SetInt32("port", port); + + if (name == "x-vnd.haiku-registrar:auth") { + // Allow the launch_daemon to access the registrar authentication + BPrivate::set_registrar_authentication_port(port); + } + } + + if (fCreateDefaultPort && !defaultPort) { + BMessage data; + data.AddInt32("capacity", B_LOOPER_PORT_DEFAULT_CAPACITY); + + port_id port = create_port(B_LOOPER_PORT_DEFAULT_CAPACITY, Name()); + if (port < 0) + return port; + + status_t result = set_port_owner(port, fTeam); + if (result != B_OK) + return result; + + data.SetInt32("port", port); + AddPort(data); + } + + return B_OK; +} + + +status_t +Job::_Launch(const char* signature, entry_ref* ref, int argCount, + const char* const* args, const char** environment) +{ + thread_id mainThread = -1; + status_t result = BRoster::Private().Launch(signature, ref, NULL, argCount, + args, environment, &fTeam, &mainThread, true); + + if (result == B_OK) { + result = _CreateAndTransferPorts(); + + if (result == B_OK) + resume_thread(mainThread); + else + kill_thread(mainThread); + } + + _SetLaunchStatus(result); + return result; +} diff --git a/src/servers/launch/Job.h b/src/servers/launch/Job.h index e2ee0b4d0f..137491db49 100644 --- a/src/servers/launch/Job.h +++ b/src/servers/launch/Job.h @@ -15,6 +15,8 @@ #include #include +#include + using namespace BSupportKit; class BMessage; @@ -22,6 +24,8 @@ class BMessage; class Finder; class Target; +struct entry_ref; + typedef std::map PortMap; @@ -68,6 +72,8 @@ public: status_t Launch(); bool IsLaunched() const; + status_t HandleGetLaunchData(BMessage* message); + protected: virtual status_t Execute(); @@ -78,6 +84,17 @@ private: void _AddStringList(std::vector& array, const BStringList& list); + void _SetLaunchStatus(status_t launchStatus); + + status_t _SendLaunchDataReply(BMessage* message); + void _SendPendingLaunchDataReplies(); + + status_t _CreateAndTransferPorts(); + + status_t _Launch(const char* signature, entry_ref* ref, + int argCount, const char* const* args, + const char** environment); + private: BStringList fArguments; BStringList fRequirements; @@ -87,8 +104,12 @@ private: PortMap fPortMap; status_t fInitStatus; team_id fTeam; + status_t fLaunchStatus; + mutex fLaunchStatusLock; ::Target* fTarget; ::Condition* fCondition; + BObjectList + fPendingLaunchDataReplies; }; diff --git a/src/servers/launch/LaunchDaemon.cpp b/src/servers/launch/LaunchDaemon.cpp index 93fbaac5dd..f9733f916c 100644 --- a/src/servers/launch/LaunchDaemon.cpp +++ b/src/servers/launch/LaunchDaemon.cpp @@ -483,31 +483,29 @@ LaunchDaemon::_HandleGetLaunchData(BMessage* message) launchJob = false; } } - } + } else + launchJob = false; + bool ownsMessage = false; if (reply.what == B_OK) { - // If the job has not been launched yet, we'll pass on our - // team here. The rationale behind this is that this team - // will temporarily own the synchronous reply ports. - reply.AddInt32("team", job->Team() < 0 - ? current_team() : job->Team()); - - PortMap::const_iterator iterator = job->Ports().begin(); - for (; iterator != job->Ports().end(); iterator++) { - BString name; - if (iterator->second.HasString("name")) - name << iterator->second.GetString("name") << "_"; - name << "port"; - - reply.AddInt32(name.String(), - iterator->second.GetInt32("port", -1)); - } - // Launch the job if it hasn't been launched already if (launchJob) _LaunchJob(job); + + DetachCurrentMessage(); + status_t result = job->HandleGetLaunchData(message); + if (result == B_OK) { + // Replying is delegated to the job. + return; + } + + ownsMessage = true; + reply.what = result; } + message->SendReply(&reply); + if (ownsMessage) + delete message; } @@ -1216,9 +1214,7 @@ LaunchDaemon::_StartSession(const char* login) exit(EXIT_FAILURE); if (passwd->pw_dir != NULL && passwd->pw_dir[0] != '\0') { - BString home="HOME=\""; - home << passwd->pw_dir << "\""; - putenv(home.String()); + setenv("HOME", passwd->pw_dir, true); if (chdir(passwd->pw_dir) != 0) { debug_printf("Could not switch to home dir %s: %s\n", @@ -1264,13 +1260,10 @@ void LaunchDaemon::_SetupEnvironment() { // Determine safemode kernel option - BString safemode = "SAFEMODE="; - safemode << (IsSafeMode() ? "yes" : "no"); - - putenv(safemode.String()); + setenv("SAFEMODE", IsSafeMode() ? "yes" : "no", true); // Default locale settings - putenv("LC_TYPE=en_US.UTF-8"); + setenv("LC_TYPE", "en_US.UTF-8", true); } diff --git a/src/servers/media/DefaultManager.cpp b/src/servers/media/DefaultManager.cpp index 6354189564..6e00e93ca8 100644 --- a/src/servers/media/DefaultManager.cpp +++ b/src/servers/media/DefaultManager.cpp @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -46,7 +45,8 @@ const char *kDefaultManagerSettingsFile = "MDefaultManager"; DefaultManager::DefaultManager() - : fMixerConnected(false), + : + fMixerConnected(false), fPhysicalVideoOut(-1), fPhysicalVideoIn(-1), fPhysicalAudioOut(-1), @@ -57,7 +57,8 @@ DefaultManager::DefaultManager() fPhysicalAudioOutInputID(0), fRescanThread(-1), fRescanRequested(0), - fRescanLock("rescan default manager") + fRescanLock("rescan default manager"), + fRoster(NULL) { strcpy(fPhysicalAudioOutInputName, "default"); fBeginHeader[0] = 0xab00150b; @@ -66,6 +67,10 @@ DefaultManager::DefaultManager() fEndHeader[0] = 0x7465726d; fEndHeader[1] = 0x6d666c67; fEndHeader[2] = 0x00000002; + + fRoster = BMediaRoster::Roster(); + if (fRoster == NULL) + TRACE("DefaultManager: The roster is NULL\n"); } @@ -393,7 +398,7 @@ DefaultManager::_RescanThread() // Connect the mixer and physical audio out (soundcard) if (!fMixerConnected && fAudioMixer != -1 && fPhysicalAudioOut != -1) { - fMixerConnected = B_OK == _ConnectMixerToOutput(); + fMixerConnected = _ConnectMixerToOutput() == B_OK; if (!fMixerConnected) TRACE("DefaultManager: failed to connect mixer and " "soundcard\n"); @@ -455,7 +460,7 @@ DefaultManager::_FindPhysical(volatile media_node_id *id, uint32 default_type, memset(&format, 0, sizeof(format)); format.type = type; count = MAX_NODE_INFOS; - rv = BMediaRoster::Roster()->GetLiveNodes(&info[0], &count, + rv = fRoster->GetLiveNodes(&info[0], &count, isInput ? NULL : &format, isInput ? &format : NULL, NULL, isInput ? B_BUFFER_PRODUCER | B_PHYSICAL_INPUT : B_BUFFER_CONSUMER | B_PHYSICAL_OUTPUT); @@ -493,7 +498,7 @@ DefaultManager::_FindPhysical(volatile media_node_id *id, uint32 default_type, } if (msg) { // we have a default info msg dormant_node_info dninfo; - if (BMediaRoster::Roster()->GetDormantNodeFor(info[i].node, + if (fRoster->GetDormantNodeFor(info[i].node, &dninfo) != B_OK) { ERROR("Couldn't GetDormantNodeFor\n"); continue; @@ -533,17 +538,17 @@ DefaultManager::_FindTimeSource() */ if (fPhysicalAudioOut != -1) { media_node clone; - if (B_OK == BMediaRoster::Roster()->GetNodeFor(fPhysicalAudioOut, - &clone)) { + if (fRoster->GetNodeFor(fPhysicalAudioOut, + &clone) == B_OK) { if (clone.kind & B_TIME_SOURCE) { fTimeSource = clone.node; - BMediaRoster::Roster()->StartTimeSource(clone, + fRoster->StartTimeSource(clone, system_time() + 1000); - BMediaRoster::Roster()->ReleaseNode(clone); + fRoster->ReleaseNode(clone); TRACE("Default DAC timesource created!\n"); return; } - BMediaRoster::Roster()->ReleaseNode(clone); + fRoster->ReleaseNode(clone); } else { TRACE("Default DAC is not a timesource!\n"); } @@ -556,7 +561,7 @@ DefaultManager::_FindTimeSource() memset(&input, 0, sizeof(input)); input.type = B_MEDIA_RAW_AUDIO; count = MAX_NODE_INFOS; - rv = BMediaRoster::Roster()->GetLiveNodes(&info[0], &count, &input, NULL, NULL, + rv = fRoster->GetLiveNodes(&info[0], &count, &input, NULL, NULL, B_TIME_SOURCE | B_PHYSICAL_OUTPUT); if (rv == B_OK && count >= 1) { for (int i = 0; i < count; i++) @@ -573,7 +578,7 @@ DefaultManager::_FindTimeSource() continue; TRACE("Default DAC timesource \"%s\" created!\n", info[i].name); fTimeSource = info[i].node.node; - BMediaRoster::Roster()->StartTimeSource(info[i].node, + fRoster->StartTimeSource(info[i].node, system_time() + 1000); return; } @@ -593,8 +598,11 @@ DefaultManager::_FindAudioMixer() int32 count; status_t rv; + if (fRoster == NULL) + fRoster = BMediaRoster::Roster(); + count = 1; - rv = BMediaRoster::Roster()->GetLiveNodes(&info, &count, NULL, NULL, NULL, + rv = fRoster->GetLiveNodes(&info, &count, NULL, NULL, NULL, B_BUFFER_PRODUCER | B_BUFFER_CONSUMER | B_SYSTEM_MIXER); if (rv != B_OK || count != 1) { TRACE("Couldn't find audio mixer node\n"); @@ -608,7 +616,6 @@ DefaultManager::_FindAudioMixer() status_t DefaultManager::_ConnectMixerToOutput() { - BMediaRoster *roster; media_node timesource; media_node mixer; media_node soundcard; @@ -623,18 +630,19 @@ DefaultManager::_ConnectMixerToOutput() int32 count; status_t rv; - roster = BMediaRoster::Roster(); + if (fRoster == NULL) + fRoster = BMediaRoster::Roster(); - rv = roster->GetNodeFor(fPhysicalAudioOut, &soundcard); + rv = fRoster->GetNodeFor(fPhysicalAudioOut, &soundcard); if (rv != B_OK) { TRACE("DefaultManager: failed to find soundcard (physical audio " "output)\n"); return B_ERROR; } - rv = roster->GetNodeFor(fAudioMixer, &mixer); + rv = fRoster->GetNodeFor(fAudioMixer, &mixer); if (rv != B_OK) { - roster->ReleaseNode(soundcard); + fRoster->ReleaseNode(soundcard); TRACE("DefaultManager: failed to find mixer\n"); return B_ERROR; } @@ -642,7 +650,7 @@ DefaultManager::_ConnectMixerToOutput() // we now have the mixer and soundcard nodes, // find a free input/output and connect them - rv = roster->GetFreeOutputsFor(mixer, &output, 1, &count, + rv = fRoster->GetFreeOutputsFor(mixer, &output, 1, &count, B_MEDIA_RAW_AUDIO); if (rv != B_OK || count != 1) { TRACE("DefaultManager: can't find free mixer output\n"); @@ -650,7 +658,7 @@ DefaultManager::_ConnectMixerToOutput() goto finish; } - rv = roster->GetFreeInputsFor(soundcard, inputs, MAX_INPUT_INFOS, &count, + rv = fRoster->GetFreeInputsFor(soundcard, inputs, MAX_INPUT_INFOS, &count, B_MEDIA_RAW_AUDIO); if (rv != B_OK || count < 1) { TRACE("DefaultManager: can't find free soundcard inputs\n"); @@ -668,7 +676,7 @@ DefaultManager::_ConnectMixerToOutput() switch (i) { case 0: TRACE("DefaultManager: Trying connect in native format (1)\n"); - if (B_OK != roster->GetFormatFor(input, &format)) { + if (fRoster->GetFormatFor(input, &format) != B_OK) { ERROR("DefaultManager: GetFormatFor failed\n"); continue; } @@ -706,7 +714,7 @@ DefaultManager::_ConnectMixerToOutput() case 4: // BeOS R5 multiaudio node bug workaround TRACE("DefaultManager: Trying connect in native format (2)\n"); - if (B_OK != roster->GetFormatFor(input, &format)) { + if (fRoster->GetFormatFor(input, &format) != B_OK) { ERROR("DefaultManager: GetFormatFor failed\n"); continue; } @@ -718,7 +726,7 @@ DefaultManager::_ConnectMixerToOutput() break; } - rv = roster->Connect(output.source, input.destination, &format, + rv = fRoster->Connect(output.source, input.destination, &format, &newoutput, &newinput); if (rv == B_OK) break; @@ -728,25 +736,25 @@ DefaultManager::_ConnectMixerToOutput() goto finish; } - roster->SetRunModeNode(mixer, BMediaNode::B_INCREASE_LATENCY); - roster->SetRunModeNode(soundcard, BMediaNode::B_RECORDING); + fRoster->SetRunModeNode(mixer, BMediaNode::B_INCREASE_LATENCY); + fRoster->SetRunModeNode(soundcard, BMediaNode::B_RECORDING); - roster->GetTimeSource(×ource); - roster->SetTimeSourceFor(mixer.node, timesource.node); - roster->SetTimeSourceFor(soundcard.node, timesource.node); - roster->PrerollNode(mixer); - roster->PrerollNode(soundcard); + fRoster->GetTimeSource(×ource); + fRoster->SetTimeSourceFor(mixer.node, timesource.node); + fRoster->SetTimeSourceFor(soundcard.node, timesource.node); + fRoster->PrerollNode(mixer); + fRoster->PrerollNode(soundcard); - ts = roster->MakeTimeSourceFor(mixer); + ts = fRoster->MakeTimeSourceFor(mixer); start_at = ts->Now() + 50000; - roster->StartNode(mixer, start_at); - roster->StartNode(soundcard, start_at); + fRoster->StartNode(mixer, start_at); + fRoster->StartNode(soundcard, start_at); ts->Release(); finish: - roster->ReleaseNode(mixer); - roster->ReleaseNode(soundcard); - roster->ReleaseNode(timesource); + fRoster->ReleaseNode(mixer); + fRoster->ReleaseNode(soundcard); + fRoster->ReleaseNode(timesource); return rv; } diff --git a/src/servers/media/DefaultManager.h b/src/servers/media/DefaultManager.h index 826b31d063..a4becac896 100644 --- a/src/servers/media/DefaultManager.h +++ b/src/servers/media/DefaultManager.h @@ -21,6 +21,7 @@ #include "DataExchange.h" #include +#include #include class NodeManager; @@ -76,6 +77,7 @@ private: thread_id fRescanThread; int32 fRescanRequested; BLocker fRescanLock; + BMediaRoster* fRoster; }; #endif // _DEFAULT_MANAGER_H diff --git a/src/servers/package/FSUtils.h b/src/servers/package/FSUtils.h index 0a1f0c4cab..004d3cdb1e 100644 --- a/src/servers/package/FSUtils.h +++ b/src/servers/package/FSUtils.h @@ -157,7 +157,7 @@ public: else if (index == 0) fPath.Truncate(1); else - fPath.Truncate(index - 1); + fPath.Truncate(index); return *this; } diff --git a/src/servers/registrar/mime/CreateAppMetaMimeThread.h b/src/servers/registrar/mime/CreateAppMetaMimeThread.h index 797ec63afa..4ec491a6fd 100644 --- a/src/servers/registrar/mime/CreateAppMetaMimeThread.h +++ b/src/servers/registrar/mime/CreateAppMetaMimeThread.h @@ -1,10 +1,10 @@ //---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered +// This software is part of the OpenBeOS distribution and is covered // by the OpenBeOS license. //--------------------------------------------------------------------- /*! \file CreateAppMetaMimeThread.h - CreateAppMetaMimeThread interface declaration + CreateAppMetaMimeThread interface declaration */ #ifndef _CREATE_APP_META_MIME_THREAD_H diff --git a/src/servers/registrar/mime/MimeUpdateThread.cpp b/src/servers/registrar/mime/MimeUpdateThread.cpp index 5b530fbc1b..733e8a9703 100644 --- a/src/servers/registrar/mime/MimeUpdateThread.cpp +++ b/src/servers/registrar/mime/MimeUpdateThread.cpp @@ -42,10 +42,11 @@ namespace Mime { If \a replyee is non-NULL and construction succeeds, the MimeThreadObject assumes resposibility for its deletion. - - Also, if \c non-NULL, \a replyee is expected to be a \c B_REG_MIME_UPDATE_MIME_INFO - or a \c B_REG_MIME_CREATE_APP_META_MIME message with a \c true \c "synchronous" - field detached from the registrar's mime manager looper (though this is not verified). + + Also, if \c non-NULL, \a replyee is expected to be a + \c B_REG_MIME_UPDATE_MIME_INFO or a \c B_REG_MIME_CREATE_APP_META_MIME + message with a \c true \c "synchronous" field detached from the registrar's + mime manager looper (though this is not verified). The message will be replied to at the end of the thread's execution. */ MimeUpdateThread::MimeUpdateThread(const char *name, int32 priority, @@ -65,9 +66,9 @@ MimeUpdateThread::MimeUpdateThread(const char *name, int32 priority, /*! \brief Destroys the MimeUpdateThread object. - If the object was properly initialized (i.e. InitCheck() returns \c B_OK) and - the replyee message passed to the constructor was \c non-NULL, the replyee - message is deleted. + If the object was properly initialized (i.e. InitCheck() returns \c B_OK) + and the replyee message passed to the constructor was \c non-NULL, the + replyee message is deleted. */ MimeUpdateThread::~MimeUpdateThread() { @@ -122,20 +123,21 @@ MimeUpdateThread::ThreadFunction() // Notify the thread manager to make a cleanup run if (!err) { BMessage msg(B_REG_MIME_UPDATE_THREAD_FINISHED); - status_t error = fManagerMessenger.SendMessage(&msg, (BHandler*)NULL, 500000); + status_t error = fManagerMessenger.SendMessage(&msg, (BHandler*)NULL, + 500000); if (error) - OUT("WARNING: ThreadManager::ThreadEntryFunction(): Termination notification " - "failed with error 0x%" B_PRIx32 "\n", error); + OUT("WARNING: ThreadManager::ThreadEntryFunction(): Termination" + " notification failed with error 0x%" B_PRIx32 "\n", error); } - DBG(OUT("(id: %ld) exiting mime update thread with result 0x%" B_PRIx32 "\n", - find_thread(NULL), err)); + DBG(OUT("(id: %ld) exiting mime update thread with result 0x%" B_PRIx32 + "\n", find_thread(NULL), err)); return err; } /*! \brief Returns true if the given device supports attributes, false if not (or if an error occurs while determining). - + Device numbers and their corresponding support info are cached in a std::list to save unnecessarily \c statvfs()ing devices that have already been statvfs()ed (which might otherwise happen quite often @@ -152,13 +154,12 @@ MimeUpdateThread::DeviceSupportsAttributes(dev_t device) // See if an entry for this device already exists std::list< std::pair >::iterator i; for (i = fAttributeSupportList.begin(); - i != fAttributeSupportList.end(); - i++) + i != fAttributeSupportList.end(); i++) { if (i->first == device) return i->second; } - + bool result = false; // If we get here, no such device is yet in our list, @@ -175,24 +176,24 @@ MimeUpdateThread::DeviceSupportsAttributes(dev_t device) else fAttributeSupportList.push_back(p); } - - return result; + + return result; } // UpdateEntry -/*! \brief Updates the given entry and then recursively updates all the entry's child - entries if the entry is a directory and \c fRecursive is true. +/*! \brief Updates the given entry and then recursively updates all the entry's + child entries if the entry is a directory and \c fRecursive is true. */ status_t MimeUpdateThread::UpdateEntry(const entry_ref *ref) { status_t err = ref ? B_OK : B_BAD_VALUE; bool entryIsDir = false; - + // Look to see if we're being terminated if (!err && fShouldExit) err = B_CANCELED; - + // Before we update, make sure this entry lives on a device that supports // attributes. If not, we skip it and any of its children for // updates (we don't signal an error, however). @@ -202,7 +203,7 @@ MimeUpdateThread::UpdateEntry(const entry_ref *ref) // (DeviceSupportsAttributes(ref->device) ? "yes" : "no")); if (!err && (device_is_root_device(ref->device) - || DeviceSupportsAttributes(ref->device))) { + || DeviceSupportsAttributes(ref->device))) { // Update this entry if (!err) { // R5 appears to ignore whether or not the update succeeds. @@ -211,8 +212,8 @@ MimeUpdateThread::UpdateEntry(const entry_ref *ref) // If we're recursing and this is a directory, update // each of the directory's children as well - if (!err && fRecursive && entryIsDir) { - BDirectory dir; + if (!err && fRecursive && entryIsDir) { + BDirectory dir; err = dir.SetTo(ref); if (!err) { entry_ref childRef; @@ -222,16 +223,15 @@ MimeUpdateThread::UpdateEntry(const entry_ref *ref) // If we've come to the end of the directory listing, // it's not an error. if (err == B_ENTRY_NOT_FOUND) - err = B_OK; + err = B_OK; break; - } else { - err = UpdateEntry(&childRef); - } - } - } + } else + err = UpdateEntry(&childRef); + } + } } } - return err; + return err; } } // namespace Mime diff --git a/src/servers/registrar/mime/RegistrarThread.cpp b/src/servers/registrar/mime/RegistrarThread.cpp index b50faec77e..b97d5bf481 100644 --- a/src/servers/registrar/mime/RegistrarThread.cpp +++ b/src/servers/registrar/mime/RegistrarThread.cpp @@ -15,32 +15,33 @@ /*! \class RegistrarThread \brief Base thread class for threads spawned and managed by the registrar - */ // constructor /*! \brief Creates a new RegistrarThread object, spawning the object's thread. - + Call Run() to actually get the thread running. - + \param name The desired name of the new thread \param priority The desired priority of the new thread \param managerMessenger A BMessenger to the thread manager to which this thread does or will belong. */ -RegistrarThread::RegistrarThread(const char *name, int32 priority, BMessenger managerMessenger) - : fManagerMessenger(managerMessenger) - , fShouldExit(false) - , fIsFinished(false) - , fStatus(B_NO_INIT) - , fId(-1) - , fPriority(priority) +RegistrarThread::RegistrarThread(const char *name, int32 priority, + BMessenger managerMessenger) + : + fManagerMessenger(managerMessenger), + fShouldExit(false), + fIsFinished(false), + fStatus(B_NO_INIT), + fId(-1), + fPriority(priority) { fName[0] = 0; status_t err = name && fManagerMessenger.IsValid() ? B_OK : B_BAD_VALUE; if (err == B_OK) - strcpy(fName, name); + strlcpy(fName, name, sizeof(fName)); fStatus = err; } @@ -71,7 +72,7 @@ RegistrarThread::Run() fId = spawn_thread(&RegistrarThread::EntryFunction, fName, fPriority, (void*)this); err = fId >= 0 ? B_OK : fId; - if (err == B_OK) + if (err == B_OK) err = resume_thread(fId); } return err; @@ -86,13 +87,13 @@ RegistrarThread::Id() const } // Name -//! Returns the name of the thread +//! Returns the name of the thread const char* RegistrarThread::Name() const { return fName; } - + // AskToExit /*! \brief Signals to thread that it needs to quit politely as soon as possible. diff --git a/src/servers/registrar/mime/RegistrarThread.h b/src/servers/registrar/mime/RegistrarThread.h index 48d9edc37b..42bcde2d7d 100644 --- a/src/servers/registrar/mime/RegistrarThread.h +++ b/src/servers/registrar/mime/RegistrarThread.h @@ -1,10 +1,10 @@ //---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered +// This software is part of the OpenBeOS distribution and is covered // by the OpenBeOS license. //--------------------------------------------------------------------- /*! \file RegistrarThread.h - RegistrarThread interface declaration + RegistrarThread interface declaration */ #ifndef REGISTRAR_THREAD_H @@ -15,30 +15,32 @@ class RegistrarThread { public: - RegistrarThread(const char *name, int32 priority, BMessenger managerMessenger); + RegistrarThread(const char *name, int32 priority, + BMessenger managerMessenger); virtual ~RegistrarThread(); - - virtual status_t InitCheck(); + + virtual status_t InitCheck(); status_t Run(); - + thread_id Id() const; const char* Name() const; - + void AskToExit(); bool IsFinished() const; - + protected: //! The function executed in the object's thread when Run() is called virtual status_t ThreadFunction() = 0; - - BMessenger fManagerMessenger; + + BMessenger fManagerMessenger; bool fShouldExit; // Initially false, may be set to true by AskToExit() - bool fIsFinished; // Initially false, set to true by the thread itself upon completion + bool fIsFinished; // Initially false, set to true by the thread itself + // upon completion private: static int32 EntryFunction(void *data); status_t fStatus; - thread_id fId; + thread_id fId; char fName[B_OS_NAME_LENGTH]; int32 fPriority; }; diff --git a/src/servers/registrar/mime/RegistrarThreadManager.cpp b/src/servers/registrar/mime/RegistrarThreadManager.cpp index 7c924d9058..9ce7690a5e 100644 --- a/src/servers/registrar/mime/RegistrarThreadManager.cpp +++ b/src/servers/registrar/mime/RegistrarThreadManager.cpp @@ -24,8 +24,8 @@ using namespace BPrivate; /*! \class RegistrarThreadManager - \brief RegistrarThreadManager is the master of all threads spawned by the registrar - + \brief RegistrarThreadManager is the master of all threads spawned by the + registrar */ //! Creates a new RegistrarThreadManager object @@ -35,8 +35,8 @@ RegistrarThreadManager::RegistrarThreadManager() } // destructor -/*! \brief Destroys the RegistrarThreadManager object, killing and deleting any still - running threads. +/*! \brief Destroys the RegistrarThreadManager object, killing and deleting any + still running threads. */ RegistrarThreadManager::~RegistrarThreadManager() { @@ -44,9 +44,11 @@ RegistrarThreadManager::~RegistrarThreadManager() } // MessageReceived -/*! \brief Handles \c B_REG_MIME_UPDATE_THREAD_FINISHED messages, passing on all others. +/*! \brief Handles \c B_REG_MIME_UPDATE_THREAD_FINISHED messages, passing on all + others. - Each \c B_REG_MIME_UPDATE_THREAD_FINISHED message triggers a call to CleanupThreads(). + Each \c B_REG_MIME_UPDATE_THREAD_FINISHED message triggers a call to + CleanupThreads(). */ void RegistrarThreadManager::MessageReceived(BMessage* message) @@ -57,7 +59,7 @@ RegistrarThreadManager::MessageReceived(BMessage* message) CleanupThreads(); break; } - + default: { BHandler::MessageReceived(message); @@ -71,15 +73,16 @@ RegistrarThreadManager::MessageReceived(BMessage* message) RegistrarThreadManager object. \param thread Pointer to a newly allocated \c RegistrarThread object. - - If the result of the function is \c B_OK, the \c RegistrarThreadManager object - assumes ownership of \a thread; if the result is an error code, it + + If the result of the function is \c B_OK, the \c RegistrarThreadManager + object assumes ownership of \a thread; if the result is an error code, it does not. - + \return - \c B_OK: success - - \c B_NO_MORE_THREADS: the number of concurrently allowed threads (defined by - RegistrarThreadManager::kThreadLimit) has already been reached + - \c B_NO_MORE_THREADS: the number of concurrently allowed threads (defined + by RegistrarThreadManager::kThreadLimit) has + already been reached - \c B_BAD_THREAD_STATE: the thread has already been launched - other error code: failure */ @@ -110,14 +113,14 @@ RegistrarThreadManager::LaunchThread(RegistrarThread *thread) } } if (!err) - DBG(OUT("RegistrarThreadManager::LaunchThread(): launched new '%s' thread, " - "id %ld\n", thread->Name(), thread->Id())); + DBG(OUT("RegistrarThreadManager::LaunchThread(): launched new '%s'" + " thread, id %ld\n", thread->Name(), thread->Id())); return err; } // CleanupThreads /*! \brief Frees the resources of any threads that are no longer running - + \todo This function should perhaps be triggered periodically by a BMessageRunner once we have our own BMessageRunner implementation. */ @@ -128,18 +131,19 @@ RegistrarThreadManager::CleanupThreads() for (i = fThreads.begin(); i != fThreads.end(); ) { if (*i) { if ((*i)->IsFinished()) { - DBG(OUT("RegistrarThreadManager::CleanupThreads(): Cleaning up thread %ld\n", - (*i)->Id())); + DBG(OUT("RegistrarThreadManager::CleanupThreads(): Cleaning up" + " thread %ld\n", (*i)->Id())); RemoveThread(i); // adjusts i } else ++i; } else { - OUT("WARNING: RegistrarThreadManager::CleanupThreads(): NULL mime_update_thread_shared_data " - "pointer found in and removed from RegistrarThreadManager::fThreads list\n"); + OUT("WARNING: RegistrarThreadManager::CleanupThreads(): NULL" + " mime_update_thread_shared_data pointer found in and removed" + " from RegistrarThreadManager::fThreads list\n"); i = fThreads.erase(i); } - } + } return B_OK; } @@ -157,28 +161,29 @@ RegistrarThreadManager::ShutdownThreads() for (i = fThreads.begin(); i != fThreads.end(); ) { if (*i) { if ((*i)->IsFinished()) { - DBG(OUT("RegistrarThreadManager::ShutdownThreads(): Cleaning up thread %ld\n", - (*i)->Id())); + DBG(OUT("RegistrarThreadManager::ShutdownThreads(): Cleaning up" + " thread %ld\n", (*i)->Id())); RemoveThread(i); // adjusts i } else { - DBG(OUT("RegistrarThreadManager::ShutdownThreads(): Shutting down thread %ld\n", - (*i)->Id())); + DBG(OUT("RegistrarThreadManager::ShutdownThreads(): Shutting" + " down thread %ld\n", (*i)->Id())); (*i)->AskToExit(); ++i; } } else { - OUT("WARNING: RegistrarThreadManager::ShutdownThreads(): NULL mime_update_thread_shared_data " - "pointer found in and removed from RegistrarThreadManager::fThreads list\n"); + OUT("WARNING: RegistrarThreadManager::ShutdownThreads(): NULL" + " mime_update_thread_shared_data pointer found in and removed" + " from RegistrarThreadManager::fThreads list\n"); i = fThreads.erase(i); } } - + /*! \todo We may want to iterate back through the list at this point, snooze for a moment if find an unfinished thread, and kill it if it still isn't finished by the time we're done snoozing. */ - + return B_OK; } @@ -195,21 +200,22 @@ RegistrarThreadManager::KillThreads() for (i = fThreads.begin(); i != fThreads.end(); ) { if (*i) { if (!(*i)->IsFinished()) { - DBG(OUT("RegistrarThreadManager::KillThreads(): Killing thread %ld\n", - (*i)->Id())); + DBG(OUT("RegistrarThreadManager::KillThreads(): Killing thread" + " %ld\n", (*i)->Id())); status_t err = kill_thread((*i)->Id()); if (err) - OUT("WARNING: RegistrarThreadManager::KillThreads(): kill_thread(%" - B_PRId32 ") failed with error code 0x%" B_PRIx32 "\n", - (*i)->Id(), err); - } - DBG(OUT("RegistrarThreadManager::KillThreads(): Cleaning up thread %ld\n", - (*i)->Id())); + OUT("WARNING: RegistrarThreadManager::KillThreads():" + " kill_thread(%" B_PRId32 ") failed with error code" + " 0x%" B_PRIx32 "\n", (*i)->Id(), err); + } + DBG(OUT("RegistrarThreadManager::KillThreads(): Cleaning up thread" + " %ld\n", (*i)->Id())); RemoveThread(i); // adjusts i } else { - OUT("WARNING: RegistrarThreadManager::KillThreads(): NULL mime_update_thread_shared_data " - "pointer found in and removed from RegistrarThreadManager::fThreads list\n"); + OUT("WARNING: RegistrarThreadManager::KillThreads(): NULL" + " mime_update_thread_shared_data pointer found in and removed" + " from RegistrarThreadManager::fThreads list\n"); i = fThreads.erase(i); } } @@ -222,7 +228,7 @@ RegistrarThreadManager::KillThreads() This is not necessarily a count of how many threads are actually running, as threads may remain in the thread list that are finished and waiting to be cleaned up. - + \return The number of threads currently under management */ uint @@ -237,6 +243,9 @@ RegistrarThreadManager::ThreadCount() const std::list::iterator& RegistrarThreadManager::RemoveThread(std::list::iterator &i) { + status_t dummy; + wait_for_thread((*i)->Id(), &dummy); + delete *i; atomic_add(&fThreadCount, -1); return (i = fThreads.erase(i)); diff --git a/src/servers/registrar/mime/RegistrarThreadManager.h b/src/servers/registrar/mime/RegistrarThreadManager.h index 6dcc59ccd5..7f395a13e5 100644 --- a/src/servers/registrar/mime/RegistrarThreadManager.h +++ b/src/servers/registrar/mime/RegistrarThreadManager.h @@ -1,10 +1,10 @@ //---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered +// This software is part of the OpenBeOS distribution and is covered // by the OpenBeOS license. //--------------------------------------------------------------------- /*! \file RegistrarThreadManager.h - RegistrarThreadManager interface declaration + RegistrarThreadManager interface declaration */ #ifndef REGISTRAR_THREAD_MANAGER_H @@ -21,7 +21,7 @@ class RegistrarThreadManager : public BHandler { public: RegistrarThreadManager(); ~RegistrarThreadManager(); - + // BHandler virtuals virtual void MessageReceived(BMessage* message); @@ -30,14 +30,15 @@ public: status_t CleanupThreads(); status_t ShutdownThreads(); status_t KillThreads(); - + uint ThreadCount() const; - + static const int kThreadLimit = 12; private: - std::list::iterator& RemoveThread(std::list::iterator &i); - + std::list::iterator& + RemoveThread(std::list::iterator &i); + std::list fThreads; int32 fThreadCount; }; diff --git a/src/system/kernel/arch/arm/arch_system_info.cpp b/src/system/kernel/arch/arm/arch_system_info.cpp index 49a3c7318b..ae8784b405 100644 --- a/src/system/kernel/arch/arm/arch_system_info.cpp +++ b/src/system/kernel/arch/arm/arch_system_info.cpp @@ -29,7 +29,8 @@ arch_fill_topology_node(cpu_topology_node_info* node, int32 cpu) { switch (node->type) { case B_TOPOLOGY_ROOT: - node->data.root.platform = B_CPU_PPC_64; + // TODO: ARM_64? + node->data.root.platform = B_CPU_ARM; break; case B_TOPOLOGY_PACKAGE: diff --git a/src/system/kernel/fs/EntryCache.cpp b/src/system/kernel/fs/EntryCache.cpp index e9a6a14db9..63743b8f4c 100644 --- a/src/system/kernel/fs/EntryCache.cpp +++ b/src/system/kernel/fs/EntryCache.cpp @@ -90,7 +90,7 @@ EntryCache::Init() status_t -EntryCache::Add(ino_t dirID, const char* name, ino_t nodeID) +EntryCache::Add(ino_t dirID, const char* name, ino_t nodeID, bool missing) { EntryCacheKey key(dirID, name); @@ -99,6 +99,7 @@ EntryCache::Add(ino_t dirID, const char* name, ino_t nodeID) EntryCacheEntry* entry = fEntries.Lookup(key); if (entry != NULL) { entry->node_id = nodeID; + entry->missing = missing; if (entry->generation != fCurrentGeneration) { if (entry->index >= 0) { fGenerations[entry->generation].entries[entry->index] = NULL; @@ -114,6 +115,7 @@ EntryCache::Add(ino_t dirID, const char* name, ino_t nodeID) entry->node_id = nodeID; entry->dir_id = dirID; + entry->missing = missing; entry->generation = fCurrentGeneration; entry->index = kEntryNotInArray; strcpy(entry->name, name); @@ -155,7 +157,8 @@ EntryCache::Remove(ino_t dirID, const char* name) bool -EntryCache::Lookup(ino_t dirID, const char* name, ino_t& _nodeID) +EntryCache::Lookup(ino_t dirID, const char* name, ino_t& _nodeID, + bool& _missing) { EntryCacheKey key(dirID, name); @@ -171,6 +174,7 @@ EntryCache::Lookup(ino_t dirID, const char* name, ino_t& _nodeID) // The entry is already in the current generation or is being moved to // it by another thread. _nodeID = entry->node_id; + _missing = entry->missing; return true; } @@ -184,6 +188,7 @@ EntryCache::Lookup(ino_t dirID, const char* name, ino_t& _nodeID) fGenerations[fCurrentGeneration].entries[index] = entry; entry->index = index; _nodeID = entry->node_id; + _missing = entry->missing; return true; } @@ -201,6 +206,7 @@ EntryCache::Lookup(ino_t dirID, const char* name, ino_t& _nodeID) _AddEntryToCurrentGeneration(entry); _nodeID = entry->node_id; + _missing = entry->missing; return true; } diff --git a/src/system/kernel/fs/EntryCache.h b/src/system/kernel/fs/EntryCache.h index 79a8df0f06..4cbf865915 100644 --- a/src/system/kernel/fs/EntryCache.h +++ b/src/system/kernel/fs/EntryCache.h @@ -36,6 +36,7 @@ struct EntryCacheEntry { ino_t dir_id; int32 generation; int32 index; + bool missing; char name[1]; }; @@ -87,12 +88,12 @@ public: status_t Init(); status_t Add(ino_t dirID, const char* name, - ino_t nodeID); + ino_t nodeID, bool missing); status_t Remove(ino_t dirID, const char* name); bool Lookup(ino_t dirID, const char* name, - ino_t& nodeID); + ino_t& nodeID, bool& missing); const char* DebugReverseLookup(ino_t nodeID, ino_t& _dirID); diff --git a/src/system/kernel/fs/Vnode.h b/src/system/kernel/fs/Vnode.h index d4ef8fd3ff..6efe921a5c 100644 --- a/src/system/kernel/fs/Vnode.h +++ b/src/system/kernel/fs/Vnode.h @@ -80,7 +80,7 @@ private: static const uint32 kFlagsCovering = 0x00000100; static const uint32 kFlagsType = 0xfffff000; - static const uint32 kBucketCount = 32; + static const uint32 kBucketCount = 32; struct LockWaiter : DoublyLinkedListLinkImpl { LockWaiter* next; diff --git a/src/system/kernel/fs/vfs.cpp b/src/system/kernel/fs/vfs.cpp index 6e98ac4f5e..b279556bd9 100644 --- a/src/system/kernel/fs/vfs.cpp +++ b/src/system/kernel/fs/vfs.cpp @@ -1145,8 +1145,8 @@ restart: rw_lock_read_unlock(&sVnodeLock); if (!canWait || --tries < 0) { // vnode doesn't seem to become unbusy - dprintf("vnode %" B_PRIdDEV ":%" B_PRIdINO " is not becoming unbusy!\n", - mountID, vnodeID); + dprintf("vnode %" B_PRIdDEV ":%" B_PRIdINO + " is not becoming unbusy!\n", mountID, vnodeID); return B_BUSY; } snooze(5000); // 5 ms @@ -1300,7 +1300,7 @@ free_unused_vnodes(int32 level) AutoLocker nodeLocker(vnode); // Check whether the node is still unused -- since we only append to the - // the tail of the unused queue, the vnode should still be at its head. + // tail of the unused queue, the vnode should still be at its head. // Alternatively we could check its ref count for 0 and its busy flag, // but if the node is no longer at the head of the queue, it means it // has been touched in the meantime, i.e. it is no longer the least @@ -2089,15 +2089,18 @@ static status_t lookup_dir_entry(struct vnode* dir, const char* name, struct vnode** _vnode) { ino_t id; + bool missing; - if (dir->mount->entry_cache.Lookup(dir->id, name, id)) - return get_vnode(dir->device, id, _vnode, true, false); + if (dir->mount->entry_cache.Lookup(dir->id, name, id, missing)) { + return missing ? B_ENTRY_NOT_FOUND + : get_vnode(dir->device, id, _vnode, true, false); + } status_t status = FS_CALL(dir, lookup, name, &id); if (status != B_OK) return status; - // The lookup() hook call get_vnode() or publish_vnode(), so we do already + // The lookup() hook calls get_vnode() or publish_vnode(), so we do already // have a reference and just need to look the node up. rw_lock_read_lock(&sVnodeLock); *_vnode = lookup_vnode(dir->device, id); @@ -4011,7 +4014,22 @@ entry_cache_add(dev_t mountID, ino_t dirID, const char* name, ino_t nodeID) return B_BAD_VALUE; locker.Unlock(); - return mount->entry_cache.Add(dirID, name, nodeID); + return mount->entry_cache.Add(dirID, name, nodeID, false); +} + + +extern "C" status_t +entry_cache_add_missing(dev_t mountID, ino_t dirID, const char* name) +{ + // lookup mount -- the caller is required to make sure that the mount + // won't go away + MutexLocker locker(sMountMutex); + struct fs_mount* mount = find_mount(mountID); + if (mount == NULL) + return B_BAD_VALUE; + locker.Unlock(); + + return mount->entry_cache.Add(dirID, name, -1, true); } @@ -8872,7 +8890,7 @@ _user_open_entry_ref(dev_t device, ino_t inode, const char* userName, if ((openMode & O_CREAT) != 0) { return file_create_entry_ref(device, inode, name, openMode, perms, - false); + false); } return file_open_entry_ref(device, inode, name, openMode, false); diff --git a/src/system/libroot/Jamfile b/src/system/libroot/Jamfile index 1b29fb53c7..b9d962207f 100644 --- a/src/system/libroot/Jamfile +++ b/src/system/libroot/Jamfile @@ -63,11 +63,6 @@ for architectureObject in [ MultiArchSubDirSetup ] { ; librootDebugObjects = $(librootDebugObjects:G=$(architecture)) ; - local librootGuardedObjects = - posix_malloc_guarded.o - ; - librootGuardedObjects = $(librootGuardedObjects:G=$(architecture)) ; - local librootNoDebugObjects = posix_malloc.o ; @@ -75,15 +70,12 @@ for architectureObject in [ MultiArchSubDirSetup ] { local libroot = [ MultiArchDefaultGristFiles libroot.so ] ; local librootDebug = $(libroot:B=libroot_debug) ; - local librootGuarded = $(libroot:B=libroot_guarded) ; DONT_LINK_AGAINST_LIBROOT on $(libroot) = true ; DONT_LINK_AGAINST_LIBROOT on $(librootDebug) = true ; - DONT_LINK_AGAINST_LIBROOT on $(librootGuarded) = true ; SetVersionScript $(libroot) : libroot_versions ; SetVersionScript $(librootDebug) : libroot_versions ; - SetVersionScript $(librootGuarded) : libroot_versions ; SharedLibrary $(libroot) : @@ -109,18 +101,6 @@ for architectureObject in [ MultiArchSubDirSetup ] { [ TargetLibgcc ] ; - HAIKU_SONAME on $(librootGuarded) = libroot.so ; - - SharedLibrary $(librootGuarded) - : - libroot_init.c - : - $(librootObjects) - $(librootGuardedObjects) - [ TargetStaticLibsupc++ ] - [ TargetLibgcc ] - ; - # Copy libroot.so and update the copy's revision section. We link # everything against the original, but the copy will end up on the disk # image (this way we avoid unnecessary dependencies). The copy will be @@ -132,18 +112,12 @@ for architectureObject in [ MultiArchSubDirSetup ] { libroot.so : revisioned ] ; local revisionedLibrootDebug = $(librootDebug:G=$(revisionedLibroot:G)) ; - local revisionedLibrootGuarded - = $(librootGuarded:G=$(revisionedLibroot:G)) ; MakeLocate $(revisionedLibroot) : $(targetDir) ; CopySetHaikuRevision $(revisionedLibroot) : $(libroot) ; MakeLocate $(revisionedLibrootDebug) : $(targetDir) ; CopySetHaikuRevision $(revisionedLibrootDebug) : $(librootDebug) ; - - MakeLocate $(revisionedLibrootGuarded) : $(targetDir) ; - CopySetHaikuRevision $(revisionedLibrootGuarded) - : $(librootGuarded) ; } } } diff --git a/src/system/libroot/libroot_init.c b/src/system/libroot/libroot_init.c index 03cb17f70d..893833eea7 100644 --- a/src/system/libroot/libroot_init.c +++ b/src/system/libroot/libroot_init.c @@ -77,9 +77,9 @@ initialize_before(image_id imageID) __gCPUCount = info.cpu_count; __init_time((addr_t)__gCommPageAddress); - __init_heap(); __init_env(__gRuntimeLoader->program_args); - __init_heap_post_env(); + __init_heap(); + __init_env_post_heap(); __init_pwd_backend(); __set_stack_protection(); } diff --git a/src/system/libroot/posix/glibc/arch/arm/Jamfile b/src/system/libroot/posix/glibc/arch/arm/Jamfile index 394d8eda0b..18924a7e2f 100644 --- a/src/system/libroot/posix/glibc/arch/arm/Jamfile +++ b/src/system/libroot/posix/glibc/arch/arm/Jamfile @@ -34,6 +34,13 @@ local genericSources = s_isnan.c s_isnanf.c s_signbit.c s_signbitf.c s_signbitl.c + s_nan.c s_nanf.c s_nanl.c + e_hypot.c e_hypotf.c e_hypotl.c + w_hypot.c w_hypotf.c w_hypotl.c + s_fpclassify.c s_fpclassifyf.c + s_clog.c s_clogf.c s_clogl.c + s_log1p.c s_log1pf.c s_log1pl.c + s_csqrt.c s_csqrtf.c s_csqrtl.c s_floor.c s_floorf.c s_ceil.c s_ceilf.c s_modf.c @@ -48,12 +55,16 @@ local genericSources = halfulp.c mpa.c mplog.c mpexp.c s_sin.c - s_atan.c s_atanf.c + s_atan.c s_atanf.c s_atanl.c s_tan.c - e_asin.c w_asin.c + e_asin.c e_asinl.c + w_asin.c w_asinl.c e_log10.c w_log10.c + e_logf.c e_logl.c e_acos.c w_acos.c - e_atan2.c w_atan2.c mpatan2.c mpatan.c mptan.c mpsqrt.c w_sqrt.c w_sqrtf.c + e_atan2.c e_atan2l.c + w_atan2.c w_atan2l.c mpatan2.c mpatan.c mptan.c mpsqrt.c w_sqrt.c w_sqrtf.c + e_sqrtl.c e_fmod.c w_fmod.c e_log.c w_log.c e_cosh.c w_cosh.c @@ -62,7 +73,7 @@ local genericSources = s_sinf.c k_sinf.c s_ldexp.c s_ldexpf.c s_scalbnf.c s_scalbn.c - s_copysign.c + s_copysign.c s_copysignf.c s_copysignl.c s_tanh.c s_tanf.c k_tanf.c s_lround.c s_lroundf.c s_round.c s_roundf.c s_rint.c s_rintf.c s_lrintf.c diff --git a/src/system/libroot/posix/glibc/arch/generic/e_logf.c b/src/system/libroot/posix/glibc/arch/generic/e_logf.c index de8f869df4..cf75e11781 100644 --- a/src/system/libroot/posix/glibc/arch/generic/e_logf.c +++ b/src/system/libroot/posix/glibc/arch/generic/e_logf.c @@ -13,18 +13,10 @@ * ==================================================== */ -#if defined(LIBM_SCCS) && !defined(lint) -static char rcsid[] = "$NetBSD: e_logf.c,v 1.4 1995/05/10 20:45:54 jtc Exp $"; -#endif +#include +#include -#include "math.h" -#include "math_private.h" - -#ifdef __STDC__ static const float -#else -static float -#endif ln2_hi = 6.9313812256e-01, /* 0x3f317180 */ ln2_lo = 9.0580006145e-06, /* 0x3717f7d1 */ two25 = 3.355443200e+07, /* 0x4c000000 */ @@ -36,18 +28,10 @@ Lg5 = 1.8183572590e-01, /* 3E3A3325 */ Lg6 = 1.5313838422e-01, /* 3E1CD04F */ Lg7 = 1.4798198640e-01; /* 3E178897 */ -#ifdef __STDC__ static const float zero = 0.0; -#else -static float zero = 0.0; -#endif -#ifdef __STDC__ - float __ieee754_logf(float x) -#else - float __ieee754_logf(x) - float x; -#endif +float +__ieee754_logf(float x) { float hfsq,f,s,z,R,w,t1,t2,dk; int32_t k,ix,i,j; @@ -56,13 +40,14 @@ static float zero = 0.0; k=0; if (ix < 0x00800000) { /* x < 2**-126 */ - if ((ix&0x7fffffff)==0) - return -two25/(x-x); /* log(+-0)=-inf */ - if (ix<0) return (x-x)/(x-x); /* log(-#) = NaN */ + if (__builtin_expect((ix&0x7fffffff)==0, 0)) + return -two25/zero; /* log(+-0)=-inf */ + if (__builtin_expect(ix<0, 0)) + return (x-x)/(x-x); /* log(-#) = NaN */ k -= 25; x *= two25; /* subnormal number, scale up x */ GET_FLOAT_WORD(ix,x); } - if (ix >= 0x7f800000) return x+x; + if (__builtin_expect(ix >= 0x7f800000, 0)) return x+x; k += (ix>>23)-127; ix &= 0x007fffff; i = (ix+(0x95f64<<3))&0x800000; @@ -76,9 +61,9 @@ static float zero = 0.0; } R = f*f*((float)0.5-(float)0.33333333333333333*f); if(k==0) return f-R; else {dk=(float)k; - return dk*ln2_hi-((R-dk*ln2_lo)-f);} + return dk*ln2_hi-((R-dk*ln2_lo)-f);} } - s = f/((float)2.0+f); + s = f/((float)2.0+f); dk = (float)k; z = s*s; i = ix-(0x6147a<<3); @@ -97,3 +82,4 @@ static float zero = 0.0; return dk*ln2_hi-((s*(f-R)-dk*ln2_lo)-f); } } +strong_alias (__ieee754_logf, __logf_finite) diff --git a/src/system/libroot/posix/glibc/arch/generic/e_logl.c b/src/system/libroot/posix/glibc/arch/generic/e_logl.c new file mode 100644 index 0000000000..7a4ea1b07f --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/generic/e_logl.c @@ -0,0 +1,14 @@ +#include +#include +#include + +long double +__ieee754_logl (long double x) +{ + fputs ("__ieee754_logl not implemented\n", stderr); + __set_errno (ENOSYS); + return 0.0; +} +strong_alias (__ieee754_logl, __logl_finite) + +stub_warning (logl) diff --git a/src/system/libroot/posix/glibc/arch/generic/e_sqrtl.c b/src/system/libroot/posix/glibc/arch/generic/e_sqrtl.c new file mode 100644 index 0000000000..ac1b22175e --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/generic/e_sqrtl.c @@ -0,0 +1,104 @@ +/* + * IBM Accurate Mathematical Library + * written by International Business Machines Corp. + * Copyright (C) 2001-2015 Free Software Foundation, Inc. + * + * This program 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 + * (at your option) any later version. + * + * This program is distributed in the hope that 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 program; if not, see . + */ +/*********************************************************************/ +/* MODULE_NAME: uroot.c */ +/* */ +/* FUNCTION: usqrt */ +/* */ +/* FILES NEEDED: dla.h endian.h mydefs.h uroot.h */ +/* uroot.tbl */ +/* */ +/* An ultimate sqrt routine. Given an IEEE double machine number x */ +/* it computes the correctly rounded (to nearest) value of square */ +/* root of x. */ +/* Assumption: Machine arithmetic operations are performed in */ +/* round to nearest mode of IEEE 754 standard. */ +/* */ +/*********************************************************************/ + +#include + +typedef union {int64_t i[2]; long double x; double d[2]; } mynumber; + +static const double + t512 = 0x1p512, + tm256 = 0x1p-256, + two54 = 0x1p54, /* 0x4350000000000000 */ + twom54 = 0x1p-54; /* 0x3C90000000000000 */ + +/*********************************************************************/ +/* An ultimate sqrt routine. Given an IEEE double machine number x */ +/* it computes the correctly rounded (to nearest) value of square */ +/* root of x. */ +/*********************************************************************/ +long double __ieee754_sqrtl(long double x) +{ + static const long double big = 134217728.0, big1 = 134217729.0; + long double t,s,i; + mynumber a,c; + uint64_t k, l; + int64_t m, n; + double d; + + a.x=x; + k=a.i[0] & INT64_C(0x7fffffffffffffff); + /*----------------- 2^-1022 <= | x |< 2^1024 -----------------*/ + if (k>INT64_C(0x000fffff00000000) && k> 53; + m = (a.i[1] >> 52) & 0x7ff; + if (m == 0) { + a.d[1] *= two54; + m = ((a.i[1] >> 52) & 0x7ff) - 54; + } + m += n; + if (m > 0) + a.i[1] = (a.i[1] & INT64_C(0x800fffffffffffff)) | (m << 52); + else if (m <= -54) { + a.i[1] &= INT64_C(0x8000000000000000); + } else { + m += 54; + a.i[1] = (a.i[1] & INT64_C(0x800fffffffffffff)) | (m << 52); + a.d[1] *= twom54; + } + } + a.i[0] = l; + s = a.x; + d = __ieee754_sqrt (a.d[0]); + c.i[0] = INT64_C(0x2000000000000000)+((k&INT64_C(0x7fe0000000000000))>>1); + c.i[1] = 0; + i = d; + t = 0.5L * (i + s / i); + i = 0.5L * (t + s / t); + return c.x * i; + } + else { + if (k>=INT64_C(0x7ff0000000000000)) { + if (a.i[0] == INT64_C(0xfff0000000000000)) + return (big1-big1)/(big-big); /* sqrt (-Inf) = NaN. */ + return x; /* sqrt (NaN) = NaN, sqrt (+Inf) = +Inf. */ + } + if (x == 0) return x; + if (x < 0) return (big1-big1)/(big-big); + return tm256*__ieee754_sqrtl(x*t512); + } +} +strong_alias (__ieee754_sqrtl, __sqrtl_finite) diff --git a/src/system/libroot/posix/glibc/arch/generic/s_atanl.c b/src/system/libroot/posix/glibc/arch/generic/s_atanl.c new file mode 100644 index 0000000000..2957d702d5 --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/generic/s_atanl.c @@ -0,0 +1,14 @@ +#include +#include +#include + +long double +__atanl (long double x) +{ + fputs ("__atanl not implemented\n", stderr); + __set_errno (ENOSYS); + return 0.0; +} +weak_alias (__atanl, atanl) + +stub_warning (atanl) diff --git a/src/system/libroot/posix/glibc/arch/generic/s_log1pl.c b/src/system/libroot/posix/glibc/arch/generic/s_log1pl.c new file mode 100644 index 0000000000..a216fb3cef --- /dev/null +++ b/src/system/libroot/posix/glibc/arch/generic/s_log1pl.c @@ -0,0 +1,13 @@ +#include +#include +#include + +long double +__log1pl (long double x) +{ + fputs ("__log1pl not implemented\n", stderr); + __set_errno (ENOSYS); + return 0.0; +} + +stub_warning (log1pl) diff --git a/src/system/libroot/posix/glibc/include/arch/arm/bits/huge_val.h b/src/system/libroot/posix/glibc/include/arch/arm/bits/huge_val.h index b4f56217f4..ac432e39ed 100644 --- a/src/system/libroot/posix/glibc/include/arch/arm/bits/huge_val.h +++ b/src/system/libroot/posix/glibc/include/arch/arm/bits/huge_val.h @@ -55,4 +55,10 @@ static __huge_val_t __huge_val = { __HUGE_VAL_bytes }; #endif /* GCC. */ +#if __GNUC_PREREQ(3,3) +# define HUGE_VALL (__builtin_huge_vall()) +#else +# define HUGE_VALL ((long double) HUGE_VAL) +#endif + #define HUGE_VALF HUGE_VAL diff --git a/src/system/libroot/posix/malloc/arch-specific.cpp b/src/system/libroot/posix/malloc/arch-specific.cpp index d2c25b8f5e..872867c38c 100644 --- a/src/system/libroot/posix/malloc/arch-specific.cpp +++ b/src/system/libroot/posix/malloc/arch-specific.cpp @@ -124,13 +124,6 @@ __init_heap(void) } -extern "C" void -__init_heap_post_env(void) -{ - // no heap options available -} - - extern "C" void __heap_terminate_after() { diff --git a/src/system/libroot/posix/malloc_debug/Jamfile b/src/system/libroot/posix/malloc_debug/Jamfile index 98d3b0bc58..0a2213d12f 100644 --- a/src/system/libroot/posix/malloc_debug/Jamfile +++ b/src/system/libroot/posix/malloc_debug/Jamfile @@ -15,10 +15,9 @@ for architectureObject in [ MultiArchSubDirSetup ] { MergeObject <$(architecture)>posix_malloc_debug.o : heap.cpp - ; - - MergeObject <$(architecture)>posix_malloc_guarded.o : guarded_heap.cpp + + malloc_debug_api.cpp ; } } diff --git a/src/system/libroot/posix/malloc_debug/guarded_heap.cpp b/src/system/libroot/posix/malloc_debug/guarded_heap.cpp index bc5e17a429..3a552bd5af 100644 --- a/src/system/libroot/posix/malloc_debug/guarded_heap.cpp +++ b/src/system/libroot/posix/malloc_debug/guarded_heap.cpp @@ -3,6 +3,8 @@ * Distributed under the terms of the MIT License. */ +#include "malloc_debug_api.h" + #include #include @@ -36,7 +38,7 @@ static int32 sStackEndTLSIndex = -1; using namespace std; static size_t sDefaultAlignment = alignof(max_align_t); #else -static size_t sDefaultAlignment = 0; +static size_t sDefaultAlignment = 8; #endif @@ -161,7 +163,8 @@ struct guarded_heap_page { size_t allocation_size; void* allocation_base; size_t alignment; - thread_id thread; + thread_id allocating_thread; + thread_id freeing_thread; list_link free_list_link; size_t alloc_stack_trace_depth; size_t free_stack_trace_depth; @@ -257,14 +260,14 @@ static void guarded_heap_print_stack_traces(guarded_heap_page& page) { if (page.alloc_stack_trace_depth > 0) { - printf("alloc stack trace (%" B_PRIuSIZE "):\n", + print_stdout("alloc stack trace (%" B_PRIuSIZE "):\n", page.alloc_stack_trace_depth); guarded_heap_print_stack_trace(page.stack_trace, page.alloc_stack_trace_depth); } if (page.free_stack_trace_depth > 0) { - printf("free stack trace (%" B_PRIuSIZE "):\n", + print_stdout("free stack trace (%" B_PRIuSIZE "):\n", page.free_stack_trace_depth); guarded_heap_print_stack_trace( &page.stack_trace[page.alloc_stack_trace_depth], @@ -314,7 +317,8 @@ guarded_heap_page_allocate(guarded_heap_area& area, size_t startPageIndex, guarded_heap_page& page = area.pages[startPageIndex + i]; page.flags = GUARDED_HEAP_PAGE_FLAG_USED; if (i == 0) { - page.thread = find_thread(NULL); + page.allocating_thread = find_thread(NULL); + page.freeing_thread = -1; page.allocation_size = allocationSize; page.allocation_base = allocationBase; page.alignment = alignment; @@ -324,7 +328,8 @@ guarded_heap_page_allocate(guarded_heap_area& area, size_t startPageIndex, page.free_stack_trace_depth = 0; firstPage = &page; } else { - page.thread = firstPage->thread; + page.allocating_thread = firstPage->allocating_thread; + page.freeing_thread = -1; page.allocation_size = allocationSize; page.allocation_base = allocationBase; page.alignment = alignment; @@ -356,7 +361,7 @@ guarded_heap_free_page(guarded_heap_area& area, size_t pageIndex, else page.flags |= GUARDED_HEAP_PAGE_FLAG_DEAD; - page.thread = find_thread(NULL); + page.freeing_thread = find_thread(NULL); list_add_item(&area.free_list, &page); @@ -494,52 +499,79 @@ guarded_heap_add_area(guarded_heap& heap, uint32 counter) } +static void* +guarded_heap_allocate_with_area(size_t size, size_t alignment) +{ + size_t infoSpace = alignment >= B_PAGE_SIZE ? B_PAGE_SIZE + : (sizeof(guarded_heap_page) + alignment - 1) & ~(alignment - 1); + + size_t pagesNeeded = (size + infoSpace + B_PAGE_SIZE - 1) / B_PAGE_SIZE; + + if (alignment > B_PAGE_SIZE) + pagesNeeded += alignment / B_PAGE_SIZE - 1; + + void* address = NULL; + area_id area = create_area("guarded_heap_huge_allocation", &address, + B_ANY_ADDRESS, (pagesNeeded + 1) * B_PAGE_SIZE, B_NO_LOCK, + B_READ_AREA | B_WRITE_AREA); + if (area < 0) { + panic("failed to create area for allocation of %" B_PRIuSIZE " pages", + pagesNeeded); + return NULL; + } + + // We just use a page object + guarded_heap_page* page = (guarded_heap_page*)address; + page->flags = GUARDED_HEAP_PAGE_FLAG_USED | GUARDED_HEAP_PAGE_FLAG_FIRST + | GUARDED_HEAP_PAGE_FLAG_AREA; + page->allocation_size = size; + page->allocation_base = (void*)(((addr_t)address + + pagesNeeded * B_PAGE_SIZE - size) & ~(alignment - 1)); + page->alignment = alignment; + page->allocating_thread = find_thread(NULL); + page->freeing_thread = -1; + page->alloc_stack_trace_depth = guarded_heap_fill_stack_trace( + page->stack_trace, sStackTraceDepth, 2); + page->free_stack_trace_depth = 0; + + if (alignment <= B_PAGE_SIZE) { + // Protect just the guard page. + mprotect((void*)((addr_t)address + pagesNeeded * B_PAGE_SIZE), + B_PAGE_SIZE, 0); + } else { + // Protect empty pages before the allocation start... + addr_t protectedStart = (addr_t)address + B_PAGE_SIZE; + size_t protectedSize = (addr_t)page->allocation_base - protectedStart; + if (protectedSize > 0) + mprotect((void*)protectedStart, protectedSize, 0); + + // ... and after allocation end. + size_t allocatedPages = (size + B_PAGE_SIZE - 1) / B_PAGE_SIZE; + protectedStart = (addr_t)page->allocation_base + + allocatedPages * B_PAGE_SIZE; + protectedSize = (addr_t)address + (pagesNeeded + 1) * B_PAGE_SIZE + - protectedStart; + + // There is at least the guard page. + mprotect((void*)protectedStart, protectedSize, 0); + } + + return page->allocation_base; +} + + static void* guarded_heap_allocate(guarded_heap& heap, size_t size, size_t alignment) { if (alignment == 0) alignment = 1; - if (alignment > B_PAGE_SIZE) { - panic("alignment of %" B_PRIuSIZE " not supported", alignment); - return NULL; - } - size_t pagesNeeded = (size + B_PAGE_SIZE - 1) / B_PAGE_SIZE + 1; - if (pagesNeeded * B_PAGE_SIZE >= GUARDED_HEAP_AREA_USE_THRESHOLD) { + if (alignment > B_PAGE_SIZE + || pagesNeeded * B_PAGE_SIZE >= GUARDED_HEAP_AREA_USE_THRESHOLD) { // Don't bother, use an area directly. Since it will also fault once // it is deleted, that fits our model quite nicely. - - pagesNeeded = (size + sizeof(guarded_heap_page) + B_PAGE_SIZE - 1) - / B_PAGE_SIZE; - - void* address = NULL; - area_id area = create_area("guarded_heap_huge_allocation", &address, - B_ANY_ADDRESS, (pagesNeeded + 1) * B_PAGE_SIZE, B_NO_LOCK, - B_READ_AREA | B_WRITE_AREA); - if (area < 0) { - panic("failed to create area for allocation of %" B_PRIuSIZE - " pages", pagesNeeded); - return NULL; - } - - // We just use a page object - guarded_heap_page* page = (guarded_heap_page*)address; - page->flags = GUARDED_HEAP_PAGE_FLAG_USED - | GUARDED_HEAP_PAGE_FLAG_FIRST | GUARDED_HEAP_PAGE_FLAG_AREA; - page->allocation_size = size; - page->allocation_base = (void*)(((addr_t)address - + pagesNeeded * B_PAGE_SIZE - size) & ~(alignment - 1)); - page->alignment = alignment; - page->thread = find_thread(NULL); - page->alloc_stack_trace_depth = guarded_heap_fill_stack_trace( - page->stack_trace, sStackTraceDepth, 2); - page->free_stack_trace_depth = 0; - - mprotect((void*)((addr_t)address + pagesNeeded * B_PAGE_SIZE), - B_PAGE_SIZE, 0); - - return page->allocation_base; + return guarded_heap_allocate_with_area(size, alignment); } void* result = NULL; @@ -745,7 +777,8 @@ guarded_heap_realloc(void* address, size_t newSize) if (oldSize == newSize) return address; - void* newBlock = guarded_heap_allocate(sGuardedHeap, newSize, 0); + void* newBlock = guarded_heap_allocate(sGuardedHeap, newSize, + sDefaultAlignment); if (newBlock == NULL) return NULL; @@ -782,7 +815,8 @@ dump_guarded_heap_page(guarded_heap_page& page) printf("allocation size: %" B_PRIuSIZE "\n", page.allocation_size); printf("allocation base: %p\n", page.allocation_base); printf("alignment: %" B_PRIuSIZE "\n", page.alignment); - printf("allocating thread: %" B_PRId32 "\n", page.thread); + printf("allocating thread: %" B_PRId32 "\n", page.allocating_thread); + printf("freeing thread: %" B_PRId32 "\n", page.freeing_thread); } @@ -833,9 +867,10 @@ dump_guarded_heap_page(void* address, bool doPanic) panic("thread %" B_PRId32 " tried accessing address %p which is " \ state " (base: 0x%" B_PRIxADDR ", size: %" B_PRIuSIZE \ ", alignment: %" B_PRIuSIZE ", allocated by thread: %" \ - B_PRId32 ")", find_thread(NULL), address, \ - page.allocation_base, page.allocation_size, page.alignment, \ - page.thread) + B_PRId32 ", freed by thread: %" B_PRId32 ")", \ + find_thread(NULL), address, page.allocation_base, \ + page.allocation_size, page.alignment, page.allocating_thread, \ + page.freeing_thread) if ((page.flags & GUARDED_HEAP_PAGE_FLAG_USED) == 0) DO_PANIC("not allocated"); @@ -951,7 +986,7 @@ dump_allocations(guarded_heap& heap, bool statsOnly, thread_id thread) continue; } - if (thread >= 0 && thread != page.thread) + if (thread >= 0 && thread != page.allocating_thread) continue; allocationCount++; @@ -962,8 +997,8 @@ dump_allocations(guarded_heap& heap, bool statsOnly, thread_id thread) print_stdout("allocation: base: %p; size: %" B_PRIuSIZE "; thread: %" B_PRId32 "; alignment: %" B_PRIuSIZE "\n", - page.allocation_base, page.allocation_size, page.thread, - page.alignment); + page.allocation_base, page.allocation_size, + page.allocating_thread, page.alignment); guarded_heap_print_stack_trace(page.stack_trace, page.alloc_stack_trace_depth); @@ -985,68 +1020,36 @@ dump_allocations_full() // #pragma mark - Heap Debug API -extern "C" status_t -heap_debug_start_wall_checking(int msInterval) -{ - return B_NOT_SUPPORTED; -} - - -extern "C" status_t -heap_debug_stop_wall_checking() -{ - return B_NOT_SUPPORTED; -} - - -extern "C" void -heap_debug_set_paranoid_validation(bool enabled) -{ -} - - -extern "C" void -heap_debug_set_memory_reuse(bool enabled) +static void +guarded_heap_set_memory_reuse(bool enabled) { sGuardedHeap.reuse_memory = enabled; } -extern "C" void -heap_debug_set_debugger_calls(bool enabled) +static void +guarded_heap_set_debugger_calls(bool enabled) { sDebuggerCalls = enabled; } -extern "C" void -heap_debug_set_default_alignment(size_t defaultAlignment) +static void +guarded_heap_set_default_alignment(size_t defaultAlignment) { sDefaultAlignment = defaultAlignment; } -extern "C" void -heap_debug_validate_heaps() -{ -} - - -extern "C" void -heap_debug_validate_walls() -{ -} - - -extern "C" void -heap_debug_dump_allocations(bool statsOnly, thread_id thread) +static void +guarded_heap_dump_allocations(bool statsOnly, thread_id thread) { dump_allocations(sGuardedHeap, statsOnly, thread); } -extern "C" void -heap_debug_dump_heaps(bool dumpAreas, bool dumpBins) +static void +guarded_heap_dump_heaps(bool dumpAreas, bool dumpBins) { WriteLocker heapLocker(sGuardedHeap.lock); dump_guarded_heap(sGuardedHeap); @@ -1070,31 +1073,16 @@ heap_debug_dump_heaps(bool dumpAreas, bool dumpBins) } -extern "C" void * -heap_debug_malloc_with_guard_page(size_t size) -{ - return malloc(size); -} - - -extern "C" status_t -heap_debug_get_allocation_info(void *address, size_t *size, - thread_id *thread) -{ - return B_NOT_SUPPORTED; -} - - -extern "C" status_t -heap_debug_dump_allocations_on_exit(bool enabled) +static status_t +guarded_heap_set_dump_allocations_on_exit(bool enabled) { sDumpAllocationsOnExit = enabled; return B_OK; } -extern "C" status_t -heap_debug_set_stack_trace_depth(size_t stackTraceDepth) +static status_t +guarded_heap_set_stack_trace_depth(size_t stackTraceDepth) { if (stackTraceDepth == 0) { sStackTraceDepth = 0; @@ -1139,8 +1127,8 @@ init_after_fork() } -extern "C" status_t -__init_heap(void) +static status_t +guarded_heap_init(void) { if (!guarded_heap_area_create(sGuardedHeap, GUARDED_HEAP_INITIAL_SIZE)) return B_ERROR; @@ -1164,35 +1152,8 @@ __init_heap(void) } -extern "C" void -__init_heap_post_env(void) -{ - const char *mode = getenv("MALLOC_DEBUG"); - if (mode != NULL) { - if (strchr(mode, 'r')) - heap_debug_set_memory_reuse(false); - if (strchr(mode, 'e')) - heap_debug_dump_allocations_on_exit(true); - - size_t defaultAlignment = 0; - const char *argument = strchr(mode, 'a'); - if (argument != NULL - && sscanf(argument, "a%" B_SCNuSIZE, &defaultAlignment) == 1) { - heap_debug_set_default_alignment(defaultAlignment); - } - - size_t stackTraceDepth = 0; - argument = strchr(mode, 's'); - if (argument != NULL - && sscanf(argument, "s%" B_SCNuSIZE, &stackTraceDepth) == 1) { - heap_debug_set_stack_trace_depth(stackTraceDepth); - } - } -} - - -extern "C" void -__heap_terminate_after() +static void +guarded_heap_terminate_after() { if (sDumpAllocationsOnExit) dump_allocations_full(); @@ -1202,17 +1163,8 @@ __heap_terminate_after() // #pragma mark - Public API -extern "C" void* -sbrk_hook(long) -{ - debug_printf("sbrk not supported on malloc debug\n"); - panic("sbrk not supported on malloc debug\n"); - return NULL; -} - - -extern "C" void* -memalign(size_t alignment, size_t size) +static void* +heap_memalign(size_t alignment, size_t size) { if (size == 0) size = 1; @@ -1221,23 +1173,23 @@ memalign(size_t alignment, size_t size) } -extern "C" void* -malloc(size_t size) +static void* +heap_malloc(size_t size) { - return memalign(sDefaultAlignment, size); + return heap_memalign(sDefaultAlignment, size); } -extern "C" void -free(void* address) +static void +heap_free(void* address) { if (!guarded_heap_free(address)) panic("free failed for address %p", address); } -extern "C" void* -realloc(void* address, size_t newSize) +static void* +heap_realloc(void* address, size_t newSize) { if (newSize == 0) { free(address); @@ -1245,40 +1197,42 @@ realloc(void* address, size_t newSize) } if (address == NULL) - return memalign(sDefaultAlignment, newSize); + return heap_memalign(sDefaultAlignment, newSize); return guarded_heap_realloc(address, newSize); } -extern "C" void* -calloc(size_t numElements, size_t size) -{ - void* address = malloc(numElements * size); - if (address != NULL) - memset(address, 0, numElements * size); +heap_implementation __mallocGuardedHeap = { + guarded_heap_init, + guarded_heap_terminate_after, - return address; -} + heap_memalign, + heap_malloc, + heap_free, + heap_realloc, + NULL, // calloc + NULL, // valloc + NULL, // posix_memalign -extern "C" void* -valloc(size_t size) -{ - return memalign(B_PAGE_SIZE, size); -} + NULL, // start_wall_checking + NULL, // stop_wall_checking + NULL, // set_paranoid_validation + guarded_heap_set_memory_reuse, + guarded_heap_set_debugger_calls, + guarded_heap_set_default_alignment, -extern "C" int -posix_memalign(void **pointer, size_t alignment, size_t size) -{ - // this cryptic line accepts zero and all powers of two - if (((~alignment + 1) | ((alignment << 1) - 1)) != ~0UL) - return EINVAL; + NULL, // validate_heaps + NULL, // validate_walls - *pointer = memalign(alignment, size); - if (*pointer == NULL) - return ENOMEM; + guarded_heap_dump_allocations, + guarded_heap_dump_heaps, + heap_malloc, - return 0; -} + NULL, // get_allocation_info + + guarded_heap_set_dump_allocations_on_exit, + guarded_heap_set_stack_trace_depth +}; diff --git a/src/system/libroot/posix/malloc_debug/heap.cpp b/src/system/libroot/posix/malloc_debug/heap.cpp index 10745f39d0..3c9ed49218 100644 --- a/src/system/libroot/posix/malloc_debug/heap.cpp +++ b/src/system/libroot/posix/malloc_debug/heap.cpp @@ -10,8 +10,9 @@ */ +#include "malloc_debug_api.h" + #include -#include #include #include #include @@ -38,6 +39,9 @@ #define ASSERT(x) if (!(x)) panic("assert failed: %s", #x); +static void *debug_heap_memalign(size_t alignment, size_t size); + + static bool sDebuggerCalls = true; static bool sReuseMemory = true; static bool sParanoidValidation = false; @@ -50,7 +54,7 @@ static bool sUseGuardPage = false; using namespace std; static size_t sDefaultAlignment = alignof(max_align_t); #else -static size_t sDefaultAlignment = 0; +static size_t sDefaultAlignment = 8; #endif @@ -773,7 +777,7 @@ heap_remove_area(heap_allocator *heap, heap_area *area) } -heap_allocator * +static heap_allocator * heap_create_allocator(const char *name, addr_t base, size_t size, const heap_class *heapClass) { @@ -1103,15 +1107,7 @@ heap_allocate_from_bin(heap_allocator *heap, uint32 binIndex, size_t size) } -static bool -is_valid_alignment(size_t number) -{ - // this cryptic line accepts zero and all powers of two - return ((~number + 1) | ((number << 1) - 1)) == ~0UL; -} - - -void * +static void * heap_memalign(heap_allocator *heap, size_t alignment, size_t size) { INFO(("memalign(alignment = %lu, size = %lu)\n", alignment, size)); @@ -1172,7 +1168,7 @@ heap_memalign(heap_allocator *heap, size_t alignment, size_t size) } -status_t +static status_t heap_free(heap_allocator *heap, void *address) { if (address == NULL) @@ -1473,7 +1469,7 @@ heap_realloc(heap_allocator *heap, void *address, void **newAddress, newSize -= sizeof(addr_t) + sizeof(heap_leak_check_info); // if not, allocate a new chunk of memory - *newAddress = memalign(sDefaultAlignment, newSize); + *newAddress = debug_heap_memalign(sDefaultAlignment, newSize); if (*newAddress == NULL) { // we tried but it didn't work out, but still the operation is done return B_OK; @@ -1643,8 +1639,8 @@ heap_wall_checker(void *data) // #pragma mark - Heap Debug API -extern "C" status_t -heap_debug_start_wall_checking(int msInterval) +static status_t +debug_heap_start_wall_checking(int msInterval) { if (sWallCheckThread < 0) { sWallCheckThread = spawn_thread(heap_wall_checker, "heap wall checker", @@ -1659,8 +1655,8 @@ heap_debug_start_wall_checking(int msInterval) } -extern "C" status_t -heap_debug_stop_wall_checking() +static status_t +debug_heap_stop_wall_checking() { int32 result; sStopWallChecking = true; @@ -1668,66 +1664,52 @@ heap_debug_stop_wall_checking() } -extern "C" void -heap_debug_set_paranoid_validation(bool enabled) +static void +debug_heap_set_paranoid_validation(bool enabled) { sParanoidValidation = enabled; } -extern "C" void -heap_debug_set_memory_reuse(bool enabled) +static void +debug_heap_set_memory_reuse(bool enabled) { sReuseMemory = enabled; } -extern "C" void -heap_debug_set_debugger_calls(bool enabled) +static void +debug_heap_set_debugger_calls(bool enabled) { sDebuggerCalls = enabled; } -extern "C" void -heap_debug_set_default_alignment(size_t defaultAlignment) +static void +debug_heap_set_default_alignment(size_t defaultAlignment) { sDefaultAlignment = defaultAlignment; } -extern "C" void -heap_debug_validate_heaps() +static void +debug_heap_validate_heaps() { for (uint32 i = 0; i < HEAP_CLASS_COUNT; i++) heap_validate_heap(sHeaps[i]); } -extern "C" void -heap_debug_validate_walls() -{ - heap_validate_walls(); -} - - -extern "C" void -heap_debug_dump_allocations(bool statsOnly, thread_id thread) -{ - dump_allocations(statsOnly, thread); -} - - -extern "C" void -heap_debug_dump_heaps(bool dumpAreas, bool dumpBins) +static void +debug_heap_dump_heaps(bool dumpAreas, bool dumpBins) { for (uint32 i = 0; i < HEAP_CLASS_COUNT; i++) dump_allocator(sHeaps[i], dumpAreas, dumpBins); } -extern "C" void * -heap_debug_malloc_with_guard_page(size_t size) +static void * +debug_heap_malloc_with_guard_page(size_t size) { size_t areaSize = ROUNDUP(size + sizeof(area_allocation_info) + B_PAGE_SIZE, B_PAGE_SIZE); @@ -1775,8 +1757,8 @@ heap_debug_malloc_with_guard_page(size_t size) } -extern "C" status_t -heap_debug_get_allocation_info(void *address, size_t *size, +static status_t +debug_heap_get_allocation_info(void *address, size_t *size, thread_id *thread) { for (uint32 i = 0; i < HEAP_CLASS_COUNT; i++) { @@ -1807,25 +1789,11 @@ heap_debug_get_allocation_info(void *address, size_t *size, } -extern "C" status_t -heap_debug_dump_allocations_on_exit(bool enabled) -{ - return B_NOT_SUPPORTED; -} - - -extern "C" status_t -heap_debug_set_stack_trace_depth(size_t stackTraceDepth) -{ - return B_NOT_SUPPORTED; -} - - // #pragma mark - Init -extern "C" status_t -__init_heap(void) +static status_t +debug_heap_init(void) { // This will locate the heap base at 384 MB and reserve the next 1152 MB // for it. They may get reclaimed by other areas, though, but the maximum @@ -1853,53 +1821,11 @@ __init_heap(void) } -extern "C" void -__init_heap_post_env(void) -{ - const char *mode = getenv("MALLOC_DEBUG"); - if (mode != NULL) { - if (strchr(mode, 'p')) - heap_debug_set_paranoid_validation(true); - if (strchr(mode, 'w')) - heap_debug_start_wall_checking(500); - else if (strchr(mode, 'W')) - heap_debug_start_wall_checking(100); - if (strchr(mode, 'g')) - sUseGuardPage = true; - if (strchr(mode, 'r')) - heap_debug_set_memory_reuse(false); - - size_t defaultAlignment = 0; - const char *argument = strchr(mode, 'a'); - if (argument != NULL - && sscanf(argument, "a%" B_SCNuSIZE, &defaultAlignment) == 1) { - heap_debug_set_default_alignment(defaultAlignment); - } - } -} - - -extern "C" void -__heap_terminate_after() -{ - // nothing to do -} - - // #pragma mark - Public API -extern "C" void * -sbrk_hook(long) -{ - debug_printf("sbrk not supported on malloc debug\n"); - panic("sbrk not supported on malloc debug\n"); - return NULL; -} - - -void * -memalign(size_t alignment, size_t size) +static void * +debug_heap_memalign(size_t alignment, size_t size) { size_t alignedSize = size + sizeof(addr_t) + sizeof(heap_leak_check_info); if (alignment != 0 && alignment < B_PAGE_SIZE) @@ -1974,18 +1900,18 @@ memalign(size_t alignment, size_t size) } -void * -malloc(size_t size) +static void * +debug_heap_malloc(size_t size) { if (sUseGuardPage) - return heap_debug_malloc_with_guard_page(size); + return debug_heap_malloc_with_guard_page(size); - return memalign(sDefaultAlignment, size); + return debug_heap_memalign(sDefaultAlignment, size); } -void -free(void *address) +static void +debug_heap_free(void *address) { for (uint32 i = 0; i < HEAP_CLASS_COUNT; i++) { heap_allocator *heap = sHeaps[i]; @@ -2017,11 +1943,11 @@ free(void *address) } -void * -realloc(void *address, size_t newSize) +static void * +debug_heap_realloc(void *address, size_t newSize) { if (address == NULL) - return memalign(sDefaultAlignment, newSize); + return debug_heap_memalign(sDefaultAlignment, newSize); if (newSize == 0) { free(address); @@ -2079,7 +2005,7 @@ realloc(void *address, size_t newSize) } // have to allocate/copy/free - TODO maybe resize the area instead? - newAddress = malloc(newSize); + newAddress = debug_heap_memalign(sDefaultAlignment, newSize); if (newAddress == NULL) { panic("realloc(): failed to allocate new block of %ld" " bytes\n", newSize); @@ -2100,33 +2026,32 @@ realloc(void *address, size_t newSize) } -void * -calloc(size_t numElements, size_t size) -{ - void *address = malloc(numElements * size); - if (address != NULL) - memset(address, 0, numElements * size); +heap_implementation __mallocDebugHeap = { + debug_heap_init, + NULL, // terminate_after - return address; -} + debug_heap_memalign, + debug_heap_malloc, + debug_heap_free, + debug_heap_realloc, + NULL, // calloc + NULL, // valloc + NULL, // posix_memalign -extern "C" void * -valloc(size_t size) -{ - return memalign(B_PAGE_SIZE, size); -} + debug_heap_start_wall_checking, + debug_heap_stop_wall_checking, + debug_heap_set_paranoid_validation, + debug_heap_set_memory_reuse, + debug_heap_set_debugger_calls, + debug_heap_set_default_alignment, + debug_heap_validate_heaps, + heap_validate_walls, + dump_allocations, + debug_heap_dump_heaps, + debug_heap_malloc_with_guard_page, + debug_heap_get_allocation_info, - -extern "C" int -posix_memalign(void **pointer, size_t alignment, size_t size) -{ - if (!is_valid_alignment(alignment)) - return EINVAL; - - *pointer = memalign(alignment, size); - if (*pointer == NULL) - return ENOMEM; - - return 0; -} + NULL, // set_dump_allocations_on_exit + NULL // set_stack_trace_depth +}; diff --git a/src/system/libroot/posix/malloc_debug/malloc_debug_api.cpp b/src/system/libroot/posix/malloc_debug/malloc_debug_api.cpp new file mode 100644 index 0000000000..45d3c1c6c3 --- /dev/null +++ b/src/system/libroot/posix/malloc_debug/malloc_debug_api.cpp @@ -0,0 +1,283 @@ +/* + * Copyright 2015, Michael Lotz . + * Distributed under the terms of the MIT License. + */ + + +#include "malloc_debug_api.h" + +#include +#include + +#include +#include + + +static heap_implementation* sCurrentHeap = NULL; + + +// #pragma mark - Heap Debug API + + +extern "C" status_t +heap_debug_start_wall_checking(int msInterval) +{ + if (sCurrentHeap->start_wall_checking != NULL) + return sCurrentHeap->start_wall_checking(msInterval); + + return B_NOT_SUPPORTED; +} + + +extern "C" status_t +heap_debug_stop_wall_checking() +{ + if (sCurrentHeap->stop_wall_checking != NULL) + return sCurrentHeap->stop_wall_checking(); + + return B_NOT_SUPPORTED; +} + + +extern "C" void +heap_debug_set_paranoid_validation(bool enabled) +{ + if (sCurrentHeap->set_paranoid_validation != NULL) + sCurrentHeap->set_paranoid_validation(enabled); +} + + +extern "C" void +heap_debug_set_memory_reuse(bool enabled) +{ + if (sCurrentHeap->set_memory_reuse != NULL) + sCurrentHeap->set_memory_reuse(enabled); +} + + +extern "C" void +heap_debug_set_debugger_calls(bool enabled) +{ + if (sCurrentHeap->set_debugger_calls != NULL) + sCurrentHeap->set_debugger_calls(enabled); +} + + +extern "C" void +heap_debug_set_default_alignment(size_t defaultAlignment) +{ + if (sCurrentHeap->set_default_alignment != NULL) + sCurrentHeap->set_default_alignment(defaultAlignment); +} + + +extern "C" void +heap_debug_validate_heaps() +{ + if (sCurrentHeap->validate_heaps != NULL) + sCurrentHeap->validate_heaps(); +} + + +extern "C" void +heap_debug_validate_walls() +{ + if (sCurrentHeap->validate_walls != NULL) + sCurrentHeap->validate_walls(); +} + + +extern "C" void +heap_debug_dump_allocations(bool statsOnly, thread_id thread) +{ + if (sCurrentHeap->dump_allocations != NULL) + sCurrentHeap->dump_allocations(statsOnly, thread); +} + + +extern "C" void +heap_debug_dump_heaps(bool dumpAreas, bool dumpBins) +{ + if (sCurrentHeap->dump_heaps != NULL) + sCurrentHeap->dump_heaps(dumpAreas, dumpBins); +} + + +extern "C" void * +heap_debug_malloc_with_guard_page(size_t size) +{ + if (sCurrentHeap->malloc_with_guard_page != NULL) + return sCurrentHeap->malloc_with_guard_page(size); + + return NULL; +} + + +extern "C" status_t +heap_debug_get_allocation_info(void *address, size_t *size, + thread_id *thread) +{ + if (sCurrentHeap->get_allocation_info != NULL) + return sCurrentHeap->get_allocation_info(address, size, thread); + + return B_NOT_SUPPORTED; +} + + +extern "C" status_t +heap_debug_set_dump_allocations_on_exit(bool enabled) +{ + if (sCurrentHeap->set_dump_allocations_on_exit != NULL) + return sCurrentHeap->set_dump_allocations_on_exit(enabled); + + return B_NOT_SUPPORTED; +} + + +extern "C" status_t +heap_debug_set_stack_trace_depth(size_t stackTraceDepth) +{ + if (sCurrentHeap->set_stack_trace_depth != NULL) + return sCurrentHeap->set_stack_trace_depth(stackTraceDepth); + + return B_NOT_SUPPORTED; +} + + +// #pragma mark - Init + + +extern "C" status_t +__init_heap(void) +{ + const char *mode = getenv("MALLOC_DEBUG"); + if (mode == NULL || strchr(mode, 'g') == NULL) + sCurrentHeap = &__mallocDebugHeap; + else + sCurrentHeap = &__mallocGuardedHeap; + + status_t result = sCurrentHeap->init(); + if (result != B_OK) + return result; + + if (mode != NULL) { + if (strchr(mode, 'p') != NULL) + heap_debug_set_paranoid_validation(true); + if (strchr(mode, 'r') != NULL) + heap_debug_set_memory_reuse(false); + if (strchr(mode, 'e') != NULL) + heap_debug_set_dump_allocations_on_exit(true); + + size_t defaultAlignment = 0; + const char *argument = strchr(mode, 'a'); + if (argument != NULL + && sscanf(argument, "a%" B_SCNuSIZE, &defaultAlignment) == 1) { + heap_debug_set_default_alignment(defaultAlignment); + } + + size_t stackTraceDepth = 0; + argument = strchr(mode, 's'); + if (argument != NULL + && sscanf(argument, "s%" B_SCNuSIZE, &stackTraceDepth) == 1) { + heap_debug_set_stack_trace_depth(stackTraceDepth); + } + + int wallCheckInterval = 0; + argument = strchr(mode, 'w'); + if (argument != NULL + && sscanf(argument, "w%d", &wallCheckInterval) == 1) { + heap_debug_start_wall_checking(wallCheckInterval); + } + } + + return B_OK; +} + + +extern "C" void +__heap_terminate_after() +{ + if (sCurrentHeap->terminate_after != NULL) + sCurrentHeap->terminate_after(); +} + + +// #pragma mark - Public API + + +extern "C" void* +sbrk_hook(long) +{ + debug_printf("sbrk not supported on malloc debug\n"); + debugger("sbrk not supported on malloc debug"); + return NULL; +} + + +extern "C" void* +memalign(size_t alignment, size_t size) +{ + return sCurrentHeap->memalign(alignment, size); +} + + +extern "C" void* +malloc(size_t size) +{ + return sCurrentHeap->malloc(size); +} + + +extern "C" void +free(void* address) +{ + sCurrentHeap->free(address); +} + + +extern "C" void* +realloc(void* address, size_t newSize) +{ + return sCurrentHeap->realloc(address, newSize); +} + + +extern "C" void* +calloc(size_t numElements, size_t size) +{ + if (sCurrentHeap->calloc != NULL) + return sCurrentHeap->calloc(numElements, size); + + void* address = malloc(numElements * size); + if (address != NULL) + memset(address, 0, numElements * size); + + return address; +} + + +extern "C" void* +valloc(size_t size) +{ + if (sCurrentHeap->valloc != NULL) + return sCurrentHeap->valloc(size); + + return memalign(B_PAGE_SIZE, size); +} + + +extern "C" int +posix_memalign(void **pointer, size_t alignment, size_t size) +{ + if (sCurrentHeap->posix_memalign != NULL) + return sCurrentHeap->posix_memalign(pointer, alignment, size); + + if (!is_valid_alignment(alignment)) + return EINVAL; + + *pointer = memalign(alignment, size); + if (*pointer == NULL) + return ENOMEM; + + return 0; +} diff --git a/src/system/libroot/posix/malloc_debug/malloc_debug_api.h b/src/system/libroot/posix/malloc_debug/malloc_debug_api.h new file mode 100644 index 0000000000..dc949a9dd9 --- /dev/null +++ b/src/system/libroot/posix/malloc_debug/malloc_debug_api.h @@ -0,0 +1,57 @@ +/* + * Copyright 2015, Michael Lotz . + * Distributed under the terms of the MIT License. + */ +#ifndef MALLOC_DEBUG_API_H +#define MALLOC_DEBUG_API_H + +#include + + +struct heap_implementation { + status_t (*init)(); + void (*terminate_after)(); + + // Mandatory hooks + void* (*memalign)(size_t alignment, size_t size); + void* (*malloc)(size_t size); + void (*free)(void* address); + void* (*realloc)(void* address, size_t newSize); + + // Hooks with default implementations + void* (*calloc)(size_t numElements, size_t size); + void* (*valloc)(size_t size); + int (*posix_memalign)(void** pointer, size_t alignment, + size_t size); + + // Heap Debug API + status_t (*start_wall_checking)(int msInterval); + status_t (*stop_wall_checking)(); + void (*set_paranoid_validation)(bool enabled); + void (*set_memory_reuse)(bool enabled); + void (*set_debugger_calls)(bool enabled); + void (*set_default_alignment)(size_t defaultAlignment); + void (*validate_heaps)(); + void (*validate_walls)(); + void (*dump_allocations)(bool statsOnly, thread_id thread); + void (*dump_heaps)(bool dumpAreas, bool dumpBins); + void* (*malloc_with_guard_page)(size_t size); + status_t (*get_allocation_info)(void* address, size_t *size, + thread_id *thread); + status_t (*set_dump_allocations_on_exit)(bool enabled); + status_t (*set_stack_trace_depth)(size_t stackTraceDepth); +}; + + +extern heap_implementation __mallocDebugHeap; +extern heap_implementation __mallocGuardedHeap; + + +static inline bool +is_valid_alignment(size_t number) +{ + // this cryptic line accepts zero and all powers of two + return ((~number + 1) | ((number << 1) - 1)) == ~0UL; +} + +#endif // MALLOC_DEBUG_API_H diff --git a/src/system/libroot/posix/stdlib/env.cpp b/src/system/libroot/posix/stdlib/env.cpp index 578a25506b..e811eeb6f5 100644 --- a/src/system/libroot/posix/stdlib/env.cpp +++ b/src/system/libroot/posix/stdlib/env.cpp @@ -205,7 +205,12 @@ __init_env(const struct user_space_program_args *args) // protect our implementation environ = args->env; sManagedEnviron = NULL; +} + +void +__init_env_post_heap() +{ atfork(environ_fork_hook); } diff --git a/src/system/libroot/stubbed/libroot_stubs.c b/src/system/libroot/stubbed/libroot_stubs.c index 961185532f..cd8ff77e4c 100644 --- a/src/system/libroot/stubbed/libroot_stubs.c +++ b/src/system/libroot/stubbed/libroot_stubs.c @@ -892,8 +892,8 @@ void __ilogb() {} void __ilogbf() {} void __ilogbl() {} void __init_env() {} +void __init_env_post_heap() {} void __init_heap() {} -void __init_heap_post_env() {} void __init_once() {} void __init_pthread() {} void __init_pwd_backend() {} diff --git a/src/system/libroot/stubbed/libroot_stubs_legacy.c b/src/system/libroot/stubbed/libroot_stubs_legacy.c index 2d72b862d0..855c3bbad2 100644 --- a/src/system/libroot/stubbed/libroot_stubs_legacy.c +++ b/src/system/libroot/stubbed/libroot_stubs_legacy.c @@ -726,8 +726,8 @@ void __ilogb() {} void __ilogbf() {} void __ilogbl() {} void __init_env() {} +void __init_env_post_heap() {} void __init_heap() {} -void __init_heap_post_env() {} void __init_once() {} void __init_pthread() {} void __init_pwd_backend() {} diff --git a/src/tests/add-ons/kernel/kernelland_emu/lock.cpp b/src/tests/add-ons/kernel/kernelland_emu/lock.cpp index 7d5ad1fbce..eb75880c79 100644 --- a/src/tests/add-ons/kernel/kernelland_emu/lock.cpp +++ b/src/tests/add-ons/kernel/kernelland_emu/lock.cpp @@ -479,11 +479,11 @@ _rw_lock_read_unlock_threads_locked(rw_lock* lock) if (--lock->active_readers > 0) return; - if (lock->active_readers < 0) { - panic("rw_lock_read_unlock(): lock %p not read-locked", lock); + if (lock->active_readers < 0) { + panic("rw_lock_read_unlock(): lock %p not read-locked", lock); lock->active_readers = 0; - return; - } + return; + } rw_lock_unblock(lock); } diff --git a/src/tests/misc/boot_time_logger.sh b/src/tests/misc/boot_time_logger.sh new file mode 100755 index 0000000000..f1a88d8e76 --- /dev/null +++ b/src/tests/misc/boot_time_logger.sh @@ -0,0 +1,34 @@ +#!/bin/sh + + +# Send a message to and wait for a reply from all servers to determine when +# everything's ready. +SIGNATURES=" + application/x-vnd.haiku-registrar + application/x-vnd.Haiku-mount_server + application/x-vnd.Haiku-powermanagement + application/x-vnd.Haiku-cddb_daemon + application/x-vnd.Haiku-midi_server + application/x-vnd.haiku-net_server + application/x-vnd.Haiku-debug_server + application/x-vnd.Be-PSRV + application/x-vnd.haiku-package_daemon + application/x-vnd.Haiku-notification_server + application/x-vnd.Be-input_server + application/x-vnd.Be.media-server + application/x-vnd.Be.addon-host + application/x-vnd.Be-TRAK + application/x-vnd.Be-TSKB" + +for SIGNATURE in $SIGNATURES +do + waitfor -m $SIGNATURE + hey -s $SIGNATURE get + if [ $? -ne 0 ] + then + echo "Failed to get a reply for $SIGNATURE" + exit 1 + fi +done + +system_time diff --git a/src/tools/fs_shell/vfs.cpp b/src/tools/fs_shell/vfs.cpp index 9308a351da..5137ddd364 100644 --- a/src/tools/fs_shell/vfs.cpp +++ b/src/tools/fs_shell/vfs.cpp @@ -2277,6 +2277,15 @@ fssh_entry_cache_add(fssh_dev_t mountID, fssh_ino_t dirID, const char* name, } +extern "C" fssh_status_t +fssh_entry_cache_add_missing(fssh_dev_t mountID, fssh_ino_t dirID, + const char* name) +{ + // We don't implement an entry cache in the FS shell. + return FSSH_B_OK; +} + + extern "C" fssh_status_t fssh_entry_cache_remove(fssh_dev_t mountID, fssh_ino_t dirID, const char* name) {