diff -Nru jd-2.8.5-120826/ChangeLog jd-2.8.6-130518/ChangeLog --- jd-2.8.5-120826/ChangeLog 2012-08-26 09:39:27.000000000 +0000 +++ jd-2.8.6-130518/ChangeLog 2013-05-17 16:34:56.000000000 +0000 @@ -11,12 +11,7 @@ ------------------------------------------------------------------------ -2.8.5-120826 - 2012/08/26(日) +2.8.6-130518 - 2013/05/18(土) ------------------------------------------------------------------------ - * リンクフィルタのコマンドでの置換文字に\0〜\9を追加 - * Youtubeのサムネイルが表示されない問題を修正 - * 正規表現ライブラリとしてPOSIX regex の代わりにPCREを使用できるようにした - * スレ一覧の時刻表示オプション「年/月/日 時:分:秒」を追加 - * スレ一覧に、スレを最後にロードした最終取得時刻を表示できるようにした - * 数値文字参照(©など)は「;」なしでも表示できるようにした + * タブを閉じたとき、タイトルとURLが変更されないことがあるバグを修正 diff -Nru jd-2.8.5-120826/Makefile.am jd-2.8.6-130518/Makefile.am --- jd-2.8.5-120826/Makefile.am 2011-11-01 12:42:44.000000000 +0000 +++ jd-2.8.6-130518/Makefile.am 2013-01-28 05:21:10.000000000 +0000 @@ -50,7 +50,7 @@ @if test -n "$(SVN)" -a -n "$(AWK)"; \ then \ - SVN_REPOSITORY=`LANG=C $(SVN) info 2>/dev/null | $(AWK) '/^URL/ {print $$2}' 2>/dev/null`; \ + SVN_REPOSITORY=`LANG=C "$(SVN)" info 2>/dev/null | $(AWK) '/^URL/ {print $$2}' 2>/dev/null`; \ if test -n "$${SVN_REPOSITORY}"; \ then \ echo "SVN: Repository = \"$${SVN_REPOSITORY}\""; \ @@ -60,7 +60,7 @@ @if test -n "$(SVNVERSION)"; \ then \ - SVN_REVISION=`LANG=C $(SVNVERSION) -n 2>/dev/null`; \ + SVN_REVISION=`LANG=C "$(SVNVERSION)" -n 2>/dev/null`; \ if test -n "$${SVN_REVISION}" -a "$${SVN_REVISION}" != "exported"; \ then \ echo "SVN: Revision = \"$${SVN_REVISION}\""; \ diff -Nru jd-2.8.5-120826/README jd-2.8.6-130518/README --- jd-2.8.5-120826/README 2012-02-06 11:47:56.000000000 +0000 +++ jd-2.8.6-130518/README 2013-03-03 16:48:57.000000000 +0000 @@ -9,7 +9,7 @@ * 著作権 - ©2006-2012 "JD Project [http://sourceforge.jp/projects/jd4linux/]" + ©2006-2013 "JD Project [http://sourceforge.jp/projects/jd4linux/]" パッチやファイルを取り込んだ場合、それらのコピーライトは「JD Project」に統一します。 diff -Nru jd-2.8.5-120826/configure.ac jd-2.8.6-130518/configure.ac --- jd-2.8.5-120826/configure.ac 1970-01-01 00:00:00.000000000 +0000 +++ jd-2.8.6-130518/configure.ac 2013-02-10 11:38:45.000000000 +0000 @@ -0,0 +1,468 @@ +dnl +dnl JD用 configure.ac +dnl +AC_PREREQ(2.50) +AC_INIT(jd, 1.0) +AM_INIT_AUTOMAKE +AC_CONFIG_HEADERS(config.h) + +AC_ISC_POSIX +AC_PROG_CC +AC_HEADER_STDC +AC_PROG_CPP +AC_PROG_CXX +AC_PROG_CXXCPP +AC_PROG_LIBTOOL +AC_LANG_CPLUSPLUS + +dnl +dnl buildinfo.h +dnl +AC_DEFINE(HAVE_BUILDINFO_H, 1, Define to 1 if you have the 'buildinfo.h' header file.) +AC_PATH_PROG(SVN, svn) +AC_PATH_PROG(SVNVERSION, svnversion) +AC_PATH_PROG(XSUM, md5sum, [cksum]) +AC_SUBST(ac_configure_args) + +dnl +dnl OSを判定してOS別の設定 +dnl +case "${host_os}" in + freebsd*) + echo "os = freebsd" + AC_DEFINE(ICONV_CONST, const, "iconv_const") + AC_DEFINE(USE_MKTIME, , "use mktime") + ;; + solaris*) + echo "os = solaris" + AC_DEFINE(ICONV_CONST, const, "iconv_const") + AC_DEFINE(NO_TIMEGM, , "no timegm") + ;; + mingw*) + echo "os = ${host_os}" + AC_DEFINE(ICONV_CONST, , "iconv_const") + AC_DEFINE(USE_MKTIME, , "use mktime") + ;; + darwin*) + echo "os = ${host_os}" + AC_DEFUN([AM_ICONV], []) + AC_DEFINE(ICONV_CONST, , "iconv_const") + AC_DEFINE(USE_MKTIME, , "use mktime") + ;; +dnl linux*|gnu*|*-gnu + *) + echo "os = ${host_os}" + AC_DEFUN([AM_ICONV], []) + AC_DEFINE(ICONV_CONST, , "iconv_const") + ;; +esac + +AM_ICONV + + +dnl --------------------------------------------------- +dnl --------------------------------------------------- +dnl +dnl ユーザー設定 +dnl + +dnl 追加コンパイルオプション +CXXFLAGS="$CXXFLAGS -ggdb -Wall" + +dnl --------------------------------------------------- +dnl --------------------------------------------------- + +LIBSM_CFLAGS="" +LIBSM_LIBS="" +GNOMEUI_CFLAGS="" +GNOMEUI_LIBS="" + +dnl +dnl パッケージのチェック +dnl +PKG_CHECK_MODULES(GTKMM,[gtkmm-2.4 >= 2.4.0], [], []) +PKG_CHECK_MODULES(GTHREAD, [gthread-2.0 >= 2.0] ) + +AC_SUBST(GTKMM_CFLAGS) +AC_SUBST(GTKMM_LIBS) +AC_SUBST(GTHREAD_CFLAGS) +AC_SUBST(GTHREAD_LIBS) + + +dnl +dnl crypt +dnl + +echo "use crypt" +AC_CHECK_HEADERS([crypt.h]) +AC_CHECK_LIB(crypt,crypt) + + +dnl +dnl zlib +dnl + +echo "use zlib" +AC_CHECK_HEADERS([zlib.h]) +AC_CHECK_LIB(z,inflate) + + +dnl +dnl packages dependent on platform +dnl +use_windres="" + +case "${host_os}" in + mingw*) + dnl + dnl winsock2 using model of socket + dnl not available uname on windows + dnl + + echo "use winsock2" + AC_CHECK_HEADERS([winsock2.h]) + AC_CHECK_LIB(ws2_32,_head_libws2_32_a) + + echo "use regex2" + AC_CHECK_HEADERS([regex.h]) + AC_CHECK_LIB(regex,regexec) + + echo "use iconv" + AC_CHECK_HEADERS([iconv.h]) + AC_CHECK_LIB(iconv,_head_libiconv_a) + + echo "use windows resources" + AC_CHECK_TOOL([WINDRES], [windres], [windres]) + AC_SUBST(WINDRES) + AC_DEFINE(USE_WINDRES, , "use windres") + use_windres="yes" + ;; + *) + dnl + dnl any other POSIX systems + dnl + + echo "use uname" + AC_CHECK_HEADERS([sys/utsname.h]) + + echo "use socket" + AC_CHECK_HEADERS([socket.h]) + AC_CHECK_LIB(socket,socket) + ;; +esac + +AM_CONDITIONAL(MAKE_WINDRES, test -n "$use_windres") + + +dnl +dnl X関連ライブラリ +dnl +X11_CFLAGS="" +X11_LIBS="" + +case "${host_os}" in + mingw*) + ;; + *) + PKG_CHECK_MODULES(X11, x11) + AC_SUBST(X11_CFLAGS) + AC_SUBST(X11_LIBS) + ;; +esac + + +dnl +dnl セッション管理 +dnl +dnl +use_xsmp=no +use_gnomeui=no + +AC_ARG_WITH(sessionlib, +[ + --with-sessionlib[[=xsmp/gnomeui/no]] + use session control library [[default=xsmp]] +], +[case "${withval}" in + xsmp) + use_xsmp=yes + ;; + gnomeui) + use_gnomeui=yes + ;; + no) + use_xsmp=no + use_gnomeui=no + ;; + *) + use_xsmp=yes + ;; +esac],use_xsmp=yes) + +dnl +dnl XSMPを使ってセッション管理をする。libSMとlibICEが必要。無ければXSMPは無効になる +dnl +dnl dirsの並びは Tk の configure に書いてあったもの + Fedora 向けにディレクトリを追加 +dnl +if test x"$use_xsmp" = "xyes" ; then + + AC_MSG_CHECKING(for SMlib.h and ICElib.h) + LIBSM_CFLAGS="" + dirs="/usr/unsupported/include /usr/local/include /usr/X386/include /usr/X11R6/include /usr/X11R5/include /usr/include/X11R5 /usr/include/X11R4 /usr/openwin/include /usr/X11/include /usr/sww/include /usr/include" + for i in $dirs ; do + if test -r $i/X11/ICE/ICElib.h -a -r $i/X11/SM/SMlib.h ; then + AC_MSG_RESULT($i) + LIBSM_CFLAGS="-I$i" + break + fi + done + if test -z "$LIBSM_CFLAGS" ; then + AC_MSG_RESULT(could not find SMlib.h and ICElib.h) + fi + + AC_MSG_CHECKING(for libSM and libICE) + LIBSM_LIBS="" + dirs="/usr/unsupported/lib /usr/local/lib /usr/X386/lib /usr/X11R6/lib /usr/X11R5/lib /usr/lib/X11R5 /usr/lib/X11R4 /usr/openwin/lib /usr/X11/lib /usr/sww/X11/lib /usr/lib /usr/X11R6/lib64 /usr/lib64" + for i in $dirs ; do + if test -r $i/libICE.so -a -r $i/libSM.so ; then + AC_MSG_RESULT($i) + LIBSM_LIBS="-L$i -lICE -lSM" + break + fi + done + if test -z "$LIBSM_LIBS" ; then + AC_MSG_RESULT(could not find libSM and libICE.) + fi + + if test -n "$LIBSM_CFLAGS" -a -n "$LIBSM_LIBS" ; then + echo "use XSMP" + AC_SUBST(LIBSM_CFLAGS) + AC_SUBST(LIBSM_LIBS) + CXXFLAGS="$CXXFLAGS -DUSE_XSMP" + fi +fi + +dnl +dnl GNOMEUIを使ってセッション管理をする。libgnomeui-develが必要。 +dnl +if test x"$use_gnomeui" = "xyes" ; then + + PKG_CHECK_MODULES(GNOMEUI, [libgnomeui-2.0 >= 2.0] ) + + echo "use GNOMEUI" + AC_SUBST(GNOMEUI_CFLAGS) + AC_SUBST(GNOMEUI_LIBS) + CXXFLAGS="$CXXFLAGS -DUSE_GNOMEUI" +fi + + +dnl +dnl SSL +dnl + +use_gnutls=yes + +AC_ARG_WITH(openssl,[ --with-openssl (use openssl)], + [ if test "$withval" != "no" ;then + use_gnutls=no + fi ]) + +case "${use_gnutls}" in + yes) + echo "use gnutls" + + PKG_CHECK_MODULES(GNUTLS, [gnutls >= 1.2], [echo "gnutls >= 1.2"]) + AC_DEFINE(USE_GNUTLS, , "use gnutls") + AC_CHECK_HEADERS([gcrypt.h]) + AC_CHECK_LIB(gcrypt, gcry_md_hash_buffer, [], [AC_MSG_ERROR([gcrypt not found])]) + AC_SUBST(GNUTLS_CFLAGS) + AC_SUBST(GNUTLS_LIBS) + ;; + *) + echo "use openssl" + PKG_CHECK_MODULES(OPENSSL, [openssl >= 0.9] ) + AC_DEFINE(USE_OPENSSL, , "use openssl") + AC_SUBST(OPENSSL_CFLAGS) + AC_SUBST(OPENSSL_LIBS) + ;; +esac + + +dnl +dnl enable gprof +dnl + +use_gprof=no + +AC_ARG_ENABLE(gprof,[ --enable-gprof (enable gprof)], + [ if test "$enable_gprof" = "yes"; then + echo "use gprof" + CXXFLAGS="$CXXFLAGS -pg" + use_gprof=yes + fi ]) + +dnl +dnl checking migemo +dnl +AC_ARG_WITH(migemo,[ --with-migemo (enable migemo search)], + [ if test "$withval" != "no" ;then + echo "use migemo" + AC_CHECK_HEADERS([migemo.h]) + AC_CHECK_LIB(migemo,migemo_open) + fi ]) + + +AC_ARG_WITH(migemodict,[ --with-migemodict (specifiy the path of migemo dictionary)], + [ if test "$withval" ;then + echo "migemodict = $withval" + AC_DEFINE_UNQUOTED(MIGEMODICT, "$withval" , "migemodict") + fi ]) + + +dnl +dnl checking xdg-open +dnl +AC_ARG_WITH(xdgopen,[ --with-xdgopen (use xdg-open as default browser)], + [ if test "$withval" ;then + echo "use xdg-open" + AC_DEFINE(XDGOPEN, , "use xdg-open") + fi ]) + + +dnl +dnl checking alsa +dnl +case "${host_os}" in + linux*|*linux) + AC_ARG_WITH(alsa,[ --with-alsa (enable alsa)], + [ if test "$withval" != "no" ;then + echo "use alsa" + PKG_CHECK_MODULES(ALSA, [alsa >= 1.0] ) + AC_DEFINE(USE_ALSA, , "use alsa") + AC_SUBST(ALSA_CFLAGS) + AC_SUBST(ALSA_LIBS) + fi ]) + ;; +esac + + +dnl +dnl checking oniguruma +dnl +AC_ARG_WITH(oniguruma,[ --with-oniguruma (enable oniguruma)], + [ if test "$withval" != "no" ;then + echo "use oniguruma" + AC_CHECK_PROG(ONIG_CONFIG, onig-config, onig-config) + if test "x${ONIG_CONFIG}" = "x" ; then + AC_MSG_ERROR([onig-config not found]) + fi + ONIG_CFLAGS=`onig-config --cflags` + CPPFLAGS="${CPPFLAGS} ${ONIG_CFLAGS}" + ONIG_LIBS=`onig-config --libs` + LDFLAGS_ORIGINAL="${LDFLAGS}" + LDFLAGS="${LDFLAGS} ${ONIG_LIBS}" + AC_CHECK_HEADER([onigposix.h], ,[AC_MSG_ERROR([onigposix.h not found])]) + AC_CHECK_LIB([onig],[regexec], ,[AC_MSG_ERROR([libonig.a not found])]) + AC_DEFINE(USE_ONIG, , "use oniguruma") + AC_SUBST(ONIG_LIBS) + LDFLAGS="${LDFLAGS_ORIGINAL}" + fi ]) + + +dnl +dnl checking PCRE +dnl +AC_ARG_WITH(pcre,[ --with-pcre (enable PCRE)], + [ if test "$withval" != "no" ;then + echo "use PCRE" + PKG_CHECK_MODULES(PCRE, [libpcre >= 6.5] ) + AC_DEFINE(USE_PCRE, , "use PCRE") + AC_SUBST(PCRE_CFLAGS) + AC_SUBST(PCRE_LIBS) + AC_CHECK_HEADERS([pcreposix.h]) + AC_CHECK_LIB(pcreposix,regexec) + fi ]) + + +dnl +dnl checking gthread +dnl +AC_ARG_WITH(gthread,[ --with-gthread (use gthread instead of pthread)], + [ if test "$withval" ;then + echo "use gthread" + AC_DEFINE(USE_GTHREAD, , "use gthread") + fi ]) + + +dnl +dnl CPU別の最適化オプション +dnl +if test "$use_gprof" = "no"; then + + dnl + dnl checking native (gcc >= 4.2 x86 & x86_64) + dnl + AC_ARG_WITH(native,[ --with-native (use native)], + [ if test "$withval" != "no"; then + echo "use native" + CXXFLAGS="$CXXFLAGS -march=native" + fi ]) + + dnl + dnl checking core2duo + dnl + AC_ARG_WITH(core2duo,[ --with-core2duo (use core2duo)], + [ if test "$withval" != "no"; then + echo "use core2duo" + CXXFLAGS="$CXXFLAGS -march=pentium-m -msse3" + fi ]) + + dnl + dnl checking athlon64 + dnl + AC_ARG_WITH(athlon64,[ --with-athlon64 (use athlon64)], + [ if test "$withval" != "no"; then + echo "use athlon64" + CXXFLAGS="$CXXFLAGS -march=athlon64" + fi ]) + + dnl + dnl checking atom + dnl + AC_ARG_WITH(atom,[ --with-atom (use atom)], + [ if test "$withval" != "no"; then + echo "use atom" + CXXFLAGS="$CXXFLAGS -march=prescott" + fi ]) + + dnl + dnl checking ppc7400 + dnl + AC_ARG_WITH(ppc7400,[ --with-ppc7400 (use PowerPC7400)], + [ if test "$withval" != "no"; then + echo "use ppc7400" + CXXFLAGS="$CXXFLAGS -mcpu=7400 -maltivec -mabi=altivec" + fi ]) + + dnl + dnl checking ppc7450 + dnl + AC_ARG_WITH(ppc7450,[ --with-ppc7450 (use PowerPC7450)], + [ if test "$withval" != "no"; then + echo "use ppc7450" + CXXFLAGS="$CXXFLAGS -mcpu=7450 -maltivec -mabi=altivec" + fi ]) +fi + + +dnl +dnl checking pangolayout +dnl +AC_ARG_WITH(pangolayout,[ --with-pangolayout (use pangolayout)], + [ if test "$withval" != "no" ;then + echo "use pango_layout for drawing" + CXXFLAGS="$CXXFLAGS -DUSE_PANGOLAYOUT" + fi ]) + + +AC_OUTPUT(Makefile src/Makefile src/skeleton/Makefile src/jdlib/Makefile src/dbtree/Makefile src/dbimg/Makefile src/bbslist/Makefile src/board/Makefile src/article/Makefile src/image/Makefile src/message/Makefile src/history/Makefile src/config/Makefile src/icons/Makefile src/sound/Makefile src/xml/Makefile src/control/Makefile ) diff -Nru jd-2.8.5-120826/configure.in jd-2.8.6-130518/configure.in --- jd-2.8.5-120826/configure.in 2012-03-03 05:31:39.000000000 +0000 +++ jd-2.8.6-130518/configure.in 1970-01-01 00:00:00.000000000 +0000 @@ -1,471 +0,0 @@ -dnl -dnl JD用 configure.in -dnl -AC_PREREQ(2.50) -AC_INIT(jd, 1.0) -AM_INIT_AUTOMAKE -AC_CONFIG_HEADERS(config.h) - -AC_ISC_POSIX -AC_PROG_CC -AM_PROG_CC_STDC -AC_HEADER_STDC -AC_PROG_CPP -AC_PROG_CXX -AC_PROG_CXXCPP -AC_PROG_LIBTOOL -AC_LANG_CPLUSPLUS - -dnl -dnl buildinfo.h -dnl -AC_DEFINE(HAVE_BUILDINFO_H, 1, Define to 1 if you have the 'buildinfo.h' header file.) -AC_PATH_PROG(SVN, svn) -AC_PATH_PROG(SVNVERSION, svnversion) -AC_PATH_PROG(XSUM, md5sum, [cksum]) -AC_SUBST(ac_configure_args) - -dnl -dnl OSを判定してOS別の設定 -dnl -case "${host_os}" in - freebsd*) - echo "os = freebsd" - AC_DEFINE(ICONV_CONST, const, "iconv_const") - AC_DEFINE(USE_MKTIME, , "use mktime") - ;; - solaris*) - echo "os = solaris" - AC_DEFINE(ICONV_CONST, const, "iconv_const") - AC_DEFINE(NO_TIMEGM, , "no timegm") - ;; - mingw*) - echo "os = ${host_os}" - AC_DEFINE(ICONV_CONST, , "iconv_const") - AC_DEFINE(USE_MKTIME, , "use mktime") - ;; - darwin*) - echo "os = ${host_os}" - AC_DEFUN([AM_ICONV], []) - AC_DEFINE(ICONV_CONST, , "iconv_const") - AC_DEFINE(USE_MKTIME, , "use mktime") - ;; -dnl linux*|gnu*|*-gnu - *) - echo "os = ${host_os}" - AC_DEFUN([AM_ICONV], []) - AC_DEFINE(ICONV_CONST, , "iconv_const") - ;; -esac - -AM_ICONV - - -dnl --------------------------------------------------- -dnl --------------------------------------------------- -dnl -dnl ユーザー設定 -dnl - -dnl 追加コンパイルオプション -CXXFLAGS="$CXXFLAGS -ggdb -Wall" - -dnl --------------------------------------------------- -dnl --------------------------------------------------- - -LIBSM_CFLAGS="" -LIBSM_LIBS="" -GNOMEUI_CFLAGS="" -GNOMEUI_LIBS="" - -dnl -dnl パッケージのチェック -dnl -PKG_CHECK_MODULES(GTKMM,[gtkmm-2.4 >= 2.4.0], [], []) -PKG_CHECK_MODULES(GTHREAD, [gthread-2.0 >= 2.0] ) - -AC_SUBST(GTKMM_CFLAGS) -AC_SUBST(GTKMM_LIBS) -AC_SUBST(GTHREAD_CFLAGS) -AC_SUBST(GTHREAD_LIBS) - - -dnl -dnl crypt -dnl - -echo "use crypt" -AC_CHECK_HEADERS([crypt.h]) -AC_CHECK_LIB(crypt,crypt) - - -dnl -dnl zlib -dnl - -echo "use zlib" -AC_CHECK_HEADERS([zlib.h]) -AC_CHECK_LIB(z,inflate) - - -dnl -dnl packages dependent on platform -dnl -use_windres="" - -case "${host_os}" in - mingw*) - dnl - dnl winsock2 using model of socket - dnl not available uname on windows - dnl - - echo "use winsock2" - AC_CHECK_HEADERS([winsock2.h]) - AC_CHECK_LIB(ws2_32,_head_libws2_32_a) - - echo "use regex2" - AC_CHECK_HEADERS([regex.h]) - AC_CHECK_LIB(regex,regexec) - - echo "use iconv" - AC_CHECK_HEADERS([iconv.h]) - AC_CHECK_LIB(iconv,_head_libiconv_a) - - echo "use windows resources" - AC_CHECK_TOOL([WINDRES], [windres], [windres]) - AC_SUBST(WINDRES) - AC_DEFINE(USE_WINDRES, , "use windres") - use_windres="yes" - ;; - *) - dnl - dnl any other POSIX systems - dnl - - echo "use uname" - AC_CHECK_HEADERS([sys/utsname.h]) - - echo "use socket" - AC_CHECK_HEADERS([socket.h]) - AC_CHECK_LIB(socket,socket) - ;; -esac - -AM_CONDITIONAL(MAKE_WINDRES, test -n "$use_windres") - - -dnl -dnl X関連ライブラリ -dnl -X11_CFLAGS="" -X11_LIBS="" - -case "${host_os}" in - mingw*) - ;; - *) - PKG_CHECK_MODULES(X11, x11) - AC_SUBST(X11_CFLAGS) - AC_SUBST(X11_LIBS) - ;; -esac - - -dnl -dnl セッション管理 -dnl -dnl -use_xsmp=no -use_gnomeui=no - -AC_ARG_WITH(sessionlib, -[ - --with-sessionlib[[=xsmp/gnomeui/no]] - use session control library [[default=xsmp]] -], -[case "${withval}" in - xsmp) - use_xsmp=yes - ;; - gnomeui) - use_gnomeui=yes - ;; - no) - use_xsmp=no - use_gnomeui=no - ;; - *) - use_xsmp=yes - ;; -esac],use_xsmp=yes) - -dnl -dnl XSMPを使ってセッション管理をする。libSMとlibICEが必要。無ければXSMPは無効になる -dnl -dnl dirsの並びは Tk の configure に書いてあったもの + Fedora 向けにディレクトリを追加 -dnl -if test x"$use_xsmp" = "xyes" ; then - - AC_MSG_CHECKING(for SMlib.h and ICElib.h) - LIBSM_CFLAGS="" - dirs="/usr/unsupported/include /usr/local/include /usr/X386/include /usr/X11R6/include /usr/X11R5/include /usr/include/X11R5 /usr/include/X11R4 /usr/openwin/include /usr/X11/include /usr/sww/include /usr/include" - for i in $dirs ; do - if test -r $i/X11/ICE/ICElib.h -a -r $i/X11/SM/SMlib.h ; then - AC_MSG_RESULT($i) - LIBSM_CFLAGS="-I$i" - break - fi - done - if test -z "$LIBSM_CFLAGS" ; then - AC_MSG_RESULT(could not find SMlib.h and ICElib.h) - fi - - AC_MSG_CHECKING(for libSM and libICE) - LIBSM_LIBS="" - dirs="/usr/unsupported/lib /usr/local/lib /usr/X386/lib /usr/X11R6/lib /usr/X11R5/lib /usr/lib/X11R5 /usr/lib/X11R4 /usr/openwin/lib /usr/X11/lib /usr/sww/X11/lib /usr/lib /usr/X11R6/lib64 /usr/lib64" - for i in $dirs ; do - if test -r $i/libICE.so -a -r $i/libSM.so ; then - AC_MSG_RESULT($i) - LIBSM_LIBS="-L$i -lICE -lSM" - break - fi - done - if test -z "$LIBSM_LIBS" ; then - AC_MSG_RESULT(could not find libSM and libICE.) - fi - - if test -n "$LIBSM_CFLAGS" -a -n "$LIBSM_LIBS" ; then - echo "use XSMP" - AC_SUBST(LIBSM_CFLAGS) - AC_SUBST(LIBSM_LIBS) - CXXFLAGS="$CXXFLAGS -DUSE_XSMP" - fi -fi - -dnl -dnl GNOMEUIを使ってセッション管理をする。libgnomeui-develが必要。 -dnl -if test x"$use_gnomeui" = "xyes" ; then - - PKG_CHECK_MODULES(GNOMEUI, [libgnomeui-2.0 >= 2.0] ) - - echo "use GNOMEUI" - AC_SUBST(GNOMEUI_CFLAGS) - AC_SUBST(GNOMEUI_LIBS) - CXXFLAGS="$CXXFLAGS -DUSE_GNOMEUI" -fi - - -dnl -dnl SSL -dnl - -use_gnutls=yes - -AC_ARG_WITH(openssl,[ --with-openssl (use openssl)], - [ if test "$withval" != "no" ;then - use_gnutls=no - fi ]) - -case "${use_gnutls}" in - yes) - echo "use gnutls" - - PKG_CHECK_MODULES(GNUTLS, [gnutls >= 1.2], [echo "gnutls >= 1.2"]) - AC_DEFINE(USE_GNUTLS, , "use gnutls") - AC_CHECK_HEADERS([gcrypt.h]) - AC_CHECK_LIB(gcrypt, gcry_md_hash_buffer, [GCRYPT_LIBS=-lgcrypt]) - GNUTLS_LIBS="$GNUTLS_LIBS $GCRYPT_LIBS" - AC_SUBST(GNUTLS_CFLAGS) - AC_SUBST(GNUTLS_LIBS) - CXXFLAGS="$CXXFLAGS -DGNUTLSVER=$GNUTLSVER" - ;; - *) - echo "use openssl" - PKG_CHECK_MODULES(OPENSSL, [openssl >= 0.9] ) - AC_DEFINE(USE_OPENSSL, , "use openssl") - AC_SUBST(OPENSSL_CFLAGS) - AC_SUBST(OPENSSL_LIBS) - ;; -esac - - -dnl -dnl enable gprof -dnl - -use_gprof=no - -AC_ARG_ENABLE(gprof,[ --enable-gprof (enable gprof)], - [ if test "$enable_gprof" = "yes"; then - echo "use gprof" - CXXFLAGS="$CXXFLAGS -pg" - use_gprof=yes - fi ]) - -dnl -dnl checking migemo -dnl -AC_ARG_WITH(migemo,[ --with-migemo (enable migemo search)], - [ if test "$withval" != "no" ;then - echo "use migemo" - AC_CHECK_HEADERS([migemo.h]) - AC_CHECK_LIB(migemo,migemo_open) - fi ]) - - -AC_ARG_WITH(migemodict,[ --with-migemodict (specifiy the path of migemo dictionary)], - [ if test "$withval" ;then - echo "migemodict = $withval" - AC_DEFINE_UNQUOTED(MIGEMODICT, "$withval" , "migemodict") - fi ]) - - -dnl -dnl checking xdg-open -dnl -AC_ARG_WITH(xdgopen,[ --with-xdgopen (use xdg-open as default browser)], - [ if test "$withval" ;then - echo "use xdg-open" - AC_DEFINE(XDGOPEN, , "use xdg-open") - fi ]) - - -dnl -dnl checking alsa -dnl -case "${host_os}" in - linux*|*linux) - AC_ARG_WITH(alsa,[ --with-alsa (enable alsa)], - [ if test "$withval" != "no" ;then - echo "use alsa" - PKG_CHECK_MODULES(ALSA, [alsa >= 1.0] ) - AC_DEFINE(USE_ALSA, , "use alsa") - AC_SUBST(ALSA_CFLAGS) - AC_SUBST(ALSA_LIBS) - fi ]) - ;; -esac - - -dnl -dnl checking oniguruma -dnl -AC_ARG_WITH(oniguruma,[ --with-oniguruma (enable oniguruma)], - [ if test "$withval" != "no" ;then - echo "use oniguruma" - AC_CHECK_PROG(ONIG_CONFIG, onig-config, onig-config) - if test "x${ONIG_CONFIG}" = "x" ; then - AC_MSG_ERROR([onig-config not found]) - fi - ONIG_CFLAGS=`onig-config --cflags` - CPPFLAGS="${CPPFLAGS} ${ONIG_CFLAGS}" - ONIG_LIBS=`onig-config --libs` - LDFLAGS_ORIGINAL="${LDFLAGS}" - LDFLAGS="${LDFLAGS} ${ONIG_LIBS}" - AC_CHECK_HEADER([onigposix.h], ,[AC_MSG_ERROR([onigposix.h not found])]) - AC_CHECK_LIB([onig],[regexec], ,[AC_MSG_ERROR([libonig.a not found])]) - AC_DEFINE(USE_ONIG, , "use oniguruma") - AC_SUBST(ONIG_LIBS) - LDFLAGS="${LDFLAGS_ORIGINAL}" - fi ]) - - -dnl -dnl checking PCRE -dnl -AC_ARG_WITH(pcre,[ --with-pcre (enable PCRE)], - [ if test "$withval" != "no" ;then - echo "use PCRE" - PKG_CHECK_MODULES(PCRE, [libpcre >= 6.5] ) - AC_DEFINE(USE_PCRE, , "use PCRE") - AC_SUBST(PCRE_CFLAGS) - AC_SUBST(PCRE_LIBS) - AC_CHECK_HEADERS([pcreposix.h]) - AC_CHECK_LIB(pcreposix,regexec) - fi ]) - - -dnl -dnl checking gthread -dnl -AC_ARG_WITH(gthread,[ --with-gthread (use gthread instead of pthread)], - [ if test "$withval" ;then - echo "use gthread" - AC_DEFINE(USE_GTHREAD, , "use gthread") - fi ]) - - -dnl -dnl CPU別の最適化オプション -dnl -if test "$use_gprof" = "no"; then - - dnl - dnl checking native (gcc >= 4.2 x86 & x86_64) - dnl - AC_ARG_WITH(native,[ --with-native (use native)], - [ if test "$withval" != "no"; then - echo "use native" - CXXFLAGS="$CXXFLAGS -march=native" - fi ]) - - dnl - dnl checking core2duo - dnl - AC_ARG_WITH(core2duo,[ --with-core2duo (use core2duo)], - [ if test "$withval" != "no"; then - echo "use core2duo" - CXXFLAGS="$CXXFLAGS -march=pentium-m -msse3" - fi ]) - - dnl - dnl checking athlon64 - dnl - AC_ARG_WITH(athlon64,[ --with-athlon64 (use athlon64)], - [ if test "$withval" != "no"; then - echo "use athlon64" - CXXFLAGS="$CXXFLAGS -march=athlon64" - fi ]) - - dnl - dnl checking atom - dnl - AC_ARG_WITH(atom,[ --with-atom (use atom)], - [ if test "$withval" != "no"; then - echo "use atom" - CXXFLAGS="$CXXFLAGS -march=prescott" - fi ]) - - dnl - dnl checking ppc7400 - dnl - AC_ARG_WITH(ppc7400,[ --with-ppc7400 (use PowerPC7400)], - [ if test "$withval" != "no"; then - echo "use ppc7400" - CXXFLAGS="$CXXFLAGS -mcpu=7400 -maltivec -mabi=altivec" - fi ]) - - dnl - dnl checking ppc7450 - dnl - AC_ARG_WITH(ppc7450,[ --with-ppc7450 (use PowerPC7450)], - [ if test "$withval" != "no"; then - echo "use ppc7450" - CXXFLAGS="$CXXFLAGS -mcpu=7450 -maltivec -mabi=altivec" - fi ]) -fi - - -dnl -dnl checking pangolayout -dnl -AC_ARG_WITH(pangolayout,[ --with-pangolayout (use pangolayout)], - [ if test "$withval" != "no" ;then - echo "use pango_layout for drawing" - CXXFLAGS="$CXXFLAGS -DUSE_PANGOLAYOUT" - fi ]) - - -AC_OUTPUT(Makefile src/Makefile src/skeleton/Makefile src/jdlib/Makefile src/dbtree/Makefile src/dbimg/Makefile src/bbslist/Makefile src/board/Makefile src/article/Makefile src/image/Makefile src/message/Makefile src/history/Makefile src/config/Makefile src/icons/Makefile src/sound/Makefile src/xml/Makefile src/control/Makefile ) diff -Nru jd-2.8.5-120826/debian/changelog jd-2.8.6-130518/debian/changelog --- jd-2.8.5-120826/debian/changelog 2012-11-29 10:44:48.000000000 +0000 +++ jd-2.8.6-130518/debian/changelog 2013-05-26 12:14:45.000000000 +0000 @@ -1,3 +1,9 @@ +jd (1:2.8.6-130518-0~ppa6) quantal; urgency=low + + * 2.8.6-130518 + + -- Sawa (ikoinoba) Sun, 26 May 2013 21:13:00 +0900 + jd (1:2.8.5-120826-0~ppa6.1) quantal; urgency=low * LIBOVERLAY_SCROLLBAR=0 diff -Nru jd-2.8.5-120826/debian/control jd-2.8.6-130518/debian/control --- jd-2.8.5-120826/debian/control 2012-11-28 16:22:43.000000000 +0000 +++ jd-2.8.6-130518/debian/control 2013-05-26 12:10:28.000000000 +0000 @@ -11,6 +11,6 @@ Package: jd Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, cmigemo-common -Suggests: fonts-konatu | fonts-monapo +Suggests: fonts-monapo | fonts-konatu Description: A 2ch browser JD is a 2ch browser based on gtkmm2. diff -Nru jd-2.8.5-120826/debian/docs jd-2.8.6-130518/debian/docs --- jd-2.8.5-120826/debian/docs 2011-10-03 14:46:04.000000000 +0000 +++ jd-2.8.6-130518/debian/docs 2013-05-26 12:12:28.000000000 +0000 @@ -1 +1,2 @@ README +ChangeLog diff -Nru jd-2.8.5-120826/debian/rules jd-2.8.6-130518/debian/rules --- jd-2.8.5-120826/debian/rules 2012-11-29 10:41:29.000000000 +0000 +++ jd-2.8.6-130518/debian/rules 2013-05-26 12:12:23.000000000 +0000 @@ -1,4 +1,5 @@ #!/usr/bin/make -f + # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 @@ -16,9 +17,6 @@ --with-migemo \ --with-migemodict=/usr/share/cmigemo/utf-8/migemo-dict -override_dh_installchangelogs: - dh_installchangelogs ChangeLog - override_dh_auto_install: dh_auto_install ifeq ($(call compare_ubuntu_version,12.10),y) diff -Nru jd-2.8.5-120826/jd.spec jd-2.8.6-130518/jd.spec --- jd-2.8.5-120826/jd.spec 2012-08-26 09:39:27.000000000 +0000 +++ jd-2.8.6-130518/jd.spec 2013-05-17 16:34:56.000000000 +0000 @@ -9,8 +9,8 @@ ########################################## # Defined by upsteam # -%define main_ver 2.8.5 -%define strtag 120826 +%define main_ver 2.8.6 +%define strtag 130518 %define repoid ????? # Define this if this is pre-version %define pre_release 0 diff -Nru jd-2.8.5-120826/src/Makefile.am jd-2.8.6-130518/src/Makefile.am --- jd-2.8.5-120826/src/Makefile.am 2011-06-02 15:05:53.000000000 +0000 +++ jd-2.8.6-130518/src/Makefile.am 2013-02-17 15:54:24.000000000 +0000 @@ -33,6 +33,7 @@ dndmanager.cpp \ usrcmdmanager.cpp \ linkfiltermanager.cpp \ + urlreplacemanager.cpp \ compmanager.cpp \ searchmanager.cpp \ searchloader.cpp \ @@ -87,6 +88,7 @@ dndmanager.h \ usrcmdmanager.h \ linkfiltermanager.h \ + urlreplacemanager.h \ compmanager.h \ searchmanager.h \ searchloader.h \ diff -Nru jd-2.8.5-120826/src/article/Makefile.am jd-2.8.6-130518/src/article/Makefile.am --- jd-2.8.5-120826/src/article/Makefile.am 2010-05-25 14:56:48.000000000 +0000 +++ jd-2.8.6-130518/src/article/Makefile.am 2013-01-05 15:44:26.000000000 +0000 @@ -51,4 +51,4 @@ toolbarsearch.h AM_CXXFLAGS = @GTKMM_CFLAGS@ -INCLUDES = -I$(top_srcdir)/src +AM_CPPFLAGS = -I$(top_srcdir)/src diff -Nru jd-2.8.5-120826/src/article/articleview.cpp jd-2.8.6-130518/src/article/articleview.cpp --- jd-2.8.5-120826/src/article/articleview.cpp 2011-02-27 16:15:26.000000000 +0000 +++ jd-2.8.6-130518/src/article/articleview.cpp 2012-12-09 18:35:41.000000000 +0000 @@ -545,7 +545,15 @@ set_autoreload_sec( MAX( live_sec, get_autoreload_sec() - LIVE_SEC_PLUS ) ); // messageビューが出ているときはフォーカスを移す - if( ! MESSAGE::get_admin()->empty() ) CORE::core_set_command( "switch_message" ); + if( ! MESSAGE::get_admin()->empty() ){ + // 実況モードかつポップアップが表示されている状態で、 "switch_message" コマンドを発行すると、 + // 埋め込みメッセージモードだと、 MessageAdmin に対して "focus_current_view" されるので、 + // ArticleView に focus_out イベントが発生して、ポップアップが消えてしまう + // ポップアップが表示されているときは、フォーカスを移さない + if( ! is_popup_shown() ){ + CORE::core_set_command( "switch_message" ); + } + } } drawarea()->update_live_speed( get_autoreload_sec() ); diff -Nru jd-2.8.5-120826/src/article/articleviewbase.cpp jd-2.8.6-130518/src/article/articleviewbase.cpp --- jd-2.8.5-120826/src/article/articleviewbase.cpp 2012-08-03 14:40:00.000000000 +0000 +++ jd-2.8.6-130518/src/article/articleviewbase.cpp 2013-02-10 10:03:10.000000000 +0000 @@ -193,22 +193,23 @@ action_group().clear(); action_group() = Gtk::ActionGroup::create(); action_group()->add( Gtk::Action::create( "BookMark", "しおりを設定/解除(_B)"), sigc::mem_fun( *this, &ArticleViewBase::slot_bookmark ) ); - action_group()->add( Gtk::Action::create( "OpenBrowser", ITEM_NAME_OPEN_BROWSER + std::string( "(_W)" ) ), + action_group()->add( Gtk::Action::create( "PostedMark", "書き込みマークを設定/解除(_P)"), sigc::mem_fun( *this, &ArticleViewBase::slot_postedmark ) ); + action_group()->add( Gtk::Action::create( "OpenBrowser", ITEM_NAME_OPEN_BROWSER "(_W)" ), sigc::mem_fun( *this, &ArticleViewBase::slot_open_browser ) ); - action_group()->add( Gtk::Action::create( "OpenBrowserRes", ITEM_NAME_OPEN_BROWSER + std::string( "(_S)" ) ), // レスをクリックした時のメニュー用 + action_group()->add( Gtk::Action::create( "OpenBrowserRes", ITEM_NAME_OPEN_BROWSER "(_S)" ), // レスをクリックした時のメニュー用 sigc::mem_fun( *this, &ArticleViewBase::slot_open_browser ) ); - action_group()->add( Gtk::Action::create( "OpenCacheBrowser", ITEM_NAME_OPEN_CACHE_BROWSER + std::string( "(_X)" ) ), + action_group()->add( Gtk::Action::create( "OpenCacheBrowser", ITEM_NAME_OPEN_CACHE_BROWSER "(_X)" ), sigc::mem_fun( *this, &ArticleViewBase::slot_open_cache_browser ) ); - action_group()->add( Gtk::Action::create( "CopyURL", ITEM_NAME_COPY_URL + std::string( "(_U)" ) ), + action_group()->add( Gtk::Action::create( "CopyURL", ITEM_NAME_COPY_URL "(_U)" ), sigc::mem_fun( *this, &ArticleViewBase::slot_copy_current_url ) ); - action_group()->add( Gtk::Action::create( "CopyTitleURL", ITEM_NAME_COPY_TITLE_URL_THREAD + std::string( "(_L)" ) ), + action_group()->add( Gtk::Action::create( "CopyTitleURL", ITEM_NAME_COPY_TITLE_URL_THREAD "(_L)" ), sigc::mem_fun( *this, &ArticleViewBase::slot_copy_title_url ) ); action_group()->add( Gtk::Action::create( "CopyNAME", "名前コピー(_N)"), sigc::mem_fun( *this, &ArticleViewBase::slot_copy_name ) ); action_group()->add( Gtk::Action::create( "CopyID", "IDコピー(_D)"), sigc::mem_fun( *this, &ArticleViewBase::slot_copy_id ) ); action_group()->add( Gtk::Action::create( "Copy", "Copy"), sigc::mem_fun( *this, &ArticleViewBase::slot_copy_selection_str ) ); action_group()->add( Gtk::Action::create( "WriteRes", "レスする(_W)" ),sigc::mem_fun( *this, &ArticleViewBase::slot_write_res ) ); action_group()->add( Gtk::Action::create( "QuoteRes", "引用してレスする(_Q)"),sigc::mem_fun( *this, &ArticleViewBase::slot_quote_res ) ); - action_group()->add( Gtk::Action::create( "QuoteSelectionRes", ITEM_NAME_QUOTE_SELECTION + std::string( "(_Q)" ) ), + action_group()->add( Gtk::Action::create( "QuoteSelectionRes", ITEM_NAME_QUOTE_SELECTION "(_Q)" ), sigc::mem_fun( *this, &ArticleViewBase::slot_quote_selection_res ) ); action_group()->add( Gtk::Action::create( "CopyRes", "レスをコピー(_R)"), sigc::bind< bool >( sigc::mem_fun( *this, &ArticleViewBase::slot_copy_res ), false ) ); @@ -219,12 +220,11 @@ action_group()->add( Gtk::Action::create( "DeleteOpen", "スレ情報を消さずにスレ再取得(_R)"), sigc::mem_fun( *this, &ArticleViewBase::delete_open_view ) ); action_group()->add( Gtk::Action::create( "AppendFavorite", "AppendFavorite"), sigc::mem_fun( *this, &ArticleViewBase::set_favorite ) ); action_group()->add( Gtk::Action::create( "Reload", "Reload"), sigc::mem_fun( *this, &ArticleViewBase::exec_reload ) ); - action_group()->add( Gtk::Action::create( "PreferenceArticle", ITEM_NAME_PREF_THREAD + std::string( "(_P)..." ) ), - sigc::mem_fun( *this, &ArticleViewBase::show_preference ) ); - action_group()->add( Gtk::Action::create( "PreferenceImage", "画像のプロパティ(_M)..."), sigc::mem_fun( *this, &ArticleViewBase::slot_preferences_image ) ); + action_group()->add( Gtk::Action::create( "PreferenceArticle", "PreferenceArticle" ), sigc::mem_fun( *this, &ArticleViewBase::show_preference ) ); + action_group()->add( Gtk::Action::create( "PreferenceImage", ITEM_NAME_PREF_IMAGE "(_M)..." ), sigc::mem_fun( *this, &ArticleViewBase::slot_preferences_image ) ); // 検索 - action_group()->add( Gtk::Action::create( "Search_Menu", ITEM_NAME_SEARCH + std::string( "(_H)" ) ) ); + action_group()->add( Gtk::Action::create( "Search_Menu", ITEM_NAME_SEARCH "(_H)" ) ); action_group()->add( Gtk::Action::create( "SearchNextArticle", "SearchNextArticle"), sigc::mem_fun( *this, &ArticleViewBase::slot_search_next ) ); action_group()->add( Gtk::Action::create( "SearchWeb", "SearchWeb" ), sigc::mem_fun( *this, &ArticleViewBase::slot_search_web ) ); action_group()->add( Gtk::Action::create( "SearchCacheLocal", "SearchCacheLocal" ), sigc::mem_fun( *this, &ArticleViewBase::slot_search_cachelocal ) ); @@ -233,7 +233,7 @@ action_group()->add( Gtk::Action::create( "SearchTitle", "SearchTitle" ), sigc::mem_fun( *this, &ArticleViewBase::slot_search_title ) ); // 抽出系 - action_group()->add( Gtk::Action::create( "Drawout_Menu", ITEM_NAME_DRAWOUT + std::string( "(_E)" ) ) ); + action_group()->add( Gtk::Action::create( "Drawout_Menu", ITEM_NAME_DRAWOUT "(_E)" ) ); action_group()->add( Gtk::Action::create( "DrawoutWord", "キーワード抽出(_K)"), sigc::mem_fun( *this, &ArticleViewBase::slot_drawout_selection_str ) ); action_group()->add( Gtk::Action::create( "DrawoutRes", "レス抽出(_R)"), sigc::mem_fun( *this, &ArticleViewBase::slot_drawout_res ) ); action_group()->add( Gtk::Action::create( "DrawoutNAME", "名前抽出(_E)"), sigc::mem_fun( *this, &ArticleViewBase::slot_drawout_name ) ); @@ -246,9 +246,9 @@ action_group()->add( Gtk::Action::create( "DrawoutTmp", "テンプレート抽出(_T)"), sigc::mem_fun( *this, &ArticleViewBase::slot_drawout_tmp ) ); // あぼーん系 - action_group()->add( Gtk::Action::create( "AboneWord_Menu", ITEM_NAME_NGWORD + std::string( "(_N)" ) ) ); + action_group()->add( Gtk::Action::create( "AboneWord_Menu", ITEM_NAME_NGWORD "(_N)" ) ); action_group()->add( Gtk::Action::create( "AboneRes", "レスをあぼ〜んする(_A)"), sigc::mem_fun( *this, &ArticleViewBase::slot_abone_res ) ); - action_group()->add( Gtk::Action::create( "AboneSelectionRes", ITEM_NAME_ABONE_SELECTION + std::string( "(_A)") ), + action_group()->add( Gtk::Action::create( "AboneSelectionRes", "AboneSelectionRes" ), sigc::mem_fun( *this, &ArticleViewBase::slot_abone_selection_res ) ); action_group()->add( Gtk::Action::create( "AboneID", "NG IDに追加(_G)"), sigc::mem_fun( *this, &ArticleViewBase::slot_abone_id ) ); action_group()->add( Gtk::Action::create( "AboneName", "NG 名前に追加 (対象: ローカル)(_L)"), sigc::mem_fun( *this, &ArticleViewBase::slot_abone_name ) ); @@ -274,7 +274,7 @@ action_group()->add( Gtk::Action::create( "SetupAboneAll", "あぼ〜ん設定(対象: 全体)(_A)..." ), sigc::mem_fun( *this, &ArticleViewBase::slot_setup_abone_all ) ); // 移動系 - action_group()->add( Gtk::Action::create( "Move_Menu", ITEM_NAME_GO + std::string( "(_M)" ) ) ); + action_group()->add( Gtk::Action::create( "Move_Menu", ITEM_NAME_GO "(_M)" ) ); action_group()->add( Gtk::Action::create( "Home", "Home"), sigc::mem_fun( *this, &ArticleViewBase::goto_top ) ); action_group()->add( Gtk::Action::create( "GotoNew", "GotoNew"), sigc::mem_fun( *this, &ArticleViewBase::goto_new ) ); action_group()->add( Gtk::Action::create( "End", "End"), sigc::mem_fun( *this, &ArticleViewBase::goto_bottom ) ); @@ -291,12 +291,12 @@ // 画像系 action_group()->add( Gtk::Action::create( "Cancel_Mosaic", "モザイク解除(_C)"), sigc::mem_fun( *this, &ArticleViewBase::slot_cancel_mosaic ) ); action_group()->add( Gtk::Action::create( "Show_Mosaic", "モザイクで開く(_M)"), sigc::mem_fun( *this, &ArticleViewBase::slot_show_image_with_mosaic ) ); - action_group()->add( Gtk::Action::create( "Show_SelectImg", ITEM_NAME_SELECTIMG + std::string( "(_G)" ) ) + action_group()->add( Gtk::Action::create( "ShowSelectImage", "ShowSelectImage" ) , sigc::mem_fun( *this, &ArticleViewBase::slot_show_selection_images ) ); - action_group()->add( Gtk::Action::create( "DeleteSelectImage_Menu", ITEM_NAME_SELECTDELIMG + std::string( "(_T)" ) ) ); - action_group()->add( Gtk::Action::create( "DeleteSelectImage", "削除する(_D)"), sigc::mem_fun( *this, &ArticleViewBase::slot_delete_selection_images ) ); - action_group()->add( Gtk::Action::create( "AboneSelectImage_Menu", ITEM_NAME_SELECTABONEIMG + std::string( "(_B)" ) ) ); - action_group()->add( Gtk::Action::create( "AboneSelectImage", "あぼ〜んする(_A)"), sigc::mem_fun( *this, &ArticleViewBase::slot_abone_selection_images ) ); + action_group()->add( Gtk::Action::create( "DeleteSelectImage_Menu", ITEM_NAME_SELECTDELIMG "(_T)" ) ); + action_group()->add( Gtk::Action::create( "DeleteSelectImage", "DeleteSelectImage"), sigc::mem_fun( *this, &ArticleViewBase::slot_delete_selection_images ) ); + action_group()->add( Gtk::Action::create( "AboneSelectImage_Menu", ITEM_NAME_SELECTABONEIMG "(_B)" ) ); + action_group()->add( Gtk::Action::create( "AboneSelectImage", "AboneSelectImage"), sigc::mem_fun( *this, &ArticleViewBase::slot_abone_selection_images ) ); action_group()->add( Gtk::Action::create( "ShowLargeImg", "サイズが大きい画像を表示(_L)"), sigc::mem_fun( *this, &ArticleViewBase::slot_show_large_img ) ); action_group()->add( Gtk::ToggleAction::create( "ProtectImage", "キャッシュを保護する(_P)", std::string(), false ), @@ -308,9 +308,9 @@ sigc::mem_fun( *this, &ArticleViewBase::slot_abone_img ) ); // その他 - action_group()->add( Gtk::Action::create( "Etc_Menu", ITEM_NAME_ETC + std::string( "(_O)" ) ) ); - action_group()->add( Gtk::Action::create( "SaveDat", ITEM_NAME_SAVE_DAT + std::string( "(_D)..." ) ), sigc::mem_fun( *this, &ArticleViewBase::slot_save_dat ) ); - action_group()->add( Gtk::Action::create( "CopyInfo", ITEM_NAME_COPY_THREAD_INFO + std::string( "(_I)..." ) ), + action_group()->add( Gtk::Action::create( "Etc_Menu", ITEM_NAME_ETC "(_O)" ) ); + action_group()->add( Gtk::Action::create( "SaveDat", "SaveDat" ), sigc::mem_fun( *this, &ArticleViewBase::slot_save_dat ) ); + action_group()->add( Gtk::Action::create( "CopyInfo", ITEM_NAME_COPY_THREAD_INFO "(_I)..." ), sigc::mem_fun( *this, &ArticleViewBase::slot_copy_article_info ) ); m_usrcmd = CORE::get_usrcmd_manager()->create_usrcmd_menu( action_group() ); @@ -343,6 +343,7 @@ const std::string menu_res = "" "" + "" "" "" @@ -651,7 +652,7 @@ // 選択範囲の画像を開く case ITEM_SELECTIMG: - return ""; + return ""; // 選択範囲の画像を削除 case ITEM_SELECTDELIMG: @@ -813,7 +814,7 @@ } // ポップアップが出てたらそっちにクロックを回す - else if( is_popup_shown() && m_popup_win->view() ){ + if( is_popup_shown() && m_popup_win->view() ){ m_popup_win->view()->clock_in(); return; } @@ -1106,6 +1107,11 @@ up_search(); break; + // datを保存 + case CONTROL::Save: + slot_save_dat(); + break; + // 閉じる case CONTROL::Quit: close_view(); @@ -1227,6 +1233,31 @@ slot_search_cacheall(); break; + // 選択範囲の画像を開く + case CONTROL::ShowSelectImage: + slot_show_selection_images(); + break; + + // 選択範囲の画像を削除 + case CONTROL::DeleteSelectImage: + slot_delete_selection_images(); + break; + + // 選択範囲の画像をあぼ〜ん + case CONTROL::AboneSelectImage: + slot_abone_selection_images(); + break; + + // 選択範囲のレスをあぼ〜ん + case CONTROL::AboneSelectionRes: + slot_abone_selection_res(); + break; + + // スレのプロパティ + case CONTROL::PreferenceView: + show_preference(); + break; + default: return false; } @@ -3049,7 +3080,7 @@ else act->set_sensitive( true ); } - act = action_group()->get_action( "Show_SelectImg" ); + act = action_group()->get_action( "ShowSelectImage" ); if( act ){ if( str_select.empty() || ! m_drawarea->get_selection_imgurls().size() ) act->set_sensitive( false ); else act->set_sensitive( true ); @@ -3487,6 +3518,24 @@ // +// 書き込みマーク設定、解除 +// +// 呼び出す前に m_str_num に対象のレス番号を入れておくこと +// +void ArticleViewBase::slot_postedmark() +{ + if( m_str_num.empty() ) return; + + int number = atoi( m_str_num.c_str() ); + bool postedmark = ! m_article->is_posted( number ); + m_article->set_posted( number, postedmark ); + redraw_view(); + ARTICLE::get_admin()->set_command( "redraw_views", m_url_article ); +} + + + +// // ポップアップメニューでブラウザで開くを選択 // void ArticleViewBase::slot_open_browser() @@ -4041,7 +4090,9 @@ for( ; it != m_drawarea->get_selection_imgurls().end(); ++it ){ const std::string& url = (*it).url; - if( DBIMG::is_cached( url ) ) CORE::core_set_command( "delete_image", url ); + if( ! DBIMG::is_protected( url ) ){ + CORE::core_set_command( "delete_image", url ); + } } redraw_view(); @@ -4064,8 +4115,10 @@ for( ; it != m_drawarea->get_selection_imgurls().end(); ++it ){ const std::string& url = (*it).url; - DBIMG::set_abone( url, true ); - CORE::core_set_command( "delete_image", url ); + if( ! DBIMG::is_protected( url ) ){ + DBIMG::set_abone( url, true ); + CORE::core_set_command( "delete_image", url ); + } } redraw_view(); diff -Nru jd-2.8.5-120826/src/article/articleviewbase.h jd-2.8.6-130518/src/article/articleviewbase.h --- jd-2.8.5-120826/src/article/articleviewbase.h 2011-07-27 15:53:11.000000000 +0000 +++ jd-2.8.6-130518/src/article/articleviewbase.h 2012-12-09 18:35:41.000000000 +0000 @@ -170,6 +170,9 @@ // レスポップアップを隠す void hide_popup( const bool force = false ); + // ポップアップが表示されているか + const bool is_popup_shown() const; + // 初期設定 void setup_view(); @@ -265,9 +268,6 @@ // レスポップアップ関係 - // ポップアップが表示されているか - const bool is_popup_shown() const; - // ポップアップが表示されていてかつマウスがその上にあるか const bool is_mouse_on_popup(); @@ -278,6 +278,7 @@ void warp_pointer_to_popup(); // マウスポインタをポップアップの上に移動する void slot_bookmark(); + void slot_postedmark(); void slot_open_browser(); void slot_open_cache_browser(); void slot_write_res(); diff -Nru jd-2.8.5-120826/src/article/drawareabase.cpp jd-2.8.6-130518/src/article/drawareabase.cpp --- jd-2.8.5-120826/src/article/drawareabase.cpp 2012-08-03 14:40:00.000000000 +0000 +++ jd-2.8.6-130518/src/article/drawareabase.cpp 2013-03-09 12:18:26.000000000 +0000 @@ -99,6 +99,7 @@ , m_draw_frame( false ) , m_back_frame( NULL ) , m_ready_back_frame( false ) + , m_strict_of_char( false ) , m_configure_reserve( false ) , m_configure_width( 0 ) , m_configure_height( 0 ) @@ -331,37 +332,63 @@ // void DrawAreaBase::init_font() { - std::string fontname = CONFIG::get_fontname( get_fontid() ); - - if( fontname.empty() ) return; + // スレビューで文字幅の近似を厳密にするか + m_strict_of_char = CONFIG::get_strict_char_width(); m_context = get_pango_context(); assert( m_context ); + std::string fontname = CONFIG::get_fontname( m_defaultfontid ); + if( fontname.empty() ) return; + + init_fontinfo( m_defaultfont, fontname ); + + std::string aafontname = CONFIG::get_fontname( FONT_AA ); + if( aafontname.empty() ) aafontname = fontname; + + init_fontinfo( m_aafont, aafontname ); + +#ifdef _DEBUG + std::cout << "DrawAreaBase::aa_fontname = " << aafontname << std::endl; +#endif + + // layoutにフォントをセット + m_font = &m_defaultfont; + m_pango_layout->set_font_description( m_font->pfd ); + modify_font( m_font->pfd ); +} + + +// +// フォント情報初期化 +// +void DrawAreaBase::init_fontinfo( FONTINFO& fi, std::string& fontname ) +{ + fi.fontname = fontname; + // layoutにフォントをセット - Pango::FontDescription pfd( fontname ); - pfd.set_weight( Pango::WEIGHT_NORMAL ); - m_pango_layout->set_font_description( pfd ); - modify_font( pfd ); + fi.pfd = Pango::FontDescription( fontname ); + fi.pfd.set_weight( Pango::WEIGHT_NORMAL ); + m_pango_layout->set_font_description( fi.pfd ); // フォント情報取得 - Pango::FontMetrics metrics = m_context->get_metrics( pfd ); - m_font_ascent = PANGO_PIXELS( metrics.get_ascent() ); - m_font_descent = PANGO_PIXELS( metrics.get_descent() ); - m_font_height = m_font_ascent + m_font_descent; + Pango::FontMetrics metrics = m_context->get_metrics( fi.pfd ); + fi.ascent = PANGO_PIXELS( metrics.get_ascent() ); + fi.descent = PANGO_PIXELS( metrics.get_descent() ); + fi.height = fi.ascent + fi.descent; // 改行高さ ( トップからの距離 ) - m_br_size = ( int )( m_font_height * CONFIG::get_adjust_line_space() ); + fi.br_size = ( int )( fi.height * CONFIG::get_adjust_line_space() ); const char* wstr = "あいうえお"; m_pango_layout->set_text( wstr ); // リンクの下線の位置 ( トップからの距離 ) #if GTKMM_CHECK_VERSION(2,5,0) - m_underline_pos = PANGO_PIXELS( ( metrics.get_ascent() - metrics.get_underline_position() ) + fi.underline_pos = PANGO_PIXELS( ( metrics.get_ascent() - metrics.get_underline_position() ) * CONFIG::get_adjust_underline_pos() ); #else - m_underline_pos = int( ( m_pango_layout->get_pixel_logical_extents().get_height() ) + fi.underline_pos = int( ( m_pango_layout->get_pixel_logical_extents().get_height() ) * CONFIG::get_adjust_underline_pos() ); #endif @@ -369,7 +396,7 @@ // マージン幅は真面目にやると大変そうなので文字列 wstr の平均を取る int width = m_pango_layout->get_pixel_ink_extents().get_width() / 5; - m_mrg_right = width /2 * 3; + fi.mrg_right = width /2 * 3; } @@ -823,9 +850,12 @@ int x, y = 0; LAYOUT* header = m_layout_tree->top_header(); - CORE::get_css_manager()->set_size( &m_css_body, m_font_height ); + // フォント設定 + set_node_font( header ); + + CORE::get_css_manager()->set_size( &m_css_body, m_font->height ); - y += offset_y * m_br_size; + y += offset_y * m_font->br_size; y += m_css_body.padding_top; while( header ){ @@ -833,9 +863,12 @@ LAYOUT* layout = header->next_layout; if( ! layout ) break; + // フォント設定 + set_node_font( header ); + // (注) header は div ノードであり、クラス名は "res" // 詳しくは LayoutTree::create_layout_header() を参照せよ - CORE::get_css_manager()->set_size( header->css, m_font_height ); + CORE::get_css_manager()->set_size( header->css, m_font->height ); // div の位置と幅を計算 // 高さは子ノードのレイアウトが全て済んでから計算 @@ -853,11 +886,14 @@ y += header->css->padding_top; LAYOUT* current_div = NULL; - int br_size = m_br_size; // 現在行の改行サイズ + int br_size = m_font->br_size; // 現在行の改行サイズ // 先頭の子ノードから順にレイアウトしていく while ( layout ){ + // フォント設定 + set_node_font( layout ); + switch( layout->type ){ // div (注) div の中に div は作れない仕様になっている( header は除く ) @@ -880,7 +916,7 @@ // div の位置と幅を計算 // 高さは違う div に切り替わった時に計算 - CORE::get_css_manager()->set_size( current_div->css, m_font_height ); + CORE::get_css_manager()->set_size( current_div->css, m_font->height ); x = header->rect->x + header->css->padding_left; x += current_div->css->mrg_left; y += current_div->css->mrg_top; @@ -930,9 +966,9 @@ y += EIMG_MRG; layout_one_img_node( layout, x, y, br_size, m_width_client, is_popup, 0 ); - if( layout->rect->height > m_br_size ){ + if( layout->rect->height > m_font->br_size ){ - br_size = m_br_size; + br_size = m_font->br_size; y += layout->rect->height - br_size; } @@ -969,7 +1005,7 @@ ////////////////////////////////////////// case DBTREE::NODE_HTAB: // 水平タブ - x += m_font_height * SPACE_TAB; + x += m_font->height * SPACE_TAB; break; } @@ -982,7 +1018,7 @@ // divの中なら右スペースの分も足す if( layout->div ) width_tmp += ( layout->div->css->padding_right + layout->div->css->mrg_right ); - width_tmp += m_mrg_right + m_css_body.padding_right; + width_tmp += m_font->mrg_right + m_css_body.padding_right; if( width_tmp > width_view ) width_tmp = width_view; width_tmp += width_base_vscrbar; @@ -1059,7 +1095,7 @@ adjust->set_lower( 0 ); adjust->set_upper( m_height_client ); adjust->set_page_size( height_view ); - adjust->set_step_increment( m_br_size ); + adjust->set_step_increment( m_font->br_size ); adjust->set_page_increment( height_view / 2 ); m_cancel_change_adjust = true; @@ -1196,7 +1232,7 @@ int border = 0; if( div ) border = div->rect->x + div->rect->width - div->css->padding_right; else border = width_view; - border -= m_mrg_right; + border -= m_font->mrg_right; // 先頭の RECTANGLE型のメモリ確保 // wrapが起きたらまたRECTANGLE型のメモリを確保してリストの後ろに繋ぐ @@ -1247,7 +1283,7 @@ } // 座標情報更新 - br_size = m_br_size; + br_size = m_font->br_size; rect->end = true; rect->x = x; rect->y = y; @@ -1328,7 +1364,7 @@ x = 0; if( div ) x = div->rect->x + div->css->padding_left; y += br_size; - br_size = m_br_size; + br_size = m_font->br_size; rect->x = x; rect->y = y; @@ -1345,7 +1381,7 @@ // bool DrawAreaBase::set_init_wide_mode( const char* str, const int pos_start, const int pos_to ) { - if( ! CONFIG::get_strict_char_width() ) return false; + if( ! m_strict_of_char ) return false; bool wide_mode = true; int i = pos_start; @@ -1389,9 +1425,7 @@ // キャッシュに無かったら幅を調べてキャッシュに登録 if( ! ARTICLE::get_width_of_char( utfstr, byte, pre_char, width, width_wide, mode ) ){ - char tmpchar[ 64 ]; - memcpy( tmpchar, utfstr, byte ); - tmpchar[ byte ] = '\0'; + const std::string tmpchar( utfstr, byte ); #ifdef _DEBUG std::cout << "no cache [" << tmpchar << "] " << byte <<" byte "; @@ -1400,7 +1434,7 @@ #endif // 厳密な幅計算をしない場合 - if( ! CONFIG::get_strict_char_width() ){ + if( ! m_strict_of_char ){ m_pango_layout->set_text( tmpchar ); width = width_wide = m_pango_layout->get_logical_extents().get_width(); @@ -1412,7 +1446,7 @@ // 全角モードでの幅 if( ! width_wide ){ - std::string str_dummy = "ぁ"; + const std::string str_dummy( "ぁ" ); m_pango_layout->set_text( str_dummy + str_dummy ); int width_dummy = m_pango_layout->get_logical_extents().get_width() / 2; @@ -1426,14 +1460,14 @@ // 半角モードではひとつ前の文字によって幅が変わることに注意する if( ! width ){ - char char_dummy[ 8 ] = "a"; + std::string char_dummy( "a" ); if( pre_char && IS_ALPHABET( pre_char ) ) char_dummy[ 0 ] = pre_char; - std::string str_dummy = std::string( char_dummy ) + char_dummy; + const std::string str_dummy( char_dummy + char_dummy ); m_pango_layout->set_text( str_dummy ); int width_dummy = m_pango_layout->get_logical_extents().get_width() / 2; - std::string str_tmp = char_dummy + std::string( tmpchar ); + const std::string str_tmp( char_dummy + tmpchar ); m_pango_layout->set_text( str_tmp ); width = m_pango_layout->get_logical_extents().get_width() - width_dummy; @@ -1452,7 +1486,7 @@ if( width_wide <= 0 ){ int byte_tmp; - const unsigned int code = MISC::utf8toucs2( tmpchar, byte_tmp ); + const unsigned int code = MISC::utf8toucs2( tmpchar.c_str(), byte_tmp ); std::stringstream ss_err; ss_err << "unknown font byte = " << byte_tmp << " ucs2 = " << code << " width = " << width; @@ -1476,7 +1510,7 @@ int ret = 0; // 厳密に計算しない場合 - if( ! CONFIG::get_strict_char_width() ) ret = width_wide; + if( ! m_strict_of_char ) ret = width_wide; else{ @@ -1508,34 +1542,6 @@ // -// 文字列を wrap するか判定する関数 -// -// str != NULL なら禁則処理も考える -// -bool DrawAreaBase::is_wrapped( const int x, const int border, const char* str ) -{ - const unsigned char* tmpchar = ( const unsigned char* ) str; - - if( x < border - - // 禁則文字 - || ( tmpchar && tmpchar[ 0 ] == ',' ) - - || ( tmpchar && tmpchar[ 0 ] == '.' ) - - // UTF-8で"。" - || ( tmpchar && tmpchar[ 0 ] == 0xe3 && tmpchar[ 1 ] == 0x80 && tmpchar[ 2 ] == 0x82 ) - - // UTF-8で"、" - || ( tmpchar && tmpchar[ 0 ] == 0xe3 && tmpchar[ 1 ] == 0x80 && tmpchar[ 2 ] == 0x81 ) - - ) return false; - - return true; -} - - -// // スクリーン描画 // // y から height の高さ分だけ描画する @@ -1703,7 +1709,8 @@ while( ! m_layout_tree->get_header_of_res_const( num ) && num-- > 0 ); lastheader = m_layout_tree->get_header_of_res_const( num ); } - if( lastheader && lastheader->rect->y + lastheader->rect->height/2 < pos_y + height_view ){ + if( lastheader && lastheader->rect + && lastheader->rect->y + lastheader->rect->height/2 < pos_y + height_view ){ m_seen_current = m_layout_tree->max_res_number(); } @@ -1759,12 +1766,15 @@ bool relayout = false; while( header && header->rect->y < pos_y + height_view ){ + // フォント設定 + set_node_font( header ); + // 現在みているレス番号取得 if( ! m_seen_current ){ if( ! header->next_header // 最後のレス - || ( header->next_header->rect->y >= ( pos_y + m_br_size ) // 改行分下にずらす - && header->rect->y <= ( pos_y + m_br_size ) ) ){ + || ( header->next_header->rect->y >= ( pos_y + m_font->br_size ) // 改行分下にずらす + && header->rect->y <= ( pos_y + m_font->br_size ) ) ){ m_seen_current = header->res_number; } @@ -1777,6 +1787,9 @@ LAYOUT* layout = header; while ( layout ){ + // フォント設定 + set_node_font( layout ); + RECTANGLE* rect = layout->rect; while( rect ){ @@ -1992,7 +2005,7 @@ if( ! m_pixbuf_bkmk ) m_pixbuf_bkmk = ICON::get_icon( ICON::BKMARK_THREAD ); const int height_bkmk = m_pixbuf_bkmk->get_height(); - y += ( m_font_height - height_bkmk ) / 2; + y += ( m_font->height - height_bkmk ) / 2; const int s_top = MAX( 0, upper - y ); const int s_bottom = MIN( height_bkmk, lower - y ); @@ -2012,7 +2025,7 @@ if( ! m_pixbuf_post ) m_pixbuf_post = ICON::get_icon( ICON::POST ); const int height_post = m_pixbuf_post->get_height(); - if( y == y_org ) y += ( m_font_height - height_post ) / 2; + if( y == y_org ) y += ( m_font->height - height_post ) / 2; const int s_top = MAX( 0, upper - y ); const int s_bottom = MIN( height_post, lower - y ); @@ -2030,7 +2043,7 @@ if( ! m_pixbuf_refer_post ) m_pixbuf_refer_post = ICON::get_icon( ICON::POST_REFER ); const int height_refer_post = m_pixbuf_refer_post->get_height(); - if( y == y_org ) y += ( m_font_height - height_refer_post ) / 2; + if( y == y_org ) y += ( m_font->height - height_refer_post ) / 2; const int s_top = MAX( 0, upper - y ); const int s_bottom = MIN( height_refer_post, lower - y ); @@ -2303,6 +2316,50 @@ // +// ノードのフォント設定 +// +void DrawAreaBase::set_node_font( LAYOUT* layout ) +{ + char layout_fontid; + if( ! layout->node ) return; + + // フォント設定 + switch( layout->node->fontid ){ + case FONT_AA: + layout_fontid = layout->node->fontid; + break; + case FONT_EMPTY: // フォントID未決定 + case FONT_DEFAULT: + default: + layout_fontid = m_defaultfontid; // デフォルトフォント情報 + break; + } + + if( m_fontid != layout_fontid ){ + m_fontid = layout_fontid; // 新しいフォントIDをセット + switch( m_fontid ){ + case FONT_AA: + m_font = &m_aafont; + break; + default: + m_font = &m_defaultfont; + break; + } + +#if 0 // _DEBUG + std::cout << "DrawAreaBase::set_node_font : fontid = " << (int)layout_fontid + << " res = " << layout->header->res_number + << " type = " << (int)(layout->node->type) << std::endl; +#endif + + // layoutにフォントをセット + m_pango_layout->set_font_description( m_font->pfd ); + modify_font( m_font->pfd ); + } +} + + +// // テキストの含まれているノードひとつを描画する関数 // // width_view : 描画領域の幅 @@ -2580,7 +2637,7 @@ assert( m_context ); m_gc->set_foreground( m_color[ color_back ] ); - m_backscreen->draw_rectangle( m_gc, true, x, y, width_line, m_font_height ); + m_backscreen->draw_rectangle( m_gc, true, x, y, width_line, m_font->height ); m_gc->set_foreground( m_color[ color ] ); @@ -2596,8 +2653,8 @@ Pango::Rectangle pango_rect = grl.get_logical_extents( item.get_analysis().get_font() ); int width = PANGO_PIXELS( pango_rect.get_width() ); - m_backscreen->draw_glyphs( m_gc, item.get_analysis().get_font(), x, y + m_font_ascent, grl ); - if( node->bold ) m_backscreen->draw_glyphs( m_gc, item.get_analysis().get_font(), x +1, y + m_font_ascent, grl ); + m_backscreen->draw_glyphs( m_gc, item.get_analysis().get_font(), x, y + m_font->ascent, grl ); + if( node->bold ) m_backscreen->draw_glyphs( m_gc, item.get_analysis().get_font(), x +1, y + m_font->ascent, grl ); x += width; } @@ -2610,7 +2667,7 @@ if( node->link && CONFIG::get_draw_underline() ){ m_gc->set_foreground( m_color[ color ] ); - m_backscreen->draw_line( m_gc, xx, y + m_underline_pos, xx + width_line, y + m_underline_pos ); + m_backscreen->draw_line( m_gc, xx, y + m_font->underline_pos, xx + width_line, y + m_font->underline_pos ); } } @@ -3476,7 +3533,7 @@ #endif Gtk::Adjustment* adjust = m_vscrbar->get_adjustment(); - if( ( int ) adjust->get_value() > y || ( int ) adjust->get_value() + ( int ) adjust->get_page_size() - m_br_size < y ){ + if( ( int ) adjust->get_value() > y || ( int ) adjust->get_value() + ( int ) adjust->get_page_size() - m_font->br_size < y ){ m_cancel_change_adjust = true; adjust->set_value( y ); @@ -3647,6 +3704,8 @@ continue; } + // フォント設定 + set_node_font( layout ); ////////////////////////////////////////////// // @@ -3863,6 +3922,9 @@ continue; } + // フォント設定 + set_node_font( layout ); + // ポインタの下にあるノードを探す int pos; while( rect ){ @@ -4838,7 +4900,7 @@ if( m_drugging ){ // ポインタが画面外に近かったらオートスクロールを開始する - const int mrg = ( int )( (double)m_br_size*0.5 ); + const int mrg = ( int )( (double)m_font->br_size*0.5 ); // スクロールのリセット if ( diff -Nru jd-2.8.5-120826/src/article/drawareabase.h jd-2.8.6-130518/src/article/drawareabase.h --- jd-2.8.5-120826/src/article/drawareabase.h 2011-07-27 15:53:11.000000000 +0000 +++ jd-2.8.6-130518/src/article/drawareabase.h 2013-01-19 16:14:05.000000000 +0000 @@ -63,6 +63,19 @@ int height; }; + // フォント情報 + struct FONTINFO + { + std::string fontname; + Pango::FontDescription pfd; + int ascent; + int descent; + int height; + int underline_pos; // 下線の位置(文字の上からのピクセル値) + int br_size; // 改行量 (ピクセル値) + int mrg_right; // wrap計算のときに使用する右マージン幅 (ピクセル値) + }; + /////////////////////////////////// @@ -137,12 +150,13 @@ // レイアウト用 CORE::CSS_PROPERTY m_css_body; // body の cssプロパティ int m_fontid; - int m_font_ascent; - int m_font_descent; - int m_font_height; - int m_underline_pos; // 下線の位置(文字の上からのピクセル値) - int m_br_size; // 改行量 (ピクセル値) - int m_mrg_right; // wrap計算のときに使用する右マージン幅 (ピクセル値) + int m_defaultfontid; + FONTINFO *m_font; // カレントフォント情報 + FONTINFO m_defaultfont; // デフォルトフォント情報 + FONTINFO m_aafont; // AA用フォント情報 + + // スレビューで文字幅の近似を厳密にするか + bool m_strict_of_char; // ビューのリサイズ用 bool m_configure_reserve; // true の時は再描画する前に再レイアウトする @@ -203,7 +217,7 @@ SIG_LEAVE_URL sig_leave_url(){ return m_sig_leave_url; } DrawAreaBase( const std::string& url ); - ~DrawAreaBase(); + virtual ~DrawAreaBase(); const std::string& get_url() const { return m_url; } const int& width_client() const { return m_width_client; } @@ -218,7 +232,7 @@ // フォントID( fontid.h にある ID を指定) const int get_fontid() const { return m_fontid; } - void set_fontid( int id ){ m_fontid = id; } + void set_fontid( int id ){ m_fontid = id; m_defaultfontid = id; } // 新着セパレータのあるレス番号の取得とセット const int get_separator_new(); @@ -342,6 +356,7 @@ void create_scrbar(); void init_color(); void init_font(); + void init_fontinfo( FONTINFO& fi, std::string& fontname ); // レイアウト処理 void set_align( LAYOUT* div, int id_end, int align ); @@ -368,6 +383,7 @@ void draw_string( LAYOUT* node, const int pos_y, const int width_view, const int color, const int color_back, const int byte_from, const int byte_to ); const bool draw_one_img_node( LAYOUT* layout, const int pos_y, const int upper, const int lower ); + void set_node_font( LAYOUT* layout ); // drawarea がリサイズ実行 void configure_impl(); @@ -425,6 +441,33 @@ const bool slot_key_press_event( GdkEventKey* event ); bool slot_key_release_event( GdkEventKey* event ); }; + + + // + // 文字列を wrap するか判定する関数 + // + // str != NULL なら禁則処理も考える + // + inline bool DrawAreaBase::is_wrapped( const int x, const int border, const char* str ) + { + const unsigned char* tmpchar = ( const unsigned char* ) str; + + if( x < border ) return false; + if( ! tmpchar ) return true; + + // 禁則文字 + if( ( tmpchar[ 0 ] == ',' ) + || ( tmpchar[ 0 ] == '.' ) + + // UTF-8で"。" + || ( tmpchar[ 0 ] == 0xe3 && tmpchar[ 1 ] == 0x80 && tmpchar[ 2 ] == 0x82 ) + + // UTF-8で"、" + || ( tmpchar[ 0 ] == 0xe3 && tmpchar[ 1 ] == 0x80 && tmpchar[ 2 ] == 0x81 ) + ) return false; + + return true; + } } #endif diff -Nru jd-2.8.5-120826/src/article/font.cpp jd-2.8.6-130518/src/article/font.cpp --- jd-2.8.5-120826/src/article/font.cpp 2009-05-12 15:58:36.000000000 +0000 +++ jd-2.8.6-130518/src/article/font.cpp 2013-01-13 09:32:27.000000000 +0000 @@ -24,7 +24,8 @@ }; -WIDTH_DATA* width_of_char[ FONT_NUM ]; +static WIDTH_DATA* width_of_char[ FONT_NUM ]; +static bool strict_of_char = false; enum { @@ -37,6 +38,9 @@ // void ARTICLE::init_font() { + // スレビューで文字幅の近似を厳密にするか + strict_of_char = CONFIG::get_strict_char_width(); + for( int i = 0; i< FONT_NUM ; i++ ){ if( width_of_char[ i ] ){ @@ -72,8 +76,10 @@ width_wide = 0; if( ! width_of_char[ mode ] ){ - width_of_char[ mode ] = ( WIDTH_DATA* ) malloc( sizeof( WIDTH_DATA ) * ( UCS2_MAX + 16 ) ); - memset( width_of_char[ mode ], 0, sizeof( WIDTH_DATA ) * UCS2_MAX ); + const int size = sizeof( WIDTH_DATA ) * UCS2_MAX; + + width_of_char[ mode ] = ( WIDTH_DATA* ) malloc( size ); + memset( width_of_char[ mode ], 0, size ); } const int ucs2 = MISC::utf8toucs2( utfstr, byte ); @@ -86,13 +92,13 @@ width = width_wide; // 厳密に求める場合 - if( byte == 1 && CONFIG::get_strict_char_width() ){ + if( byte == 1 && strict_of_char ){ if( ! width_of_char[ mode ][ ucs2 ].width ){ + const int size = sizeof( unsigned int ) * 128; - const int size = 128; - width_of_char[ mode ][ ucs2 ].width = ( unsigned int* ) malloc( sizeof( unsigned int ) * ( size + 16 ) ); - memset( width_of_char[ mode ][ ucs2 ].width, 0, sizeof( unsigned int ) * size ); + width_of_char[ mode ][ ucs2 ].width = ( unsigned int* ) malloc( size ); + memset( width_of_char[ mode ][ ucs2 ].width, 0, size ); } const int pre_char_num = ( const int ) pre_char; @@ -123,7 +129,7 @@ if( ucs2 >= UCS2_MAX ) return; // 半角モードの幅を厳密に求める場合 - if( byte == 1 && CONFIG::get_strict_char_width() ){ + if( byte == 1 && strict_of_char ){ const int pre_char_num = ( const int ) pre_char; if( pre_char_num < 128 ) width_of_char[ mode ][ ucs2 ].width[ pre_char_num ] = width; diff -Nru jd-2.8.5-120826/src/article/layouttree.cpp jd-2.8.6-130518/src/article/layouttree.cpp --- jd-2.8.5-120826/src/article/layouttree.cpp 2011-07-27 15:53:11.000000000 +0000 +++ jd-2.8.6-130518/src/article/layouttree.cpp 2013-04-10 16:35:03.000000000 +0000 @@ -15,6 +15,7 @@ #include "global.h" #include "colorid.h" +#include "fontid.h" #include "cssmanager.h" enum @@ -569,6 +570,10 @@ LAYOUT* header = create_layout_div( classid ); header->type = DBTREE::NODE_HEADER; + DBTREE::NODE* node = ( DBTREE::NODE* ) m_heap.heap_alloc( sizeof( DBTREE::NODE ) ); + node->fontid = FONT_DEFAULT; // デフォルトフォントを設定 + header->node = node; + if( header->css->bg_color < 0 ) header->css->bg_color = COLOR_SEPARATOR_NEW; LAYOUT* layout = create_layout_text( "ここまで読んだ", NULL, false ); diff -Nru jd-2.8.5-120826/src/bbslist/Makefile.am jd-2.8.6-130518/src/bbslist/Makefile.am --- jd-2.8.5-120826/src/bbslist/Makefile.am 2009-07-25 05:00:52.000000000 +0000 +++ jd-2.8.6-130518/src/bbslist/Makefile.am 2013-01-05 15:44:26.000000000 +0000 @@ -27,4 +27,4 @@ toolbar.h AM_CXXFLAGS = @GTKMM_CFLAGS@ -INCLUDES = -I$(top_srcdir)/src +AM_CPPFLAGS = -I$(top_srcdir)/src diff -Nru jd-2.8.5-120826/src/bbslist/bbslistviewbase.cpp jd-2.8.6-130518/src/bbslist/bbslistviewbase.cpp --- jd-2.8.5-120826/src/bbslist/bbslistviewbase.cpp 2012-08-03 14:40:00.000000000 +0000 +++ jd-2.8.6-130518/src/bbslist/bbslistviewbase.cpp 2013-01-10 15:18:32.000000000 +0000 @@ -198,9 +198,9 @@ // アクショングループを作ってUIマネージャに登録 action_group() = Gtk::ActionGroup::create(); action_group()->add( Gtk::Action::create( "OpenTab", "タブで開く(_T)"), sigc::mem_fun( *this, &BBSListViewBase::slot_open_tab ) ); - action_group()->add( Gtk::Action::create( "OpenBrowser", ITEM_NAME_OPEN_BROWSER + std::string( "(_W)" ) ), + action_group()->add( Gtk::Action::create( "OpenBrowser", ITEM_NAME_OPEN_BROWSER "(_W)" ), sigc::mem_fun( *this, &BBSListViewBase::slot_open_browser ) ); - action_group()->add( Gtk::Action::create( "OpenCacheBrowser", ITEM_NAME_OPEN_CACHE_BROWSER + std::string( "(_X)" ) ), + action_group()->add( Gtk::Action::create( "OpenCacheBrowser", ITEM_NAME_OPEN_CACHE_BROWSER "(_X)" ), sigc::mem_fun( *this, &BBSListViewBase::slot_open_cache_browser ) ); action_group()->add( Gtk::Action::create( "AppendFavorite", "AppendFavorite"), sigc::mem_fun( *this, &BBSListViewBase::slot_append_favorite ) ); action_group()->add( Gtk::Action::create( "NewDir", "新規ディレクトリ(_N)"), sigc::mem_fun( *this, &BBSListViewBase::slot_newdir ) ); @@ -218,8 +218,8 @@ action_group()->add( Gtk::Action::create( "CheckUpdateOpenRows", "更新された行をタブで開く(_E)"), sigc::mem_fun( *this, &BBSListViewBase::slot_checkupdate_open_selected_rows ) ); - action_group()->add( Gtk::Action::create( "CopyURL", ITEM_NAME_COPY_URL + std::string( "(_U)" )), sigc::mem_fun( *this, &BBSListViewBase::slot_copy_url ) ); - action_group()->add( Gtk::Action::create( "CopyTitleURL", ITEM_NAME_COPY_TITLE_URL + std::string( "(_L)") ), + action_group()->add( Gtk::Action::create( "CopyURL", ITEM_NAME_COPY_URL "(_U)"), sigc::mem_fun( *this, &BBSListViewBase::slot_copy_url ) ); + action_group()->add( Gtk::Action::create( "CopyTitleURL", ITEM_NAME_COPY_TITLE_URL "(_L)" ), sigc::mem_fun( *this, &BBSListViewBase::slot_copy_title_url ) ); action_group()->add( Gtk::Action::create( "SelectDir", "全て選択(_A)"), sigc::mem_fun( *this, &BBSListViewBase::slot_select_all_dir ) ); @@ -242,10 +242,9 @@ action_group()->add( Gtk::Action::create( "SearchCacheBoard", "キャッシュ内ログ検索(_S)"), sigc::mem_fun( *this, &BBSListViewBase::slot_search_cache_board ) ); action_group()->add( Gtk::Action::create( "ImportDat", "datのインポート(_I)"), sigc::mem_fun( *this, &BBSListViewBase::slot_import_dat ) ); - action_group()->add( Gtk::Action::create( "PreferenceArticle", ITEM_NAME_PREF_THREAD + std::string( "(_P)..." ) ), - sigc::mem_fun( *this, &BBSListViewBase::slot_preferences_article ) ); - action_group()->add( Gtk::Action::create( "PreferenceBoard", "板のプロパティ(_O)..."), sigc::mem_fun( *this, &BBSListViewBase::slot_preferences_board ) ); - action_group()->add( Gtk::Action::create( "PreferenceImage", "画像のプロパティ(_M)..."), sigc::mem_fun( *this, &BBSListViewBase::slot_preferences_image ) ); + action_group()->add( Gtk::Action::create( "PreferenceArticle", ITEM_NAME_PREF_THREAD "(_P)..." ), sigc::mem_fun( *this, &BBSListViewBase::slot_preferences_article ) ); + action_group()->add( Gtk::Action::create( "PreferenceBoard", ITEM_NAME_PREF_BOARD "(_O)..." ), sigc::mem_fun( *this, &BBSListViewBase::slot_preferences_board ) ); + action_group()->add( Gtk::Action::create( "PreferenceImage", ITEM_NAME_PREF_IMAGE "(_M)..." ), sigc::mem_fun( *this, &BBSListViewBase::slot_preferences_image ) ); ui_manager() = Gtk::UIManager::create(); diff -Nru jd-2.8.5-120826/src/board/Makefile.am jd-2.8.6-130518/src/board/Makefile.am --- jd-2.8.5-120826/src/board/Makefile.am 2010-03-18 15:04:09.000000000 +0000 +++ jd-2.8.6-130518/src/board/Makefile.am 2013-01-05 15:44:26.000000000 +0000 @@ -22,4 +22,4 @@ preference.h AM_CXXFLAGS = @GTKMM_CFLAGS@ -INCLUDES = -I$(top_srcdir)/src +AM_CPPFLAGS = -I$(top_srcdir)/src diff -Nru jd-2.8.5-120826/src/board/boardadmin.cpp jd-2.8.6-130518/src/board/boardadmin.cpp --- jd-2.8.5-120826/src/board/boardadmin.cpp 2011-08-07 15:50:51.000000000 +0000 +++ jd-2.8.6-130518/src/board/boardadmin.cpp 2012-12-03 14:43:37.000000000 +0000 @@ -4,10 +4,12 @@ #include "jddebug.h" #include "boardadmin.h" +#include "boardviewnext.h" #include "toolbar.h" #include "dbtree/interface.h" +#include "skeleton/admin.h" #include "skeleton/view.h" #include "skeleton/dragnote.h" @@ -252,6 +254,44 @@ // +// view_modeに該当するページを探す +// +int BoardAdmin::find_view( const std::string& view_mode ) +{ + if( view_mode.empty() ) return -1; + + // 検索の基準を、アクティブなタブに仮定 + const int page = m_notebook->get_current_page(); + const int pages = m_notebook->get_n_pages(); + + // "boardnext" なら次スレ検索のタブで開く + if( view_mode.find( "boardnext" ) != std::string::npos ){ + + // アクティブな開始タブの右側から順に、すべてのタブをループ + int i = page; + while( i >= 0 ){ + // BoardViewNextクラスのタブを探す + BOARD::BoardViewNext* view = dynamic_cast< BOARD::BoardViewNext* >( m_notebook->get_nth_page( i ) ); + if( view ){ + if( ! view->is_locked() ){ + // ページが見つかった + return i; + } + // ロックされていれば次に該当するタブを探す + } + + // 次のタブへインクリメント + i++; + if( i >= pages ) i = 0; // 右端まで探したら左端から + if( i == page ) break; // 一巡しても見つからなかった + } + } + // 該当するタブが見つからない場合 + return -1; +} + + +// // ツールバー表示 // void BoardAdmin::show_toolbar() diff -Nru jd-2.8.5-120826/src/board/boardadmin.h jd-2.8.6-130518/src/board/boardadmin.h --- jd-2.8.5-120826/src/board/boardadmin.h 2011-06-20 15:21:47.000000000 +0000 +++ jd-2.8.6-130518/src/board/boardadmin.h 2012-12-01 15:49:44.000000000 +0000 @@ -31,6 +31,9 @@ virtual COMMAND_ARGS get_open_list_args( const std::string& url, const COMMAND_ARGS& command_list ); virtual SKELETON::View* create_view( const COMMAND_ARGS& command ); + // view_modeに該当するページを探す + virtual int find_view( const std::string& view_mode ); + // ツールバー virtual void show_toolbar(); virtual void toggle_toolbar(); diff -Nru jd-2.8.5-120826/src/board/boardviewbase.cpp jd-2.8.6-130518/src/board/boardviewbase.cpp --- jd-2.8.5-120826/src/board/boardviewbase.cpp 2012-08-03 14:40:00.000000000 +0000 +++ jd-2.8.6-130518/src/board/boardviewbase.cpp 2013-02-10 10:45:11.000000000 +0000 @@ -257,16 +257,16 @@ // アクショングループを作ってUIマネージャに登録 action_group() = Gtk::ActionGroup::create(); - action_group()->add( Gtk::Action::create( "BookMark", ITEM_NAME_BOOKMARK + std::string( "(_B)" ) ), + action_group()->add( Gtk::Action::create( "BookMark", ITEM_NAME_BOOKMARK "(_B)" ), sigc::bind< int >( sigc::mem_fun( *this, &BoardViewBase::slot_bookmark ), BOOKMARK_AUTO ) ); action_group()->add( Gtk::Action::create( "SetBookMark", "しおりを設定(_S)" ), // 未使用 sigc::bind< int >( sigc::mem_fun( *this, &BoardViewBase::slot_bookmark ), BOOKMARK_SET ) ); action_group()->add( Gtk::Action::create( "UnsetBookMark", "しおりを解除(_U)" ), // 未使用 sigc::bind< int >( sigc::mem_fun( *this, &BoardViewBase::slot_bookmark ), BOOKMARK_UNSET ) ); action_group()->add( Gtk::Action::create( "OpenTab", "OpenArticleTab" ), sigc::mem_fun( *this, &BoardViewBase::slot_open_tab ) ); - action_group()->add( Gtk::Action::create( "RegetArticle", ITEM_NAME_REGETARTICLE + std::string( "(_R)" ) ), + action_group()->add( Gtk::Action::create( "RegetArticle", ITEM_NAME_REGETARTICLE "(_R)" ), sigc::mem_fun( *this, &BoardViewBase::slot_reget_article ) ); - action_group()->add( Gtk::Action::create( "Favorite_Article", ITEM_NAME_FAVORITE_ARTICLE + std::string( "(_F)..." ) ), + action_group()->add( Gtk::Action::create( "Favorite_Article", ITEM_NAME_FAVORITE_ARTICLE "(_F)..." ), sigc::mem_fun( *this, &BoardViewBase::slot_favorite_thread ) ); action_group()->add( Gtk::Action::create( "Favorite_Board", "板をお気に入りに追加(_A)" ), sigc::mem_fun( *this, &BoardViewBase::slot_favorite_board ) ); action_group()->add( Gtk::Action::create( "GotoTop", "一番上に移動(_T)" ), sigc::mem_fun( *this, &BoardViewBase::goto_top ) ); @@ -277,24 +277,22 @@ sigc::bind< bool >( sigc::mem_fun( *this, &BoardViewBase::open_selected_rows ), false ) ); action_group()->add( Gtk::Action::create( "RegetRows", "スレ情報を消さずにスレを再取得(_R)" ), sigc::bind< bool >( sigc::mem_fun( *this, &BoardViewBase::open_selected_rows ), true ) ); - action_group()->add( Gtk::Action::create( "CopyURL", ITEM_NAME_COPY_URL + std::string( "(_U)" ) ), sigc::mem_fun( *this, &BoardViewBase::slot_copy_url ) ); - action_group()->add( Gtk::Action::create( "CopyTitleURL", ITEM_NAME_COPY_TITLE_URL + std::string( "(_L)" ) ), + action_group()->add( Gtk::Action::create( "CopyURL", ITEM_NAME_COPY_URL "(_U)" ), sigc::mem_fun( *this, &BoardViewBase::slot_copy_url ) ); + action_group()->add( Gtk::Action::create( "CopyTitleURL", ITEM_NAME_COPY_TITLE_URL "(_L)" ), sigc::mem_fun( *this, &BoardViewBase::slot_copy_title_url ) ); - action_group()->add( Gtk::Action::create( "OpenBrowser", ITEM_NAME_OPEN_BROWSER + std::string( "(_W)" ) ), + action_group()->add( Gtk::Action::create( "OpenBrowser", ITEM_NAME_OPEN_BROWSER "(_W)" ), sigc::mem_fun( *this, &BoardViewBase::slot_open_browser ) ); - action_group()->add( Gtk::Action::create( "AboneThread", ITEM_NAME_ABONE_ARTICLE + std::string( "(_N)" ) ), + action_group()->add( Gtk::Action::create( "AboneThread", ITEM_NAME_ABONE_ARTICLE "(_N)" ), sigc::mem_fun( *this, &BoardViewBase::slot_abone_thread ) ); - action_group()->add( Gtk::Action::create( "PreferenceArticle", ITEM_NAME_PREF_THREAD + std::string( "(_P)..." ) ), - sigc::mem_fun( *this, &BoardViewBase::slot_preferences_article ) ); - action_group()->add( Gtk::Action::create( "PreferenceBoard", ITEM_NAME_PREF_BOARD + std::string( "(_O)..." ) ), - sigc::mem_fun( *this, &BoardViewBase::show_preference ) ); - action_group()->add( Gtk::Action::create( "SaveDat", ITEM_NAME_SAVE_DAT + std::string( "(_S)..." ) ), + action_group()->add( Gtk::Action::create( "PreferenceArticle", ITEM_NAME_PREF_THREAD "(_P)..." ), sigc::mem_fun( *this, &BoardViewBase::slot_preferences_article ) ); + action_group()->add( Gtk::Action::create( "PreferenceBoard", "PreferenceBoard" ), sigc::mem_fun( *this, &BoardViewBase::show_preference ) ); + action_group()->add( Gtk::Action::create( "SaveDat", "SaveDat" ), sigc::mem_fun( *this, &BoardViewBase::slot_save_dat ) ); action_group()->add( Gtk::Action::create( "SearchNextArticle", ITEM_NAME_NEXTARTICLE ), sigc::mem_fun( *this, &BoardViewBase::slot_search_next ) ); // その他 - action_group()->add( Gtk::Action::create( "Etc_Menu", ITEM_NAME_ETC + std::string( "(_O)" ) ) ); + action_group()->add( Gtk::Action::create( "Etc_Menu", ITEM_NAME_ETC "(_O)" ) ); ui_manager().clear(); ui_manager() = Gtk::UIManager::create(); @@ -1476,6 +1474,12 @@ forward_viewhistory( 1 ); break; + // datを保存 + case CONTROL::Save: + slot_save_dat(); + break; + + // 閉じる case CONTROL::Quit: close_view(); break; @@ -1535,6 +1539,11 @@ up_search(); break; + // 板のプロパティ + case CONTROL::PreferenceView: + show_preference(); + break; + default: return false; } @@ -2765,9 +2774,10 @@ // ひとつだけ名前を付けて保存 if( list_it.size() == 1 ){ + Gtk::TreePath path = m_treeview.get_current_path(); - if( m_path_selected.empty() ) return; - const std::string url = path2daturl( m_path_selected ); + if( path.empty() ) return; + const std::string url = path2daturl( path ); DBTREE::article_save_dat( url, std::string() ); return; diff -Nru jd-2.8.5-120826/src/cache.cpp jd-2.8.6-130518/src/cache.cpp --- jd-2.8.5-120826/src/cache.cpp 2011-10-24 12:31:06.000000000 +0000 +++ jd-2.8.6-130518/src/cache.cpp 2013-02-17 15:54:24.000000000 +0000 @@ -164,6 +164,13 @@ } +// URL変換設定ファイル +std::string CACHE::path_urlreplace() +{ + return CACHE::path_root() + "urlreplace.conf"; +} + + // 履歴 std::string CACHE::path_xml_history() { diff -Nru jd-2.8.5-120826/src/cache.h jd-2.8.6-130518/src/cache.h --- jd-2.8.5-120826/src/cache.h 2012-07-17 15:50:07.000000000 +0000 +++ jd-2.8.6-130518/src/cache.h 2013-02-17 15:54:24.000000000 +0000 @@ -77,6 +77,9 @@ // リンクフィルタ std::string path_linkfilter(); + // URL変換設定ファイル + std::string path_urlreplace(); + // スレ履歴 std::string path_xml_history(); diff -Nru jd-2.8.5-120826/src/config/Makefile.am jd-2.8.6-130518/src/config/Makefile.am --- jd-2.8.5-120826/src/config/Makefile.am 2008-12-21 03:01:44.000000000 +0000 +++ jd-2.8.6-130518/src/config/Makefile.am 2013-01-05 15:44:26.000000000 +0000 @@ -8,4 +8,4 @@ configitems.h globalconf.h defaultconf.h aboutconfig.h aboutconfigdiag.h AM_CXXFLAGS = @GTKMM_CFLAGS@ -INCLUDES = -I$(top_srcdir)/src +AM_CPPFLAGS = -I$(top_srcdir)/src diff -Nru jd-2.8.5-120826/src/config/aboutconfig.cpp jd-2.8.6-130518/src/config/aboutconfig.cpp --- jd-2.8.5-120826/src/config/aboutconfig.cpp 2012-02-13 14:47:05.000000000 +0000 +++ jd-2.8.6-130518/src/config/aboutconfig.cpp 2013-02-23 06:23:30.000000000 +0000 @@ -266,6 +266,7 @@ append_row( "類似度判定のしきい値(小さいほど判定が甘くなる、最大10)", get_confitem()->threshold_next, CONF_THRESHOLD_NEXT ); append_row( "移行時にお気に入りのアドレスと名前を自動更新する(0: しない, 1:する, 2:追加)", get_confitem()->replace_favorite_next, CONF_REPLACE_FAVORITE_NEXT ); append_row( "お気に入り自動更新の確認ダイアログを表示する", get_confitem()->show_diag_replace_favorite, CONF_SHOW_DIAG_REPLACE_FAVORITE ); + append_row( "次スレ検索を開くときのタブの位置 ( 0: 次スレ検索タブ 1:新しいタブ 2:アクティブなタブを置き換え )", get_confitem()->boardnexttab_pos, CONF_BOARDNEXTTAB_POS ); // スレタイ検索 append_row( "" ); diff -Nru jd-2.8.5-120826/src/config/configitems.cpp jd-2.8.6-130518/src/config/configitems.cpp --- jd-2.8.5-120826/src/config/configitems.cpp 2011-08-07 15:50:51.000000000 +0000 +++ jd-2.8.6-130518/src/config/configitems.cpp 2013-01-19 16:14:05.000000000 +0000 @@ -123,6 +123,9 @@ ref_prefix_space = cf.get_option_int( "ref_prefix_space", CONF_REF_PREFIX_SPACE, 0, 16 ); for( int i = 0; i < ref_prefix_space; ++i ) ref_prefix_space_str += " "; + // レスにアスキーアートがあると判定する正規表現 + regex_res_aa = cf.get_option_str( "regex_res_aa", CONF_REGEX_RES_AA ); + // キャッシュのルートディレクトリ(旧バージョンとの互換のため残している) path_cacheroot = cf.get_option_str( "path_cacheroot", CONF_PATH_CACHEROOT ); @@ -479,6 +482,9 @@ // ビュー内から他のビューを開いたときのタブの位置 ( 0: 一番右端 1:右隣 2:左隣 ) newtab_pos = cf.get_option_int( "newtab_pos", CONF_NEWTAB_POS, 0, 2 ); + // 次スレ検索を開くときのタブの位置 ( 0: 次スレ検索タブ 1:新しいタブ 2:アクティブなタブを置き換え -1:2.8.5以前の動作 ) + boardnexttab_pos = cf.get_option_int( "boardnexttab_pos", CONF_BOARDNEXTTAB_POS, -1, 2 ); + // スレビューに書き込みマークを表示するか show_post_mark = cf.get_option_bool( "show_post_mark", CONF_SHOW_POST_MARK ); @@ -664,6 +670,7 @@ cf.update( "fontname_main", fontname[ FONT_MAIN ] ); cf.update( "fontname_popup", fontname[ FONT_POPUP ] ); + cf.update( "fontname_aa", fontname[ FONT_AA ] ); cf.update( "fontname_bbs", fontname[ FONT_BBS ] ); cf.update( "fontname_board", fontname[ FONT_BOARD ] ); cf.update( "fontname_message", fontname[ FONT_MESSAGE ] ); @@ -671,6 +678,8 @@ cf.update( "ref_prefix", ref_prefix ); cf.update( "ref_prefix_space", ref_prefix_space ); + cf.update( "regex_res_aa", regex_res_aa ); + cf.update( "path_cacheroot", path_cacheroot ); cf.update( "agent_for2ch", agent_for2ch ); @@ -865,6 +874,8 @@ cf.update( "newtab_pos", newtab_pos ); + cf.update( "boardnexttab_pos", boardnexttab_pos ); + cf.update( "show_post_mark", show_post_mark ); cf.update( "flat_button", flat_button ); @@ -941,6 +952,9 @@ // ポップアップのフォント fontname[ FONT_POPUP ] = cf.get_option_str( "fontname_popup", defaultfont + " " + std::string( CONF_FONTSIZE_POPUP ) ); + // AA(スレビュー)のフォント + fontname[ FONT_AA ] = cf.get_option_str( "fontname_aa", fontname[ FONT_MAIN ] ); + // スレ一覧のフォント fontname[ FONT_BBS ] = cf.get_option_str( "fontname_bbs", defaultfont + " " + std::string( CONF_FONTSIZE_TREE ) ); diff -Nru jd-2.8.5-120826/src/config/configitems.h jd-2.8.6-130518/src/config/configitems.h --- jd-2.8.5-120826/src/config/configitems.h 2011-08-07 15:50:51.000000000 +0000 +++ jd-2.8.6-130518/src/config/configitems.h 2013-01-19 16:14:05.000000000 +0000 @@ -43,6 +43,9 @@ int ref_prefix_space; std::string ref_prefix_space_str; + // レスにアスキーアートがあると判定する正規表現 + std::string regex_res_aa; + // キャッシュのルートディレクトリ // 旧バージョンとの互換のため残しているだけで使用していない std::string path_cacheroot; @@ -405,6 +408,9 @@ // ビュー内から他のビューを開いたときのタブの位置 ( 0: 一番右端 1:右隣 2:左隣 ) int newtab_pos; + // 次スレ検索を開くときのタブの位置 ( 0: 次スレ検索タブ 1:新しいタブ 2:アクティブなタブを置き換え ) + int boardnexttab_pos; + // スレビューに書き込みマークを表示するか bool show_post_mark; diff -Nru jd-2.8.5-120826/src/config/defaultconf.h jd-2.8.6-130518/src/config/defaultconf.h --- jd-2.8.5-120826/src/config/defaultconf.h 2012-01-13 11:23:11.000000000 +0000 +++ jd-2.8.6-130518/src/config/defaultconf.h 2013-01-19 16:14:05.000000000 +0000 @@ -104,6 +104,7 @@ CONF_SHOW_TAB_ICON = 1, // タブにアイコンを表示するか CONF_SWITCHTAB_WHEEL = 1, // タブ上でマウスホイールを回転してタブを切り替える CONF_NEWTAB_POS = 1, // ビュー内から他のビューを開いたときのタブの位置 ( 0: 一番右端 1:右隣 2:左隣 ) + CONF_BOARDNEXTTAB_POS = 0, // 次スレ検索を開くときのタブの位置 ( 0: 次スレ検索タブ 1:新しいタブ 2:アクティブなタブを置き換え ) CONF_SHOW_POST_MARK = 1, // スレビューに書き込みマークを表示するか CONF_FLAT_BUTTON = 1, // ボタンをフラットにするか CONF_DRAW_TOOLBARBACK = 0, // ツールバーの背景描画 @@ -180,6 +181,9 @@ // レスを参照するときに前に付ける文字 #define CONF_REF_PREFIX ">" +// レスにアスキーアートがあると判定する正規表現 +#define CONF_REGEX_RES_AA "\"  \"" + // キャッシュのルートディレクトリ(旧バージョンとの互換のため残している) #define CONF_PATH_CACHEROOT "~/.jd/" diff -Nru jd-2.8.5-120826/src/config/globalconf.cpp jd-2.8.6-130518/src/config/globalconf.cpp --- jd-2.8.5-120826/src/config/globalconf.cpp 2012-01-23 15:00:45.000000000 +0000 +++ jd-2.8.6-130518/src/config/globalconf.cpp 2013-02-23 06:23:30.000000000 +0000 @@ -131,6 +131,21 @@ const std::string CONFIG::get_ref_prefix(){ return get_confitem()->ref_prefix + get_confitem()->ref_prefix_space_str; } const int CONFIG::ref_prefix_space(){ return get_confitem()->ref_prefix_space; } +// レスにアスキーアートがあると判定する正規表現 +const std::string CONFIG::get_regex_res_aa(){ + std::string str = get_confitem()->regex_res_aa; + int size = str.size(); + + // ダブルクオートの削除 + if( size > 2 && str[ 0 ] == '"' && str[ size - 1 ] == '"' ){ + str = str.substr( 1, size - 2 ); + } + return str; +} +void CONFIG::set_regex_res_aa( const std::string& regex ){ + get_confitem()->regex_res_aa = "\"" + regex + "\""; +} + const std::string& CONFIG::get_url_jdhp() { return get_confitem()->url_jdhp; } // 2chの認証サーバのアドレス @@ -425,6 +440,9 @@ // ビュー内から他のビューを開いたときのタブの位置 ( 0: 一番右端 1:右隣 2:左隣 ) const int CONFIG::get_newtab_pos(){ return get_confitem()->newtab_pos; } +// 次スレ検索を開くときのタブの位置 ( 0: 次スレ検索タブ 1:新しいタブ 2:アクティブなタブを置き換え ) +const int CONFIG::get_boardnexttab_pos(){ return get_confitem()->boardnexttab_pos; } + const bool CONFIG::get_show_post_mark(){ return get_confitem()->show_post_mark; } void CONFIG::set_show_post_mark( const bool show ){ get_confitem()->show_post_mark = show; } diff -Nru jd-2.8.5-120826/src/config/globalconf.h jd-2.8.6-130518/src/config/globalconf.h --- jd-2.8.5-120826/src/config/globalconf.h 2012-01-23 15:00:45.000000000 +0000 +++ jd-2.8.6-130518/src/config/globalconf.h 2013-02-23 06:23:30.000000000 +0000 @@ -84,6 +84,10 @@ // 参照文字( ref_prefix ) の後のスペースの数 const int ref_prefix_space(); + // レスにアスキーアートがあると判定する正規表現 + const std::string get_regex_res_aa(); + void set_regex_res_aa( const std::string& regex ); + // JD ホームページのアドレス const std::string& get_url_jdhp(); @@ -454,6 +458,9 @@ // ビュー内から他のビューを開いたときのタブの位置 ( 0: 一番右端 1:右隣 2:左隣 ) const int get_newtab_pos(); + // 次スレ検索を開くときのタブの位置 ( 0: 次スレ検索タブ 1:新しいタブ 2:アクティブなタブを置き換え ) + const int get_boardnexttab_pos(); + // スレビューに書き込みマークを表示するか const bool get_show_post_mark(); void set_show_post_mark( const bool show ); diff -Nru jd-2.8.5-120826/src/control/Makefile.am jd-2.8.6-130518/src/control/Makefile.am --- jd-2.8.5-120826/src/control/Makefile.am 2008-12-21 03:01:44.000000000 +0000 +++ jd-2.8.6-130518/src/control/Makefile.am 2013-01-05 15:44:26.000000000 +0000 @@ -17,4 +17,4 @@ defaultconf.h AM_CXXFLAGS = @GTKMM_CFLAGS@ -INCLUDES = -I$(top_srcdir)/src +AM_CPPFLAGS = -I$(top_srcdir)/src diff -Nru jd-2.8.5-120826/src/control/control.cpp jd-2.8.6-130518/src/control/control.cpp --- jd-2.8.5-120826/src/control/control.cpp 2011-04-04 15:21:12.000000000 +0000 +++ jd-2.8.6-130518/src/control/control.cpp 2013-01-19 07:12:56.000000000 +0000 @@ -63,13 +63,24 @@ // 戻り値はコントロールID const int Control::key_press( const GdkEventKey* event ) { - const guint key = event->keyval; + guint key = event->keyval; const bool ctrl = ( event->state ) & GDK_CONTROL_MASK; bool shift = ( event->state ) & GDK_SHIFT_MASK; const bool alt = ( event->state ) & GDK_MOD1_MASK; + const bool caps = ( event->state ) & GDK_LOCK_MASK; // caps lock const bool dblclick = false; const bool trpclick = false; + // caps lockされている場合は、アスキー文字を大文字小文字入れ替えて、capsを無視する + // InputDiag::on_key_press_event()も参照のこと + if( caps ){ + if( key >= 'A' && key <= 'Z' ){ + key += 'a' - 'A'; + } else if( key >= 'a' && key <= 'z' ){ + key += 'A' - 'a'; + } + } + // keyがアスキー文字の場合は shift を無視する (大文字除く) // KeyConfig::set_one_motion()も参照せよ if( CONTROL::is_ascii( key ) && ( key < 'A' || key > 'Z' ) ) shift = false; @@ -79,6 +90,7 @@ if( ctrl ) std::cout << " ctrl"; if( shift ) std::cout << " shift"; if( alt ) std::cout << " alt"; + if( caps ) std::cout << " caps"; std::cout << "\n"; #endif diff -Nru jd-2.8.5-120826/src/control/controlid.h jd-2.8.6-130518/src/control/controlid.h --- jd-2.8.5-120826/src/control/controlid.h 2011-07-25 13:08:23.000000000 +0000 +++ jd-2.8.6-130518/src/control/controlid.h 2013-02-10 10:03:10.000000000 +0000 @@ -97,6 +97,7 @@ Quit, Save, + SaveDat, // alias: Save Delete, Reload, ReloadArticle, @@ -106,9 +107,13 @@ Copy, SelectAll, AppendFavorite, - Property, Lock, - + + PreferenceView, + PreferenceBoard, // alias: PreferenceView + PreferenceArticle, // alias: PreferenceView + PreferenceImage, // alias: PreferenceView + Search, CloseSearchBar, HiLightOff, @@ -193,6 +198,11 @@ SearchCacheLocal, SearchCacheAll, + ShowSelectImage, + DeleteSelectImage, + AboneSelectImage, + AboneSelectionRes, + PopupWarpButton, // 以下、マウスボタン専用の設定 ReferResButton, BmResButton, diff -Nru jd-2.8.5-120826/src/control/controllabel.h jd-2.8.6-130518/src/control/controllabel.h --- jd-2.8.5-120826/src/control/controllabel.h 2011-07-25 13:08:23.000000000 +0000 +++ jd-2.8.6-130518/src/control/controllabel.h 2013-02-10 10:03:10.000000000 +0000 @@ -103,6 +103,7 @@ { "Quit", ITEM_NAME_QUIT }, { "Save", "名前を付けて保存..." }, + { "SaveDat", ITEM_NAME_SAVE_DAT "..." }, { "Delete", ITEM_NAME_DELETE }, { "Reload", ITEM_NAME_RELOAD }, { "ReloadArticle", "元のスレを開く" }, @@ -111,9 +112,13 @@ { "Copy", ITEM_NAME_COPY }, { "SelectAll", "全て選択" }, { "AppendFavorite", ITEM_NAME_APPENDFAVORITE "..." }, - { "Property", "プロパティ..." }, { "Lock", ITEM_NAME_LOCK }, + { "PreferenceView", ITEM_NAME_PREFERENCEVIEW "..." }, + { "PreferenceBoard", ITEM_NAME_PREF_BOARD "..." }, + { "PreferenceArticle", ITEM_NAME_PREF_THREAD "..." }, + { "PreferenceImage", ITEM_NAME_PREF_IMAGE "..." }, + { "Search", ITEM_NAME_SEARCH }, { "CloseSearchBar", "検索バーを閉じる" }, { "HiLightOff", ITEM_NAME_CLEAR_HIGHLIGHT }, @@ -201,6 +206,11 @@ { "SearchCacheLocal", "ログ検索(対象: 板)" }, { "SearchCacheAll", "ログ検索(対象: 全ログ)" }, + { "ShowSelectImage", ITEM_NAME_SELECTIMG }, + { "DeleteSelectImage", "削除する" }, + { "AboneSelectImage", "あぼ〜んする" }, + { "AboneSelectionRes", ITEM_NAME_ABONE_SELECTION }, + { "PopupWarpButton", "クリックで多重ポップアップモードに移行" }, { "ReferResButton", "参照レスポップアップ表示" }, { "BmResButton", "ブックマーク" }, diff -Nru jd-2.8.5-120826/src/control/controlutil.cpp jd-2.8.6-130518/src/control/controlutil.cpp --- jd-2.8.5-120826/src/control/controlutil.cpp 2011-07-25 13:08:23.000000000 +0000 +++ jd-2.8.6-130518/src/control/controlutil.cpp 2013-02-10 10:03:10.000000000 +0000 @@ -312,20 +312,30 @@ { switch ( id ) { - case CONTROL::Save: //名前を付けて保存... + case CONTROL::Save: //名前を付けて保存... + case CONTROL::SaveDat: //datを保存... label.replace( pos, strlen( "..." ), "(_S)..." ); break; - case CONTROL::Property: //プロパティ... + case CONTROL::AppendFavorite: //お気に入りに追加.. + label.replace( pos, strlen( "..." ), "(_F)..." ); + break; + + case CONTROL::OpenURL: //URLを開く + label.replace( pos, strlen( "..." ), "(_U)..." ); + break; + + case CONTROL::PreferenceView: //プロパティ... + case CONTROL::PreferenceArticle: //スレのプロパティ... label.replace( pos, strlen( "..." ), "(_P)..." ); break; - case CONTROL::AppendFavorite: //お気に入りに追加.. - label.replace( pos, strlen( "..." ), "(_F)..." ); + case CONTROL::PreferenceBoard: //板のプロパティ... + label.replace( pos, strlen( "..." ), "(_O)..." ); break; - case CONTROL::OpenURL: //URLを開く - label.replace( pos, strlen( "..." ), "(_U)..." ); + case CONTROL::PreferenceImage: //画像のプロパティ... + label.replace( pos, strlen( "..." ), "(_M)..." ); break; } } @@ -429,6 +439,22 @@ label += "(_A)"; break; + case CONTROL::ShowSelectImage: // 選択範囲の画像を開く + label += "(_G)"; + break; + + case CONTROL::DeleteSelectImage: // 選択範囲の画像を削除(サブメニュー) + label += "(_D)"; + break; + + case CONTROL::AboneSelectImage: // 選択範囲の画像をあぼ〜ん(サブメニュー) + label += "(_A)"; + break; + + case CONTROL::AboneSelectionRes: // 選択範囲のレスをあぼ〜ん + label += "(_A)"; + break; + case CONTROL::CancelMosaic: //モザイク解除 label += "(_M)"; break; @@ -462,8 +488,24 @@ // IDからキーボードとマウスジェスチャの両方を取得 const std::string CONTROL::get_str_motions( const int id ) { - std::string str_motion = get_str_keymotions( id ); - std::string mouse_motion = get_str_mousemotions( id ); + int ctl = id; + + // メニューのラベルとコントロールのIDが異なる、共通コントロールIDの場合は、ここで変換する + switch( ctl ){ + // 表示中のビューのプロパティを表示 + case CONTROL::PreferenceArticle: //スレのプロパティ... + case CONTROL::PreferenceBoard: //板のプロパティ... + case CONTROL::PreferenceImage: //画像のプロパティ... + ctl = CONTROL::PreferenceView; + break; + //名前を付けて保存... + case CONTROL::SaveDat: //datを保存... + ctl = CONTROL::Save; + break; + } + + std::string str_motion = get_str_keymotions( ctl ); + std::string mouse_motion = get_str_mousemotions( ctl ); if( ! mouse_motion.empty() ){ if( !str_motion.empty() ) str_motion += " "; str_motion += "( " + mouse_motion + " )"; diff -Nru jd-2.8.5-120826/src/control/defaultconf.h jd-2.8.6-130518/src/control/defaultconf.h --- jd-2.8.5-120826/src/control/defaultconf.h 2011-07-25 13:08:23.000000000 +0000 +++ jd-2.8.6-130518/src/control/defaultconf.h 2013-01-10 14:23:49.000000000 +0000 @@ -76,6 +76,7 @@ #define KEYCONF_Copy "Ctrl+c" #define KEYCONF_SelectAll "Ctrl+a" #define KEYCONF_AppendFavorite "Ctrl+d" +#define KEYCONF_PreferenceView "Ctrl+P" #define KEYCONF_Search "Ctrl+f / KP_Divide" #define KEYCONF_SearchInvert "?" @@ -125,6 +126,11 @@ #define KEYCONF_SearchCacheLocal "Ctrl+Enter" #define KEYCONF_SearchCacheAll "" +#define KEYCONF_ShowSelectImage "Ctrl+I" +#define KEYCONF_DeleteSelectImage "" +#define KEYCONF_AboneSelectImage "" +#define KEYCONF_AboneSelectionRes "" + // IMAGE #define KEYCONF_CancelMosaic "c" #define KEYCONF_ZoomFitImage "x" diff -Nru jd-2.8.5-120826/src/control/keyconfig.cpp jd-2.8.6-130518/src/control/keyconfig.cpp --- jd-2.8.5-120826/src/control/keyconfig.cpp 2011-07-25 13:08:23.000000000 +0000 +++ jd-2.8.6-130518/src/control/keyconfig.cpp 2013-01-10 14:23:49.000000000 +0000 @@ -100,6 +100,7 @@ SETKEYMOTION( "Copy", KEYCONF_Copy ); SETKEYMOTION( "SelectAll", KEYCONF_SelectAll ); SETKEYMOTION( "AppendFavorite", KEYCONF_AppendFavorite ); + SETMOTION( "PreferenceView", KEYCONF_PreferenceView ); SETKEYMOTION( "Search", KEYCONF_Search ); SETKEYMOTION( "SearchInvert", KEYCONF_SearchInvert ); @@ -149,6 +150,11 @@ SETKEYMOTION( "SearchCacheLocal", KEYCONF_SearchCacheLocal ); SETKEYMOTION( "SearchCacheAll", KEYCONF_SearchCacheAll ); + SETKEYMOTION( "ShowSelectImage", KEYCONF_ShowSelectImage ); + SETKEYMOTION( "DeleteSelectImage", KEYCONF_DeleteSelectImage ); + SETKEYMOTION( "AboneSelectImage", KEYCONF_AboneSelectImage ); + SETKEYMOTION( "AboneSelectionRes", KEYCONF_AboneSelectionRes ); + // IMAGE SETKEYMOTION( "CancelMosaic", KEYCONF_CancelMosaic ); SETKEYMOTION( "ZoomFitImage", KEYCONF_ZoomFitImage ); diff -Nru jd-2.8.5-120826/src/control/keypref.cpp jd-2.8.6-130518/src/control/keypref.cpp --- jd-2.8.5-120826/src/control/keypref.cpp 2011-07-25 13:08:23.000000000 +0000 +++ jd-2.8.6-130518/src/control/keypref.cpp 2013-01-10 14:23:49.000000000 +0000 @@ -7,6 +7,7 @@ #include "controlid.h" #include "controlutil.h" +#include "global.h" using namespace CONTROL; @@ -123,6 +124,7 @@ append_row( CONTROL::Copy ); append_row( CONTROL::SelectAll ); append_row( CONTROL::AppendFavorite ); + append_row( CONTROL::PreferenceView ); append_row( CONTROL::Search ); append_row( CONTROL::SearchInvert ); @@ -192,6 +194,11 @@ append_row( CONTROL::LiveStartStop ); + append_row( CONTROL::ShowSelectImage ); + append_row( CONTROL::DeleteSelectImage, ITEM_NAME_SELECTDELIMG ); + append_row( CONTROL::AboneSelectImage, ITEM_NAME_SELECTABONEIMG ); + append_row( CONTROL::AboneSelectionRes ); + append_comment_row( "" ); append_comment_row( "■ " + CONTROL::get_mode_label( CONTROL::MODE_IMAGEVIEW ) ); append_row( CONTROL::CancelMosaic ); diff -Nru jd-2.8.5-120826/src/control/mousekeypref.cpp jd-2.8.6-130518/src/control/mousekeypref.cpp --- jd-2.8.5-120826/src/control/mousekeypref.cpp 2009-02-28 13:52:07.000000000 +0000 +++ jd-2.8.6-130518/src/control/mousekeypref.cpp 2013-01-19 07:12:56.000000000 +0000 @@ -46,13 +46,24 @@ bool InputDiag::on_key_press_event( GdkEventKey* event ) { - const guint key = event->keyval; + guint key = event->keyval; const bool ctrl = ( event->state ) & GDK_CONTROL_MASK; bool shift = ( event->state ) & GDK_SHIFT_MASK; const bool alt = ( event->state ) & GDK_MOD1_MASK; + const bool caps = ( event->state ) & GDK_LOCK_MASK; // caps lock if( m_mode & INPUTDIAG_MODE_KEY ){ + // caps lockされている場合は、アスキー文字を大文字小文字入れ替えて、capsを無視する + // Control::key_press()も参照のこと + if( caps ){ + if( key >= 'A' && key <= 'Z' ){ + key += 'a' - 'A'; + } else if( key >= 'a' && key <= 'z' ){ + key += 'A' - 'a'; + } + } + // keyがアスキー文字の場合は shift を無視する // KeyConfig::set_one_motion()も参照せよ if( CONTROL::is_ascii( key ) ) shift = false; @@ -525,7 +536,7 @@ // 行追加 -void MouseKeyPref::append_row( const int id ) +void MouseKeyPref::append_row( const int id, const std::string& label ) { Gtk::TreeModel::Row row; row = *( get_liststore()->append() ); @@ -533,7 +544,11 @@ const std::string motions = get_str_motions( id ); - row[ get_colums().m_col_label ] = CONTROL::get_label( id ); + if( label.empty() ){ + row[ get_colums().m_col_label ] = CONTROL::get_label( id ); + }else{ + row[ get_colums().m_col_label ] = label; + } row[ get_colums().m_col_motions ] = motions; row[ get_colums().m_col_id ] = id; if( motions != get_default_motions( id ) ) row[ get_colums().m_col_drawbg ] = true; diff -Nru jd-2.8.5-120826/src/control/mousekeypref.h jd-2.8.6-130518/src/control/mousekeypref.h --- jd-2.8.5-120826/src/control/mousekeypref.h 2008-10-27 14:43:27.000000000 +0000 +++ jd-2.8.6-130518/src/control/mousekeypref.h 2012-12-02 11:02:56.000000000 +0000 @@ -181,7 +181,7 @@ Glib::RefPtr< Gtk::ListStore >& get_liststore(){ return m_liststore; } MouseKeyTreeColumn& get_colums(){ return m_columns; } - void append_row( const int id ); + void append_row( const int id, const std::string& label = std::string() ); void append_comment_row( const std::string& comment ); virtual MouseKeyDiag* create_setting_diag( const int id, const std::string& str_motions ) = 0; diff -Nru jd-2.8.5-120826/src/core.cpp jd-2.8.6-130518/src/core.cpp --- jd-2.8.5-120826/src/core.cpp 2012-03-02 15:45:58.000000000 +0000 +++ jd-2.8.6-130518/src/core.cpp 2013-03-12 13:31:39.000000000 +0000 @@ -721,17 +721,17 @@ Glib::ustring menu_font = "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - ""; + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; Glib::ustring str_ui = "" @@ -739,290 +739,276 @@ // ファイル "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" "" // 表示 "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - - "" - "" - "" - "" - - "" - "" - "" - "" - - "" - "" - - "" - - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - - "" - "" - - "" - "" - "" - "" - "" - - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - - "" - "" - "" - "" - "" - "" - "" - "" - "" - - "" - "" - "" - "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + + "" + "" + "" + "" + + "" + "" + "" + "" + + "" + "" + + // 詳細設定 + "" + + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + + "" + "" + "" + "" + "" + + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + + "" + "" + "" + "" + "" + "" + "" + "" + "" + + "" + "" + "" + "" + + "" + "" + "" + "" + ""; - "" - "" - "" - "" - - "" - - + menu_font - - + "" - "" + str_ui += menu_font; + str_ui += + "" - "" - "" - "" - "" - - "" - "" - "" - "" - - "" - - "" - "" - "" - "" - "" - "" - "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + + "" + "" + "" + "" + "" + "" + "" - "" + "" "" // 履歴 - "" - "" - "" - "" + "" + "" + "" + "" // ツール "" - "" - "" - - "" - "" - - "" - "" - "" - "" - "" - - "" - "" - "" - "" - "" - - "" - "" - "" - "" - "" - "" - "" - "" - - "" - "" - - "" - "" - - "" - "" + "" + "" + "" + "" + + "" + "" + "" + "" + "" + + "" + "" + "" + "" + "" + + "" + "" + "" + "" + "" + "" + "" + "" + "" + + "" + "" + "" + "" + "" "" // 設定 "" - "" - "" - "" - "" - "" - "" - - "" - - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - - "" - - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - - ""; - + "" + "" + "" + "" + "" + "" + "" + + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; str_ui += menu_font; - str_ui += + "" - "" - "" - "" - "" - "" - "" - "" - "" - - "" - - "" - "" - "" - "" - "" - "" - "" - - "" + "" + "" + "" + "" + "" + "" + "" + "" + + "" + "" + "" + "" + "" + "" + "" + "" // プライバシー - "" - "" - "" - "" - "" - "" - "" - "" - - "" + "" + "" + "" + "" + "" + "" + "" + "" + "" // その他 - "" - "" - "" - "" - "" - "" - "" + "" + "" + "" + "" + "" + "" + "" - "" + "" // ヘルプ "" - "" - "" - "" - "" - "" - "" - "" + "" + "" + "" + "" + "" + "" + "" "" ""; @@ -1323,7 +1309,7 @@ -inline void toggle_sidebar_action( Glib::RefPtr< Gtk::ActionGroup >& group, const std::string& action, const std::string url ) +static inline void toggle_sidebar_action( Glib::RefPtr< Gtk::ActionGroup >& group, const std::string& action, const std::string url ) { Glib::RefPtr< Gtk::Action > act; Glib::RefPtr< Gtk::ToggleAction > tact; @@ -2344,10 +2330,28 @@ // 次スレ検索 else if( command.command == "open_board_next" ){ - // タブだらけになってしまうので実況中の場合はタブで開かない - const bool live = SESSION::is_live( command.arg1 ); - std::string str_tab = "newtab"; - if( live ) str_tab = "false"; + int tabpos = CONFIG::get_boardnexttab_pos(); + std::string str_tab; + std::string str_mode = ""; + switch (tabpos) { + case -1: // 2.8.5以前の動作 + { // タブだらけになってしまうので実況中の場合はタブで開かない + const bool live = SESSION::is_live( command.arg1 ); + str_tab = (live) ? "false" : "newtab"; + break; + } + case 1: // 新しいタブで開く + str_tab = "newtab"; + break; + case 2: // アクティブなタブを置き換える + str_tab = "false"; + break; + case 0: // 次スレ検索タブで開く + default: + str_tab = "replace"; + str_mode = "boardnext"; + break; + } BOARD::get_admin()->set_command( "open_view", command.url, @@ -2356,7 +2360,7 @@ // 詳しくは Admin::open_view() を参照せよ str_tab, // 開く位置 "false", // 既にビューを開いてるかチェックする - "", // 開き方のモード + str_mode, // 開き方のモード "NEXT", // モード diff -Nru jd-2.8.5-120826/src/dbimg/Makefile.am jd-2.8.6-130518/src/dbimg/Makefile.am --- jd-2.8.5-120826/src/dbimg/Makefile.am 2007-08-10 12:17:59.000000000 +0000 +++ jd-2.8.6-130518/src/dbimg/Makefile.am 2013-01-05 15:44:26.000000000 +0000 @@ -14,4 +14,4 @@ delimgcachediag.h AM_CXXFLAGS = @GTKMM_CFLAGS@ -INCLUDES = -I$(top_srcdir)/src +AM_CPPFLAGS = -I$(top_srcdir)/src diff -Nru jd-2.8.5-120826/src/dbimg/img.cpp jd-2.8.6-130518/src/dbimg/img.cpp --- jd-2.8.5-120826/src/dbimg/img.cpp 2011-01-10 02:11:16.000000000 +0000 +++ jd-2.8.6-130518/src/dbimg/img.cpp 2013-02-19 15:39:31.000000000 +0000 @@ -19,6 +19,7 @@ #include "cache.h" #include "session.h" #include "global.h" +#include "urlreplacemanager.h" #include #include @@ -68,6 +69,8 @@ set_priority_low(); + m_imgctrl = CORE::get_urlreplace_manager()->get_imgctrl( url ); + reset(); } @@ -300,6 +303,10 @@ if( ! m_url_alt.empty() ) data.url = m_url_alt; else data.url = m_url; + // Urlreplaceによるリファラ指定 + std::string referer; + if( CORE::get_urlreplace_manager()->referer( m_url, referer ) ) data.referer = referer; + if( !start_load( data ) ) receive_finish(); else CORE::core_set_command( "redraw", m_url ); } @@ -418,6 +425,7 @@ const bool Img::is_fake() { if( ! is_cached() ) return false; + if( m_imgctrl & CORE::IMGCTRL_GENUINE ) return false; bool ret = false; diff -Nru jd-2.8.5-120826/src/dbimg/img.h jd-2.8.6-130518/src/dbimg/img.h --- jd-2.8.5-120826/src/dbimg/img.h 2010-02-08 14:48:13.000000000 +0000 +++ jd-2.8.6-130518/src/dbimg/img.h 2013-02-19 15:39:31.000000000 +0000 @@ -22,6 +22,7 @@ std::string m_url_alt; // リダイレクトなどで使用するアドレス int m_count_redirect; // リダイレクト回数 + int m_imgctrl; // 画像コントロール int m_type; // 画像タイプ // 幅、高さ @@ -65,6 +66,8 @@ const bool is_wait() const{ return m_wait; } + const int get_imgctrl() const { return m_imgctrl; } + const int get_type() const { return m_type; } void set_type( const int type ){ m_type = type; } diff -Nru jd-2.8.5-120826/src/dbimg/imginterface.h jd-2.8.6-130518/src/dbimg/imginterface.h --- jd-2.8.5-120826/src/dbimg/imginterface.h 2010-02-08 14:48:13.000000000 +0000 +++ jd-2.8.6-130518/src/dbimg/imginterface.h 2013-03-30 05:23:47.000000000 +0000 @@ -31,7 +31,9 @@ T_WRITEFAILED, T_NOT_FOUND, T_NODATA, - T_UNKNOWN + + T_UNKNOWN, // 画像ではない + T_FORCEIMAGE, // 拡張子がなくても画像として扱う }; class Img; diff -Nru jd-2.8.5-120826/src/dbimg/imgroot.cpp jd-2.8.6-130518/src/dbimg/imgroot.cpp --- jd-2.8.5-120826/src/dbimg/imgroot.cpp 2011-03-23 15:01:45.000000000 +0000 +++ jd-2.8.6-130518/src/dbimg/imgroot.cpp 2013-02-23 06:21:01.000000000 +0000 @@ -17,6 +17,7 @@ #include "cache.h" #include "command.h" #include "prefdiagfactory.h" +#include "urlreplacemanager.h" #include @@ -164,11 +165,20 @@ int ImgRoot::get_type_ext( const char* url, int n ) { + // Urlreplaceによる画像コントロールを取得する + int imgctrl = CORE::get_urlreplace_manager()->get_imgctrl( url ); + + // URLに拡張子があっても画像として扱わない + if( imgctrl & CORE::IMGCTRL_FORCEBROWSER ) return T_UNKNOWN; + if( is_jpg( url, n ) ) return T_JPG; if( is_png( url, n ) ) return T_PNG; if( is_gif( url, n ) ) return T_GIF; if( is_bmp( url, n ) ) return T_BMP; + // URLに拡張子がない場合でも画像として扱うか + if( imgctrl & CORE::IMGCTRL_FORCEIMAGE ) return T_FORCEIMAGE; + return T_UNKNOWN; } diff -Nru jd-2.8.5-120826/src/dbtree/Makefile.am jd-2.8.6-130518/src/dbtree/Makefile.am --- jd-2.8.5-120826/src/dbtree/Makefile.am 2009-05-03 03:18:09.000000000 +0000 +++ jd-2.8.6-130518/src/dbtree/Makefile.am 2013-01-05 15:44:26.000000000 +0000 @@ -68,4 +68,4 @@ nodetreedummy.h AM_CXXFLAGS = @GTKMM_CFLAGS@ -INCLUDES = -I$(top_srcdir)/src +AM_CPPFLAGS = -I$(top_srcdir)/src diff -Nru jd-2.8.5-120826/src/dbtree/articlebase.cpp jd-2.8.6-130518/src/dbtree/articlebase.cpp --- jd-2.8.5-120826/src/dbtree/articlebase.cpp 2012-03-03 08:03:36.000000000 +0000 +++ jd-2.8.6-130518/src/dbtree/articlebase.cpp 2012-12-02 06:42:07.000000000 +0000 @@ -293,9 +293,7 @@ // std::list< int > ArticleBase::get_res_reference( const int number ) { - std::list< int > res_num; - res_num.push_back( number ); - return get_res_reference( res_num ); + return get_nodetree()->get_res_reference( number ); } @@ -956,6 +954,24 @@ } +// 書き込みマークセット +void ArticleBase::set_posted( const int number, const bool set ) +{ + if( number <= 0 || number > m_number_load ) return; + + // まだnodetreeが作られてなくて情報が得られてないのでnodetreeを作って情報取得 + if( ! m_vec_posted.size() ) get_nodetree(); + + if( ! m_vec_posted.size() ) m_vec_posted.resize( MAX_RESNUMBER ); + + m_save_info = true; + m_vec_posted[ number ] = set; + + // nodetreeに情報反映 + m_nodetree->set_posted( number, set ); +} + + // 書き込み履歴のリセット void ArticleBase::clear_post_history() { diff -Nru jd-2.8.5-120826/src/dbtree/articlebase.h jd-2.8.6-130518/src/dbtree/articlebase.h --- jd-2.8.5-120826/src/dbtree/articlebase.h 2012-03-03 08:03:36.000000000 +0000 +++ jd-2.8.6-130518/src/dbtree/articlebase.h 2012-12-02 06:42:07.000000000 +0000 @@ -252,6 +252,9 @@ // 自分の書き込みにレスしたか const bool is_refer_posted( const int number ); + // 書き込みマークセット + void set_posted( const int number, const bool set ); + // 書き込み履歴のリセット void clear_post_history(); diff -Nru jd-2.8.5-120826/src/dbtree/board2chcompati.cpp jd-2.8.6-130518/src/dbtree/board2chcompati.cpp --- jd-2.8.5-120826/src/dbtree/board2chcompati.cpp 2011-02-13 14:14:24.000000000 +0000 +++ jd-2.8.6-130518/src/dbtree/board2chcompati.cpp 2013-01-12 15:06:22.000000000 +0000 @@ -339,7 +339,6 @@ const int max_subject = 1024; const char* pos = str_subject_txt; - char str_tmp[ max_subject ]; while( *pos != '\0' ){ @@ -390,9 +389,13 @@ // レス数取得 ++pos; int i = 0; - while( *pos != ')' && *pos != '\0' && *pos != '\n' && i < 16 ) str_num[ i++ ] = *( pos++ ); + while( '0' <= *pos && *pos <= '9' && i < 16 ) str_num[ i++ ] = *( pos++ ); // 壊れてる + if( i == 0 ){ + MISC::ERRMSG( "subject.txt is broken (res)" ); + break; + } if( *pos == '\0' ) break; if( *pos == '\n' ) { ++pos; continue; } @@ -402,14 +405,13 @@ // id, subject, number 取得 ARTICLE_INFO artinfo; - memcpy( str_tmp, str_id_dat, lng_id_dat ); - str_tmp[ lng_id_dat ] = '\0'; - artinfo.id = str_tmp; - - memcpy( str_tmp, str_subject, lng_subject ); - if( str_tmp[ lng_subject-1 ] == ' ' ) lng_subject--; // 2chのsubject.txtは()の前に空白が一つ入る - str_tmp[ lng_subject ] = '\0'; - artinfo.subject = str_tmp; + artinfo.id.assign( str_id_dat, lng_id_dat ); + + if( str_subject[ lng_subject-1 ] == ' ' ){ + lng_subject--; // 2chのsubject.txtは()の前に空白が一つ入る + } + artinfo.subject.assign( str_subject, lng_subject ); + if( exist_amp ){ artinfo.subject = MISC::replace_str( artinfo.subject, "<", "<" ); artinfo.subject = MISC::replace_str( artinfo.subject, ">", ">" ); diff -Nru jd-2.8.5-120826/src/dbtree/boardjbbs.cpp jd-2.8.6-130518/src/dbtree/boardjbbs.cpp --- jd-2.8.5-120826/src/dbtree/boardjbbs.cpp 2010-04-01 16:35:28.000000000 +0000 +++ jd-2.8.6-130518/src/dbtree/boardjbbs.cpp 2013-01-12 15:06:22.000000000 +0000 @@ -155,7 +155,6 @@ #endif const char* pos = str_subject_txt; - char str_tmp[ 1024 ]; while( *pos != '\0' ){ @@ -191,9 +190,13 @@ // レス数取得 ++pos; int i = 0; - while( *pos != ')' && *pos != '\0' && *pos != '\n' && i < 16 ) str_num[ i++ ] = *( pos++ ); + while( '0' <= *pos && *pos <= '9' && i < 16 ) str_num[ i++ ] = *( pos++ ); // 壊れてる + if( i == 0 ){ + MISC::ERRMSG( "subject.txt is broken (res)" ); + break; + } if( *pos == '\0' ) break; if( *pos == '\n' ) { ++pos; continue; } @@ -203,13 +206,11 @@ // id, subject, number 取得 ARTICLE_INFO artinfo; - memcpy( str_tmp, str_id_dat, lng_id_dat ); - str_tmp[ lng_id_dat ] = '\0'; - artinfo.id = MISC::remove_space( str_tmp ); - - memcpy( str_tmp, str_subject, lng_subject ); - str_tmp[ lng_subject ] = '\0'; - artinfo.subject = MISC::remove_space( str_tmp ); + artinfo.id.assign( str_id_dat, lng_id_dat ); + artinfo.id = MISC::remove_space( artinfo.id ); + + artinfo.subject.assign( str_subject, lng_subject ); + artinfo.subject = MISC::remove_space( artinfo.subject ); artinfo.subject = MISC::replace_str( artinfo.subject, "<", "<" ); artinfo.subject = MISC::replace_str( artinfo.subject, ">", ">" ); diff -Nru jd-2.8.5-120826/src/dbtree/boardmachi.cpp jd-2.8.6-130518/src/dbtree/boardmachi.cpp --- jd-2.8.5-120826/src/dbtree/boardmachi.cpp 2011-01-10 02:11:16.000000000 +0000 +++ jd-2.8.6-130518/src/dbtree/boardmachi.cpp 2013-01-12 15:06:22.000000000 +0000 @@ -215,7 +215,6 @@ #endif const char* pos = str_subject_txt; - char str_tmp[ 1024 ]; while( *pos != '\0' ){ @@ -251,9 +250,13 @@ // レス数取得 ++pos; int i = 0; - while( *pos != ')' && *pos != '\0' && *pos != '\n' && i < 16 ) str_num[ i++ ] = *( pos++ ); + while( '0' <= *pos && *pos <= '9' && i < 16 ) str_num[ i++ ] = *( pos++ ); // 壊れてる + if( i == 0 ){ + MISC::ERRMSG( "subject.txt is broken (res)" ); + break; + } if( *pos == '\0' ) break; if( *pos == '\n' ) { ++pos; continue; } @@ -263,13 +266,11 @@ // id, subject, number 取得 ARTICLE_INFO artinfo; - memcpy( str_tmp, str_id_dat, lng_id_dat ); - str_tmp[ lng_id_dat ] = '\0'; - artinfo.id = MISC::remove_space( str_tmp ); - - memcpy( str_tmp, str_subject, lng_subject ); - str_tmp[ lng_subject ] = '\0'; - artinfo.subject = MISC::remove_space( str_tmp ); + artinfo.id.assign( str_id_dat, lng_id_dat ); + artinfo.id = MISC::remove_space( artinfo.id ); + + artinfo.subject.assign( str_subject, lng_subject ); + artinfo.subject = MISC::remove_space( artinfo.subject ); artinfo.subject = MISC::replace_str( artinfo.subject, "<", "<" ); artinfo.subject = MISC::replace_str( artinfo.subject, ">", ">" ); diff -Nru jd-2.8.5-120826/src/dbtree/node.h jd-2.8.6-130518/src/dbtree/node.h --- jd-2.8.5-120826/src/dbtree/node.h 2011-07-27 15:53:11.000000000 +0000 +++ jd-2.8.6-130518/src/dbtree/node.h 2013-03-03 04:30:00.000000000 +0000 @@ -119,6 +119,7 @@ char* text; unsigned char color_text; // 色 bool bold; + char fontid; // fontid.h // ヘッダ拡張情報 HEADERINFO* headinfo; diff -Nru jd-2.8.5-120826/src/dbtree/nodetreebase.cpp jd-2.8.6-130518/src/dbtree/nodetreebase.cpp --- jd-2.8.5-120826/src/dbtree/nodetreebase.cpp 2012-02-13 15:17:31.000000000 +0000 +++ jd-2.8.6-130518/src/dbtree/nodetreebase.cpp 2013-03-30 05:23:47.000000000 +0000 @@ -21,9 +21,11 @@ #include "global.h" #include "httpcode.h" #include "colorid.h" +#include "fontid.h" #include "command.h" #include "cache.h" #include "session.h" +#include "urlreplacemanager.h" #include #include @@ -50,7 +52,9 @@ MAX_LINK_DIGIT = 4, // レスアンカーでMAX_LINK_DIGIT 桁までリンクにする MAXSISE_OF_LINES = 512 * 1024, // ロード時に1回の呼び出しで読み込まれる最大データサイズ - SIZE_OF_HEAP = MAXSISE_OF_LINES + 64 + SIZE_OF_HEAP = MAXSISE_OF_LINES + 64, + + INITIAL_RES_BUFSIZE = 128, // レスの文字列を返すときの初期バッファサイズ }; @@ -113,6 +117,9 @@ m_num_id[ LINK_HIGH ] = CONFIG::get_num_id_high(); m_num_id[ LINK_LOW ] = CONFIG::get_num_id_low(); + // レスにアスキーアートがあると判定する正規表現 + m_aa_regex = CONFIG::get_regex_res_aa(); + #ifdef _DEBUG std::cout << "NodeTreeBase::NodeTreeBase url = " << m_url << " modified = " << get_date_modified() << " noname = " << m_default_noname << std::endl; @@ -401,6 +408,17 @@ // +// number番のレスを参照しているレス番号をリストにして取得 +// +std::list< int > NodeTreeBase::get_res_reference( const int number ) +{ + std::list< int > res_num; + res_num.push_back( number ); + return get_res_reference( res_num ); +} + + +// // res_num に含まれるレスを参照しているレス番号をリストにして取得 // std::list< int > NodeTreeBase::get_res_reference( const std::list< int >& res_num ) @@ -478,7 +496,49 @@ return list_resnum; } - + + +// +// number番のレスに含まれるレスアンカーをリストにして取得 +// +std::list< ANCINFO* > NodeTreeBase::get_res_anchors( const int number ) +{ + std::list< ANCINFO* > list_resnum; + + NODE* head = res_header( number ); + if( head && head->headinfo + && ! head->headinfo->abone ){ + + for( int block = 0; block < BLOCK_NUM; ++block ){ + + NODE* node = head->headinfo->block[ block ]; + while( node ){ + + // アンカーノードの時は node->linkinfo->ancinfo != NULL; + if( node->type == NODE_LINK + && node->linkinfo->ancinfo ){ + + for(int anc = 0; ; ++anc){ + + ANCINFO* anchor = &( node->linkinfo->ancinfo[ anc ] ); + if( anchor->anc_from == 0 ) break; + + // >>1-1000 みたいなアンカーは弾く + if( anchor->anc_to - anchor->anc_from < RANGE_REF ){ + list_resnum.push_back( anchor ); + } + } + } + node = node->next_node; + + } // while( node ) + + } // for( block ) + + } // if( head ) + return list_resnum; +} + // // query を含むレス番号をリストにして取得 @@ -578,6 +638,7 @@ std::string ref_prefix; if( ref ) ref_prefix = CONFIG::get_ref_prefix(); + str_res.reserve( INITIAL_RES_BUFSIZE ); str_res += ref_prefix; NODE* node; @@ -742,6 +803,7 @@ NODE* tmpnode = ( NODE* ) m_heap.heap_alloc( sizeof( NODE ) ); tmpnode->id_header = m_id_header; + tmpnode->fontid = FONT_EMPTY; // フォントID未設定 if( m_node_previous ) m_node_previous->next_node = tmpnode; m_node_previous = tmpnode; @@ -861,14 +923,18 @@ NODE* NodeTreeBase::create_node_link( const char* text, const int n, const char* link, const int n_link, const int color_text, const bool bold ) { NODE* tmpnode = create_node_ntext( text, n, color_text, bold ); + if( tmpnode ){ tmpnode->type = NODE_LINK; - + + // リンク情報作成 + char *tmplink = ( char* )m_heap.heap_alloc( n_link +4 ); + memcpy( tmplink, link, n_link ); + tmplink[ n_link ] = '\0'; + // リンク情報セット tmpnode->linkinfo = ( LINKINFO* )m_heap.heap_alloc( sizeof( LINKINFO ) ); - - tmpnode->linkinfo->link = ( char* )m_heap.heap_alloc( n_link +4 ); - memcpy( tmpnode->linkinfo->link, link, n_link ); tmpnode->linkinfo->link[ n_link ] = '\0'; + tmpnode->linkinfo->link = tmplink; } return tmpnode; @@ -901,11 +967,14 @@ NODE* tmpnode = create_node(); tmpnode->type = NODE_SSSP; + // リンク情報作成 + char *tmplink = ( char* )m_heap.heap_alloc( n_link +4 ); + memcpy( tmplink, link, n_link ); + tmplink[ n_link ] = '\0'; + // リンク情報セット tmpnode->linkinfo = ( LINKINFO* )m_heap.heap_alloc( sizeof( LINKINFO ) ); - tmpnode->linkinfo->link = ( char* )m_heap.heap_alloc( n_link +4 ); - memcpy( tmpnode->linkinfo->link, link, n_link ); - tmpnode->linkinfo->link[ n_link ] = '\0'; + tmpnode->linkinfo->link = tmplink; tmpnode->linkinfo->image = true; tmpnode->linkinfo->imglink = tmpnode->linkinfo->link; @@ -929,6 +998,27 @@ // +// サムネイル画像ノード ( youtubeなどのサムネイル表示用 ) +// +NODE* NodeTreeBase::create_node_thumbnail( const char* text, const int n, const char* link, const int n_link, const char* thumb, const int n_thumb, const int color_text, const bool bold ) +{ + NODE* tmpnode = create_node_link( text, n, link, n_link, color_text, bold ); + + if( tmpnode ){ + // サムネイル画像のURLをセット + char *tmpthumb = ( char* )m_heap.heap_alloc( n_thumb +4 ); + memcpy( tmpthumb, thumb, n_thumb ); + tmpthumb[ n_thumb ] = '\0'; + + tmpnode->linkinfo->imglink = tmpthumb; + } + + return tmpnode; +} + + + +// // テキストノード作成 // NODE* NodeTreeBase::create_node_text( const char* text, const int color_text, const bool bold ) @@ -960,70 +1050,6 @@ } -// -// Youtube ノード -// -NODE* NodeTreeBase::create_node_youtube( const char* text, const int n, const char* link, const int n_link, const int color_text, const bool bold ) -{ - NODE* tmpnode = create_node_link( text, n, link, n_link, color_text, bold ); - - // 「http://www.youtube.com」の後にセット - int pos = 22; - - if( *( link + (pos++) ) == '/' - && *( link + (pos++) ) == 'w' - && *( link + (pos++) ) == 'a' - && *( link + (pos++) ) == 't' - && *( link + (pos++) ) == 'c' - && *( link + (pos++) ) == 'h' ){ - - // 「?v=」または「&v=」を探す - while ( pos < n_link - && ! ( ( *( link + pos ) == '?' || *( link + pos ) == '&' ) - && *( link + pos + 1 ) == 'v' - && *( link + pos + 2 ) == '=' ) ){ - pos++; - } - if( pos == n_link ){ - return tmpnode; // 見つからない - } - pos += 3; - - // 「v=...」をidに格納 - char id[ LNG_LINK +16 ]; - int lng_id = 0; - while( pos < n_link - && *( link + pos ) != '&' - && *( link + pos ) != '#' ){ - id[ lng_id++ ] = *( link + (pos++) ); - } - - // 画像のURL「http://img.youtube.com/vi//0.jpg」を生成 - const char *server = "http://img.youtube.com/vi/"; - const char *file = "/0.jpg"; - char thumb[ LNG_LINK +16 ]; - int lng_thumb = strlen( server ); - const int lng_file = strlen( file ); - - memmove( thumb, server, lng_thumb ); - memmove( thumb + lng_thumb, id, lng_id ); - lng_thumb += lng_id; - memmove( thumb + lng_thumb, file, lng_file ); - lng_thumb += lng_file; - - // 画像のURLをセット - tmpnode->linkinfo->imglink = ( char* )m_heap.heap_alloc( lng_thumb +4 ); - memcpy( tmpnode->linkinfo->imglink, thumb, lng_thumb ); - tmpnode->linkinfo->imglink[ lng_thumb ] = '\0'; - -#ifdef _DEBUG - std::cout << "NodeTreeBase::create_node_youtube url = " << tmpnode->linkinfo->imglink << std::endl; -#endif - } - - return tmpnode; -} - // // html をコメントとして追加 @@ -1463,6 +1489,9 @@ // 参照数更新 update_reference( num_before +1, m_id_header ); + // フォント判定 + update_fontid( num_before +1, m_id_header ); + // articlebase クラスに状態が変わったことを知らせる m_sig_updated.emit(); } @@ -2124,7 +2153,8 @@ // アンカーのチェック int n_in = 0; int n_out = 0; - char tmpstr[ LNG_LINK +16 ], tmplink[ LNG_LINK +16 ]; + char tmpstr[ LNG_LINK +16 ]; // 画面に表示する文字列 + char tmplink[ LNG_LINK +16 ]; // 編集したリンク文字列 int lng_str = 0, lng_link = strlen( PROTO_ANCHORE ); ANCINFO ancinfo[ MAX_ANCINFO ]; int lng_anc = 0; @@ -2169,50 +2199,82 @@ /////////////////////// // リンク(http)のチェック - const int linktype = check_link( pos, (int)( pos_end - pos ), n_in, tmplink, LNG_LINK ); + char tmpreplace[ LNG_LINK +16 ]; // Urlreplaceで変換した後のリンク文字列 + int lng_replace = 0; + int linktype = check_link( pos, (int)( pos_end - pos ), n_in, tmplink, LNG_LINK ); + if( linktype != MISC::SCHEME_NONE ){ + // リンクノードで実際にアクセスするURLの変換 + while( remove_imenu( tmplink ) ); // ime.nuなどの除去 + lng_link = convert_amp( tmplink, strlen( tmplink ) ); // & → & + + // Urlreplaceによる正規表現変換 + std::string tmpurl( tmplink, lng_link ); + if( CORE::get_urlreplace_manager()->exec( tmpurl ) == false ){ + // 変換されてない + lng_replace = lng_link; + memcpy( tmpreplace, tmplink, lng_replace +1 ); + + } else { + if( tmpurl.size() > LNG_LINK ){ + MISC::ERRMSG( std::string( "too long replaced url : " ) + tmplink ); + + // 変換後のURLが長すぎるので、元のURLのままにする + lng_replace = lng_link; + memcpy( tmpreplace, tmplink, lng_replace +1 ); + } else { + // 正常に変換された + lng_replace = tmpurl.size(); + memcpy( tmpreplace, tmpurl.c_str(), lng_replace +1 ); + + // 正規表現変換の結果、スキームだけの簡易チェックをする + int delim_pos = 0; + if( MISC::SCHEME_NONE == MISC::is_url_scheme( tmpreplace, &delim_pos ) ){ + // スキーム http:// が消えていた + linktype = MISC::SCHEME_NONE; + } + } + } + } + // リンクノードか再チェック if( linktype != MISC::SCHEME_NONE ){ - // フラッシュしてからリンクノードつくる create_node_ntext( m_parsed_text, lng_text, color_text, bold ); lng_text = 0; - while( remove_imenu( tmplink ) ); - - lng_link = strlen( tmplink ); + // リンクノードの表示テキスト + memcpy( tmpstr, pos, n_in ); + tmpstr[ n_in ] = '\0'; + lng_str = convert_amp( tmpstr, n_in ); // & → & // ssspアイコン if( enable_sssp && linktype == MISC::SCHEME_SSSP ){ - create_node_sssp( tmplink, lng_link ); + create_node_sssp( tmpreplace, lng_replace ); enable_sssp = false; } - // 画像リンク - else if( DBIMG::get_type_ext( tmplink, lng_link ) != DBIMG::T_UNKNOWN ){ - create_node_img( pos, n_in, tmplink , lng_link, COLOR_IMG_NOCACHE, bold ); - } + else { + // Urlreplaceによる画像コントロールを取得する + int imgctrl = CORE::get_urlreplace_manager()->get_imgctrl( std::string( tmpreplace, lng_replace ) ); - // youtube - else if( *( tmplink + 11) == 'y' - && *( tmplink + 12) == 'o' - && *( tmplink + 13) == 'u' - && *( tmplink + 14) == 't' - && *( tmplink + 15) == 'u' - && *( tmplink + 16) == 'b' - && *( tmplink + 17) == 'e' - ){ + // youtubeなどのサムネイル画像リンク + if( imgctrl & CORE::IMGCTRL_THUMBNAIL ){ + create_node_thumbnail( tmpstr, lng_str, tmplink , lng_link, tmpreplace, lng_replace, COLOR_CHAR_LINK, bold ); + } - create_node_youtube( pos, n_in, tmplink , lng_link, COLOR_CHAR_LINK, bold ); + // 画像リンク + else if( DBIMG::get_type_ext( tmpreplace, lng_replace ) != DBIMG::T_UNKNOWN ){ + create_node_img( tmpstr, lng_str, tmpreplace , lng_replace, COLOR_IMG_NOCACHE, bold ); + } + + // 一般リンク + else create_node_link( tmpstr, lng_str, tmpreplace , lng_replace, COLOR_CHAR_LINK, bold ); } - // 一般リンク - else create_node_link( pos, n_in, tmplink , lng_link, COLOR_CHAR_LINK, bold ); - pos += n_in; // forのところで++されるので--しておく --pos; continue; } - /////////////////////// // 特殊文字デコード @@ -2346,6 +2408,15 @@ continue; } + // amp + else if( *pos == '&' && ( *( pos + 1 ) == 'a' && *( pos + 2 ) == 'm' && *( pos + 3 ) == 'p' && *( pos + 4 ) == ';' ) ){ + + *(pos_write++) = '&'; + pos += 4; + + continue; + } + // quot else if( *pos == '&' && ( *( pos + 1 ) == 'q' && *( pos + 2 ) == 'u' && *( pos + 3 ) == 'o' && *( pos + 4 ) == 't' && *( pos + 5 ) == ';' ) ){ @@ -2561,6 +2632,8 @@ // str_in : 入力文字列の先頭アドレス // lng_str : str_inのバッファサイズ // lng_link : str_linkのバッファサイズ +// linktype : is_url_scheme()のリタンコード +// delim_pos : is_url_scheme()で得たスキーム文字列の長さ // // 出力 // n_in : str_in から何バイト読み取ったか @@ -2570,106 +2643,107 @@ // // 注意 : MISC::is_url_scheme() と MISC::is_url_char() の仕様に合わせる事 // -const int NodeTreeBase::check_link( const char* str_in, const int lng_in, int& n_in, char* str_link, const int lng_link ) +const int NodeTreeBase::check_link_impl( const char* str_in, const int lng_in, int& n_in, char* str_link, const int lng_link, const int linktype, const int delim_pos ) { - // http://, https://, ftp://, ttp(s)://, tp(s):// のチェック - int delim_pos = 0; - const int linktype = MISC::is_url_scheme( str_in, &delim_pos ); - - if( linktype == MISC::SCHEME_NONE ) return MISC::SCHEME_NONE; - // CONFIG::get_loose_url() == true の時はRFCで規定されていない文字も含める const bool loose_url = CONFIG::get_loose_url(); // リンクの長さを取得 n_in = delim_pos; - bool url_encode = false; int n_in_tmp, n_out_tmp; - char cchar = *( str_in + n_in ); - - while( + char buf[16]; - // バッファサイズを超えない - n_in < lng_in + while( n_in < lng_in ){ // URLとして扱う文字かどうか - && MISC::is_url_char( &cchar, loose_url ) + if ( MISC::is_url_char( str_in + n_in, loose_url ) == false ) break; - // HTML特殊文字は除く( &〜; ) - && ! ( - *( str_in + n_in ) == '&' - && DBTREE::decode_char( str_in + n_in, n_in_tmp, NULL, n_out_tmp, true ) != DBTREE::NODE_NONE - ) - ){ + // HTML特殊文字( &〜; ) + if ( *( str_in + n_in ) == '&' && + DBTREE::decode_char( str_in + n_in, n_in_tmp, buf, n_out_tmp, false ) != DBTREE::NODE_NONE ){ - // "^"と"|"はエンコードする - // "[]"はダウンローダに渡す用途のためにエンコードしないでおく - if( loose_url && ( cchar == '^' || cchar == '|' ) ) url_encode = true; + // デコード結果が"&(&)"でないもの + if( n_out_tmp != 1 || buf[0] != '&' ) break; + } - ++n_in; - cchar = *( str_in + n_in ); + n_in++; } // URLとして短かすぎる場合は除外する( 最短ドメイン名の例 "1.cc" ) if( n_in - delim_pos < 4 ) return MISC::SCHEME_NONE; - int offset = 0; - if( linktype == MISC::SCHEME_TTP || linktype == MISC::SCHEME_TP ){ // ttp://, tp:// の場合、リンクの先頭にhを補完 + // URL出力バッファより長いときも除外する( 一般に256バイトを超えるとキャッシュをファイル名として扱えなくなる ) + if( lng_link <= n_in ) return MISC::SCHEME_NONE; - str_link[ 0 ] = 'h'; - offset = 1; + char *pos = str_link; - if( linktype == MISC::SCHEME_TP ){ // tp:// の場合、さらにリンク先頭にtを補完 - str_link[ 1 ] = 't'; - offset = 2; - } - } + // URLスキームを修正 + int str_pos = 0; + switch( linktype ){ + + // ttp -> http + case MISC::SCHEME_TTP: + + if( n_in + 1 >= lng_link ) return MISC::SCHEME_NONE; + + *pos = 'h'; + pos++; + break; + + // tp -> http + case MISC::SCHEME_TP: - if( n_in + offset >= lng_link ) return MISC::SCHEME_NONE; + if( n_in + 2 >= lng_link ) return MISC::SCHEME_NONE; - if( ! url_encode ){ - memcpy( str_link + offset, str_in, n_in ); - str_link[ n_in + offset ] = '\0'; + *pos = 'h'; + *(++pos) = 't'; + pos++; + break; + + // sssp -> http + case MISC::SCHEME_SSSP: + + *pos = 'h'; + *(++pos) = 't'; + *(++pos) = 't'; + pos++; + str_pos = 3; + break; } - else{ // URLエンコードが必要な場合 - char *pos = str_link + offset; - int tmp_out = offset; - for( int i = 0; i < n_in; ++i, ++pos ){ + // srr_inの文字列をstr_linkにコピー + int i = str_pos; + for( ; i < n_in; i++, pos++ ){ - if( str_in[ i ] == '^' ){ // '^' -> %5e - *( pos++ ) = '%'; - *( pos++ ) = '5'; - *pos = 'e'; - tmp_out += 3; - } - else if( str_in[ i ] == '|' ){ // '|' -> %7c - *( pos++ ) = '%'; - *( pos++ ) = '7'; - *pos = 'c'; - tmp_out += 3; - } - else{ - *pos = str_in[ i ]; - ++tmp_out; + *pos = str_in[ i ]; + + // loose_urlで含める"^"と"|"をエンコードする + // "[]"はダウンローダに渡す用途のためにエンコードしないでおく + if( loose_url == true ){ + + if( str_in[ i ] == '^' ){ + + // '^' → "%5E"(+2Byte) + if( n_in + 2 >= lng_link ) return MISC::SCHEME_NONE; + + *pos = '%'; + *(++pos) = '5'; + *(++pos) = 'E'; } + else if( str_in[ i ] == '|' ){ - if( tmp_out >= lng_link ){ -#ifdef _DEBUG - std::cout << " tmp_out = " << tmp_out << " lng_link = " << lng_link << " n_in + offset = " << n_in + offset << std::endl; -#endif - return MISC::SCHEME_NONE; + // '|' → "%7C"(+2Byte) + if( n_in + 2 >= lng_link ) return MISC::SCHEME_NONE; + + *pos = '%'; + *(++pos) = '7'; + *(++pos) = 'C'; } } - *pos = '\0'; } - // sssp -> http - if( linktype == MISC::SCHEME_SSSP ){ - str_link[ 0 ] = 'h'; - str_link[ 1 ] = 't'; - str_link[ 2 ] = 't'; - } + // str_linkの終端 + *pos = '\0'; #ifdef _DEBUG std::cout << str_link << std::endl @@ -2763,6 +2837,9 @@ // 参照状態更新 clear_reference(); update_reference( 1, m_id_header ); + + // フォント判定更新 + update_fontid( 1, m_id_header ); } @@ -3397,6 +3474,62 @@ } +// +// from_number番から to_number 番までのレスのフォント判定を更新 +// +void NodeTreeBase::update_fontid( const int from_number, const int to_number ) +{ + if( empty() ) return; + if( to_number < from_number ) return; + for( int i = from_number ; i <= to_number; ++i ) check_fontid( i ); +} + + +// +// number番のレスのフォント判定を更新 +// +void NodeTreeBase::check_fontid( const int number ) +{ + NODE* head = res_header( number ); + if( ! head ) return; + if( ! head->headinfo ) return; + if( head->fontid != FONT_EMPTY ) return; + + // ヘッダノードには、フォント判定済みの意味を兼ねて、デフォルトフォントを設定しておく + head->fontid = FONT_DEFAULT; + + char fontid_mes = FONT_DEFAULT; // 本文のフォント(fontid.h) + + const std::string res_str = get_res_str( number ); + JDLIB::Regex regex; + const size_t offset = 0; + const bool icase = false; + const bool newline = true; + const bool usemigemo = false; + const bool wchar = false; + + // AAフォント判定 + if( ! m_aa_regex.empty() ) { + if( regex.exec( m_aa_regex, res_str, offset, icase, newline, usemigemo, wchar ) ){ + fontid_mes = FONT_AA; +#ifdef _DEBUG + std::cout << "NodeTreeBase::check_fontid() fontid = " << FONT_AA + << " res = " << number << std::endl; +#endif + } + } + + // 本文のフォントを設定 + if( fontid_mes != FONT_DEFAULT ){ + NODE *node = head->headinfo->block[ BLOCK_MES ]; + while (node) { + node->fontid = fontid_mes; + node = node->next_node; + } + } +} + + // @@ -3443,6 +3576,34 @@ } +// 文字列中の"&"を"&"に変換する +int NodeTreeBase::convert_amp( char* text, const int n ) +{ + int m = n; + + int i; + for( i = 0; i < m; i++ ){ + + if( text[ i ] == '&' && + m > (i + 4) && + text[i + 1] == 'a' && + text[i + 2] == 'm' && + text[i + 3] == 'p' && + text[i + 4] == ';' ){ + + // &の次, &の次, &の次からの長さ + memmove( text + i + 1, text + i + 5, n - i - 5 ); + + // "amp;"の分減らす + m -= 4; + } + } + + text[m] = '\0'; + return m; +} + + // 自分の書き込みにレスしたか const bool NodeTreeBase::is_refer_posted( const int number ) { @@ -3453,6 +3614,52 @@ } +// 書き込みマークセット +void NodeTreeBase::set_posted( const int number, const bool set ) +{ + if( ! m_vec_posted.size() ) m_vec_posted.resize( MAX_RESNUMBER ); + if( ! m_vec_refer_posted.size() ) m_vec_refer_posted.resize( MAX_RESNUMBER ); + + m_vec_posted[ number ] = set; + + // 自分の書き込みに対するレス + std::list< int > res_num = get_res_reference( number ); + std::list< int >::const_iterator it_res = res_num.begin(); + + // レスされたマークを設定する + if( set ){ + for( ; it_res != res_num.end(); ++it_res ){ + const int n = ( *it_res ); + m_vec_refer_posted[ n ] = true; + } + } + + // レスされてなくなったので、マークを解除する + else{ + for( ; it_res != res_num.end(); ++it_res ){ + const int n = ( *it_res ); + + // レスアンカーのリストを取得 + std::list< ANCINFO* > anchors = get_res_anchors( n ); + std::list< ANCINFO* >::const_iterator it_anchor = anchors.begin(); + for( ; it_anchor != anchors.end(); ++it_anchor ){ + + // 他の自分の書き込みに対するレスになっていないか? + ANCINFO* anchor = ( *it_anchor ); + for( int i = anchor->anc_from; i <= anchor->anc_to; i++ ){ + // 他の自分の書き込みに対するレス + if( m_vec_posted[ i ] ) goto KEEP_POSTMARK; + } + } + + // マークを解除する + m_vec_refer_posted[ n ] = false; +KEEP_POSTMARK:; + } + } +} + + // 書き込み履歴のリセット void NodeTreeBase::clear_post_history() { diff -Nru jd-2.8.5-120826/src/dbtree/nodetreebase.h jd-2.8.6-130518/src/dbtree/nodetreebase.h --- jd-2.8.5-120826/src/dbtree/nodetreebase.h 2011-07-30 14:19:45.000000000 +0000 +++ jd-2.8.6-130518/src/dbtree/nodetreebase.h 2013-03-30 05:23:47.000000000 +0000 @@ -12,6 +12,7 @@ #include "skeleton/loadable.h" #include "jdlib/heap.h" +#include "jdlib/miscutil.h" #include #include @@ -122,6 +123,9 @@ // パース用雑用変数 NODE* m_node_previous; + // AA判定用 + std::string m_aa_regex; + // その他のエラーメッセージ std::string m_ext_err; @@ -194,6 +198,9 @@ // 含まれる URL をリストにして取得 std::list< std::string > get_urls(); + // number番のレスを参照しているレス番号をリストにして取得 + std::list< int > get_res_reference( const int number ); + // res_num に含まれるレスを参照しているレス番号をリストにして取得 std::list< int > get_res_reference( const std::list< int >& res_num ); @@ -246,6 +253,9 @@ // 自分の書き込みにレスしたか const bool is_refer_posted( const int number ); + // 書き込みマークセット + void set_posted( const int number, const bool set ); + // 書き込み履歴のリセット void clear_post_history(); @@ -290,7 +300,7 @@ NODE* create_node_img( const char* text, const int n, const char* link, const int n_link, const int color_text, const bool bold ); NODE* create_node_text( const char* text, const int color_text, const bool bold = false ); NODE* create_node_ntext( const char* text, const int n, const int color_text, const bool bold = false ); - NODE* create_node_youtube( const char* text, const int n, const char* link, const int n_link, const int color_text, const bool bold ); + NODE* create_node_thumbnail( const char* text, const int n, const char* link, const int n_link, const char* thumb, const int n_thumb, const int color_text, const bool bold ); // 以下、構文解析用関数 void add_raw_lines( char* rawines, size_t size ); @@ -315,6 +325,7 @@ const bool check_anchor( const int mode, const char* str_in, int& n, char* str_out, char* str_link, int lng_link, ANCINFO* ancinfo ); const int check_link( const char* str_in, const int lng_in, int& n_in, char* str_link, const int lng_link ); + const int check_link_impl( const char* str_in, const int lng_in, int& n_in, char* str_link, const int lng_link, const int linktype, const int delim_pos ); // あぼーんのクリア void clear_abone(); @@ -331,6 +342,9 @@ const bool check_abone_chain( const int number ); + // number番のレスに含まれるレスアンカーをリストにして取得 + std::list< ANCINFO* > get_res_anchors( const int number ); + // 参照数(num_reference)と色のクリア void clear_reference(); @@ -357,9 +371,36 @@ // IDノードの色も変更する void set_num_id_name( NODE* header, const int num_id_name, NODE* pre_id_name_header ); + + // from_number番から to_number 番までのレスのフォント判定を更新 + void update_fontid( const int from_number, const int to_number ); + + // number番のレスのフォント判定を更新 + void check_fontid( const int number ); + + // http://ime.nu/ などをリンクから削除 bool remove_imenu( char* str_link ); + + // 文字列中の"&"を"&"に変換する + int convert_amp( char* text, const int n ); }; + + + // + // リンクが現れたかチェックして文字列を取得する関数 + // (引数の値は、check_link_impl()を見ること) + // + inline const int NodeTreeBase::check_link( const char* str_in, const int lng_in, int& n_in, char* str_link, const int lng_link ) + { + // http://, https://, ftp://, ttp(s)://, tp(s):// のチェック + int delim_pos = 0; + const int linktype = MISC::is_url_scheme( str_in, &delim_pos ); + + if( linktype == MISC::SCHEME_NONE ) return linktype; + + return check_link_impl( str_in, lng_in, n_in, str_link, lng_link, linktype, delim_pos ); + } } #endif diff -Nru jd-2.8.5-120826/src/environment.cpp jd-2.8.6-130518/src/environment.cpp --- jd-2.8.5-120826/src/environment.cpp 2012-01-24 12:51:10.000000000 +0000 +++ jd-2.8.6-130518/src/environment.cpp 2013-01-27 14:23:42.000000000 +0000 @@ -181,6 +181,7 @@ { switch (osvi.dwMinorVersion) { + case 2: vstr << " Server 2012"; break; case 1: vstr << " Server 2008 R2"; break; case 0: vstr << " Server 2008"; break; } @@ -189,6 +190,7 @@ { switch (osvi.dwMinorVersion) { + case 2: vstr << " 8"; break; case 1: vstr << " 7"; break; case 0: vstr << " Vista"; break; } @@ -282,8 +284,35 @@ std::string tmp; std::string text_data; + // 各ディストリビューション共通の形式として定められた + // http://www.freedesktop.org/software/systemd/man/os-release.html + // 旧形式のコードは頃合いを見て削除する予定 + if( CACHE::load_rawdata( "/etc/os-release", text_data ) ) + { + std::list< std::string > lines = MISC::get_lines( text_data ); + std::list< std::string >::reverse_iterator it = lines.rbegin(); + while( it != lines.rend() ) + { + std::string name, value; + + size_t e; + if( ( e = (*it).find( "=" ) ) != std::string::npos ) + { + name = MISC::remove_spaces( (*it).substr( 0, e ) ); + value = MISC::remove_spaces( (*it).substr( e + 1 ) ); + } + + if( name == "PRETTY_NAME" && ! value.empty() ) + { + tmp = MISC::cut_str( value, "\"", "\"" ); + break; + } + + ++it; + } + } // LSB系 ( Ubuntu ..etc ) - if( CACHE::load_rawdata( "/etc/lsb-release", text_data ) ) + else if( CACHE::load_rawdata( "/etc/lsb-release", text_data ) ) { std::list< std::string > lines = MISC::get_lines( text_data ); std::list< std::string >::reverse_iterator it = lines.rbegin(); @@ -326,11 +355,6 @@ tmp = "Debian GNU/Linux "; tmp.append( text_data ); } - // Arch Linux (2012/01/24現在"/etc/arch-release"は空) - else if( CACHE::file_exists( "/etc/arch-release" ) == CACHE::EXIST_FILE ) - { - tmp = "Arch Linux"; - } // Solaris系 else if( CACHE::load_rawdata( "/etc/release", text_data ) ) { @@ -444,6 +468,7 @@ if( str_wm.find( "xfce" ) != std::string::npos ) window_manager = WM_XFCE; else if( str_wm.find( "gnome" ) != std::string::npos ) window_manager = WM_GNOME; else if( str_wm.find( "kde" ) != std::string::npos ) window_manager = WM_KDE; + else if( str_wm.find( "LXDE" ) != std::string::npos ) window_manager = WM_LXDE; if( window_manager == WM_UNKNOWN ) { @@ -481,6 +506,7 @@ case WM_GNOME : desktop = "GNOME"; break; case WM_XFCE : desktop = "XFCE"; break; case WM_KDE : desktop = "KDE"; break; + case WM_LXDE : desktop = "LXDE"; break; } #endif diff -Nru jd-2.8.5-120826/src/environment.h jd-2.8.6-130518/src/environment.h --- jd-2.8.5-120826/src/environment.h 2010-07-25 15:02:45.000000000 +0000 +++ jd-2.8.6-130518/src/environment.h 2013-01-27 14:23:42.000000000 +0000 @@ -13,6 +13,7 @@ WM_GNOME = 0, WM_XFCE, WM_KDE, + WM_LXDE, WM_UNKNOWN }; diff -Nru jd-2.8.5-120826/src/fontcolorpref.cpp jd-2.8.6-130518/src/fontcolorpref.cpp --- jd-2.8.5-120826/src/fontcolorpref.cpp 2011-03-27 16:20:21.000000000 +0000 +++ jd-2.8.6-130518/src/fontcolorpref.cpp 2013-02-23 06:23:30.000000000 +0000 @@ -26,6 +26,7 @@ FontColorPref::FontColorPref( Gtk::Window* parent, const std::string& url ) : SKELETON::PrefDiag( parent, url, true, true ), + m_label_aafont( true, "AAレスと判定する正規表現(_R): " ), m_bt_reset_font( "フォントの設定を全てデフォルトに戻す(_F)", true ), m_bt_change_color( "選択行の色を設定する(_S)", true ), @@ -39,6 +40,7 @@ // フォント設定をセット set_font_settings( "スレビュー", FONT_MAIN, "スレビューのフォント" ); set_font_settings( "ポップアップ", FONT_POPUP, "ポップアップのフォント" ); + set_font_settings( "アスキーアート", FONT_AA, "AA(スレビュー)のフォント" ); set_font_settings( "板一覧/お気に入り", FONT_BBS, "板一覧/お気に入りのフォント" ); set_font_settings( "スレ一覧", FONT_BOARD, "スレ一覧のフォント" ); set_font_settings( "書き込みビュー", FONT_MESSAGE, "書き込みビューのフォント" ); @@ -161,6 +163,13 @@ set_activate_entry( m_spin_ubar ); + // AAレスと判定する正規表現 + m_label_aafont.set_text( CONFIG::get_regex_res_aa() ); + m_vbox_font.pack_start( m_label_aafont, Gtk::PACK_SHRINK, mrg/2 ); + m_tooltips.set_tip( m_label_aafont, "この正規表現に一致したレスは、アスキーアートフォントで表示します( 次に開いたスレから有効 )" ); + + set_activate_entry( m_label_aafont ); + // フォントのリセット m_bt_reset_font.signal_clicked().connect( sigc::mem_fun( *this, &FontColorPref::slot_reset_font ) ); m_vbox_font.pack_end( m_bt_reset_font, Gtk::PACK_SHRINK ); @@ -241,6 +250,7 @@ CONFIG::set_adjust_line_space( m_spin_space.get_value() ); CONFIG::set_adjust_underline_pos( m_spin_ubar.get_value() ); + CONFIG::set_regex_res_aa( m_label_aafont.get_text() ); CONFIG::set_strict_char_width( m_checkbutton_font.property_active() ); diff -Nru jd-2.8.5-120826/src/fontcolorpref.h jd-2.8.6-130518/src/fontcolorpref.h --- jd-2.8.5-120826/src/fontcolorpref.h 2009-12-23 14:12:31.000000000 +0000 +++ jd-2.8.6-130518/src/fontcolorpref.h 2013-02-23 06:23:30.000000000 +0000 @@ -5,6 +5,7 @@ #include "skeleton/prefdiag.h" #include "skeleton/spinbutton.h" +#include "skeleton/label_entry.h" #include @@ -59,6 +60,8 @@ Gtk::Label m_label_ubar; SKELETON::SpinButtonDouble m_spin_ubar; + SKELETON::LabelEntry m_label_aafont; + Gtk::Button m_bt_reset_font; // 色の設定 diff -Nru jd-2.8.5-120826/src/fontid.h jd-2.8.6-130518/src/fontid.h --- jd-2.8.5-120826/src/fontid.h 2007-08-03 14:46:43.000000000 +0000 +++ jd-2.8.6-130518/src/fontid.h 2013-01-19 16:14:05.000000000 +0000 @@ -7,6 +7,7 @@ { FONT_MAIN = 0, // スレッドビューなどの基本の物 FONT_POPUP, // ポップアップ + FONT_AA, // AA(スレビュー) FONT_BBS, // スレ一覧 @@ -16,7 +17,10 @@ FONT_ENTRY_DEFAULT, // Gtk::Entryのデフォルトフォント - FONT_NUM + FONT_NUM, + + FONT_EMPTY, // フォントID未設定 + FONT_DEFAULT, // ビューの標準フォントを使用 }; #endif diff -Nru jd-2.8.5-120826/src/global.h jd-2.8.6-130518/src/global.h --- jd-2.8.5-120826/src/global.h 2012-03-03 08:03:36.000000000 +0000 +++ jd-2.8.6-130518/src/global.h 2013-02-23 06:24:45.000000000 +0000 @@ -109,8 +109,10 @@ #define ITEM_NAME_SELECTDELIMG "選択範囲の画像を削除" #define ITEM_NAME_SELECTABONEIMG "選択範囲の画像をあぼ〜ん" +#define ITEM_NAME_PREFERENCEVIEW "プロパティ" #define ITEM_NAME_PREF_BOARD "板のプロパティ" #define ITEM_NAME_PREF_THREAD "スレのプロパティ" +#define ITEM_NAME_PREF_IMAGE "画像のプロパティ" // SESSION::get_item_*() の戻り値 @@ -198,8 +200,10 @@ ITEM_SELECTDELIMG, ITEM_SELECTABONEIMG, + ITEM_PREFERENCEVIEW, ITEM_PREF_BOARD, ITEM_PREF_THREAD, + ITEM_PREF_IMAGE, ITEM_END }; @@ -228,12 +232,12 @@ enum { - AUTORELOAD_MINSEC = 10, // オートリロードの最小秒数 - MIN_LIVE_RELOAD_SEC = AUTORELOAD_MINSEC, // 実況時の最小リロード間隔 + AUTORELOAD_MINSEC = 2, // オートリロードの最小秒数 + MIN_LIVE_RELOAD_SEC = 10, // 実況時の最小リロード間隔 - WAITLOADIMG_SEC = 6, // 画像のロード待ち間隔 + WAITLOADIMG_SEC = 2, // 画像のロード待ち間隔 - CHECKUPDATE_MINSEC = 300 // 更新チェックの最小秒数 + CHECKUPDATE_MINSEC = 60 // 更新チェックの最小秒数 }; diff -Nru jd-2.8.5-120826/src/history/Makefile.am jd-2.8.6-130518/src/history/Makefile.am --- jd-2.8.5-120826/src/history/Makefile.am 2008-01-13 13:56:09.000000000 +0000 +++ jd-2.8.6-130518/src/history/Makefile.am 2013-01-05 15:44:26.000000000 +0000 @@ -15,4 +15,4 @@ viewhistoryitem.h AM_CXXFLAGS = @GTKMM_CFLAGS@ -INCLUDES = -I$(top_srcdir)/src +AM_CPPFLAGS = -I$(top_srcdir)/src diff -Nru jd-2.8.5-120826/src/icons/Makefile.am jd-2.8.6-130518/src/icons/Makefile.am --- jd-2.8.5-120826/src/icons/Makefile.am 2011-06-20 15:21:47.000000000 +0000 +++ jd-2.8.6-130518/src/icons/Makefile.am 2013-01-05 15:44:26.000000000 +0000 @@ -13,7 +13,7 @@ iconmanager.h $(icon_headers) AM_CXXFLAGS = @GTKMM_CFLAGS@ -INCLUDES = -I$(top_srcdir)/src +AM_CPPFLAGS = -I$(top_srcdir)/src DISTCLEANFILES = $(icon_headers) diff -Nru jd-2.8.5-120826/src/image/Makefile.am jd-2.8.6-130518/src/image/Makefile.am --- jd-2.8.5-120826/src/image/Makefile.am 2007-02-08 15:12:57.000000000 +0000 +++ jd-2.8.6-130518/src/image/Makefile.am 2013-01-05 15:44:26.000000000 +0000 @@ -31,4 +31,4 @@ imageviewpopup.h AM_CXXFLAGS = @GTKMM_CFLAGS@ -INCLUDES = -I$(top_srcdir)/src +AM_CPPFLAGS = -I$(top_srcdir)/src diff -Nru jd-2.8.5-120826/src/image/imageviewbase.cpp jd-2.8.6-130518/src/image/imageviewbase.cpp --- jd-2.8.5-120826/src/image/imageviewbase.cpp 2011-04-03 14:10:58.000000000 +0000 +++ jd-2.8.6-130518/src/image/imageviewbase.cpp 2013-01-10 15:18:32.000000000 +0000 @@ -140,7 +140,7 @@ action_group()->add( action, sigc::bind< int >( sigc::mem_fun( *this, &ImageViewBase::slot_resize_image ), tmp_size ) ); } - action_group()->add( Gtk::Action::create( "Move_Menu", ITEM_NAME_GO + std::string( "(_M)" ) ) ); + action_group()->add( Gtk::Action::create( "Move_Menu", ITEM_NAME_GO "(_M)" ) ); action_group()->add( Gtk::Action::create( "MoveHead", "先頭に移動(_H)" ), sigc::mem_fun( *this, &ImageViewBase::slot_move_head ) ); action_group()->add( Gtk::Action::create( "MoveTail", "最後に移動(_T)" ), sigc::mem_fun( *this, &ImageViewBase::slot_move_tail ) ); @@ -159,12 +159,12 @@ action_group()->add( Gtk::ToggleAction::create( "LockTab", "タブをロックする(_K)", std::string(), false ), sigc::mem_fun( *this, &ImageViewBase::slot_lock ) ); - action_group()->add( Gtk::Action::create( "OpenBrowser", ITEM_NAME_OPEN_BROWSER + std::string( "(_W)" ) ), + action_group()->add( Gtk::Action::create( "OpenBrowser", ITEM_NAME_OPEN_BROWSER "(_W)" ), sigc::mem_fun( *this, &ImageViewBase::slot_open_browser ) ); - action_group()->add( Gtk::Action::create( "OpenCacheBrowser", ITEM_NAME_OPEN_CACHE_BROWSER + std::string( "(_X)" ) ), + action_group()->add( Gtk::Action::create( "OpenCacheBrowser", ITEM_NAME_OPEN_CACHE_BROWSER "(_X)" ), sigc::mem_fun( *this, &ImageViewBase::slot_open_cache_browser ) ); action_group()->add( Gtk::Action::create( "OpenRef", "参照元のレスを開く(_O)"), sigc::mem_fun( *this, &ImageViewBase::slot_open_ref ) ); - action_group()->add( Gtk::Action::create( "CopyURL", ITEM_NAME_COPY_URL + std::string( "(_U)" ) ), sigc::mem_fun( *this, &ImageViewBase::slot_copy_url ) ); + action_group()->add( Gtk::Action::create( "CopyURL", ITEM_NAME_COPY_URL "(_U)" ), sigc::mem_fun( *this, &ImageViewBase::slot_copy_url ) ); action_group()->add( Gtk::Action::create( "Save", "Save"), sigc::mem_fun( *this, &ImageViewBase::slot_save ) ); action_group()->add( Gtk::Action::create( "SaveAll", "全ての画像を保存(_A)..."), sigc::mem_fun( *this, &ImageViewBase::slot_save_all ) ); @@ -175,6 +175,7 @@ action_group()->add( Gtk::Action::create( "AboneImage", "画像をあぼ〜んする(_B)"), sigc::mem_fun( *this, &ImageViewBase::slot_abone_img ) ); + action_group()->add( Gtk::Action::create( "PreferenceImage", "PreferenceImage"), sigc::mem_fun( *this, &ImageViewBase::show_preference ) ); action_group()->add( Gtk::Action::create( "Preference", "プロパティ(_P)..."), sigc::mem_fun( *this, &ImageViewBase::show_preference ) ); const std::string usrcmd = CORE::get_usrcmd_manager()->create_usrcmd_menu( action_group() ); @@ -243,7 +244,7 @@ "" - "" + "" "" ); @@ -717,6 +718,11 @@ slot_favorite(); break; + // 画像のプロパティ + case CONTROL::PreferenceView: + show_preference(); + break; + default: return false; } diff -Nru jd-2.8.5-120826/src/jdlib/Makefile.am jd-2.8.6-130518/src/jdlib/Makefile.am --- jd-2.8.5-120826/src/jdlib/Makefile.am 2010-06-15 15:08:07.000000000 +0000 +++ jd-2.8.6-130518/src/jdlib/Makefile.am 2013-01-05 15:44:26.000000000 +0000 @@ -48,4 +48,4 @@ hkana.h AM_CXXFLAGS = @GTKMM_CFLAGS@ @GNUTLS_CFLAGS@ @OPENSSL_CFLAGS@ @X11_CFLAGS@ -INCLUDES = -I$(top_srcdir)/src +AM_CPPFLAGS = -I$(top_srcdir)/src diff -Nru jd-2.8.5-120826/src/jdlib/jdregex.cpp jd-2.8.6-130518/src/jdlib/jdregex.cpp --- jd-2.8.5-120826/src/jdlib/jdregex.cpp 2012-03-03 05:31:39.000000000 +0000 +++ jd-2.8.6-130518/src/jdlib/jdregex.cpp 2013-04-04 13:26:24.000000000 +0000 @@ -32,10 +32,10 @@ Regex::~Regex() { - dispose(); + dispose(); - if( m_target_asc ) free( m_target_asc ); - if( m_table_pos ) free( m_table_pos ); + if( m_target_asc ) free( m_target_asc ); + if( m_table_pos ) free( m_table_pos ); } @@ -67,6 +67,7 @@ #ifdef USE_PCRE int cflags = REG_UTF8; + if( ! newline ) cflags |= REG_DOTALL; // . を改行にマッチさせる #else int cflags = REG_EXTENDED; #endif @@ -128,7 +129,7 @@ memset(pmatch, 0, sizeof(pmatch)); if ( ! m_compiled ) return false; - + if( target.empty() ) return false; if( target.length() <= offset ) return false; diff -Nru jd-2.8.5-120826/src/jdlib/miscutil.cpp jd-2.8.6-130518/src/jdlib/miscutil.cpp --- jd-2.8.5-120826/src/jdlib/miscutil.cpp 2012-08-10 01:58:11.000000000 +0000 +++ jd-2.8.6-130518/src/jdlib/miscutil.cpp 2013-03-09 05:49:37.000000000 +0000 @@ -29,8 +29,7 @@ r = 0; if( str[ i2 - 1 ] == '\r' ) r = 1; if( i2 - i > 0 ){ - std::string str_tmp = str.substr( i, i2 - i - r ); - lines.push_back( str_tmp ); + lines.push_back( str.substr( i, i2 - i - r ) ); } i = i2 + 1; } @@ -298,7 +297,6 @@ std::string str_space = " "; size_t lng_space = str_space.length(); - std::string str_out; size_t lng = str.length(); if( lng == 0 ) return str; @@ -332,9 +330,7 @@ else break; } - str_out = str.substr( i, i2 - i + 1 ); - - return str_out; + return str.substr( i, i2 - i + 1 ); } @@ -434,14 +430,17 @@ const std::string MISC::replace_str( const std::string& str, const std::string& str1, const std::string& str2 ) { std::string str_out; + str_out.reserve( str.length() ); + size_t i, pos = 0; while( ( i = str.find( str1 , pos ) ) != std::string::npos ){ - str_out += str.substr( pos, ( i - pos ) ) + str2; - pos += ( i - pos ) + str1.length(); + str_out.append( str, pos, ( i - pos ) ); + str_out.append( str2 ); + pos = i + str1.length(); } - str_out += str.substr( pos ); + str_out.append( str, pos, str.length() ); return str_out; } @@ -467,18 +466,20 @@ if( str_in.empty() || replace.empty() ) return str_in; std::string str_out; + str_out.reserve( str_in.length() ); size_t pos = 0, found = 0; while( ( found = str_in.find_first_of( "\r\n", pos ) ) != std::string::npos ) { - str_out.append( str_in.substr( pos, ( found - pos ) ) + replace ); + str_out.append( str_in, pos, ( found - pos ) ); + str_out.append( replace ); pos = found + 1; if( str_in[ found ] == '\r' && str_in[ found + 1 ] == '\n' ) ++pos; } - str_out.append( str_in.substr( pos ) ); + str_out.append( str_in, pos, str_in.length() ); return str_out; } @@ -944,14 +945,11 @@ // 戻り値 : スキームタイプ // length : "http://"等の文字数 // -const int MISC::is_url_scheme( const char* str_in, int* length ) +const int MISC::is_url_scheme_impl( const char* str_in, int* length ) { int scheme = SCHEME_NONE; int len = 0; - // 候補になり得ない場合は以降の処理はしない - if( *str_in != 'h' && *str_in != 'f' && *str_in != 't' && *str_in != 's' ) return scheme; - // http https if( *str_in == 'h' && *( str_in + 1 ) == 't' && *( str_in + 2 ) == 't' && *( str_in + 3 ) == 'p' ) @@ -1013,46 +1011,39 @@ // "RFC 3986" : http://www.ietf.org/rfc/rfc3986.txt // "RFC 2396" : http://www.ietf.org/rfc/rfc2396.txt // +static const char s_url_char[ 128 ] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +// ! " # $ % & ' ( ) * + , - . / + 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +// 0 1 2 3 4 5 6 7 8 9 : ; < = > ? + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, +// @ A B C D E F G H I J K L M N O + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +// P Q R S T U V W X Y Z [ \ ] ^ _ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 2, 2, 1, +// ` a b c d e f g h i j k l m n o + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +// p q r s t u v w x y z { | } ~ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 0, 1, 0, +}; const bool MISC::is_url_char( const char* str_in, const bool loose_url ) { - if( - // 出現頻度が高いと思われる順にチェック - ( *str_in >= 'a' && *str_in <= 'z' ) - || ( *str_in >= '0' && *str_in <= '9' ) - || ( *str_in >= 'A' && *str_in <= 'Z' ) - || *str_in == '.' - || *str_in == '/' - || *str_in == '-' - || *str_in == '%' - || *str_in == '?' - || *str_in == '=' - || *str_in == ':' - || *str_in == '~' - || *str_in == '&' - - // あとの並びはASCIIコード順(なんとなく) - || *str_in == '!' - || *str_in == '#' - || *str_in == '$' - || *str_in == '\'' - || *str_in == '(' - || *str_in == ')' - || *str_in == '*' - || *str_in == '+' - || *str_in == ',' - || *str_in == ';' - || *str_in == '@' - || *str_in == '_' - - // RFC 3986(2.2.)では"[]"が予約文字として定義されているが - // RFC 2396(2.4.3.)では除外されていて、普通にURLとして扱う - // と問題がありそうなので"loose_url"の扱いにしておく。 - || ( loose_url && ( *str_in == '[' - || *str_in == ']' - || *str_in == '^' - || *str_in == '|' ) ) - ) return true; - else return false; + unsigned char c = (unsigned char)(*str_in); + + // 128以上のテーブルはないので先に判定 + if( c & 0x80 ) return false; + + // 基本 + if( s_url_char[ c ] == 1 ) return true; + + // 拡張 + // RFC 3986(2.2.)では"[]"が予約文字として定義されているが + // RFC 2396(2.4.3.)では除外されていて、普通にURLとして扱う + // と問題がありそうなので"loose_url"の扱いにしておく。 + if( loose_url && s_url_char[ c ] == 2 ) return true; + + return false; } @@ -1072,21 +1063,22 @@ unsigned int a, b; for( a = 0, b = a; a < url_length; ++a, ++b ) { - if( url[a] == '%' ) + if( url[a] == '%' && ( a + 2 < url_length ) ) { - char src[3]; - memset( src, 0, 3 ); - memcpy( src, &url[ a + 1 ], 2 ); - - char tmp[3]; - memset( tmp, 0, 3 ); + char src[3] = { url[ a + 1 ], url[ a + 2 ], '\0' }; + char tmp[3] = { '\0', '\0', '\0' }; if( chrtobin( src, tmp ) == 2 ) { + // '%4A' など、2文字が変換できていること decoded[b] = *tmp; a += 2; } - else decoded[b] = url[a]; + else + { + // 変換失敗は、単なる '%' 文字として扱う + decoded[b] = url[a]; + } } else if( url[a] == '+' ) { @@ -1190,8 +1182,11 @@ { char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - std::string out; int lng = str.length(); + + std::string out; + out.reserve( lng * 2 ); + std::string data = str + "\0\0\0\0"; for( int i = 0; i < lng; i += 3 ){ @@ -1211,10 +1206,11 @@ } if( lng % 3 == 1 ){ - out = out.substr( 0, out.length()-2 ) + "=="; + out[ out.length()-2 ] = '='; + out[ out.length()-1 ] = '='; } else if( lng % 3 == 2 ){ - out = out.substr( 0, out.length()-1 ) + "="; + out[ out.length()-1 ] = '='; } #ifdef _DEBUG @@ -1491,17 +1487,17 @@ { // WAVE DASH 問題 const size_t size = 4; - const unsigned char Win[size][4] = { - { 0xef, 0xbd, 0x9e, '\0' }, // FULLWIDTH TILDE (U+FF5E) - { 0xe2, 0x80, 0x95, '\0' }, // HORIZONTAL BAR (U+2015) - { 0xe2, 0x88, 0xa5, '\0' }, // PARALLEL TO (U+2225) - { 0xef, 0xbc, 0x8d, '\0' } // FULLWIDTH HYPHEN-MINUS (U+FF0D) + const char Win[size][4] = { + { -17, -67, -98, '\0' }, // FULLWIDTH TILDE (U+FF5E) + { -30, -128, -107, '\0' }, // HORIZONTAL BAR (U+2015) + { -30, -120, -91, '\0' }, // PARALLEL TO (U+2225) + { -17, -68, -115, '\0' } // FULLWIDTH HYPHEN-MINUS (U+FF0D) }; - const unsigned char Unix[size][4] = { - { 0xe3, 0x80, 0x9c, '\0' }, // WAVE DASH (U+301C) - { 0xe2, 0x80, 0x94, '\0' }, // EM DASH(U+2014) - { 0xe2, 0x80, 0x96, '\0' }, // DOUBLE VERTICAL LINE (U+2016) - { 0xe2, 0x88, 0x92, '\0' } // MINUS SIGN (U+2212) + const char Unix[size][4] = { + { -29, -128, -100, '\0' }, // WAVE DASH (U+301C) + { -30, -128, -108, '\0' }, // EM DASH(U+2014) + { -30, -128, -106, '\0' }, // DOUBLE VERTICAL LINE (U+2016) + { -30, -120, -110, '\0' } // MINUS SIGN (U+2212) }; std::string ret(str); diff -Nru jd-2.8.5-120826/src/jdlib/miscutil.h jd-2.8.6-130518/src/jdlib/miscutil.h --- jd-2.8.5-120826/src/jdlib/miscutil.h 2010-12-21 13:45:11.000000000 +0000 +++ jd-2.8.6-130518/src/jdlib/miscutil.h 2013-01-13 19:09:38.000000000 +0000 @@ -158,6 +158,7 @@ // 戻り値 : スキームタイプ // length : "http://"等の文字数 const int is_url_scheme( const char* str_in, int* length = NULL ); + const int is_url_scheme_impl( const char* str_in, int* length ); // URLとして扱う文字かどうか判別する // 基本 : 「!#$%&'()*+,-./0-9:;=?@A-Z_a-z~」 @@ -265,6 +266,17 @@ // table_pos : 置き換えた文字列の位置 // n : str2 と table_pos のバッファサイズ void asc( const char* str1, char* str2, int* table_pos, const size_t n ); + + + // URL中のスキームを判別する + inline const int is_url_scheme( const char* str_in, int* length ) + { + // 候補になり得ない場合は以降の処理はしない + if( *str_in != 'h' && *str_in != 'f' && *str_in != 't' && *str_in != 's' ) + return SCHEME_NONE; + + return is_url_scheme_impl( str_in, length ); + } } diff -Nru jd-2.8.5-120826/src/jdversion.h jd-2.8.6-130518/src/jdversion.h --- jd-2.8.5-120826/src/jdversion.h 2012-08-26 09:39:27.000000000 +0000 +++ jd-2.8.6-130518/src/jdversion.h 2013-05-17 16:34:56.000000000 +0000 @@ -15,8 +15,8 @@ #define MAJORVERSION 2 #define MINORVERSION 8 -#define MICROVERSION 5 -#define JDDATE "120826" +#define MICROVERSION 6 +#define JDDATE "130518" #define JDTAG "" //--------------------------------- @@ -27,7 +27,7 @@ //--------------------------------- #define JDCOMMENT "JD は gtkmm/GTK+2 を用いた2chブラウザです。" -#define JDCOPYRIGHT "(c) 2006-2012 JD project" +#define JDCOPYRIGHT "(c) 2006-2013 JD project" #define JDBBS CONFIG::get_url_jdhp()+"cgi-bin/bbs/support/" #define JD2CHLOG CONFIG::get_url_jdhp()+"old2ch/" #define JDHELP CONFIG::get_url_jdhp()+"manual/"+MISC::itostr( JDVERSION )+"/" diff -Nru jd-2.8.5-120826/src/message/Makefile.am jd-2.8.6-130518/src/message/Makefile.am --- jd-2.8.5-120826/src/message/Makefile.am 2010-05-04 05:01:26.000000000 +0000 +++ jd-2.8.6-130518/src/message/Makefile.am 2013-01-05 15:44:26.000000000 +0000 @@ -21,4 +21,4 @@ confirmdiag.h AM_CXXFLAGS = @GTKMM_CFLAGS@ -INCLUDES = -I$(top_srcdir)/src +AM_CPPFLAGS = -I$(top_srcdir)/src diff -Nru jd-2.8.5-120826/src/message/logmanager.cpp jd-2.8.6-130518/src/message/logmanager.cpp --- jd-2.8.5-120826/src/message/logmanager.cpp 2010-10-23 16:04:24.000000000 +0000 +++ jd-2.8.6-130518/src/message/logmanager.cpp 2013-03-09 05:49:37.000000000 +0000 @@ -170,7 +170,7 @@ // // headsize > 0 の時は先頭の headsize 文字だけを比較 // -const bool Log_Manager::check_write( const std::string& url, const bool newthread, const char* msg, const size_t headsize ) +const bool Log_Manager::check_write( const std::string& url, const bool newthread, const char* msg_in, const size_t headsize ) { if( ! m_logitems.size() ) return false; @@ -178,6 +178,14 @@ std::cout << "Log_Manager::check_write url = " << url << " newthread = " << newthread << " headsize = " << headsize << std::endl; #endif +#ifndef _WIN32 + const char* msg = msg_in; +#else + // WAVE DASH 問題 ( UNIX用の文字コードになっていることがある ) + const std::string msg_buf = MISC::utf8_fix_wavedash( msg_in, MISC::UNIXtoWIN ); + const char* msg = msg_buf.c_str(); +#endif + std::list< LogItem* >::iterator it = m_logitems.begin(); for( ; it != m_logitems.end(); ++it ){ diff -Nru jd-2.8.5-120826/src/message/logmanager.h jd-2.8.6-130518/src/message/logmanager.h --- jd-2.8.5-120826/src/message/logmanager.h 2008-12-23 08:06:43.000000000 +0000 +++ jd-2.8.6-130518/src/message/logmanager.h 2013-03-09 05:49:37.000000000 +0000 @@ -30,7 +30,7 @@ // messageが自分の書き込んだものかチェックする // newthread == true の時は新スレの>>1のチェック // headsize > 0 の時は先頭の headsize 文字だけを比較 - const bool check_write( const std::string& url, const bool newthread, const char* msg, const size_t headsize ); + const bool check_write( const std::string& url, const bool newthread, const char* msg_in, const size_t headsize ); // 自分の書き込みの判定用データの保存 void push_logitem( const std::string& url, const bool newthread, const std::string& msg ); diff -Nru jd-2.8.5-120826/src/message/post.cpp jd-2.8.6-130518/src/message/post.cpp --- jd-2.8.5-120826/src/message/post.cpp 2011-02-24 14:44:32.000000000 +0000 +++ jd-2.8.6-130518/src/message/post.cpp 2013-04-04 11:17:15.000000000 +0000 @@ -312,9 +312,14 @@ // samba秒取得 icase = false; - newline = true; - if( regex.exec( "ERROR +- +593 +([0-9]+) +sec", m_errmsg, offset, icase, newline, usemigemo, wchar ) ){ - time_t sec = atoi( regex.str( 1 ).c_str() ); + newline = false; // . に改行をマッチさせる + // Smaba24規制の場合 + // ERROR - 593 60 sec たたないと書けません。(1回目、8 sec しかたってない) + // 忍法帖規制の場合 ( samba秒だけ取得する。 ) + // ERROR:修行が足りません(Lv=2)。しばらくたってから投稿してください。(48 sec) + // この板のsambaは samba=30 sec + if( regex.exec( "ERROR( +- +593 +|:.+samba=)([0-9]+) +sec", m_errmsg, offset, icase, newline, usemigemo, wchar ) ){ + time_t sec = atoi( regex.str( 2 ).c_str() ); #ifdef _DEBUG std::cout << "samba = " << sec << std::endl; #endif diff -Nru jd-2.8.5-120826/src/skeleton/Makefile.am jd-2.8.6-130518/src/skeleton/Makefile.am --- jd-2.8.5-120826/src/skeleton/Makefile.am 2011-02-24 13:50:01.000000000 +0000 +++ jd-2.8.6-130518/src/skeleton/Makefile.am 2013-01-05 15:44:26.000000000 +0000 @@ -100,4 +100,4 @@ undobuffer.h AM_CXXFLAGS = @GTKMM_CFLAGS@ -INCLUDES = -I$(top_srcdir)/src +AM_CPPFLAGS = -I$(top_srcdir)/src diff -Nru jd-2.8.5-120826/src/skeleton/admin.cpp jd-2.8.6-130518/src/skeleton/admin.cpp --- jd-2.8.5-120826/src/skeleton/admin.cpp 2011-08-07 15:50:51.000000000 +0000 +++ jd-2.8.6-130518/src/skeleton/admin.cpp 2013-05-04 07:54:37.000000000 +0000 @@ -153,10 +153,10 @@ m_action_group->add( Gtk::Action::create( "ReloadAll", "再読み込み(_R)" ), sigc::mem_fun( *this, &Admin::slot_reload_all_tabs ) ); m_action_group->add( Gtk::Action::create( "CancelReloadAll", "キャンセル(_C)" ), sigc::mem_fun( *this, &Admin::slot_cancel_reload_all_tabs ) ); - m_action_group->add( Gtk::Action::create( "OpenBrowser", ITEM_NAME_OPEN_BROWSER + std::string( "(_W)" ) ), + m_action_group->add( Gtk::Action::create( "OpenBrowser", ITEM_NAME_OPEN_BROWSER "(_W)" ), sigc::mem_fun( *this, &Admin::slot_open_by_browser ) ); - m_action_group->add( Gtk::Action::create( "CopyURL", ITEM_NAME_COPY_URL + std::string( "(_U)" ) ), sigc::mem_fun( *this, &Admin::slot_copy_url ) ); - m_action_group->add( Gtk::Action::create( "CopyTitleURL", ITEM_NAME_COPY_TITLE_URL + std::string( "(_L)" ) ), + m_action_group->add( Gtk::Action::create( "CopyURL", ITEM_NAME_COPY_URL "(_U)" ), sigc::mem_fun( *this, &Admin::slot_copy_url ) ); + m_action_group->add( Gtk::Action::create( "CopyTitleURL", ITEM_NAME_COPY_TITLE_URL "(_L)" ), sigc::mem_fun( *this, &Admin::slot_copy_title_url ) ); m_action_group->add( Gtk::Action::create( "Preference", "プロパティ(_P)..."), sigc::mem_fun( *this, &Admin::show_preference ) ); @@ -944,29 +944,26 @@ // // command.arg1: 開く位置 // -// "false" ならアクティブなタブを置き換える +// "false" ならアクティブなタブを置き換える ( デフォルト ) // "true" なら一番右側に新しいタブを開く // "right" ならアクティブなタブの右に開く // "newtab" なら設定によってアクティブなタブの右に開くか一番右側に開くか切り替える // "left" ならアクティブなタブの左に開く // "page数字" なら指定した位置にタブで開く +// "replace" なら arg3 に指定したタブがあれば置き換え、なければ "newtab" で動作する // // command.arg2: "true" なら既に command.url を開いているかチェックしない // // command.arg3: モード ( 複数指定する場合は空白で空ける ) // // "auto"なら表示されていればリロードせずに切替える -// されていなければarg1で指定した場所に新しいタブで開いてロード -// スレ番号ジャンプなどで使用する -// +// されていなければarg1で指定した場所に新しいタブで開いてロード +// スレ番号ジャンプなどで使用する // "noswitch"ならタブを切り替えない(連続して開くときに使用) -// // "lock" なら開いてからロックする -// // "offline" なら オフラインで開く -// // "reget" なら読み込み時にキャッシュ等を消してから再読み込みする -// +// "boardnext" など、 "replace" で置き換えるタブの種類を指定する // // その他のargは各ビュー別の設定 // @@ -1032,12 +1029,43 @@ } } + // 開く位置の基準を、アクティブなタブに仮定 + int page = m_notebook->get_current_page(); + + std::string open_method = command.arg1; + if( open_method.empty() ){ + open_method = "false"; + } + + // 置き替えるページを探す + if( open_method == "replace" ){ + // 該当するタブが見つからない場合のために、新しいタブで開くモードに仮設定 + open_method = "newtab"; + + // タブの種類 (command.arg3) に該当するタブを探す + int find_page = find_view( command.arg3 ); +#ifdef _DEBUG + std::cout << "replace mode = " << command.arg3 + << " page = " << page << " find = " << find_page << std::endl; +#endif + if( find_page >= 0 ){ + SKELETON::View* found_view = dynamic_cast< View* >( m_notebook->get_nth_page( page ) ); + if( found_view ){ + // 指定したタブを置き換えるモードに設定 + open_method = "false"; + + // 開く位置の基準を、見つかったタブに設定 + page = find_page; + current_view = found_view; + } + } + } + view = create_view( command ); if( !view ) return; - const int page = m_notebook->get_current_page(); const bool open_tab = ( page == -1 - || ( ! command.arg1.empty() && command.arg1 != "false" ) + || open_method != "false" || ( mode & OPEN_MODE_AUTO ) // オートモードの時もタブで開く || is_locked( page ) ); @@ -1051,10 +1079,10 @@ int openpage = -1; // 現在のページの右に表示 - if( command.arg1 == "right" ) openpage = page +1; + if( open_method == "right" ) openpage = page +1; // 設定によって切り替える - if( command.arg1 == "newtab" ){ + if( open_method == "newtab" ){ switch( CONFIG::get_newtab_pos() ){ case 1: openpage = page +1; break; case 2: openpage = page; break; @@ -1062,16 +1090,16 @@ } // 現在のページの左に表示 - else if( command.arg1 == "left" ) openpage = page; + else if( open_method == "left" ) openpage = page; // 指定した位置に表示 - else if( command.arg1.find( "page" ) == 0 ) openpage = atoi( command.arg1.c_str() + 4 ); + else if( open_method.find( "page" ) == 0 ) openpage = atoi( open_method.c_str() + 4 ); // ロックされていたら右に表示 - else if( command.arg1 != "true" && page != -1 && is_locked( page ) ) openpage = page +1; + else if( open_method != "true" && page != -1 && is_locked( page ) ) openpage = page +1; #ifdef _DEBUG - std::cout << "append page = " << openpage << std::endl; + std::cout << "append openpage = " << openpage << " / page = " << page << std::endl; #endif @@ -1451,7 +1479,8 @@ if( page == current_page ){ // その前に開いていたビューに切り替える - if( m_use_switchhistory && m_list_switchhistory.size() ) switch_view( m_list_switchhistory.back() ); + const std::string hist_url = get_valid_switchhistory(); + if( ! hist_url.empty() ) switch_view( hist_url ); // もし現在表示中のビューを消すときは予めひとつ右のビューにスイッチしておく // そうしないと左のビューを一度表示してしまうので遅くなる @@ -2797,3 +2826,39 @@ } #endif } + + +// +// タブの切り替え履歴から、有効な最後のURLを返す +// +// 表示されているビューに存在しないURLは履歴から削除して、表示されているビューのURLを返す。 +// 見つからないときは空文字列を返す。 +// +// NOTE: +// タブの切り替え履歴にあるビューは、表示されているビューのうちのどれかであるはずだが、 +// 検索ビューなどでURLが変更になる場合があり、 ( View::set_url()で変更できてしまう。 ) +// タブの切り替え履歴にあるURLと、表示されているビューのURLが不一致となることがある。 +// また、その不一致なタブの切り替え履歴を、セッション情報 ( article_switchhistoryなど ) に +// 保存してしまっていたため、ここで不一致な履歴の削除を行うことで、履歴を修復する。 +// +const std::string Admin::get_valid_switchhistory() +{ + if( ! m_use_switchhistory ) return std::string(); + + while( m_list_switchhistory.size() > 0 ){ + + // タブの切り替え履歴から、最後のURLを取り出す + const std::string url = m_list_switchhistory.back(); + + // 表示されているビューであれば、そのURLを返す + SKELETON::View* view = get_view( url ); + if( view ) return url; + + // 表示されていないので、最後のURLを削除する + m_list_switchhistory.pop_back(); +#ifdef _DEBUG + std::cout << "Admin::get_valid_switchhistory remove = " << url << std::endl; +#endif + } + return std::string(); +} diff -Nru jd-2.8.5-120826/src/skeleton/admin.h jd-2.8.6-130518/src/skeleton/admin.h --- jd-2.8.5-120826/src/skeleton/admin.h 2011-08-07 15:50:51.000000000 +0000 +++ jd-2.8.6-130518/src/skeleton/admin.h 2013-05-04 07:54:37.000000000 +0000 @@ -27,8 +27,11 @@ std::string m_url; JDWindow * m_win; + + protected: DragableNoteBook* m_notebook; + private: bool m_focus; std::list< COMMAND_ARGS > m_list_command; @@ -170,6 +173,9 @@ // COMMAND_ARGS からビューの URL を取得する virtual const std::string command_to_url( const COMMAND_ARGS& command ){ return command.url; } + // view_modeに該当するページを探す + virtual int find_view( const std::string& view_mode ){ return -1; }; + virtual void open_view( const COMMAND_ARGS& command ); virtual void switch_admin() = 0; // CORE::core_set_command( "switch_*" ) を送る virtual void switch_view( const std::string& url ); @@ -332,6 +338,7 @@ // タブの切り替え履歴を更新 void append_switchhistory( const std::string& url ); void remove_switchhistory( const std::string& url ); + const std::string get_valid_switchhistory(); }; } diff -Nru jd-2.8.5-120826/src/skeleton/dragtreeview.cpp jd-2.8.6-130518/src/skeleton/dragtreeview.cpp --- jd-2.8.5-120826/src/skeleton/dragtreeview.cpp 2010-12-28 14:18:42.000000000 +0000 +++ jd-2.8.6-130518/src/skeleton/dragtreeview.cpp 2012-12-08 14:56:29.000000000 +0000 @@ -397,7 +397,7 @@ m_dragging = true; CORE::DND_Begin(); - return Gtk::TreeView::on_drag_begin( context ); + Gtk::TreeView::on_drag_begin( context ); } diff -Nru jd-2.8.5-120826/src/skeleton/tablabel.h jd-2.8.6-130518/src/skeleton/tablabel.h --- jd-2.8.5-120826/src/skeleton/tablabel.h 2011-01-18 14:37:54.000000000 +0000 +++ jd-2.8.6-130518/src/skeleton/tablabel.h 2013-01-13 18:17:35.000000000 +0000 @@ -46,7 +46,7 @@ public: TabLabel( const std::string& url ); - ~TabLabel(); + virtual ~TabLabel(); SIG_TAB_MOTION_EVENT sig_tab_motion_event(){ return m_sig_tab_motion_event; } SIG_TAB_LEAVE_EVENT sig_tab_leave_event(){ return m_sig_tab_leave_event; } diff -Nru jd-2.8.5-120826/src/skeleton/tabswitchmenu.h jd-2.8.6-130518/src/skeleton/tabswitchmenu.h --- jd-2.8.5-120826/src/skeleton/tabswitchmenu.h 2009-08-16 16:32:15.000000000 +0000 +++ jd-2.8.6-130518/src/skeleton/tabswitchmenu.h 2013-01-13 18:17:35.000000000 +0000 @@ -26,7 +26,7 @@ public: TabSwitchMenu( DragableNoteBook* notebook, Admin* admin ); - ~TabSwitchMenu(); + virtual ~TabSwitchMenu(); void remove_items(); void append_items(); diff -Nru jd-2.8.5-120826/src/skeleton/view.cpp jd-2.8.6-130518/src/skeleton/view.cpp --- jd-2.8.5-120826/src/skeleton/view.cpp 2011-05-29 13:02:00.000000000 +0000 +++ jd-2.8.6-130518/src/skeleton/view.cpp 2013-03-30 05:27:51.000000000 +0000 @@ -25,6 +25,8 @@ m_enable_mg( false ), m_enable_autoreload( false ), m_autoreload_mode( AUTORELOAD_NOT ), + m_autoreload_sec( 0 ), + m_autoreload_counter( 0 ), m_keyjump_counter( 0 ), m_keyjump_num( 0 ), m_lockable( true ), diff -Nru jd-2.8.5-120826/src/skeleton/window.h jd-2.8.6-130518/src/skeleton/window.h --- jd-2.8.5-120826/src/skeleton/window.h 2012-08-03 14:40:00.000000000 +0000 +++ jd-2.8.6-130518/src/skeleton/window.h 2013-01-13 18:17:35.000000000 +0000 @@ -54,7 +54,7 @@ public: JDWindow( const bool fold_when_focusout, const bool need_mginfo = true ); - ~JDWindow(); + virtual ~JDWindow(); Gtk::HBox& get_statbar(){ return m_statbar; } diff -Nru jd-2.8.5-120826/src/sound/Makefile.am jd-2.8.6-130518/src/sound/Makefile.am --- jd-2.8.5-120826/src/sound/Makefile.am 2008-05-24 17:32:10.000000000 +0000 +++ jd-2.8.6-130518/src/sound/Makefile.am 2013-01-05 15:44:26.000000000 +0000 @@ -9,4 +9,4 @@ soundmanager.h AM_CXXFLAGS = @GTKMM_CFLAGS@ @ALSA_CFLAGS@ -INCLUDES = -I$(top_srcdir)/src +AM_CPPFLAGS = -I$(top_srcdir)/src diff -Nru jd-2.8.5-120826/src/urlreplacemanager.cpp jd-2.8.6-130518/src/urlreplacemanager.cpp --- jd-2.8.5-120826/src/urlreplacemanager.cpp 1970-01-01 00:00:00.000000000 +0000 +++ jd-2.8.6-130518/src/urlreplacemanager.cpp 2013-03-30 05:23:47.000000000 +0000 @@ -0,0 +1,280 @@ +// ライセンス: GPL2 + +//#define _DEBUG +#include "jddebug.h" + +#include "urlreplacemanager.h" +#include "cache.h" +#include "type.h" + +#include "jdlib/miscutil.h" +#include "jdlib/miscmsg.h" + +CORE::Urlreplace_Manager* instance_urlreplace_manager = NULL; + +CORE::Urlreplace_Manager* CORE::get_urlreplace_manager() +{ + if( ! instance_urlreplace_manager ) instance_urlreplace_manager = new Urlreplace_Manager(); + assert( instance_urlreplace_manager ); + + return instance_urlreplace_manager; +} + + +void CORE::delete_urlreplace_manager() +{ + if( instance_urlreplace_manager ) delete instance_urlreplace_manager; + instance_urlreplace_manager = NULL; +} + +/////////////////////////////////////////////// + +using namespace CORE; + +#define DEFALUT_CONFIG \ + "#\n" \ + "# UrlReplace設定ファイル (urlreplace.conf)\n" \ + "#\n" \ + "# 設定ファイルの書式:\n" \ + "# 正規表現<タブ>変換後URL<タブ>リファラURL<タブ>制御文字\n" \ + "#\n" \ + "# 設定例:\n" \ + "# http://www\\.foobar\\.com/(view/|img\\.php\\?id=)([0-9]+) http://www.foobar.com/view/$2 $0 $IMAGE\n" \ + "#\n" \ + "# 詳細な書式はマニュアルを参照してください。\n" \ + "# この機能を無効にする場合は、このファイルの内容を空にして保存してください。\n" \ + "#\n" \ + "http://www\\.youtube\\.com/watch\\?(|[^#]+&)v=([^&#/]+) http://img.youtube.com/vi/$2/0.jpg\n" \ + "http://youtu\\.be/([^#&=/]+) http://img.youtube.com/vi/$1/0.jpg\n" \ + "http://img\\.youtube\\.com/vi/[^/]+/0.jpg $0 $THUMBNAIL\n" \ + "\n" + + +Urlreplace_Manager::Urlreplace_Manager() +{ + std::string conf; + const std::string path = CACHE::path_urlreplace(); + if( CACHE::load_rawdata( path, conf ) ){ + conf2list( conf ); + } else { + // 読み込みエラー、または空ファイル + if( CACHE::file_exists( path ) == CACHE::EXIST_ERROR ){ + // ファイルが存在しないとき、デフォルト設定ファイルを作成する + conf = DEFALUT_CONFIG; + if( CACHE::save_rawdata( path, conf ) ){ + conf2list( conf ); + } + } + } +} + + +// +// conf -> リスト +// +void Urlreplace_Manager::conf2list( const std::string& conf ) +{ + m_list_cmd.clear(); + if( conf.empty() ) return; + + std::list< std::string > lines = MISC::get_lines( conf ); + if( lines.size() == 0 ) return; + + std::list < std::string >::iterator it = lines.begin(); + for( ; it != lines.end(); ++it ){ + if( (*it).length() <= 0 ) continue; + if( (*it)[0] == '#' ) continue; // コメント行 + + std::list< std::string > line = MISC::StringTokenizer( *it, '\t' ); + if( line.size() < 2 ) continue; + + UrlreplaceItem item; + std::string ctrl; + std::list < std::string >::iterator str = line.begin(); + // 1: 検索URL + item.match = *str; + // 2: 置換URL + item.replace = *(++str); + // 3: リファラURL + item.referer.clear(); + if( (++str) != line.end() ) item.referer = *str; + // 4: コントロール + item.imgctrl = IMGCTRL_NONE; + item.match_break = false; + if( (++str) != line.end() ){ + ctrl = *str; + int imgctrl = IMGCTRL_INIT; + + // 拡張子がない場合でも画像として扱う + if( ctrl.find( "$IMAGE" ) != std::string::npos ){ + imgctrl += IMGCTRL_FORCEIMAGE; + } + // 拡張子があっても画像として扱わない + else if( ctrl.find( "$BROWSER" ) != std::string::npos ){ + imgctrl += IMGCTRL_FORCEBROWSER; // $IMAGEを優先 + } + // 拡張子の偽装をチェックしない + if( ctrl.find( "$GENUINE" ) != std::string::npos ){ + imgctrl += IMGCTRL_GENUINE; + } + // サムネイル画像 + if( ctrl.find( "$THUMBNAIL" ) != std::string::npos ){ + imgctrl += IMGCTRL_THUMBNAIL; + } + + if( imgctrl != IMGCTRL_INIT ) item.imgctrl = imgctrl; + + // 正規表現に一致したら以降の判定を行わない + item.match_break = ( ctrl.find( "$BREAK" ) != std::string::npos ); + } + + if( ! item.match.empty() && ! item.replace.empty() ) m_list_cmd.push_back( item ); + } +} + + + +// +// URLを任意の正規表現で変換する +// +const bool Urlreplace_Manager::exec( std::string &url ) +{ + if( m_list_cmd.empty() ) return false; + + JDLIB::Regex regex; + const size_t offset = 0; + const bool icase = false; + const bool newline = true; + const bool usemigemo = false; + const bool wchar = false; + + // いずれかの正規表現に一致するか + bool matched = false; + std::list< UrlreplaceItem >::iterator it = m_list_cmd.begin(); + for( ; it != m_list_cmd.end(); ++it ){ + if( regex.exec( (*it).match, url, + offset, icase, newline, usemigemo, wchar ) ){ + matched = true; + + // 置換URLの変換 + url = (*it).replace; + replace( regex, url ); + + // URLが空になったか、以降の判定を行わない + if( url.empty() || (*it).match_break ) break; + } + } + return matched; +} + + +// +// URLからリファラを求める +// +const bool Urlreplace_Manager::referer( const std::string &url, std::string &referer ) +{ + if( m_list_cmd.empty() ) return false; + + referer = url; + + JDLIB::Regex regex; + const size_t offset = 0; + const bool icase = false; + const bool newline = true; + const bool usemigemo = false; + const bool wchar = false; + + // いずれかの正規表現に一致するか + bool matched = false; + std::list< UrlreplaceItem >::iterator it = m_list_cmd.begin(); + for( ; it != m_list_cmd.end(); ++it ){ + if( regex.exec( (*it).match, referer, + offset, icase, newline, usemigemo, wchar ) ){ + matched = true; + + // リファラURLの変換 + referer = (*it).referer; + replace( regex, referer ); + + // URLが空になったか、以降の判定を行わない + if( referer.empty() || (*it).match_break ) break; + } + } + return matched; +} + + +// +// URLの画像コントロールを取得する (URLキャッシュ) +// +const int Urlreplace_Manager::get_imgctrl( const std::string &url ) +{ + if( m_list_cmd.empty() ) return IMGCTRL_NONE; + + // 取得済みのURLか + std::map< std::string, int >::iterator it = m_map_imgctrl.find( url ); + if( it != m_map_imgctrl.end() ) return ( *it ).second; + + // 新たに取得してキャッシュする + int imgctrl = get_imgctrl_impl( url ); + m_map_imgctrl.insert( make_pair( url, imgctrl ) ); + + return imgctrl; +} + +// +// URLの画像コントロールを取得する +// +const int Urlreplace_Manager::get_imgctrl_impl( const std::string &url ) +{ + int imgctrl = IMGCTRL_NONE; + + JDLIB::Regex regex; + const size_t offset = 0; + const bool icase = false; + const bool newline = true; + const bool usemigemo = false; + const bool wchar = false; + + // いずれかの正規表現に一致するか + std::list< UrlreplaceItem >::iterator it = m_list_cmd.begin(); + for( ; it != m_list_cmd.end(); ++it ){ + if( regex.exec( (*it).match, url, + offset, icase, newline, usemigemo, wchar ) ){ + + // 画像コントロールを取得 + imgctrl = (*it).imgctrl; + + // 以降の判定を行わない + if( (*it).match_break ) break; + } + } + return imgctrl; +} + + +// +// 置換文字列を変換 +// \0 ... \9 ( $0 ... $9 ) : 正規表現の部分一致 +// +void Urlreplace_Manager::replace( JDLIB::Regex ®ex, std::string &str ) +{ + if( str.empty() ) return; + + char rep1[] = "\\0"; + char rep2[] = "$0"; + for( int i = 0; i < 9; i++ ){ + if( regex.pos( i ) == -1 ){ + break; + } + rep1[ 1 ] = '0' + i; + if( str.find( rep1 ) != std::string::npos ){ + str = MISC::replace_str( str, rep1, regex.str( i ) ); + } + rep2[ 1 ] = '0' + i; + if( str.find( rep2 ) != std::string::npos ){ + str = MISC::replace_str( str, rep2, regex.str( i ) ); + } + } +} + diff -Nru jd-2.8.5-120826/src/urlreplacemanager.h jd-2.8.6-130518/src/urlreplacemanager.h --- jd-2.8.5-120826/src/urlreplacemanager.h 1970-01-01 00:00:00.000000000 +0000 +++ jd-2.8.6-130518/src/urlreplacemanager.h 2013-03-30 05:23:47.000000000 +0000 @@ -0,0 +1,70 @@ +// ライセンス: GPL2 + +#ifndef _URLREPLACEMANAGER_H +#define _URLREPLACEMANAGER_H + +#include +#include +#include + +#include "jdlib/jdregex.h" + +namespace CORE +{ + enum + { + IMGCTRL_INIT = 0, + IMGCTRL_NONE = 1, + + IMGCTRL_FORCEIMAGE = 2, + IMGCTRL_FORCEBROWSER = 4, + IMGCTRL_GENUINE = 8, + IMGCTRL_THUMBNAIL = 16, + }; + + struct UrlreplaceItem + { + std::string match; + std::string replace; + std::string referer; + int imgctrl; + bool match_break; + }; + + class Urlreplace_Manager + { + std::list< UrlreplaceItem > m_list_cmd; + std::map< std::string, int > m_map_imgctrl; // 画像コントロールのキャッシュ + + public: + + Urlreplace_Manager(); + virtual ~Urlreplace_Manager(){} + + // URLを任意の正規表現で変換する + const bool exec( std::string &url ); + + // URLからリファラを求める + const bool referer( const std::string &url, std::string &referer ); + + // URLの画像コントロールを取得する + const int get_imgctrl( const std::string &url ); + + private: + + void conf2list( const std::string& conf ); + const int get_imgctrl_impl( const std::string &url ); + + // 置換文字列を変換 + void replace( JDLIB::Regex ®ex, std::string &str ); + }; + + /////////////////////////////////////// + // インターフェース + + Urlreplace_Manager* get_urlreplace_manager(); + void delete_urlreplace_manager(); +} + + +#endif diff -Nru jd-2.8.5-120826/src/xml/Makefile.am jd-2.8.6-130518/src/xml/Makefile.am --- jd-2.8.5-120826/src/xml/Makefile.am 2007-06-01 11:50:18.000000000 +0000 +++ jd-2.8.6-130518/src/xml/Makefile.am 2013-01-05 15:44:26.000000000 +0000 @@ -13,4 +13,4 @@ tools.h AM_CXXFLAGS = @GTKMM_CFLAGS@ -INCLUDES = -I$(top_srcdir)/src +AM_CPPFLAGS = -I$(top_srcdir)/src