├── AUTHORS ├── CMakeLists.txt ├── COPYING ├── INSTALL ├── NEWS ├── README ├── autoconf ├── aclocal.m4 ├── configure ├── configure.ac └── makefile.in ├── debian ├── changelog ├── compat ├── control ├── copyright ├── postinst ├── postrm └── rules ├── intl ├── compile.sh ├── en_US.po ├── mo │ ├── en_US │ │ └── simple-fb2-reader.mo │ └── ru │ │ └── simple-fb2-reader.mo ├── prepare.sh ├── ru.po └── simple-fb2-reader.pot ├── res ├── application-x-fictionbook+xml.svg ├── application-x-zip-compressed-fb2.svg ├── simple-fb2-reader.css ├── simple-fb2-reader.desktop ├── simple-fb2-reader.glade ├── simple-fb2-reader.svg └── simple-fb2-reader.xml ├── slackbuild ├── doinst.sh ├── simple-fb2-reader.SlackBuild ├── simple-fb2-reader.info └── slack-desc └── src ├── callbacks ├── callbacks_chunk.h ├── context_menu_callbacks │ ├── about_callback.c │ ├── auto_scroll_callback.c │ ├── backward_callback.c │ ├── book_search_callback.c │ ├── close_book_callback.c │ ├── exit_callback.c │ ├── navigation_callback.c │ ├── navigation_section_callback.c │ └── open_file_callback.c ├── main_wnd_callbacks.c ├── search_wnd_callbacks.c └── text_view_callback │ ├── link_tag_enevt_callback.c │ ├── motion_event_callback.c │ ├── popup_menu_callback.c │ ├── scroll_event_callback.c │ └── tooltip_callback.c ├── chunks.h ├── formats ├── fb2 │ ├── FictionBook │ │ ├── FictionBook.c │ │ ├── FictionBook_chunks.h │ │ ├── attributes │ │ │ ├── attributes_chunks.h │ │ │ └── id.c │ │ ├── binary │ │ │ └── binary.c │ │ ├── body │ │ │ ├── body.c │ │ │ ├── body_chunks.h │ │ │ ├── epigraph.c │ │ │ ├── image.c │ │ │ ├── section │ │ │ │ ├── a.c │ │ │ │ ├── cite.c │ │ │ │ ├── date.c │ │ │ │ ├── empty_line.c │ │ │ │ ├── image_inline.c │ │ │ │ ├── p │ │ │ │ │ ├── p.c │ │ │ │ │ ├── p_chunks.h │ │ │ │ │ ├── p_length.c │ │ │ │ │ └── p_text.c │ │ │ │ ├── poem.c │ │ │ │ ├── poem │ │ │ │ │ ├── poem.h │ │ │ │ │ ├── stanza.c │ │ │ │ │ └── v.c │ │ │ │ ├── section.c │ │ │ │ ├── section_chunks.h │ │ │ │ ├── style.c │ │ │ │ ├── subtitle.c │ │ │ │ ├── table │ │ │ │ │ ├── table.c │ │ │ │ │ ├── table_chunks.h │ │ │ │ │ ├── table_put_line.c │ │ │ │ │ ├── table_size.c │ │ │ │ │ ├── table_tr_next.c │ │ │ │ │ └── tr.c │ │ │ │ └── text_autor.c │ │ │ └── title.c │ │ └── description │ │ │ ├── annotation.c │ │ │ ├── book_title.c │ │ │ ├── coverpage.c │ │ │ ├── description.c │ │ │ ├── description_chunks.h │ │ │ └── title-info.c │ ├── fb2_chunks.h │ └── fb2_parser.c ├── fb2_zip │ ├── fb2_zip_chunks.h │ └── fb2_zip_parser.c └── formats_chunks.h ├── main.c └── reader ├── reader_app ├── reader_app.h ├── reader_app_config.c ├── reader_app_gui.c ├── reader_close_app.c └── reader_search_wnd.c ├── reader_book ├── reader_add_book_to_start_screen.c ├── reader_book_chunks.h ├── reader_book_hash.c ├── reader_books_db.c ├── reader_close_book.c └── reader_open_book.c ├── reader_chunks.h ├── reader_color_theme.c ├── reader_scroll.c ├── reader_start_screen.c └── reader_text_tags.c /AUTHORS: -------------------------------------------------------------------------------- 1 | Created by Cactus 2 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.0.2) 2 | 3 | include (GNUInstallDirs) 4 | include (FindPkgConfig) 5 | 6 | set (PROJECT simple-fb2-reader) 7 | set (VERSION 1.1.3) 8 | 9 | if (NOT DEFINED CMAKE_INSTALL_PREFIX) 10 | set(CMAKE_INSTALL_PREFIX "/usr") 11 | endif () 12 | 13 | project (${PROJECT} C) 14 | 15 | file (GLOB_RECURSE SOURCES RELATIVE ${PROJECT_SOURCE_DIR} "src/*.c") 16 | file (GLOB_RECURSE HEADERS RELATIVE ${PROJECT_SOURCE_DIR} "src/*.h") 17 | 18 | pkg_search_module (GTK3 REQUIRED gtk+-3.0) 19 | pkg_search_module (LIBZIP REQUIRED libzip) 20 | pkg_search_module (SQLITE3 REQUIRED sqlite3) 21 | pkg_search_module (LIBXML2 REQUIRED libxml-2.0) 22 | pkg_search_module (GLIB REQUIRED glib-2.0) 23 | 24 | set (LIBRARIES 25 | ${GTK3_LIBRARIES} 26 | ${LIBZIP_LIBRARIES} 27 | ${SQLITE3_LIBRARIES} 28 | ${LIBXML2_LIBRARIES} 29 | ${GLIB_LIBRARIES}) 30 | 31 | 32 | set (INCLUDES 33 | ${GTK3_INCLUDE_DIRS} 34 | ${LIBZIP_INCLUDE_DIRS} 35 | ${SQLITE3_INCLUDE_DIRS} 36 | ${LIBXML2_INCLUDE_DIRS} 37 | ${GLIB_INCLUDE_DIRS}) 38 | 39 | 40 | #BUILD 41 | 42 | set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99") 43 | set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -export-dynamic") 44 | 45 | add_definitions (-DGUI_CONSTRUCT_PATH="${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT}/${PROJECT}.glade") 46 | add_definitions (-DPACKAGE_VERSION="${VERSION}") 47 | add_definitions (-DPACKAGE_NAME="${PROJECT}") 48 | 49 | include_directories (${INCLUDES}) 50 | add_executable (${PROJECT} ${HEADERS} ${SOURCES}) 51 | target_link_libraries (${PROJECT} ${LIBRARIES}) 52 | 53 | 54 | #INSTALL 55 | 56 | install (TARGETS ${PROJECT} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 57 | install (FILES res/${PROJECT}.glade DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT}/) 58 | install (FILES res/${PROJECT}.css DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT}/) 59 | 60 | install (FILES intl/mo/en_US/${PROJECT}.mo DESTINATION ${CMAKE_INSTALL_LOCALEDIR}/en_US/LC_MESSAGES/) 61 | install (FILES intl/mo/ru/${PROJECT}.mo DESTINATION ${CMAKE_INSTALL_LOCALEDIR}/ru/LC_MESSAGES/) 62 | 63 | install (FILES res/${PROJECT}.desktop DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications/) 64 | install (FILES res/${PROJECT}.svg DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/scalable/apps/) 65 | 66 | install (FILES res/${PROJECT}.xml DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/mime/packages/) 67 | install (FILES res/application-x-fictionbook+xml.svg DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/scalable/mimetypes/) 68 | install (FILES res/application-x-zip-compressed-fb2.svg DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/scalable/mimetypes/) 69 | 70 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | If you whant use autotools, remove CMakeLists.txt and copy files from autotools directory. 2 | 3 | DEBIAN: 4 | ################################################ 5 | $ cd ~/ 6 | $ git clone https://github.com/Cactus64k/simple-fb2-reader.git 7 | # apt-get install debhelper libxml2-dev libgtk-3-dev libzip-dev pkg-config gettext libsqlite3-dev cmake 8 | $ cd simple-fb2-reader 9 | $ dpkg-buildpackage -uc -us 10 | $ cd .. 11 | # dpkg -i simple-fb2-reader_*.deb 12 | 13 | ARCHLINUX 14 | ################################################ 15 | https://aur.archlinux.org/packages/simple-fb2-reader 16 | 17 | SLACKWARE 18 | ################################################ 19 | Use ./slackbuild 20 | 21 | FEDORA 22 | ################################################ 23 | https://copr.fedoraproject.org/coprs/dexpl/simple-fb2-reader/ 24 | 25 | ANOTHER SYSTEMS: 26 | ################################################ 27 | $ cd ~/ 28 | $ git clone https://github.com/Cactus64k/simple-fb2-reader.git 29 | $ cd simple-fb2-reader 30 | $ cmake CMakeLists.txt 31 | $ make 32 | $ make install 33 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | 2 | 1.0.1 (00/00/0000): 3 | Fix navigaiton chapter content 4 | 5 | 1.0.2 (00/00/0000): 6 | Refactoring, add in book open dialog "file-activate" handler 7 | 8 | 1.0.3 (00/00/0000): 9 | Add command line options 10 | 11 | 1.0.4 (00/00/0000): 12 | Add autotools scripts, more themes options, arrow key scrolling 13 | 14 | 1.0.5 (00/00/0000): 15 | Fix autotools scripts 16 | 17 | 1.0.6 (00/00/0000): 18 | Fix line spacing, Fix empty start book paramether crash, Fix memory leak if you open non-book file. 19 | 20 | 1.0.7 (00/00/0000): 21 | Refactoring, Fix memory leak on tag attributes, tooltip on link, increase table support, INSTALL file update 22 | 23 | 1.0.8 (00/00/0000): 24 | Fix 1.0.7 25 | 26 | 1.0.9 (25/04/2015): 27 | Word wrap in tables, fix memory leak, tables optimisation, fix book icon link 28 | 29 | 1.1.0 (27/06/2016): 30 | Saving reading position in sqlite database, deleting plain text format support, refactoring, error dialog. 31 | 32 | 1.1.1 (12/07/2016): 33 | Autoscroll, refactoring. 34 | 35 | 1.1.3 (12/08/2019): 36 | User themes based on css, update GTK API 37 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | # simple-fb2-reader 2 | Simple tool to read FB2 books. Developed using GTK+3. 3 | ===================================================== 4 | 5 | Features: 6 | - supports fb2 and fb2.zip 7 | - saving reading position 8 | - saving window state, size and position 9 | - search text in book 10 | - URI(with backward button and tooltips) 11 | - full 2.1 format support(without stylesheet and partial table support) 12 | - navigation 13 | - russian and english gui 14 | - user themes 15 | edit ~/.config/simple-fb2-reader/simple-fb2-reader.css 16 | example dark theme /usr/share/simple-fb2-reader/simple-fb2-reader.css 17 | - auto scrolling(see config for customise scrolling speed) 18 | - hotkeys 19 | 20 | All features located in context menu. 21 | Hotkeys description in "About" menu item. 22 | 23 | Depends: 24 | - libxml2 >= 2.9.4 25 | - libgtk-3-0 >= 3.24.10 26 | - libzip >= 1.5.1 27 | - libsqlite3-0 >= 3.29.0 28 | 29 | 30 | Build Depends: 31 | - debhelper >= 12.3 32 | - libxml2-dev >= 2.9.4 33 | - libgtk-3-dev >= 3.24.10 34 | - libzip-dev >= 1.5.1 35 | - pkg-config >= 0.29 36 | - gettext >= 0.19.8 37 | - libsqlite3-dev >= 3.29.0 38 | - cmake >= 3.13.4 39 | -------------------------------------------------------------------------------- /autoconf/aclocal.m4: -------------------------------------------------------------------------------- 1 | # generated automatically by aclocal 1.14.1 -*- Autoconf -*- 2 | 3 | # Copyright (C) 1996-2013 Free Software Foundation, Inc. 4 | 5 | # This file is free software; the Free Software Foundation 6 | # gives unlimited permission to copy and/or distribute it, 7 | # with or without modifications, as long as this notice is preserved. 8 | 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY, to the extent permitted by law; without 11 | # even the implied warranty of MERCHANTABILITY or FITNESS FOR A 12 | # PARTICULAR PURPOSE. 13 | 14 | m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) 15 | # pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- 16 | # serial 1 (pkg-config-0.24) 17 | # 18 | # Copyright © 2004 Scott James Remnant . 19 | # 20 | # This program is free software; you can redistribute it and/or modify 21 | # it under the terms of the GNU General Public License as published by 22 | # the Free Software Foundation; either version 2 of the License, or 23 | # (at your option) any later version. 24 | # 25 | # This program is distributed in the hope that it will be useful, but 26 | # WITHOUT ANY WARRANTY; without even the implied warranty of 27 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 28 | # General Public License for more details. 29 | # 30 | # You should have received a copy of the GNU General Public License 31 | # along with this program; if not, write to the Free Software 32 | # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 33 | # 34 | # As a special exception to the GNU General Public License, if you 35 | # distribute this file as part of a program that contains a 36 | # configuration script generated by Autoconf, you may include it under 37 | # the same distribution terms that you use for the rest of that program. 38 | 39 | # PKG_PROG_PKG_CONFIG([MIN-VERSION]) 40 | # ---------------------------------- 41 | AC_DEFUN([PKG_PROG_PKG_CONFIG], 42 | [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) 43 | m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) 44 | m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) 45 | AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) 46 | AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) 47 | AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) 48 | 49 | if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then 50 | AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) 51 | fi 52 | if test -n "$PKG_CONFIG"; then 53 | _pkg_min_version=m4_default([$1], [0.9.0]) 54 | AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) 55 | if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then 56 | AC_MSG_RESULT([yes]) 57 | else 58 | AC_MSG_RESULT([no]) 59 | PKG_CONFIG="" 60 | fi 61 | fi[]dnl 62 | ])# PKG_PROG_PKG_CONFIG 63 | 64 | # PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) 65 | # 66 | # Check to see whether a particular set of modules exists. Similar 67 | # to PKG_CHECK_MODULES(), but does not set variables or print errors. 68 | # 69 | # Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) 70 | # only at the first occurence in configure.ac, so if the first place 71 | # it's called might be skipped (such as if it is within an "if", you 72 | # have to call PKG_CHECK_EXISTS manually 73 | # -------------------------------------------------------------- 74 | AC_DEFUN([PKG_CHECK_EXISTS], 75 | [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl 76 | if test -n "$PKG_CONFIG" && \ 77 | AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then 78 | m4_default([$2], [:]) 79 | m4_ifvaln([$3], [else 80 | $3])dnl 81 | fi]) 82 | 83 | # _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) 84 | # --------------------------------------------- 85 | m4_define([_PKG_CONFIG], 86 | [if test -n "$$1"; then 87 | pkg_cv_[]$1="$$1" 88 | elif test -n "$PKG_CONFIG"; then 89 | PKG_CHECK_EXISTS([$3], 90 | [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` 91 | test "x$?" != "x0" && pkg_failed=yes ], 92 | [pkg_failed=yes]) 93 | else 94 | pkg_failed=untried 95 | fi[]dnl 96 | ])# _PKG_CONFIG 97 | 98 | # _PKG_SHORT_ERRORS_SUPPORTED 99 | # ----------------------------- 100 | AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], 101 | [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) 102 | if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then 103 | _pkg_short_errors_supported=yes 104 | else 105 | _pkg_short_errors_supported=no 106 | fi[]dnl 107 | ])# _PKG_SHORT_ERRORS_SUPPORTED 108 | 109 | 110 | # PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], 111 | # [ACTION-IF-NOT-FOUND]) 112 | # 113 | # 114 | # Note that if there is a possibility the first call to 115 | # PKG_CHECK_MODULES might not happen, you should be sure to include an 116 | # explicit call to PKG_PROG_PKG_CONFIG in your configure.ac 117 | # 118 | # 119 | # -------------------------------------------------------------- 120 | AC_DEFUN([PKG_CHECK_MODULES], 121 | [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl 122 | AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl 123 | AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl 124 | 125 | pkg_failed=no 126 | AC_MSG_CHECKING([for $1]) 127 | 128 | _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) 129 | _PKG_CONFIG([$1][_LIBS], [libs], [$2]) 130 | 131 | m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS 132 | and $1[]_LIBS to avoid the need to call pkg-config. 133 | See the pkg-config man page for more details.]) 134 | 135 | if test $pkg_failed = yes; then 136 | AC_MSG_RESULT([no]) 137 | _PKG_SHORT_ERRORS_SUPPORTED 138 | if test $_pkg_short_errors_supported = yes; then 139 | $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` 140 | else 141 | $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` 142 | fi 143 | # Put the nasty error message in config.log where it belongs 144 | echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD 145 | 146 | m4_default([$4], [AC_MSG_ERROR( 147 | [Package requirements ($2) were not met: 148 | 149 | $$1_PKG_ERRORS 150 | 151 | Consider adjusting the PKG_CONFIG_PATH environment variable if you 152 | installed software in a non-standard prefix. 153 | 154 | _PKG_TEXT])[]dnl 155 | ]) 156 | elif test $pkg_failed = untried; then 157 | AC_MSG_RESULT([no]) 158 | m4_default([$4], [AC_MSG_FAILURE( 159 | [The pkg-config script could not be found or is too old. Make sure it 160 | is in your PATH or set the PKG_CONFIG environment variable to the full 161 | path to pkg-config. 162 | 163 | _PKG_TEXT 164 | 165 | To get pkg-config, see .])[]dnl 166 | ]) 167 | else 168 | $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS 169 | $1[]_LIBS=$pkg_cv_[]$1[]_LIBS 170 | AC_MSG_RESULT([yes]) 171 | $3 172 | fi[]dnl 173 | ])# PKG_CHECK_MODULES 174 | 175 | 176 | # PKG_INSTALLDIR(DIRECTORY) 177 | # ------------------------- 178 | # Substitutes the variable pkgconfigdir as the location where a module 179 | # should install pkg-config .pc files. By default the directory is 180 | # $libdir/pkgconfig, but the default can be changed by passing 181 | # DIRECTORY. The user can override through the --with-pkgconfigdir 182 | # parameter. 183 | AC_DEFUN([PKG_INSTALLDIR], 184 | [m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) 185 | m4_pushdef([pkg_description], 186 | [pkg-config installation directory @<:@]pkg_default[@:>@]) 187 | AC_ARG_WITH([pkgconfigdir], 188 | [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, 189 | [with_pkgconfigdir=]pkg_default) 190 | AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) 191 | m4_popdef([pkg_default]) 192 | m4_popdef([pkg_description]) 193 | ]) dnl PKG_INSTALLDIR 194 | 195 | 196 | # PKG_NOARCH_INSTALLDIR(DIRECTORY) 197 | # ------------------------- 198 | # Substitutes the variable noarch_pkgconfigdir as the location where a 199 | # module should install arch-independent pkg-config .pc files. By 200 | # default the directory is $datadir/pkgconfig, but the default can be 201 | # changed by passing DIRECTORY. The user can override through the 202 | # --with-noarch-pkgconfigdir parameter. 203 | AC_DEFUN([PKG_NOARCH_INSTALLDIR], 204 | [m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) 205 | m4_pushdef([pkg_description], 206 | [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) 207 | AC_ARG_WITH([noarch-pkgconfigdir], 208 | [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, 209 | [with_noarch_pkgconfigdir=]pkg_default) 210 | AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) 211 | m4_popdef([pkg_default]) 212 | m4_popdef([pkg_description]) 213 | ]) dnl PKG_NOARCH_INSTALLDIR 214 | 215 | 216 | # PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, 217 | # [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) 218 | # ------------------------------------------- 219 | # Retrieves the value of the pkg-config variable for the given module. 220 | AC_DEFUN([PKG_CHECK_VAR], 221 | [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl 222 | AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl 223 | 224 | _PKG_CONFIG([$1], [variable="][$3]["], [$2]) 225 | AS_VAR_COPY([$1], [pkg_cv_][$1]) 226 | 227 | AS_VAR_IF([$1], [""], [$5], [$4])dnl 228 | ])# PKG_CHECK_VAR 229 | 230 | -------------------------------------------------------------------------------- /autoconf/configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ([2.69]) 5 | AC_INIT([simple-fb2-reader], [1.1.3], [medved_cool@mail.ru], [], [https://github.com/Cactus64k/simple-fb2-reader]) 6 | # AM_INIT_AUTOMAKE 7 | # AC_CONFIG_SRCDIR([src/]) 8 | # AC_CONFIG_HEADERS([src/config.h.in]) 9 | 10 | # Checks for programs. 11 | AC_PROG_CC_C99 12 | 13 | # Checks for libraries. 14 | PKG_CHECK_MODULES([XML], [libxml-2.0 >= 2.9.1]) 15 | PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.32.4]) 16 | PKG_CHECK_MODULES([GTK], [gtk+-3.0 >= 3.14.5]) 17 | PKG_CHECK_MODULES([ZIP], [libzip >= 0.11.2]) 18 | PKG_CHECK_MODULES([SQLITE3], [sqlite3 >= 3.8.7.1]) 19 | 20 | 21 | # Checks for header files. 22 | AC_CHECK_HEADERS([libintl.h locale.h stddef.h stdint.h stdlib.h string.h stdint.h stdio.h assert.h]) 23 | 24 | # Checks for typedefs, structures, and compiler characteristics. 25 | AC_TYPE_SIZE_T 26 | AC_TYPE_SSIZE_T 27 | 28 | # Checks for library functions. 29 | AC_FUNC_REALLOC 30 | AC_CHECK_FUNCS([memset setlocale strchr strerror]) 31 | 32 | AC_DEFINE_UNQUOTED([PACKAGE_VERSION], "${PACKAGE_VERSION}") 33 | AC_DEFINE_UNQUOTED([PACKAGE_NAME], "${PACKAGE_NAME}") 34 | 35 | 36 | AC_CONFIG_FILES([makefile]) 37 | AC_OUTPUT 38 | -------------------------------------------------------------------------------- /autoconf/makefile.in: -------------------------------------------------------------------------------- 1 | prefix = @prefix@ 2 | exec_prefix = @exec_prefix@ 3 | bindir = @bindir@ 4 | exec_prefix = @exec_prefix@ 5 | sysconfdir = @sysconfdir@ 6 | datarootdir = @datarootdir@ 7 | localedir = @localedir@ 8 | 9 | #################################################################################### 10 | PACKAGE_NAME = @PACKAGE_NAME@ 11 | PACKAGE_VERSION = @PACKAGE_VERSION@ 12 | SOURCES = $(shell find . -name '*.c' -printf './%P ') 13 | OBJECTS = $(SOURCES:.c=.o) 14 | 15 | DEFINIONS = -DGUI_CONSTRUCT_PATH='"$(datarootdir)/$(PACKAGE_NAME)/$(PACKAGE_NAME).glade"' \ 16 | -DPACKAGE_VERSION='"$(PACKAGE_VERSION)"' \ 17 | -DPACKAGE_NAME='"$(PACKAGE_NAME)"' 18 | CC = @CC@ 19 | CFLAGS = @CFLAGS@ $(DEFINIONS) 20 | LDFLAGS = -export-dynamic 21 | 22 | #################################################################################### 23 | LIBS = @GTK_LIBS@\ 24 | @XML_LIBS@\ 25 | @GLIB_LIBS@\ 26 | @ZIP_LIBS@\ 27 | @SQLITE3_LIBS@ 28 | 29 | #################################################################################### 30 | INCLUDE = @GTK_CFLAGS@\ 31 | @XML_CFLAGS@\ 32 | @GLIB_CFLAGS@\ 33 | @ZIP_CFLAGS@\ 34 | @SQLITE3_CFLAGS@ 35 | 36 | all: $(SOURCES) $(PACKAGE_NAME) TRANSLATE_TARGET 37 | 38 | TRANSLATE_TARGET: 39 | msgfmt intl/ru.po --output-file=intl/ru.mo 40 | msgfmt intl/en_US.po --output-file=intl/en_US.mo 41 | 42 | $(PACKAGE_NAME): $(OBJECTS) 43 | $(CC) $(LDFLAGS) $(OBJECTS) $(LIBS) -o $@ 44 | 45 | .c.o: 46 | $(CC) $(CFLAGS) -c $< -o $@ $(INCLUDE) 47 | 48 | cppcheck_start: 49 | cppcheck -j`nproc` -q --inconclusive --library=gtk --enable=all --std=c99 --report-progress --max-configs=1 `pkg-config gtk+-3.0 --cflags-only-I` ./src/ 50 | 51 | clean: 52 | find -name "*.o" -delete 53 | find -name "*.mo" -delete 54 | rm -f $(PACKAGE_NAME) 55 | 56 | # FIXME for new project 57 | mk_folders: 58 | mkdir -p $(DESTDIR)$(bindir) 59 | mkdir -p $(DESTDIR)$(localedir)/en_US/LC_MESSAGES/ 60 | mkdir -p $(DESTDIR)$(localedir)/ru/LC_MESSAGES/ 61 | mkdir -p $(DESTDIR)$(datarootdir)/applications/ 62 | mkdir -p $(DESTDIR)$(datarootdir)/icons/hicolor/scalable/apps/ 63 | mkdir -p $(DESTDIR)$(datarootdir)/mime/packages/ 64 | mkdir -p $(DESTDIR)$(datarootdir)/icons/hicolor/scalable/mimetypes/ 65 | mkdir -p $(DESTDIR)$(datarootdir)/$(PACKAGE_NAME)/ 66 | 67 | # FIXME for new project 68 | install:mk_folders 69 | install $(PACKAGE_NAME) $(DESTDIR)$(bindir)/$(PACKAGE_NAME) 70 | cp intl/ru.mo $(DESTDIR)$(localedir)/ru/LC_MESSAGES/$(PACKAGE_NAME).mo 71 | cp intl/en_US.mo $(DESTDIR)$(localedir)/en_US/LC_MESSAGES/$(PACKAGE_NAME).mo 72 | cp res/$(PACKAGE_NAME).desktop $(DESTDIR)$(datarootdir)/applications/$(PACKAGE_NAME).desktop 73 | cp res/$(PACKAGE_NAME).svg $(DESTDIR)$(datarootdir)/icons/hicolor/scalable/apps/$(PACKAGE_NAME).svg 74 | cp res/simple-fb2-reader.xml $(DESTDIR)$(datarootdir)/mime/packages/simple-fb2-reader.xml 75 | cp res/application-x-fictionbook+xml.svg $(DESTDIR)$(datarootdir)/icons/hicolor/scalable/mimetypes/application-x-fictionbook+xml.svg 76 | cp res/$(PACKAGE_NAME).glade $(DESTDIR)$(datarootdir)/$(PACKAGE_NAME)/$(PACKAGE_NAME).glade 77 | cp res/$(PACKAGE_NAME).css $(DESTDIR)$(datarootdir)/$(PACKAGE_NAME)/$(PACKAGE_NAME).css 78 | ln -sr $(DESTDIR)$(datarootdir)/icons/hicolor/scalable/mimetypes/application-x-fictionbook+xml.svg $(DESTDIR)$(datarootdir)/icons/hicolor/scalable/mimetypes/application-x-zip-compressed-fb2.svg 79 | 80 | 81 | -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | simple-fb2-reader (1.1.3) unstable; urgency=low 2 | 3 | * Initial release (Closes: #nnnn) 4 | 5 | -- Cactus Sun, 08 Mar 2015 00:29:56 +0300 6 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 9 2 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: simple-fb2-reader 2 | Section: text 3 | Priority: optional 4 | Maintainer: Cactus 5 | Build-Depends: debhelper (>= 12.3), libxml2-dev (>= 2.9.4), libgtk-3-dev (>= 3.24.10), libzip-dev (>= 1.5.1), pkg-config (>= 0.29), gettext (>= 0.19.8), libsqlite3-dev (>= 3.29.0), cmake (>= 3.13.4) 6 | Standards-Version: 3.9.3 7 | Homepage: https://github.com/Cactus64k/simple-fb2-reader 8 | #Vcs-Git: git://git.debian.org/collab-maint/simple-fb2-reader.git 9 | #Vcs-Browser: http://git.debian.org/?p=collab-maint/simple-fb2-reader.git;a=summary 10 | 11 | Package: simple-fb2-reader 12 | Architecture: amd64 13 | Depends: ${shlibs:Depends} 14 | Description: Simple tool to read FB2 books. Developed using GTK+3. 15 | Features: 16 | - supports fb2 and fb2.zip 17 | - saving reading position 18 | - saving window state, size and position 19 | - search text in book 20 | - URI(with backward button and tooltips) 21 | - full 2.1 format support(without stylesheet and partial table tag support) 22 | - navigation 23 | - russian and english gui 24 | - user themes 25 | edit ~/.config/simple-fb2-reader/simple-fb2-reader.css 26 | example dark theme /usr/share/simple-fb2-reader/simple-fb2-reader.css 27 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: simple-fb2-reader 3 | Source: https://github.com/Cactus64k/simple-fb2-reader 4 | 5 | Files: ALL 6 | Copyright: 2015 Cactus 7 | License: GPL-3+ 8 | This package is free software; you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation; either version 3 of the License, or 11 | (at your option) any later version. 12 | . 13 | This package is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | . 18 | You should have received a copy of the GNU General Public License 19 | along with this program. If not, see 20 | . 21 | On Debian systems, the complete text of the GNU General 22 | Public License version 3 can be found in "/usr/share/common-licenses/GPL-3". 23 | 24 | Files: debian/* 25 | Copyright: 2015 Cactus 26 | License: GPL-3+ 27 | This package is free software; you can redistribute it and/or modify 28 | it under the terms of the GNU General Public License as published by 29 | the Free Software Foundation; either version 3 of the License, or 30 | (at your option) any later version. 31 | . 32 | This package is distributed in the hope that it will be useful, 33 | but WITHOUT ANY WARRANTY; without even the implied warranty of 34 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 35 | GNU General Public License for more details. 36 | . 37 | You should have received a copy of the GNU General Public License 38 | along with this program. If not, see 39 | . 40 | On Debian systems, the complete text of the GNU General 41 | Public License version 3 can be found in "/usr/share/common-licenses/GPL-3". 42 | 43 | # Please also look if there are files or directories which have a 44 | # different copyright/license attached and list them here. 45 | # Please avoid to pick license terms that are more restrictive than the 46 | # packaged work, as it may make Debian's contributions unacceptable upstream. 47 | -------------------------------------------------------------------------------- /debian/postinst: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | # Automatically added by dh_installmenu 4 | if [ "$1" = "configure" ] && [ -x "`which update-menus 2>/dev/null`" ]; then 5 | update-menus 6 | fi 7 | # End automatically added section 8 | # Automatically added by dh_installmime 9 | if [ "$1" = "configure" ] && [ -x "`which update-mime-database 2>/dev/null`" ]; then 10 | update-mime-database /usr/share/mime 11 | fi 12 | # End automatically added section 13 | -------------------------------------------------------------------------------- /debian/postrm: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | # Automatically added by dh_installmime 4 | if [ -x "`which update-mime-database 2>/dev/null`" ]; then 5 | update-mime-database /usr/share/mime 6 | fi 7 | # End automatically added section 8 | # Automatically added by dh_installmenu 9 | if [ -x "`which update-menus 2>/dev/null`" ]; then update-menus ; fi 10 | # End automatically added section 11 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | # -*- makefile -*- 3 | # Sample debian/rules that uses debhelper. 4 | # This file was originally written by Joey Hess and Craig Small. 5 | # As a special exception, when this file is copied by dh-make into a 6 | # dh-make output file, you may use that output file without restriction. 7 | # This special exception was added by Craig Small in version 0.37 of dh-make. 8 | 9 | # Uncomment this to turn on verbose mode. 10 | #export DH_VERBOSE=1 11 | 12 | %: 13 | dh $@ 14 | -------------------------------------------------------------------------------- /intl/compile.sh: -------------------------------------------------------------------------------- 1 | # bin/bash 2 | 3 | PACKAGE_NAME=simple-fb2-reader 4 | mkdir -p mo/ru/ 5 | mkdir -p mo/en_US/ 6 | msgfmt ru.po --output-file=mo/ru/${PACKAGE_NAME}.mo 7 | msgfmt en_US.po --output-file=mo/en_US/${PACKAGE_NAME}.mo 8 | -------------------------------------------------------------------------------- /intl/en_US.po: -------------------------------------------------------------------------------- 1 | # English translations for simple-fb2-reader package. 2 | # Copyright (C) 2016 THE simple-fb2-reader'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the simple-fb2-reader package. 4 | # Automatically generated, 2016. 5 | # 6 | msgid "" 7 | msgstr "" 8 | "Project-Id-Version: simple-fb2-reader 1.0.0\n" 9 | "Report-Msgid-Bugs-To: medved_cool@mail.ru\n" 10 | "POT-Creation-Date: 2017-01-03 19:51+0300\n" 11 | "PO-Revision-Date: 2016-12-30 19:08+0300\n" 12 | "Last-Translator: Automatically generated\n" 13 | "Language-Team: none\n" 14 | "Language: en_US\n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=UTF-8\n" 17 | "Content-Transfer-Encoding: 8bit\n" 18 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 19 | 20 | #: ../res/simple-fb2-reader.glade:93 21 | msgid "" 22 | "\n" 23 | "ctrl+n\t\t\t\tNavigation\n" 24 | "ctrl+f\t\t\t\tSearch\n" 25 | "ctrl+h\t\t\t\tAbout\n" 26 | "ctrl+o\t\t\t\tOpen book\n" 27 | "ctrl+q\t\t\t\tExit\n" 28 | "ctrl+c\t\t\t\tCopy text\n" 29 | "ctrl+mouse-wheel \tFont scale\n" 30 | "ctrl+0\t\t\t \tDefault font scale\n" 31 | "left-arrow\t\t\tPrevious position(link navigation)\n" 32 | "\n" 33 | "\t\t\tHave nice reading!\n" 34 | msgstr "" 35 | "\n" 36 | "ctrl+n\t\t\t\tNavigation\n" 37 | "ctrl+f\t\t\t\tSearch\n" 38 | "ctrl+h\t\t\t\tAbout\n" 39 | "ctrl+o\t\t\t\tOpen book\n" 40 | "ctrl+q\t\t\t\tExit\n" 41 | "ctrl+c\t\t\t\tCopy text\n" 42 | "ctrl+mouse-wheel \tFont scale\n" 43 | "ctrl+0\t\t\t \tDefault font scale\n" 44 | "left-arrow\t\t\tPrevious position(link navigation)\n" 45 | "\n" 46 | "\t\t\tHave nice reading!\n" 47 | 48 | #: ../res/simple-fb2-reader.glade:118 49 | msgid "Search" 50 | msgstr "" 51 | 52 | #: ../res/simple-fb2-reader.glade:190 53 | #: ../src/callbacks/text_view_callback/popup_menu_callback.c:12 54 | msgid "Backward" 55 | msgstr "Backward" 56 | 57 | #: ../res/simple-fb2-reader.glade:207 58 | msgid "Forward" 59 | msgstr "Forward" 60 | 61 | #: ../res/simple-fb2-reader.glade:248 62 | msgid "Case ensitive" 63 | msgstr "Case ensitive" 64 | 65 | #: ../res/simple-fb2-reader.glade:282 66 | #: ../src/callbacks/text_view_callback/popup_menu_callback.c:22 67 | msgid "Navigation" 68 | msgstr "Navigation" 69 | 70 | #: ../res/simple-fb2-reader.glade:396 71 | msgid "Select file" 72 | msgstr "" 73 | 74 | #: ../src/reader/reader_start_screen.c:16 75 | msgid "" 76 | "\n" 77 | "\n" 78 | "Recent books:\n" 79 | "\n" 80 | msgstr "" 81 | "\n" 82 | "\n" 83 | "Recent books:\n" 84 | "\n" 85 | 86 | #: ../src/reader/reader_start_screen.c:34 87 | msgid "No name book" 88 | msgstr "No name book" 89 | 90 | #: ../src/reader/reader_book/reader_open_book.c:51 91 | #, c-format 92 | msgid "" 93 | "Failed to open book:\n" 94 | "%s" 95 | msgstr "" 96 | 97 | #: ../src/callbacks/text_view_callback/popup_menu_callback.c:27 98 | msgid "Find" 99 | msgstr "Find" 100 | 101 | #: ../src/callbacks/text_view_callback/popup_menu_callback.c:37 102 | msgid "Auto scrolling" 103 | msgstr "Auto scrolling" 104 | 105 | #: ../src/callbacks/text_view_callback/popup_menu_callback.c:44 106 | msgid "Color Theme" 107 | msgstr "Color Theme" 108 | 109 | #: ../src/callbacks/text_view_callback/popup_menu_callback.c:51 110 | msgid "About" 111 | msgstr "About" 112 | 113 | #: ../src/callbacks/text_view_callback/popup_menu_callback.c:56 114 | msgid "Open Book" 115 | msgstr "Open Book" 116 | 117 | #: ../src/callbacks/text_view_callback/popup_menu_callback.c:61 118 | msgid "Close Book" 119 | msgstr "Close Book" 120 | 121 | #: ../src/callbacks/text_view_callback/popup_menu_callback.c:70 122 | msgid "Exit" 123 | msgstr "Exit" 124 | 125 | #: ../src/callbacks/context_menu_callbacks/auto_scroll_callback.c:28 126 | msgid "Enable" 127 | msgstr "Enable" 128 | 129 | #: ../src/callbacks/context_menu_callbacks/auto_scroll_callback.c:33 130 | msgid "Disable" 131 | msgstr "Disable" 132 | 133 | #: ../src/formats/fb2/FictionBook/body/section/section.c:18 134 | msgid "Section without title" 135 | msgstr "Section without title" 136 | 137 | #: ../src/formats/fb2/FictionBook/body/body.c:15 138 | msgid "Body tag without title" 139 | msgstr "Body tag without title" 140 | 141 | #: ../src/formats/fb2/FictionBook/FictionBook.c:60 142 | msgid "End read book\n" 143 | msgstr "End read book\n" 144 | 145 | #: ../src/main.c:20 146 | msgid "Local path to book" 147 | msgstr "Local path to book" 148 | 149 | #: ../src/main.c:21 150 | msgid "Print reader version" 151 | msgstr "Print reader version" 152 | -------------------------------------------------------------------------------- /intl/mo/en_US/simple-fb2-reader.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cactus64k/simple-fb2-reader/46ef64c5d50a8f80e4837bebfaeb035ea0574104/intl/mo/en_US/simple-fb2-reader.mo -------------------------------------------------------------------------------- /intl/mo/ru/simple-fb2-reader.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cactus64k/simple-fb2-reader/46ef64c5d50a8f80e4837bebfaeb035ea0574104/intl/mo/ru/simple-fb2-reader.mo -------------------------------------------------------------------------------- /intl/prepare.sh: -------------------------------------------------------------------------------- 1 | # bin/bash 2 | export PROGNAME=simple-fb2-reader 3 | export VERSION=1.0.0 4 | export MAIL=medved_cool@mail.ru 5 | export KEYWORD=_C 6 | export SRC=`(find ../ -name '*.c' -printf '../%P ')` 7 | export GLADE=`(find ../ -name '*.glade' -printf '../%P ')` 8 | 9 | echo ${SRC[0]} 10 | 11 | xgettext --package-name=$PROGNAME --package-version=$VERSION --msgid-bugs-address=$MAIL --i --from-code=UTF-8 --output=./$PROGNAME.pot $GLADE 12 | xgettext -j --keyword=$KEYWORD --package-name=$PROGNAME --package-version=$VERSION --msgid-bugs-address=$MAIL --i --from-code=UTF-8 --output=./$PROGNAME.pot $SRC 13 | 14 | if [ -f ru.po ]; 15 | then 16 | msgmerge --update ru.po $PROGNAME.pot 17 | echo "merging ru.po" 18 | else 19 | msginit --no-translator --locale=ru_RU.utf8 --input=$PROGNAME.pot --output-file=ru.po 20 | fi 21 | 22 | if [ -f en_US.po ]; 23 | then 24 | msgmerge --update en_US.po $PROGNAME.pot 25 | echo "merging en_US.po" 26 | else 27 | msginit --no-translator --locale=en_US.utf8 --input=$PROGNAME.pot --output-file=en_US.po 28 | fi 29 | -------------------------------------------------------------------------------- /intl/ru.po: -------------------------------------------------------------------------------- 1 | # Russian translations for simple-fb2-reader package 2 | # Английские переводы для пакета simple-fb2-reader. 3 | # Copyright (C) 2016 THE simple-fb2-reader'S COPYRIGHT HOLDER 4 | # This file is distributed under the same license as the simple-fb2-reader package. 5 | # Automatically generated, 2016. 6 | # 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: simple-fb2-reader 1.0.0\n" 10 | "Report-Msgid-Bugs-To: medved_cool@mail.ru\n" 11 | "POT-Creation-Date: 2017-01-03 19:51+0300\n" 12 | "PO-Revision-Date: 2016-12-30 19:08+0300\n" 13 | "Last-Translator: Automatically generated\n" 14 | "Language-Team: none\n" 15 | "Language: ru\n" 16 | "MIME-Version: 1.0\n" 17 | "Content-Type: text/plain; charset=UTF-8\n" 18 | "Content-Transfer-Encoding: 8bit\n" 19 | "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" 20 | "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" 21 | 22 | #: ../res/simple-fb2-reader.glade:93 23 | msgid "" 24 | "\n" 25 | "ctrl+n\t\t\t\tNavigation\n" 26 | "ctrl+f\t\t\t\tSearch\n" 27 | "ctrl+h\t\t\t\tAbout\n" 28 | "ctrl+o\t\t\t\tOpen book\n" 29 | "ctrl+q\t\t\t\tExit\n" 30 | "ctrl+c\t\t\t\tCopy text\n" 31 | "ctrl+mouse-wheel \tFont scale\n" 32 | "ctrl+0\t\t\t \tDefault font scale\n" 33 | "left-arrow\t\t\tPrevious position(link navigation)\n" 34 | "\n" 35 | "\t\t\tHave nice reading!\n" 36 | msgstr "" 37 | "\n" 38 | "ctrl+n\t\t\t\tНавигация\n" 39 | "ctrl+f\t\t\t\tПоиск\n" 40 | "ctrl+h\t\t\t\tО программе\n" 41 | "ctrl+o\t\t\t\tОткрыть книгу\n" 42 | "ctrl+q\t\t\t\tВыход\n" 43 | "ctrl+c\t\t\t\tКопировать текст\n" 44 | "ctrl+mouse-wheel \tРазмер шрифта\n" 45 | "ctrl+0\t\t\t \tСтандартный размер шрифта\n" 46 | "left-arrow\t\t\tПредыдущая позиция(переходы по ссылкам)\n" 47 | "\n" 48 | "\t\t\tПриятного чтения!\n" 49 | 50 | #: ../res/simple-fb2-reader.glade:118 51 | msgid "Search" 52 | msgstr "Поиск" 53 | 54 | #: ../res/simple-fb2-reader.glade:190 55 | #: ../src/callbacks/text_view_callback/popup_menu_callback.c:12 56 | msgid "Backward" 57 | msgstr "Назад" 58 | 59 | #: ../res/simple-fb2-reader.glade:207 60 | msgid "Forward" 61 | msgstr "Вперед" 62 | 63 | #: ../res/simple-fb2-reader.glade:248 64 | msgid "Case ensitive" 65 | msgstr "Учитывать регистр" 66 | 67 | #: ../res/simple-fb2-reader.glade:282 68 | #: ../src/callbacks/text_view_callback/popup_menu_callback.c:22 69 | msgid "Navigation" 70 | msgstr "Навигация" 71 | 72 | #: ../res/simple-fb2-reader.glade:396 73 | msgid "Select file" 74 | msgstr "Выберите файл" 75 | 76 | #: ../src/reader/reader_start_screen.c:16 77 | msgid "" 78 | "\n" 79 | "\n" 80 | "Recent books:\n" 81 | "\n" 82 | msgstr "" 83 | "\n" 84 | "\n" 85 | "Последние книги:\n" 86 | "\n" 87 | 88 | #: ../src/reader/reader_start_screen.c:34 89 | msgid "No name book" 90 | msgstr "Книга без имени" 91 | 92 | #: ../src/reader/reader_book/reader_open_book.c:51 93 | #, c-format 94 | msgid "" 95 | "Failed to open book:\n" 96 | "%s" 97 | msgstr "" 98 | "Невозможно открыть книгу:\n" 99 | "%s" 100 | 101 | #: ../src/callbacks/text_view_callback/popup_menu_callback.c:27 102 | msgid "Find" 103 | msgstr "Найти" 104 | 105 | #: ../src/callbacks/text_view_callback/popup_menu_callback.c:37 106 | msgid "Auto scrolling" 107 | msgstr "Авто прокрутка" 108 | 109 | #: ../src/callbacks/text_view_callback/popup_menu_callback.c:44 110 | msgid "Color Theme" 111 | msgstr "Цветовая тема" 112 | 113 | #: ../src/callbacks/text_view_callback/popup_menu_callback.c:51 114 | msgid "About" 115 | msgstr "О программе" 116 | 117 | #: ../src/callbacks/text_view_callback/popup_menu_callback.c:56 118 | msgid "Open Book" 119 | msgstr "Открыть книгу" 120 | 121 | #: ../src/callbacks/text_view_callback/popup_menu_callback.c:61 122 | msgid "Close Book" 123 | msgstr "Закрыть книгу" 124 | 125 | #: ../src/callbacks/text_view_callback/popup_menu_callback.c:70 126 | msgid "Exit" 127 | msgstr "Выход" 128 | 129 | #: ../src/callbacks/context_menu_callbacks/auto_scroll_callback.c:28 130 | msgid "Enable" 131 | msgstr "Включить" 132 | 133 | #: ../src/callbacks/context_menu_callbacks/auto_scroll_callback.c:33 134 | msgid "Disable" 135 | msgstr "Выключить" 136 | 137 | #: ../src/formats/fb2/FictionBook/body/section/section.c:18 138 | msgid "Section without title" 139 | msgstr "Секция без заголовка" 140 | 141 | #: ../src/formats/fb2/FictionBook/body/body.c:15 142 | msgid "Body tag without title" 143 | msgstr "Тело без заголовка" 144 | 145 | #: ../src/formats/fb2/FictionBook/FictionBook.c:60 146 | msgid "End read book\n" 147 | msgstr "Окончание чтения книги\n" 148 | 149 | #: ../src/main.c:20 150 | msgid "Local path to book" 151 | msgstr "Локальный путь к книге" 152 | 153 | #: ../src/main.c:21 154 | msgid "Print reader version" 155 | msgstr "Вывести версию читалки" 156 | -------------------------------------------------------------------------------- /intl/simple-fb2-reader.pot: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "Project-Id-Version: simple-fb2-reader 1.0.0\n" 9 | "Report-Msgid-Bugs-To: medved_cool@mail.ru\n" 10 | "POT-Creation-Date: 2017-01-03 19:51+0300\n" 11 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 12 | "Last-Translator: FULL NAME \n" 13 | "Language-Team: LANGUAGE \n" 14 | "Language: \n" 15 | "MIME-Version: 1.0\n" 16 | "Content-Type: text/plain; charset=CHARSET\n" 17 | "Content-Transfer-Encoding: 8bit\n" 18 | 19 | #: ../res/simple-fb2-reader.glade:93 20 | msgid "\n" 21 | "ctrl+n\t\t\t\tNavigation\n" 22 | "ctrl+f\t\t\t\tSearch\n" 23 | "ctrl+h\t\t\t\tAbout\n" 24 | "ctrl+o\t\t\t\tOpen book\n" 25 | "ctrl+q\t\t\t\tExit\n" 26 | "ctrl+c\t\t\t\tCopy text\n" 27 | "ctrl+mouse-wheel \tFont scale\n" 28 | "ctrl+0\t\t\t \tDefault font scale\n" 29 | "left-arrow\t\t\tPrevious position(link navigation)\n" 30 | "\n" 31 | "\t\t\tHave nice reading!\n" 32 | msgstr "" 33 | 34 | #: ../res/simple-fb2-reader.glade:118 35 | msgid "Search" 36 | msgstr "" 37 | 38 | #: ../res/simple-fb2-reader.glade:190 39 | #: ../src/callbacks/text_view_callback/popup_menu_callback.c:12 40 | msgid "Backward" 41 | msgstr "" 42 | 43 | #: ../res/simple-fb2-reader.glade:207 44 | msgid "Forward" 45 | msgstr "" 46 | 47 | #: ../res/simple-fb2-reader.glade:248 48 | msgid "Case ensitive" 49 | msgstr "" 50 | 51 | #: ../res/simple-fb2-reader.glade:282 52 | #: ../src/callbacks/text_view_callback/popup_menu_callback.c:22 53 | msgid "Navigation" 54 | msgstr "" 55 | 56 | #: ../res/simple-fb2-reader.glade:396 57 | msgid "Select file" 58 | msgstr "" 59 | 60 | #: ../src/reader/reader_start_screen.c:16 61 | msgid "\n" 62 | "\n" 63 | "Recent books:\n" 64 | "\n" 65 | msgstr "" 66 | 67 | #: ../src/reader/reader_start_screen.c:34 68 | msgid "No name book" 69 | msgstr "" 70 | 71 | #: ../src/reader/reader_book/reader_open_book.c:51 72 | #, c-format 73 | msgid "Failed to open book:\n" 74 | "%s" 75 | msgstr "" 76 | 77 | #: ../src/callbacks/text_view_callback/popup_menu_callback.c:27 78 | msgid "Find" 79 | msgstr "" 80 | 81 | #: ../src/callbacks/text_view_callback/popup_menu_callback.c:37 82 | msgid "Auto scrolling" 83 | msgstr "" 84 | 85 | #: ../src/callbacks/text_view_callback/popup_menu_callback.c:44 86 | msgid "Color Theme" 87 | msgstr "" 88 | 89 | #: ../src/callbacks/text_view_callback/popup_menu_callback.c:51 90 | msgid "About" 91 | msgstr "" 92 | 93 | #: ../src/callbacks/text_view_callback/popup_menu_callback.c:56 94 | msgid "Open Book" 95 | msgstr "" 96 | 97 | #: ../src/callbacks/text_view_callback/popup_menu_callback.c:61 98 | msgid "Close Book" 99 | msgstr "" 100 | 101 | #: ../src/callbacks/text_view_callback/popup_menu_callback.c:70 102 | msgid "Exit" 103 | msgstr "" 104 | 105 | #: ../src/callbacks/context_menu_callbacks/auto_scroll_callback.c:28 106 | msgid "Enable" 107 | msgstr "" 108 | 109 | #: ../src/callbacks/context_menu_callbacks/auto_scroll_callback.c:33 110 | msgid "Disable" 111 | msgstr "" 112 | 113 | #: ../src/formats/fb2/FictionBook/body/section/section.c:18 114 | msgid "Section without title" 115 | msgstr "" 116 | 117 | #: ../src/formats/fb2/FictionBook/body/body.c:15 118 | msgid "Body tag without title" 119 | msgstr "" 120 | 121 | #: ../src/formats/fb2/FictionBook/FictionBook.c:60 122 | msgid "End read book\n" 123 | msgstr "" 124 | 125 | #: ../src/main.c:20 126 | msgid "Local path to book" 127 | msgstr "" 128 | 129 | #: ../src/main.c:21 130 | msgid "Print reader version" 131 | msgstr "" 132 | -------------------------------------------------------------------------------- /res/application-x-fictionbook+xml.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 23 | 27 | 31 | 32 | 39 | 43 | 46 | 50 | 51 | 59 | 67 | 69 | 72 | 76 | 77 | 84 | 87 | 91 | 92 | 100 | 108 | 115 | 119 | 123 | 124 | 132 | 140 | 142 | 146 | 150 | 151 | 153 | 157 | 161 | 162 | 170 | 174 | 179 | 180 | 187 | 190 | 194 | 195 | 203 | 207 | 211 | 212 | 221 | 223 | 227 | 232 | 233 | 241 | 245 | 249 | 250 | 259 | 260 | 283 | 285 | 286 | 288 | image/svg+xml 289 | 291 | 292 | 293 | 294 | 295 | 300 | 303 | 306 | 309 | 312 | 320 | 323 | 326 | 328 | 337 | 341 | 346 | 347 | 348 | 349 | 352 | 356 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | -------------------------------------------------------------------------------- /res/application-x-zip-compressed-fb2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 23 | 27 | 31 | 32 | 39 | 43 | 46 | 50 | 51 | 59 | 67 | 69 | 72 | 76 | 77 | 84 | 87 | 91 | 92 | 100 | 108 | 115 | 119 | 123 | 124 | 132 | 140 | 142 | 146 | 150 | 151 | 153 | 157 | 161 | 162 | 170 | 174 | 179 | 180 | 187 | 190 | 194 | 195 | 203 | 207 | 211 | 212 | 221 | 223 | 227 | 232 | 233 | 241 | 245 | 249 | 250 | 259 | 260 | 283 | 285 | 286 | 288 | image/svg+xml 289 | 291 | 292 | 293 | 294 | 295 | 300 | 303 | 306 | 309 | 312 | 320 | 323 | 326 | 328 | 337 | 341 | 346 | 347 | 348 | 349 | 352 | 356 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | -------------------------------------------------------------------------------- /res/simple-fb2-reader.css: -------------------------------------------------------------------------------- 1 | .book_textview text selection { 2 | color: white; 3 | background-color: #888A85; 4 | } 5 | 6 | .book_textview text { 7 | color: #e8e2b7; 8 | background-color: #293134; 9 | } 10 | 11 | .book_textview { 12 | font-family: Sans; 13 | } 14 | 15 | -------------------------------------------------------------------------------- /res/simple-fb2-reader.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Categories=Utility;Viewer; 3 | Comment=Simple tool to read FB2 books on GTK+3 4 | Comment[ru]=Простая читалка на GTK+3 для чтения FB2 книг 5 | Exec=simple-fb2-reader --book=%f 6 | Icon=simple-fb2-reader 7 | Name=Simple FB2 Reader 8 | Type=Application 9 | MimeType=application/x-fictionbook+xml;application/x-zip-compressed-fb2; 10 | Terminal=false 11 | GenericName=Simple FB2 Reader 12 | -------------------------------------------------------------------------------- /res/simple-fb2-reader.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | image/svg+xml 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /res/simple-fb2-reader.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Compressed book FB2 6 | Сжатая книга FB2 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /slackbuild/doinst.sh: -------------------------------------------------------------------------------- 1 | if [ -x /usr/bin/update-desktop-database ]; then 2 | /usr/bin/update-desktop-database -q usr/share/applications >/dev/null 2>&1 3 | fi 4 | 5 | if [ -x /usr/bin/update-mime-database ]; then 6 | /usr/bin/update-mime-database usr/share/mime >/dev/null 2>&1 7 | fi 8 | 9 | if [ -e usr/share/icons/hicolor/icon-theme.cache ]; then 10 | if [ -x /usr/bin/gtk-update-icon-cache ]; then 11 | /usr/bin/gtk-update-icon-cache usr/share/icons/hicolor >/dev/null 2>&1 12 | fi 13 | fi 14 | -------------------------------------------------------------------------------- /slackbuild/simple-fb2-reader.SlackBuild: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Slackware build script for simple-fb2-reader 4 | 5 | # Copyright Serg Bormant, 2012 6 | # All rights reserved. 7 | # 8 | # Redistribution and use of this script, with or without modification, is 9 | # permitted provided that the following conditions are met: 10 | # 11 | # 1. Redistributions of this script must retain the above copyright 12 | # notice, this list of conditions and the following disclaimer. 13 | # 14 | # THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED 15 | # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 16 | # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 17 | # EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 | # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20 | # OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21 | # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 22 | # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 | # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | PRGNAM=simple-fb2-reader 26 | VERSION=${VERSION:-1.1.2} 27 | BUILD=${BUILD:-1} 28 | TAG=${TAG:-_SBo} 29 | 30 | # Automatically determine the architecture we're building on: 31 | if [ -z "$ARCH" ]; then 32 | case "$( uname -m )" in 33 | i?86) ARCH=i486 ;; 34 | arm*) ARCH=arm ;; 35 | # Unless $ARCH is already set, use uname -m for all other archs: 36 | *) ARCH=$( uname -m ) ;; 37 | esac 38 | fi 39 | 40 | CWD=$(pwd) 41 | TMP=${TMP:-/tmp/SBo} 42 | PKG=$TMP/package-$PRGNAM 43 | OUTPUT=${OUTPUT:-/tmp} 44 | 45 | if [ "$ARCH" = "i486" ]; then 46 | SLKCFLAGS="-O2 -march=i486 -mtune=i686" 47 | LIBDIRSUFFIX="" 48 | elif [ "$ARCH" = "i686" ]; then 49 | SLKCFLAGS="-O2 -march=i686 -mtune=i686" 50 | LIBDIRSUFFIX="" 51 | elif [ "$ARCH" = "x86_64" ]; then 52 | SLKCFLAGS="-O2 -fPIC" 53 | LIBDIRSUFFIX="64" 54 | else 55 | SLKCFLAGS="-O2" 56 | LIBDIRSUFFIX="" 57 | fi 58 | 59 | set -e # Exit on most errors 60 | 61 | rm -rf $PKG 62 | mkdir -p $TMP $PKG $OUTPUT 63 | cd $TMP 64 | rm -rf $PRGNAM-$VERSION 65 | tar xvf $CWD/$VERSION.tar.gz 66 | cd $PRGNAM-$VERSION 67 | chown -R root:root . 68 | find -L . \ 69 | \( -perm 777 -o -perm 775 -o -perm 750 -o -perm 711 -o -perm 555 \ 70 | -o -perm 511 \) -exec chmod 755 {} \; -o \ 71 | \( -perm 666 -o -perm 664 -o -perm 640 -o -perm 600 -o -perm 444 \ 72 | -o -perm 440 -o -perm 400 \) -exec chmod 644 {} \; 73 | 74 | CFLAGS="$SLKCFLAGS" \ 75 | CXXFLAGS="$SLKCFLAGS" \ 76 | ./configure \ 77 | --prefix=/usr \ 78 | --libdir=/usr/lib${LIBDIRSUFFIX} \ 79 | --sysconfdir=/etc \ 80 | --localstatedir=/var \ 81 | --mandir=/usr/man \ 82 | --docdir=/usr/doc/$PRGNAM-$VERSION \ 83 | --build=$ARCH-slackware-linux 84 | 85 | # Compile the application and install it into the $PKG directory 86 | make 87 | make install DESTDIR=$PKG 88 | 89 | # Strip binaries and libraries 90 | find $PKG -print0 | xargs -0 file | grep -e "executable" -e "shared object" | grep ELF \ 91 | | cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null || true 92 | 93 | # Compress man pages 94 | #find $PKG/usr/man -type f -exec gzip -9 {} \; 95 | #for i in $( find $PKG/usr/man -type l ) ; do ln -s $( readlink $i ).gz $i.gz ; rm $i ; done 96 | 97 | # Compress info pages and remove the package's dir file 98 | #rm -f $PKG/usr/info/dir 99 | #gzip -9 $PKG/usr/info/*.info* 100 | 101 | # Copy program documentation into the package 102 | mkdir -p $PKG/usr/doc/$PRGNAM-$VERSION 103 | cp -a \ 104 | README NEWS COPYING AUTHORS \ 105 | $PKG/usr/doc/$PRGNAM-$VERSION 106 | cat $CWD/$PRGNAM.SlackBuild > $PKG/usr/doc/$PRGNAM-$VERSION/$PRGNAM.SlackBuild 107 | 108 | # Copy the slack-desc (and a custom doinst.sh if necessary) into ./install 109 | mkdir -p $PKG/install 110 | cat $CWD/slack-desc > $PKG/install/slack-desc 111 | cat $CWD/doinst.sh > $PKG/install/doinst.sh 112 | 113 | # Make the package 114 | cd $PKG 115 | /sbin/makepkg -l y -c n $OUTPUT/$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.${PKGTYPE:-tgz} 116 | -------------------------------------------------------------------------------- /slackbuild/simple-fb2-reader.info: -------------------------------------------------------------------------------- 1 | PRGNAM="simple-fb2-reader" 2 | VERSION="1.1.3" 3 | HOMEPAGE="https://github.com/Cactus64k/simple-fb2-reader" 4 | DOWNLOAD="https://github.com/Cactus64k/simple-fb2-reader/archive/1.1.3.tar.gz" 5 | MD5SUM="" 6 | DOWNLOAD_x86_64="" 7 | MD5SUM_x86_64="" 8 | REQUIRES="" 9 | MAINTAINER="Serg Bormant" 10 | EMAIL="bormant@mail.ru" 11 | -------------------------------------------------------------------------------- /slackbuild/slack-desc: -------------------------------------------------------------------------------- 1 | # HOW TO EDIT THIS FILE: 2 | # The "handy ruler" below makes it easier to edit a package description. 3 | # Line up the first '|' above the ':' following the base package name, and 4 | # the '|' on the right side marks the last column you can put a character in. 5 | # You must make exactly 11 lines for the formatting to be correct. It's also 6 | # customary to leave one space after the ':' except on otherwise blank lines. 7 | 8 | |-----handy-ruler------------------------------------------------------| 9 | simple-fb2-reader: simple-fb2-reader (simple GTK+3 tool to read FB2 books) 10 | simple-fb2-reader: 11 | simple-fb2-reader: The simple tool for reading books in FictionBook format. 12 | simple-fb2-reader: Developed using GTK+3. Supports FB 2.1 format. 13 | simple-fb2-reader: 14 | simple-fb2-reader: 15 | simple-fb2-reader: 16 | simple-fb2-reader: 17 | simple-fb2-reader: 18 | simple-fb2-reader: 19 | simple-fb2-reader: Homepage: https://github.com/Cactus64k/simple-fb2-reader 20 | -------------------------------------------------------------------------------- /src/callbacks/callbacks_chunk.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef CALLBACKS_CHUNK_H_ 3 | #define CALLBACKS_CHUNK_H_ 4 | 5 | #include "../chunks.h" 6 | 7 | void encode_treeview_cursor_changed_cb (GtkTreeView* tree_view, gpointer user_data); 8 | void txt_encode_dialog_show_cb (GtkWidget* widget, gpointer user_data); 9 | 10 | gboolean main_wnd_delete_event_cb (GtkWidget* widget, GdkEvent *event, gpointer user_data); 11 | void file_quit_imagemenuitem_activate_cb (GtkMenuItem* menuitem, gpointer user_data); 12 | 13 | void main_wnd_size_allocate_cb (GtkWidget* widget, GdkRectangle *allocation, gpointer user_data); 14 | gboolean main_wnd_key_press_event_cb (GtkWidget* widget, GdkEventKey* event, gpointer user_data); 15 | 16 | void search_wnd_close_button_clicked_cb (GtkButton* widget, gpointer user_data); 17 | gboolean search_wnd_key_press_event_cb (GtkWidget* widget, GdkEvent* event, gpointer user_data); 18 | void search_wnd_search_button_clicked_cb (GtkButton* button, gpointer user_data); 19 | void search_query_changed_cb (GtkEditable* editable, gpointer user_data); 20 | 21 | void open_file_menuitem_activate_cb (GtkMenuItem *menuitem, gpointer user_data); 22 | 23 | void close_book_menuitem_activate_cb (GtkMenuItem *menuitem, gpointer user_data); 24 | 25 | void search_menuitem_activate_cb (GtkMenuItem* menuitem, gpointer user_data); 26 | void navigation_treeview_row_activated_cb (GtkTreeView* tree_view, GtkTreePath* path, GtkTreeViewColumn* column, gpointer user_data); 27 | void navigation_menuitem_activate_cb (GtkMenuItem *menuitem, gpointer user_data); 28 | 29 | void about_menuitem_activate_cb (GtkMenuItem *menuitem, gpointer user_data); 30 | void backward_itemmenu_cb (GtkMenuItem* menuitem, gpointer user_data); 31 | 32 | void auto_scroll_toggled_cb (GtkCheckMenuItem* menuitem, gpointer user_data); 33 | 34 | void exit_menuitem_activate_cb (GtkMenuItem *menuitem, gpointer user_data); 35 | 36 | gboolean a_tag_event_cb(GtkTextTag* tag, GObject* object, GdkEvent* event, GtkTextIter* iter, gpointer user_data); 37 | 38 | 39 | #endif /* CALLBACKS_CHUNK_H_ */ 40 | -------------------------------------------------------------------------------- /src/callbacks/context_menu_callbacks/about_callback.c: -------------------------------------------------------------------------------- 1 | #include "../callbacks_chunk.h" 2 | 3 | G_MODULE_EXPORT void about_menuitem_activate_cb(GtkMenuItem *menuitem, gpointer user_data) 4 | { 5 | APP* app = (APP*)user_data; 6 | GtkAboutDialog* about_dialog = app->about_dialog; 7 | gtk_dialog_run(GTK_DIALOG(about_dialog)); 8 | gtk_widget_hide(GTK_WIDGET(about_dialog)); 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/callbacks/context_menu_callbacks/auto_scroll_callback.c: -------------------------------------------------------------------------------- 1 | #include "../callbacks_chunk.h" 2 | 3 | G_MODULE_EXPORT void auto_scroll_toggled_cb(GtkCheckMenuItem* menuitem, gpointer user_data) 4 | { 5 | APP* app = (APP*)user_data; 6 | GKeyFile* app_config = app->app_config; 7 | GtkWidget* sub_menu = gtk_menu_item_get_submenu(menuitem); 8 | 9 | if((gtk_check_menu_item_get_active(menuitem) == TRUE) && (app->book_type != BOOK_TYPE_NONE)) 10 | { 11 | app->auto_scroll = TRUE; 12 | int period = app->auto_scroll_period; 13 | g_timeout_add(period, auto_scroll_update, app); 14 | } 15 | else 16 | app->auto_scroll = FALSE; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/callbacks/context_menu_callbacks/backward_callback.c: -------------------------------------------------------------------------------- 1 | #include "../callbacks_chunk.h" 2 | 3 | G_MODULE_EXPORT void backward_itemmenu_cb(GtkMenuItem* menuitem, gpointer user_data) 4 | { 5 | APP* app = (APP*)user_data; 6 | GtkTextView* text_view = app->text_view; 7 | GList* book_jump_list = app->book_jump_list; 8 | 9 | GtkAdjustment* horisontal_adj = gtk_scrollable_get_hadjustment(GTK_SCROLLABLE(text_view)); 10 | 11 | if(book_jump_list != NULL) 12 | { 13 | GtkTextMark* mark = GTK_TEXT_MARK(book_jump_list->data); 14 | gtk_text_view_scroll_to_mark(text_view, mark, 0.0, TRUE, 0.0, 0.0); 15 | 16 | gtk_adjustment_set_value(horisontal_adj, 0.0); 17 | 18 | app->book_jump_list = g_list_remove(book_jump_list, mark); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/callbacks/context_menu_callbacks/book_search_callback.c: -------------------------------------------------------------------------------- 1 | #include "../callbacks_chunk.h" 2 | 3 | G_MODULE_EXPORT void search_menuitem_activate_cb(GtkMenuItem* menuitem, gpointer user_data) 4 | { 5 | APP* app = (APP*)user_data; 6 | GtkWidget* search_window = app->search_window.search_wnd; 7 | GtkEntry* search_entry = app->search_window.search_query_entry; 8 | BOOK_TYPE book_type = app->book_type; 9 | 10 | if(book_type != BOOK_TYPE_NONE) 11 | { 12 | gtk_widget_show(search_window); 13 | gtk_widget_grab_focus(GTK_WIDGET(search_entry)); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/callbacks/context_menu_callbacks/close_book_callback.c: -------------------------------------------------------------------------------- 1 | #include "../callbacks_chunk.h" 2 | 3 | G_MODULE_EXPORT void close_book_menuitem_activate_cb(GtkMenuItem *menuitem, gpointer user_data) 4 | { 5 | APP* app = (APP*)user_data; 6 | 7 | if(app->book_type != BOOK_TYPE_NONE) 8 | { 9 | reader_close_book(app); 10 | reader_start_screen(app); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/callbacks/context_menu_callbacks/exit_callback.c: -------------------------------------------------------------------------------- 1 | #include "../callbacks_chunk.h" 2 | 3 | G_MODULE_EXPORT void exit_menuitem_activate_cb(GtkMenuItem *menuitem, gpointer user_data) 4 | { 5 | APP* app = (APP*)user_data; 6 | reader_close_book(app); 7 | reader_close_app(app); 8 | gtk_main_quit(); 9 | } 10 | -------------------------------------------------------------------------------- /src/callbacks/context_menu_callbacks/navigation_callback.c: -------------------------------------------------------------------------------- 1 | #include "../callbacks_chunk.h" 2 | 3 | G_MODULE_EXPORT void navigation_menuitem_activate_cb(GtkMenuItem *menuitem, gpointer user_data) 4 | { 5 | APP* app = (APP*)user_data; 6 | GtkDialog* navigation_dialog = app->navigation_dialog; 7 | GtkTreeStore* section_store = app->sections_treestore; 8 | BOOK_TYPE book_type = app->book_type; 9 | GtkTreeView* tree_view = app->sections_treeview; 10 | 11 | GtkTreeIter tree_iter; 12 | gint line = 0; 13 | 14 | if(book_type != BOOK_TYPE_NONE) 15 | { 16 | gtk_widget_grab_focus(GTK_WIDGET(navigation_dialog)); 17 | 18 | if(gtk_dialog_run(navigation_dialog) == 2) 19 | { 20 | gtk_widget_hide(GTK_WIDGET(navigation_dialog)); 21 | 22 | GtkTreeModel* tree_model = GTK_TREE_MODEL(section_store); 23 | 24 | GtkTreeSelection* tree_selection = gtk_tree_view_get_selection(tree_view); 25 | gtk_tree_selection_get_selected(tree_selection, &tree_model, &tree_iter); 26 | gtk_tree_model_get(GTK_TREE_MODEL(section_store), &tree_iter, SECTION_STRING_COLUMN, &line, -1); 27 | 28 | reader_scroll_restore(app, line, 0); 29 | } 30 | 31 | gtk_widget_hide(GTK_WIDGET(navigation_dialog)); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/callbacks/context_menu_callbacks/navigation_section_callback.c: -------------------------------------------------------------------------------- 1 | #include "../callbacks_chunk.h" 2 | 3 | G_MODULE_EXPORT void navigation_treeview_row_activated_cb(GtkTreeView* tree_view, GtkTreePath* path, GtkTreeViewColumn* column, gpointer user_data) 4 | { 5 | 6 | APP* app = (APP*)user_data; 7 | GtkDialog* dialog = app->navigation_dialog; 8 | GtkTreeStore* section_store = app->sections_treestore; 9 | GtkTreeIter tree_iter; 10 | gint line = 0; 11 | 12 | gtk_widget_hide(GTK_WIDGET(dialog)); 13 | 14 | if(gtk_tree_model_get_iter(GTK_TREE_MODEL(section_store), &tree_iter, path) == TRUE) 15 | { 16 | gtk_tree_model_get(GTK_TREE_MODEL(section_store), &tree_iter, SECTION_STRING_COLUMN, &line, -1); 17 | 18 | reader_scroll_to_line_offset(app, line, 0); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/callbacks/context_menu_callbacks/open_file_callback.c: -------------------------------------------------------------------------------- 1 | #include "../callbacks_chunk.h" 2 | 3 | G_MODULE_EXPORT void open_file_menuitem_activate_cb(GtkMenuItem* menuitem, gpointer user_data) 4 | { 5 | APP* app = (APP*)user_data; 6 | GtkFileChooserDialog* file_open_dialog = app->filechooserdialog; 7 | 8 | if(gtk_dialog_run(GTK_DIALOG(file_open_dialog)) == 2) 9 | { 10 | gtk_widget_hide(GTK_WIDGET(file_open_dialog)); 11 | 12 | char* file_path = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_open_dialog)); 13 | reader_close_book(app); 14 | reader_open_book(app, file_path); 15 | g_free(file_path); 16 | } 17 | 18 | gtk_widget_hide(GTK_WIDGET(file_open_dialog)); 19 | } 20 | 21 | G_MODULE_EXPORT void book_filechooserdialog_file_activated_cb(GtkFileChooser* chooser, gpointer user_data) 22 | { 23 | APP* app = (APP*)user_data; 24 | GtkFileChooserDialog* file_open_dialog = app->filechooserdialog; 25 | char* book_path = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_open_dialog)); 26 | 27 | BOOK_TYPE book_type = reader_get_book_type(book_path); 28 | if(book_type != BOOK_TYPE_NONE) 29 | { 30 | gtk_widget_hide(GTK_WIDGET(file_open_dialog)); 31 | 32 | reader_close_book(app); 33 | reader_open_book(app, book_path); 34 | g_free(book_path); 35 | 36 | } 37 | else 38 | g_free(book_path); 39 | } 40 | -------------------------------------------------------------------------------- /src/callbacks/main_wnd_callbacks.c: -------------------------------------------------------------------------------- 1 | #include "callbacks_chunk.h" 2 | 3 | G_MODULE_EXPORT gboolean main_wnd_delete_event_cb(GtkWidget *widget, GdkEvent *event, gpointer user_data) 4 | { 5 | g_return_val_if_fail(user_data != NULL, EXIT_FAILURE); 6 | APP* app = (APP*)user_data; 7 | 8 | reader_close_book(app); 9 | reader_close_app(app); 10 | return FALSE; 11 | } 12 | 13 | gboolean main_wnd_window_state_event_cb(GtkWidget* widget, GdkEventWindowState* event, gpointer user_data) 14 | { 15 | g_return_val_if_fail(user_data != NULL, EXIT_FAILURE); 16 | APP* app = (APP*)user_data; 17 | 18 | if((event->new_window_state & GDK_WINDOW_STATE_ICONIFIED) 19 | || 20 | (event->new_window_state & GDK_WINDOW_STATE_WITHDRAWN) 21 | || 22 | (event->new_window_state & GDK_WINDOW_STATE_BELOW)) 23 | { 24 | app->auto_scroll = FALSE; 25 | } 26 | 27 | return TRUE; 28 | } 29 | 30 | G_MODULE_EXPORT void main_wnd_size_allocate_cb (GtkWidget *widget, GdkRectangle *allocation, gpointer user_data) 31 | { 32 | g_return_if_fail(user_data != NULL); 33 | GtkTextView* text_view = GTK_TEXT_VIEW(user_data); 34 | 35 | gint margin = (allocation->width * 15) / 100; // 15% 36 | 37 | gtk_text_view_set_right_margin(text_view, margin); 38 | gtk_text_view_set_left_margin(text_view, margin); 39 | } 40 | 41 | G_MODULE_EXPORT gboolean main_wnd_key_press_event_cb (GtkWidget* widget, GdkEventKey* event, gpointer user_data) 42 | { 43 | g_return_val_if_fail(user_data != NULL, EXIT_FAILURE); 44 | 45 | APP* app = (APP*)user_data; 46 | GtkTextBuffer* text_buff = app->text_buff; 47 | GtkTextView* text_view = app->text_view; 48 | BOOK_TYPE book_type = app->book_type; 49 | GtkClipboard* clipboard = app->clipboard; 50 | GdkDisplay* default_display = gdk_display_get_default(); 51 | GdkKeymap* default_key_map = gdk_keymap_get_for_display(default_display); 52 | 53 | 54 | GdkKeymapKey key = {.keycode = event->hardware_keycode, 55 | .group = 0, 56 | .level = 0}; 57 | 58 | guint keyval = gdk_keymap_lookup_key(default_key_map, &key); 59 | 60 | if(event->state & GDK_CONTROL_MASK) 61 | { 62 | if(keyval == 'n') 63 | { 64 | if(book_type != BOOK_TYPE_NONE) 65 | navigation_menuitem_activate_cb(NULL, app); 66 | } 67 | else if(keyval == 'f') 68 | { 69 | if(book_type != BOOK_TYPE_NONE) 70 | search_menuitem_activate_cb(NULL, app); 71 | } 72 | else if(keyval == 'h') 73 | { 74 | about_menuitem_activate_cb(NULL, app); 75 | } 76 | else if(keyval == 'o') 77 | { 78 | open_file_menuitem_activate_cb(NULL, app); 79 | } 80 | else if((keyval == '0') || (keyval == GDK_KEY_KP_Insert)) 81 | { 82 | GtkTextTagTable* text_tag_table = gtk_text_buffer_get_tag_table(text_buff); 83 | GtkTextTag* default_tag = gtk_text_tag_table_lookup(text_tag_table, "default_tag"); 84 | GValue value = G_VALUE_INIT; 85 | 86 | g_value_init(&value, G_TYPE_DOUBLE); 87 | g_value_set_double(&value, 1.0); 88 | g_object_set_property(G_OBJECT(default_tag), "scale", &value); 89 | g_value_unset(&value); 90 | 91 | GtkAllocation size_allocation = {.width = gtk_widget_get_allocated_width(GTK_WIDGET(text_view)), 92 | .height = gtk_widget_get_allocated_height(GTK_WIDGET(text_view))}; 93 | 94 | size_allocation.width++; 95 | gtk_widget_size_allocate(GTK_WIDGET(text_view), &size_allocation); 96 | size_allocation.width--; 97 | gtk_widget_size_allocate(GTK_WIDGET(text_view), &size_allocation); 98 | } 99 | else if(keyval == 'q') 100 | { 101 | gtk_main_quit(); 102 | } 103 | else if(keyval == 'c') 104 | { 105 | if(gtk_text_buffer_get_has_selection(text_buff) == TRUE) 106 | gtk_text_buffer_copy_clipboard(text_buff, clipboard); 107 | } 108 | else if(keyval == 'w') 109 | { 110 | reader_close_book(app); 111 | } 112 | } 113 | else 114 | { 115 | if((event->keyval == GDK_KEY_Left) && (book_type != BOOK_TYPE_NONE)) 116 | backward_itemmenu_cb(NULL, app); 117 | } 118 | 119 | 120 | //printf("%x\n", event->keyval); 121 | 122 | return FALSE; 123 | } 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /src/callbacks/search_wnd_callbacks.c: -------------------------------------------------------------------------------- 1 | #include "callbacks_chunk.h" 2 | 3 | G_MODULE_EXPORT void search_wnd_close_button_clicked_cb(GtkButton* widget, gpointer user_data) 4 | { 5 | APP* app = (APP*)user_data; 6 | GtkWidget* search_window = app->search_window.search_wnd; 7 | gtk_widget_hide(search_window); 8 | } 9 | 10 | G_MODULE_EXPORT gboolean search_wnd_delete_event_cb(GtkWidget *widget, GdkEvent *event, gpointer user_data) 11 | { 12 | APP* app = (APP*)user_data; 13 | GtkWidget* search_window = app->search_window.search_wnd; 14 | gtk_widget_hide(search_window); 15 | return TRUE; 16 | } 17 | 18 | G_MODULE_EXPORT gboolean search_wnd_key_press_event_cb(GtkWidget* widget, GdkEvent* event, gpointer user_data) 19 | { 20 | APP* app = (APP*)user_data; 21 | GdkEventKey key_event = event->key; 22 | if(key_event.keyval == GDK_KEY_Escape) 23 | gtk_widget_hide(widget); 24 | else if(key_event.keyval == GDK_KEY_Return) 25 | search_wnd_search_button_clicked_cb(NULL, app); 26 | 27 | return FALSE; 28 | } 29 | 30 | G_MODULE_EXPORT void search_wnd_show_cb(GtkWidget* widget, gpointer user_data) 31 | { 32 | APP* app = (APP*)user_data; 33 | GtkTextIter* last_search_pos = &(app->search_window.last_pos); 34 | 35 | GtkTextView* text_view = app->text_view; 36 | GtkAdjustment* vertical_adj = gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(text_view)); 37 | double scroll_pos = gtk_adjustment_get_value(vertical_adj); 38 | 39 | gtk_text_view_get_iter_at_location(text_view, last_search_pos, 0, (gint)scroll_pos); 40 | } 41 | 42 | 43 | G_MODULE_EXPORT void search_wnd_search_button_clicked_cb(GtkButton* button, gpointer user_data) 44 | { 45 | APP* app = (APP*)user_data; 46 | GtkTextBuffer* text_buff = app->text_buff; 47 | GtkTextView* text_view = app->text_view; 48 | GtkEntry* search_entry = app->search_window.search_query_entry; 49 | GtkTextIter* last_search_pos = &(app->search_window.last_pos); 50 | GtkCheckButton* case_sensitive = app->search_window.case_sensitive; 51 | GtkRadioButton* forward = app->search_window.forward; 52 | 53 | const char* query = gtk_entry_get_text(search_entry); 54 | 55 | GtkTextIter match_start_iter; 56 | GtkTextIter match_end_iter; 57 | 58 | gboolean search_success = FALSE; 59 | gboolean search_forward = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(forward));; 60 | GtkTextSearchFlags case_sensitive_flag; 61 | 62 | if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(case_sensitive)) == TRUE) 63 | case_sensitive_flag = GTK_TEXT_SEARCH_VISIBLE_ONLY; 64 | else 65 | case_sensitive_flag = GTK_TEXT_SEARCH_CASE_INSENSITIVE; 66 | 67 | if(search_forward == TRUE) 68 | search_success = gtk_text_iter_forward_search(last_search_pos, query, case_sensitive_flag, &match_start_iter, &match_end_iter, NULL); 69 | else 70 | search_success = gtk_text_iter_backward_search(last_search_pos, query, case_sensitive_flag, &match_start_iter, &match_end_iter, NULL); 71 | 72 | if(search_success == TRUE) 73 | { 74 | gtk_text_buffer_select_range(text_buff, &match_start_iter, &match_end_iter); 75 | 76 | gtk_text_view_scroll_to_iter(text_view, &match_start_iter, 0.0, TRUE, 0.0, 0.0); 77 | 78 | if(search_forward == TRUE) 79 | app->search_window.last_pos = match_end_iter; 80 | else 81 | app->search_window.last_pos = match_start_iter; 82 | } 83 | else 84 | { 85 | if(search_forward == TRUE) 86 | gtk_text_buffer_get_start_iter(text_buff, last_search_pos); 87 | else 88 | gtk_text_buffer_get_end_iter(text_buff, last_search_pos); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/callbacks/text_view_callback/link_tag_enevt_callback.c: -------------------------------------------------------------------------------- 1 | #include "../callbacks_chunk.h" 2 | 3 | G_MODULE_EXPORT gboolean a_tag_event_cb(GtkTextTag* tag, GObject* object, GdkEvent* event, GtkTextIter* iter, gpointer user_data) 4 | { 5 | APP* app = (APP*)user_data; 6 | GtkTextView* text_view = GTK_TEXT_VIEW(object); 7 | GtkTextBuffer* text_buff = app->text_buff; 8 | GdkCursor* cursor_link = app->cursor_link; 9 | GHashTable* book_id_table = app->book_id_table; 10 | GList* book_jump_list = app->book_jump_list; 11 | 12 | if(event->type == GDK_BUTTON_RELEASE) 13 | { 14 | if(event->button.state & GDK_BUTTON1_MASK) 15 | { 16 | GValue value = G_VALUE_INIT; 17 | g_value_init(&value, G_TYPE_STRING); 18 | g_value_set_string(&value, "purple"); 19 | g_object_set_property(G_OBJECT(tag), "foreground", &value); 20 | g_value_unset(&value); 21 | 22 | char* href = g_object_get_data(G_OBJECT(tag), "href"); 23 | 24 | if(*href == '#') 25 | { 26 | href++; 27 | 28 | GtkTextMark* mark = gtk_text_buffer_create_mark(text_buff, NULL, iter, TRUE); 29 | app->book_jump_list = g_list_prepend(book_jump_list, mark); 30 | 31 | gint link_line_num = GPOINTER_TO_INT(g_hash_table_lookup(book_id_table, href)); 32 | 33 | reader_scroll_to_line_offset(app, link_line_num, 0); 34 | } 35 | else if(strncmp("file://", href, sizeof("file://") -1) == 0) 36 | { 37 | if(reader_get_book_type(href) != BOOK_TYPE_NONE) 38 | { 39 | reader_close_book(app); 40 | reader_open_book(app, href + sizeof("file://") - 1); 41 | } 42 | } 43 | else 44 | { 45 | GError* error = NULL; 46 | if(gtk_show_uri_on_window(NULL, href, GDK_CURRENT_TIME, NULL) == FALSE) 47 | g_log(NULL, G_LOG_LEVEL_WARNING, "%s: %s",error->message, href); 48 | } 49 | } 50 | } 51 | else if(event->type == GDK_MOTION_NOTIFY) 52 | { 53 | GdkWindow* text_view_window = gtk_text_view_get_window(text_view, GTK_TEXT_WINDOW_TEXT); 54 | gdk_window_set_cursor(text_view_window, cursor_link); 55 | } 56 | 57 | return TRUE; 58 | } 59 | 60 | -------------------------------------------------------------------------------- /src/callbacks/text_view_callback/motion_event_callback.c: -------------------------------------------------------------------------------- 1 | #include "../callbacks_chunk.h" 2 | 3 | G_MODULE_EXPORT gboolean book_textview_motion_notify_event_cb(GtkWidget* widget, GdkEventMotion* event, gpointer user_data) 4 | { 5 | GtkTextView* text_view = GTK_TEXT_VIEW(widget); 6 | 7 | GdkWindow* text_view_window = gtk_text_view_get_window(text_view, GTK_TEXT_WINDOW_TEXT); 8 | gdk_window_set_cursor(text_view_window, NULL); 9 | 10 | return FALSE; 11 | } 12 | -------------------------------------------------------------------------------- /src/callbacks/text_view_callback/popup_menu_callback.c: -------------------------------------------------------------------------------- 1 | #include "../callbacks_chunk.h" 2 | 3 | G_MODULE_EXPORT void book_textview_populate_popup_cb(GtkTextView* entry, GtkMenu* menu, gpointer user_data) 4 | { 5 | APP* app = (APP*)user_data; 6 | GList* items_list = gtk_container_get_children(GTK_CONTAINER(menu)); 7 | g_list_free_full(items_list, (GDestroyNotify)gtk_widget_destroy); 8 | 9 | GtkWidget* item; 10 | GtkWidget* sub_menu; 11 | 12 | item = gtk_menu_item_new_with_label(_C("Backward")); 13 | g_signal_connect(item, "activate", G_CALLBACK(backward_itemmenu_cb), app); 14 | gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); 15 | gtk_widget_show(item); 16 | 17 | item = gtk_separator_menu_item_new(); 18 | gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); 19 | gtk_widget_show(item); 20 | //************************************************************************************************* 21 | 22 | item = gtk_menu_item_new_with_label(_C("Navigation")); 23 | g_signal_connect(item, "activate", G_CALLBACK(navigation_menuitem_activate_cb), app); 24 | gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); 25 | gtk_widget_show(item); 26 | 27 | item = gtk_menu_item_new_with_label(_C("Find")); 28 | g_signal_connect(item, "activate", G_CALLBACK(search_menuitem_activate_cb), app); 29 | gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); 30 | gtk_widget_show(item); 31 | 32 | item = gtk_separator_menu_item_new(); 33 | gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); 34 | gtk_widget_show(item); 35 | //************************************************************************************************* 36 | 37 | item = gtk_check_menu_item_new_with_label(_C("Auto scrolling")); 38 | gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), app->auto_scroll); 39 | gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); 40 | g_signal_connect(item, "toggled", G_CALLBACK(auto_scroll_toggled_cb), app); 41 | gtk_widget_show(item); 42 | 43 | item = gtk_menu_item_new_with_label(_C("About")); 44 | g_signal_connect(item, "activate", G_CALLBACK(about_menuitem_activate_cb), app); 45 | gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); 46 | gtk_widget_show(item); 47 | 48 | item = gtk_menu_item_new_with_label(_C("Open Book")); 49 | g_signal_connect(item, "activate", G_CALLBACK(open_file_menuitem_activate_cb), app); 50 | gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); 51 | gtk_widget_show(item); 52 | 53 | item = gtk_menu_item_new_with_label(_C("Close Book")); 54 | g_signal_connect(item, "activate", G_CALLBACK(close_book_menuitem_activate_cb), app); 55 | gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); 56 | gtk_widget_show(item); 57 | 58 | item = gtk_separator_menu_item_new(); 59 | gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); 60 | gtk_widget_show(item); 61 | 62 | item = gtk_menu_item_new_with_label(_C("Exit")); 63 | g_signal_connect(item, "activate", G_CALLBACK(exit_menuitem_activate_cb), app); 64 | gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); 65 | gtk_widget_show(item); 66 | 67 | 68 | } 69 | 70 | -------------------------------------------------------------------------------- /src/callbacks/text_view_callback/scroll_event_callback.c: -------------------------------------------------------------------------------- 1 | #include "../callbacks_chunk.h" 2 | 3 | G_MODULE_EXPORT gboolean book_textview_scroll_event_cb(GtkTextView *text_view, GdkEventScroll *event, gpointer user_data) 4 | { 5 | if((event->state & GDK_CONTROL_MASK) && event->type == GDK_SCROLL) 6 | { 7 | GtkTextBuffer* text_buff = gtk_text_view_get_buffer(text_view); 8 | GtkTextTagTable* text_tag_table = gtk_text_buffer_get_tag_table(text_buff); 9 | GtkTextTag* default_tag = gtk_text_tag_table_lookup(text_tag_table, "default_tag"); 10 | GValue value = G_VALUE_INIT; 11 | 12 | g_value_init(&value, G_TYPE_DOUBLE); 13 | g_object_get_property(G_OBJECT(default_tag), "scale", &value); 14 | double text_scale = g_value_get_double(&value); 15 | 16 | if(event->direction == GDK_SCROLL_UP) 17 | text_scale = text_scale + 0.1; 18 | else if(event->direction == GDK_SCROLL_DOWN) 19 | text_scale = text_scale - 0.1; 20 | else if(event->direction == GDK_SCROLL_SMOOTH) 21 | text_scale = text_scale + event->delta_y*(-0.1); 22 | 23 | text_scale = MAX(text_scale, 0.5); 24 | text_scale = MIN(text_scale, 20.0); 25 | 26 | g_value_set_double(&value, text_scale); 27 | g_object_set_property(G_OBJECT(default_tag), "scale", &value); 28 | g_value_unset(&value); 29 | 30 | // FIXME tag-changed signal is not working 31 | GtkAllocation size_allocation = {.width = gtk_widget_get_allocated_width(GTK_WIDGET(text_view)), 32 | .height = gtk_widget_get_allocated_height(GTK_WIDGET(text_view))}; 33 | size_allocation.width++; 34 | gtk_widget_size_allocate(GTK_WIDGET(text_view), &size_allocation); 35 | size_allocation.width--; 36 | gtk_widget_size_allocate(GTK_WIDGET(text_view), &size_allocation); 37 | 38 | return TRUE; 39 | } 40 | 41 | return FALSE; 42 | } 43 | -------------------------------------------------------------------------------- /src/callbacks/text_view_callback/tooltip_callback.c: -------------------------------------------------------------------------------- 1 | #include "../callbacks_chunk.h" 2 | 3 | G_MODULE_EXPORT gboolean book_textview_query_tooltip_cb(GtkWidget* widget, gint x, gint y, gboolean keyboard_mode, GtkTooltip* tooltip, gpointer user_data) 4 | { 5 | if(keyboard_mode != TRUE) 6 | { 7 | GtkTextView* text_view = GTK_TEXT_VIEW(widget); 8 | GtkTextIter iter; 9 | gint bx, by; 10 | gtk_text_view_window_to_buffer_coords(text_view, GTK_TEXT_WINDOW_WIDGET, x, y, &bx, &by); 11 | gtk_text_view_get_iter_at_location(text_view, &iter, bx, by); 12 | 13 | GSList* tag_list = gtk_text_iter_get_tags(&iter); 14 | GSList* tag = tag_list; 15 | 16 | while(tag != NULL) 17 | { 18 | char* href = g_object_get_data(G_OBJECT(tag->data), "href"); 19 | if(href != NULL) 20 | { 21 | gtk_tooltip_set_text(tooltip, href); 22 | g_slist_free(tag_list); 23 | 24 | return TRUE; 25 | } 26 | 27 | tag = tag->next; 28 | } 29 | 30 | g_slist_free(tag_list); 31 | } 32 | 33 | return FALSE; 34 | } 35 | -------------------------------------------------------------------------------- /src/chunks.h: -------------------------------------------------------------------------------- 1 | #ifndef CHUNKS_H_ 2 | #define CHUNKS_H_ 3 | 4 | //#include "config.h" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #define _C(str) gettext(str) 22 | 23 | #ifdef DEBUG 24 | #undef GUI_CONSTRUCT_PATH 25 | #define GUI_CONSTRUCT_PATH "./res/simple-fb2-reader.glade" 26 | #endif 27 | 28 | #ifndef PACKAGE_NAME 29 | #define PACKAGE_NAME "simple-fb2-reader" 30 | #endif 31 | 32 | #ifndef PACKAGE_VERSION 33 | #define PACKAGE_VERSION "1.0.0" 34 | #endif 35 | 36 | 37 | enum 38 | { 39 | SECTION_NAME_COLUMN = 0, 40 | SECTION_STRING_COLUMN 41 | }; 42 | 43 | typedef enum 44 | { 45 | BOOK_TYPE_NONE = 0, 46 | BOOK_TYPE_FB2, 47 | BOOK_TYPE_FB2_ZIP, 48 | } BOOK_TYPE; 49 | 50 | typedef struct SEARCH_WINDOW 51 | { 52 | GtkWidget* search_wnd; 53 | GtkEntry* search_query_entry; 54 | GtkTextIter last_pos; 55 | GtkCheckButton* case_sensitive; 56 | GtkRadioButton* forward; 57 | } SEARCH_WINDOW; 58 | 59 | typedef struct APP 60 | { 61 | sqlite3* book_db; 62 | BOOK_TYPE book_type; 63 | char* book_title; 64 | char* book_hash; 65 | int64_t book_index; 66 | GList* book_jump_list; 67 | GHashTable* book_id_table; 68 | GHashTable* book_img_table; 69 | 70 | SEARCH_WINDOW search_window; 71 | 72 | GtkWidget* main_wnd; 73 | 74 | GtkTextBuffer* text_buff; 75 | GtkTextView* text_view; 76 | GtkScrolledWindow* text_scrolledwindow; 77 | 78 | GtkTreeStore* sections_treestore; 79 | GtkTreeView* sections_treeview; 80 | GtkDialog* navigation_dialog; 81 | 82 | GtkFileChooserDialog* filechooserdialog; 83 | GtkAboutDialog* about_dialog; 84 | 85 | GdkCursor* cursor_link; 86 | GdkCursor* cursor_watch; 87 | 88 | GtkClipboard* clipboard; 89 | 90 | GKeyFile* app_config; 91 | char* app_config_path; 92 | 93 | char* app_css_path; 94 | 95 | gboolean auto_scroll; 96 | int auto_scroll_period; 97 | 98 | } APP; 99 | 100 | #include "reader/reader_chunks.h" 101 | #include "formats/formats_chunks.h" 102 | #include "callbacks/callbacks_chunk.h" 103 | 104 | #endif /* CHUNKS_H_ */ 105 | -------------------------------------------------------------------------------- /src/formats/fb2/FictionBook/FictionBook.c: -------------------------------------------------------------------------------- 1 | #include "FictionBook_chunks.h" 2 | 3 | int parse_fb2_function_book(APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end) 4 | { 5 | g_return_val_if_fail(parent_node != NULL, EXIT_FAILURE); 6 | g_return_val_if_fail(text_buff_end != NULL, EXIT_FAILURE); 7 | 8 | GtkTextBuffer* text_buff = app->text_buff; 9 | 10 | xmlNode* node = parent_node->children; 11 | 12 | //************************************************************************** 13 | 14 | while(node != NULL) 15 | { 16 | if(node->type == XML_ELEMENT_NODE) 17 | { 18 | if(strcmp((char*)node->name, "binary") == 0) 19 | parse_fb2_book_binary(app, node); 20 | } 21 | 22 | node = node->next; 23 | } 24 | 25 | //************************************************************************** 26 | 27 | node = parent_node->children; 28 | 29 | while(node != NULL) 30 | { 31 | if((node->type == XML_ELEMENT_NODE) && (strcmp((char*)node->name, "description") == 0)) 32 | { 33 | parse_fb2_book_description(app, node, text_buff_end); 34 | } 35 | 36 | node = node->next; 37 | } 38 | 39 | //************************************************************************** 40 | 41 | node = parent_node->children; 42 | 43 | while(node != NULL) 44 | { 45 | if((node->type == XML_ELEMENT_NODE) && (strcmp((char*)node->name, "body") == 0)) 46 | { 47 | parse_fb2_body(app, node, text_buff_end); 48 | 49 | GtkTextIter text_buff_start; 50 | gtk_text_buffer_get_start_iter(text_buff, &text_buff_start); 51 | gtk_text_buffer_apply_tag_by_name(text_buff, "default_tag", &text_buff_start, text_buff_end); 52 | 53 | } 54 | 55 | node = node->next; 56 | } 57 | 58 | //************************************************************************** 59 | 60 | printf(_C("End read book\n")); 61 | 62 | 63 | 64 | return EXIT_SUCCESS; 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/formats/fb2/FictionBook/FictionBook_chunks.h: -------------------------------------------------------------------------------- 1 | #ifndef FICTIONBOOK_CHUNKS_H_ 2 | #define FICTIONBOOK_CHUNKS_H_ 3 | #include "../fb2_chunks.h" 4 | 5 | #include "body/body_chunks.h" 6 | #include "description/description_chunks.h" 7 | #include "attributes/attributes_chunks.h" 8 | 9 | int parse_fb2_file (APP* app, char* file_path); 10 | int parse_fb2_function_book (APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end); 11 | int parse_fb2_book_binary (APP* app, xmlNode* parent_node); 12 | 13 | #endif /* FICTIONBOOK_CHUNKS_H_ */ 14 | -------------------------------------------------------------------------------- /src/formats/fb2/FictionBook/attributes/attributes_chunks.h: -------------------------------------------------------------------------------- 1 | #ifndef FB2_FICTIONBOOK_ATTRIBUTES_CHUNKS_H_ 2 | #define FB2_FICTIONBOOK_ATTRIBUTES_CHUNKS_H_ 3 | 4 | #include "../FictionBook_chunks.h" 5 | 6 | int parse_fb2_id_attribute (APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end); 7 | 8 | 9 | #endif /* FB2_FICTIONBOOK_ATTRIBUTES_CHUNKS_H_ */ 10 | -------------------------------------------------------------------------------- /src/formats/fb2/FictionBook/attributes/id.c: -------------------------------------------------------------------------------- 1 | #include "attributes_chunks.h" 2 | 3 | int parse_fb2_id_attribute(APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end) 4 | { 5 | g_return_val_if_fail(parent_node != NULL, EXIT_FAILURE); 6 | g_return_val_if_fail(text_buff_end != NULL, EXIT_FAILURE); 7 | 8 | GHashTable* book_id_table = app->book_id_table; 9 | char* id_attr = (char*)xmlGetProp(parent_node, (xmlChar*)"id"); 10 | 11 | if(id_attr != NULL) 12 | { 13 | gint pos = gtk_text_iter_get_line(text_buff_end); 14 | 15 | if(g_hash_table_contains(book_id_table, id_attr) == FALSE) 16 | { 17 | char* id = g_strdup(id_attr); 18 | g_hash_table_insert(book_id_table, id, GINT_TO_POINTER(pos)); 19 | } 20 | else 21 | g_log(NULL, G_LOG_LEVEL_WARNING, "Id %s already exist in table", id_attr); 22 | } 23 | 24 | xmlFree(id_attr); 25 | 26 | 27 | 28 | return EXIT_SUCCESS; 29 | } 30 | -------------------------------------------------------------------------------- /src/formats/fb2/FictionBook/binary/binary.c: -------------------------------------------------------------------------------- 1 | #include "../FictionBook_chunks.h" 2 | 3 | #define READ_CHUNK_SIZE 1024 4 | int get_pixbuf_from_base64(char* base64, GdkPixbuf** pixbuf); 5 | 6 | int parse_fb2_book_binary(APP* app, xmlNode* parent_node) 7 | { 8 | g_return_val_if_fail(parent_node != NULL, EXIT_FAILURE); 9 | 10 | GHashTable* book_img_table = app->book_img_table; 11 | char* id_attr = (char*)xmlGetProp(parent_node, (xmlChar*)"id");; 12 | 13 | if(id_attr != NULL) 14 | { 15 | if(g_hash_table_contains(book_img_table, id_attr) == FALSE) 16 | { 17 | if(parent_node->children != NULL) 18 | { 19 | char* image_data = (char*)xmlNodeGetContent(parent_node); 20 | 21 | if(image_data != NULL) 22 | { 23 | GdkPixbuf* pixbuf = NULL; 24 | 25 | get_pixbuf_from_base64(image_data, &pixbuf); 26 | 27 | if(pixbuf != NULL) 28 | { 29 | char* id_dup = g_strdup(id_attr); 30 | g_hash_table_insert(book_img_table, id_dup, pixbuf); 31 | } 32 | } 33 | 34 | xmlFree(image_data); 35 | } 36 | else 37 | g_log(NULL, G_LOG_LEVEL_WARNING, "No content in tag"); 38 | } 39 | else 40 | g_log(NULL, G_LOG_LEVEL_WARNING, "Image %s already exist in table", id_attr); 41 | } 42 | else 43 | g_log(NULL, G_LOG_LEVEL_WARNING, "No id properties in tag"); 44 | 45 | xmlFree(id_attr); 46 | 47 | return EXIT_SUCCESS; 48 | } 49 | 50 | 51 | int get_pixbuf_from_base64(char* base64, GdkPixbuf** pixbuf) 52 | { 53 | g_return_val_if_fail(pixbuf != NULL, EXIT_FAILURE); 54 | g_return_val_if_fail(base64 != NULL, EXIT_FAILURE); 55 | 56 | guchar* out_buff = g_malloc((READ_CHUNK_SIZE/4)*3 + 3); 57 | GdkPixbufLoader* loader = gdk_pixbuf_loader_new(); 58 | GError* loader_error = NULL; 59 | gboolean has_error = FALSE; 60 | char* image_data = base64; 61 | size_t data_len = strlen(image_data); 62 | size_t position = 0; 63 | gint state = 0; 64 | guint save = 0; 65 | 66 | 67 | while(data_len > position) 68 | { 69 | size_t in_count = (position+READ_CHUNK_SIZE < data_len)? READ_CHUNK_SIZE : data_len%READ_CHUNK_SIZE; 70 | in_count = (in_count == 0)? READ_CHUNK_SIZE : in_count; 71 | 72 | size_t out_count = g_base64_decode_step(image_data, in_count, out_buff, &state, &save); 73 | 74 | if(gdk_pixbuf_loader_write(loader, out_buff, out_count, &loader_error) == FALSE) 75 | { 76 | g_log(NULL, G_LOG_LEVEL_ERROR, "GdkPixbufLoader: %s", loader_error->message); 77 | g_error_free(loader_error); 78 | has_error = TRUE; 79 | 80 | break; 81 | } 82 | 83 | image_data += READ_CHUNK_SIZE; 84 | position += READ_CHUNK_SIZE; 85 | 86 | } 87 | 88 | gdk_pixbuf_loader_close(loader, &loader_error); 89 | 90 | if(loader_error != NULL) 91 | { 92 | g_log(NULL, G_LOG_LEVEL_WARNING, "GdkPixbufLoader: %s", loader_error->message); 93 | g_error_free(loader_error); 94 | has_error = TRUE; 95 | } 96 | 97 | if(has_error == FALSE) 98 | { 99 | *pixbuf = gdk_pixbuf_loader_get_pixbuf(loader); 100 | g_object_ref(*pixbuf); 101 | } 102 | 103 | g_object_unref(loader); 104 | g_free(out_buff); 105 | 106 | return EXIT_SUCCESS; 107 | } 108 | -------------------------------------------------------------------------------- /src/formats/fb2/FictionBook/body/body.c: -------------------------------------------------------------------------------- 1 | #include "body_chunks.h" 2 | 3 | int parse_fb2_body(APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end) 4 | { 5 | g_return_val_if_fail(parent_node != NULL, EXIT_FAILURE); 6 | g_return_val_if_fail(text_buff_end != NULL, EXIT_FAILURE); 7 | 8 | xmlNode* node = parent_node->children; 9 | GtkTreeStore* sections_treestore = app->sections_treestore; 10 | 11 | GtkTreeIter section_iter; 12 | gtk_tree_store_append(sections_treestore, §ion_iter, NULL); 13 | gint cur_line = gtk_text_iter_get_line(text_buff_end); 14 | gtk_tree_store_set(sections_treestore, §ion_iter, SECTION_STRING_COLUMN, cur_line, 15 | SECTION_NAME_COLUMN, _C("Body tag without title"),-1); 16 | 17 | while(node != NULL) 18 | { 19 | if(node->type == XML_ELEMENT_NODE) 20 | { 21 | if(strcmp((char*)node->name, "image") == 0) 22 | parse_fb2_image(app, node, text_buff_end); 23 | else if(strcmp((char*)node->name, "title") == 0) 24 | { 25 | parse_fb2_navigation_set_chapter_by_title(app, node, §ion_iter); 26 | parse_fb2_title(app, node, text_buff_end); 27 | } 28 | else if(strcmp((char*)node->name, "epigraph") == 0) 29 | parse_fb2_epigraph(app, node, text_buff_end); 30 | else if(strcmp((char*)node->name, "section") == 0) 31 | parse_fb2_section(app, node, text_buff_end, §ion_iter); 32 | 33 | } 34 | 35 | node = node->next; 36 | } 37 | 38 | return EXIT_SUCCESS; 39 | } 40 | -------------------------------------------------------------------------------- /src/formats/fb2/FictionBook/body/body_chunks.h: -------------------------------------------------------------------------------- 1 | #ifndef BODY_CHUNKS_H_ 2 | #define BODY_CHUNKS_H_ 3 | 4 | #include "../FictionBook_chunks.h" 5 | 6 | #include "section/section_chunks.h" 7 | 8 | int parse_fb2_body (APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end); 9 | int parse_fb2_epigraph (APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end); 10 | int parse_fb2_image (APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end); 11 | int parse_fb2_title (APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end); 12 | 13 | #endif /* BODY_CHUNKS_H_ */ 14 | -------------------------------------------------------------------------------- /src/formats/fb2/FictionBook/body/epigraph.c: -------------------------------------------------------------------------------- 1 | #include "body_chunks.h" 2 | 3 | int parse_fb2_epigraph(APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end) 4 | { 5 | g_return_val_if_fail(parent_node != NULL, EXIT_FAILURE); 6 | g_return_val_if_fail(text_buff_end != NULL, EXIT_FAILURE); 7 | 8 | GtkTextBuffer* text_buff = app->text_buff; 9 | xmlNode* node = parent_node->children; 10 | 11 | gtk_text_buffer_insert(text_buff, text_buff_end, "\n", -1); 12 | 13 | parse_fb2_id_attribute(app, parent_node, text_buff_end); 14 | 15 | GtkTextMark* start_tag_mark = gtk_text_buffer_create_mark(text_buff, NULL, text_buff_end, TRUE); 16 | 17 | while(node != NULL) 18 | { 19 | if(node->type == XML_ELEMENT_NODE) 20 | { 21 | if(strcmp((char*)node->name, "p") == 0) 22 | parse_fb2_p_no_tab(app, node, text_buff_end); 23 | else if(strcmp((char*)node->name, "poem") == 0) 24 | parse_fb2_poem(app, node, text_buff_end); 25 | else if(strcmp((char*)node->name, "cite") == 0) 26 | parse_fb2_cite(app, node, text_buff_end); 27 | else if(strcmp((char*)node->name, "empty-line") == 0) 28 | parse_fb2_empty_line(app, node, text_buff_end); 29 | else if(strcmp((char*)node->name, "text-author") == 0) 30 | parse_fb2_text_autor(app, node, text_buff_end); 31 | } 32 | 33 | node = node->next; 34 | } 35 | 36 | GtkTextIter start_tag_iter; 37 | gtk_text_buffer_get_iter_at_mark(text_buff, &start_tag_iter, start_tag_mark); 38 | gtk_text_buffer_delete_mark(text_buff, start_tag_mark); 39 | //g_object_unref(G_OBJECT(start_tag_mark)); 40 | gtk_text_buffer_apply_tag_by_name(text_buff, "epigraph_tag", &start_tag_iter, text_buff_end); 41 | 42 | return EXIT_SUCCESS; 43 | } 44 | -------------------------------------------------------------------------------- /src/formats/fb2/FictionBook/body/image.c: -------------------------------------------------------------------------------- 1 | #include "body_chunks.h" 2 | 3 | int parse_fb2_image(APP* obj, xmlNode* parent_node, GtkTextIter* text_buff_end) 4 | { 5 | g_return_val_if_fail(parent_node != NULL, EXIT_FAILURE); 6 | g_return_val_if_fail(text_buff_end != NULL, EXIT_FAILURE); 7 | 8 | GtkTextBuffer* text_buff = obj->text_buff; 9 | GHashTable* book_img_table = obj->book_img_table; 10 | 11 | parse_fb2_id_attribute(obj, parent_node, text_buff_end); 12 | 13 | GtkTextMark* start_tag_mark = gtk_text_buffer_create_mark(text_buff, NULL, text_buff_end, TRUE); 14 | char* href_attr = (char*)xmlGetProp(parent_node, (xmlChar*)"href"); 15 | char* title_attr = (char*)xmlGetProp(parent_node, (xmlChar*)"title"); 16 | 17 | if(href_attr != NULL) 18 | { 19 | if(*href_attr == '#') // local 20 | { 21 | GdkPixbuf* image = g_hash_table_lookup(book_img_table, href_attr+1); 22 | if(image != NULL) 23 | { 24 | gtk_text_buffer_insert_pixbuf(text_buff, text_buff_end, image); 25 | gtk_text_buffer_insert(text_buff, text_buff_end, "\n", -1); 26 | 27 | if(title_attr != NULL) 28 | gtk_text_buffer_insert(text_buff, text_buff_end, title_attr, -1); 29 | } 30 | else 31 | g_log(NULL, G_LOG_LEVEL_WARNING, "Image %s not found in table", href_attr+1); 32 | } 33 | else 34 | g_log(NULL, G_LOG_LEVEL_WARNING, "Not local links not supported"); 35 | } 36 | 37 | xmlFree(href_attr); 38 | xmlFree(title_attr); 39 | 40 | GtkTextIter start_tag_iter; 41 | gtk_text_buffer_get_iter_at_mark(text_buff, &start_tag_iter, start_tag_mark); 42 | gtk_text_buffer_delete_mark(text_buff, start_tag_mark); 43 | gtk_text_buffer_apply_tag_by_name(text_buff, "image_tag", &start_tag_iter, text_buff_end); 44 | 45 | return EXIT_SUCCESS; 46 | } 47 | -------------------------------------------------------------------------------- /src/formats/fb2/FictionBook/body/section/a.c: -------------------------------------------------------------------------------- 1 | #include "section_chunks.h" 2 | 3 | int parse_fb2_a__(APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end); 4 | 5 | int parse_fb2_a(APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end) 6 | { 7 | g_return_val_if_fail(parent_node != NULL, EXIT_FAILURE); 8 | g_return_val_if_fail(text_buff_end != NULL, EXIT_FAILURE); 9 | 10 | 11 | GtkTextBuffer* text_buff = app->text_buff; 12 | xmlNode* node = parent_node->children; 13 | 14 | GtkTextMark* start_tag_mark = gtk_text_buffer_create_mark(text_buff, NULL, text_buff_end, TRUE); 15 | GtkTextTag* a_tag = gtk_text_buffer_create_tag(text_buff, NULL, "foreground", "blue", 16 | "underline", PANGO_UNDERLINE_SINGLE, NULL); 17 | 18 | char* href_attr = (char*)xmlGetProp(parent_node, (xmlChar*)"href"); 19 | 20 | if(href_attr != NULL) 21 | { 22 | char* href_dup = g_strdup(href_attr); 23 | g_signal_connect(G_OBJECT(a_tag), "event", G_CALLBACK(a_tag_event_cb), app); 24 | g_object_set_data_full(G_OBJECT(a_tag), "href", href_dup, g_free); 25 | } 26 | 27 | xmlFree(href_attr); 28 | 29 | parse_fb2_a__(app, node, text_buff_end); 30 | 31 | GtkTextIter start_tag_iter; 32 | gtk_text_buffer_get_iter_at_mark(text_buff, &start_tag_iter, start_tag_mark); 33 | gtk_text_buffer_delete_mark(text_buff, start_tag_mark); 34 | gtk_text_buffer_apply_tag(text_buff, a_tag, &start_tag_iter, text_buff_end); 35 | 36 | return EXIT_SUCCESS; 37 | } 38 | 39 | int parse_fb2_a__(APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end) // своя функция для форматирования текста в угоду соблюдения стандарта 40 | { 41 | g_return_val_if_fail(parent_node != NULL, EXIT_FAILURE); 42 | g_return_val_if_fail(text_buff_end != NULL, EXIT_FAILURE); 43 | 44 | GtkTextBuffer* text_buff = app->text_buff; 45 | xmlNode* node = parent_node; 46 | 47 | const char* tag = NULL; 48 | 49 | while(node != NULL) 50 | { 51 | tag = NULL; 52 | 53 | if(node->type == XML_TEXT_NODE) 54 | gtk_text_buffer_insert(text_buff, text_buff_end, (char*)node->content, -1); 55 | else if(node->type == XML_ELEMENT_NODE) 56 | { 57 | if(strcmp((char*)node->name, "strong") == 0) // жирный 58 | tag = "strong_tag"; 59 | else if(strcmp((char*)node->name, "emphasis") == 0) // курсив 60 | tag = "emphasis_tag"; 61 | else if(strcmp((char*)node->name, "strikethrough") == 0) // зачеркнутый 62 | tag = "strikethrough_tag"; 63 | else if(strcmp((char*)node->name, "sub") == 0) // нижний индекс 64 | tag = "sub_tag"; 65 | else if(strcmp((char*)node->name, "sup") == 0) // верхний индекс 66 | tag = "sup_tag"; 67 | else if(strcmp((char*)node->name, "code") == 0) // код, моноширинный шрифт 68 | tag = "code_tag"; 69 | else if(strcmp((char*)node->name, "image") == 0) // картинка 70 | parse_fb2_image_inline(app, node, text_buff_end); 71 | } 72 | 73 | 74 | if(tag != NULL) 75 | { 76 | GtkTextMark* start_tag_mark = gtk_text_buffer_create_mark(text_buff, NULL, text_buff_end, TRUE); 77 | 78 | parse_fb2_a__(app, node->children, text_buff_end); 79 | 80 | GtkTextIter start_tag_iter; 81 | gtk_text_buffer_get_iter_at_mark(text_buff, &start_tag_iter, start_tag_mark); 82 | gtk_text_buffer_delete_mark(text_buff, start_tag_mark); 83 | //g_object_unref(G_OBJECT(start_tag_mark)); 84 | gtk_text_buffer_apply_tag_by_name(text_buff, tag, &start_tag_iter, text_buff_end); 85 | 86 | } 87 | 88 | node = node->next; 89 | } 90 | return EXIT_SUCCESS; 91 | } 92 | -------------------------------------------------------------------------------- /src/formats/fb2/FictionBook/body/section/cite.c: -------------------------------------------------------------------------------- 1 | #include "section_chunks.h" 2 | 3 | int parse_fb2_cite(APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end) 4 | { 5 | g_return_val_if_fail(parent_node != NULL, EXIT_FAILURE); 6 | g_return_val_if_fail(text_buff_end != NULL, EXIT_FAILURE); 7 | 8 | GtkTextBuffer* text_buff = app->text_buff; 9 | xmlNode* node = parent_node->children; 10 | 11 | parse_fb2_id_attribute(app, parent_node, text_buff_end); 12 | 13 | GtkTextMark* start_tag_mark = gtk_text_buffer_create_mark(text_buff, NULL, text_buff_end, TRUE); 14 | 15 | gtk_text_buffer_insert(text_buff, text_buff_end, "\n", -1); 16 | 17 | while(node != NULL) 18 | { 19 | if(node->type == XML_ELEMENT_NODE) 20 | { 21 | if(strcmp((char*)node->name, "p") == 0) 22 | parse_fb2_p(app, node, text_buff_end); 23 | else if(strcmp((char*)node->name, "subtitle") == 0) 24 | parse_fb2_subtitle(app, node, text_buff_end); 25 | else if(strcmp((char*)node->name, "empty-line") == 0) 26 | parse_fb2_empty_line(app, node, text_buff_end); 27 | else if(strcmp((char*)node->name, "poem") == 0) 28 | parse_fb2_poem(app, node, text_buff_end); 29 | else if(strcmp((char*)node->name, "table") == 0) 30 | parse_fb2_table(app, node, text_buff_end); 31 | else if(strcmp((char*)node->name, "text-author") == 0) 32 | parse_fb2_text_autor(app, node, text_buff_end); 33 | } 34 | 35 | node = node->next; 36 | } 37 | 38 | //gtk_text_buffer_insert(text_buff, text_buff_end, "\n", -1); 39 | 40 | GtkTextIter start_tag_iter; 41 | gtk_text_buffer_get_iter_at_mark(text_buff, &start_tag_iter, start_tag_mark); 42 | gtk_text_buffer_delete_mark(text_buff, start_tag_mark); 43 | gtk_text_buffer_apply_tag_by_name(text_buff, "cite_tag", &start_tag_iter, text_buff_end); 44 | return EXIT_SUCCESS; 45 | } 46 | -------------------------------------------------------------------------------- /src/formats/fb2/FictionBook/body/section/date.c: -------------------------------------------------------------------------------- 1 | #include "section_chunks.h" 2 | 3 | int parse_fb2_date(APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end) 4 | { 5 | g_return_val_if_fail(parent_node != NULL, EXIT_FAILURE); 6 | g_return_val_if_fail(text_buff_end != NULL, EXIT_FAILURE); 7 | 8 | GtkTextBuffer* text_buff = app->text_buff; 9 | char* value_attr = (char*)xmlGetProp(parent_node, (xmlChar*)"id"); 10 | 11 | GtkTextMark* start_tag_mark = gtk_text_buffer_create_mark(text_buff, NULL, text_buff_end, TRUE); 12 | 13 | if(value_attr != NULL) 14 | gtk_text_buffer_insert(text_buff, text_buff_end, value_attr, -1); 15 | else 16 | { 17 | xmlNode* node = parent_node->children; 18 | if(node != NULL) 19 | { 20 | if(node->type == XML_TEXT_NODE) 21 | gtk_text_buffer_insert(text_buff, text_buff_end, (char*)node->content, -1); 22 | } 23 | } 24 | 25 | xmlFree(value_attr); 26 | 27 | gtk_text_buffer_insert(text_buff, text_buff_end, "\n", -1); 28 | 29 | GtkTextIter start_tag_iter; 30 | gtk_text_buffer_get_iter_at_mark(text_buff, &start_tag_iter, start_tag_mark); 31 | gtk_text_buffer_delete_mark(text_buff, start_tag_mark); 32 | //g_object_unref(G_OBJECT(start_tag_mark)); 33 | gtk_text_buffer_apply_tag_by_name(text_buff, "date_tag", &start_tag_iter, text_buff_end); 34 | 35 | return EXIT_SUCCESS; 36 | } 37 | -------------------------------------------------------------------------------- /src/formats/fb2/FictionBook/body/section/empty_line.c: -------------------------------------------------------------------------------- 1 | #include "section_chunks.h" 2 | 3 | int parse_fb2_empty_line(APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end) 4 | { 5 | GtkTextBuffer* text_buff = app->text_buff; 6 | 7 | gtk_text_buffer_insert(text_buff, text_buff_end, "\n", -1); 8 | 9 | return EXIT_SUCCESS; 10 | } 11 | -------------------------------------------------------------------------------- /src/formats/fb2/FictionBook/body/section/image_inline.c: -------------------------------------------------------------------------------- 1 | #include "section_chunks.h" 2 | 3 | int parse_fb2_image_inline(APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end) 4 | { 5 | g_return_val_if_fail(parent_node != NULL, EXIT_FAILURE); 6 | g_return_val_if_fail(text_buff_end != NULL, EXIT_FAILURE); 7 | 8 | GtkTextBuffer* text_buff = app->text_buff; 9 | GHashTable* book_img_table = app->book_img_table; 10 | 11 | parse_fb2_id_attribute(app, parent_node, text_buff_end); 12 | 13 | char* href_attr = (char*)xmlGetProp(parent_node, (xmlChar*)"href"); 14 | 15 | if(href_attr != NULL) 16 | { 17 | if(*href_attr == '#') // local 18 | { 19 | GdkPixbuf* image = g_hash_table_lookup(book_img_table, href_attr+1); 20 | if(image != NULL) 21 | gtk_text_buffer_insert_pixbuf(text_buff, text_buff_end, image); 22 | else 23 | g_log(NULL, G_LOG_LEVEL_WARNING, "Image %s not found in table", href_attr+1); 24 | } 25 | else 26 | g_log(NULL, G_LOG_LEVEL_WARNING, "Not local links not supported"); 27 | 28 | } 29 | 30 | xmlFree(href_attr); 31 | 32 | return EXIT_SUCCESS; 33 | } 34 | 35 | -------------------------------------------------------------------------------- /src/formats/fb2/FictionBook/body/section/p/p.c: -------------------------------------------------------------------------------- 1 | #include "p_chunks.h" 2 | 3 | int parse_fb2_p(APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end) 4 | { 5 | g_return_val_if_fail(parent_node != NULL, EXIT_FAILURE); 6 | g_return_val_if_fail(text_buff_end != NULL, EXIT_FAILURE); 7 | 8 | GtkTextBuffer* text_buff = app->text_buff; 9 | 10 | gtk_text_buffer_insert(text_buff, text_buff_end, "\t", -1); 11 | parse_fb2_p_no_tab(app, parent_node, text_buff_end); 12 | 13 | return EXIT_SUCCESS; 14 | } 15 | 16 | int parse_fb2_p_no_tab(APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end) 17 | { 18 | g_return_val_if_fail(parent_node != NULL, EXIT_FAILURE); 19 | g_return_val_if_fail(text_buff_end != NULL, EXIT_FAILURE); 20 | 21 | GtkTextBuffer* text_buff = app->text_buff; 22 | 23 | parse_fb2_p_inline(app, parent_node, text_buff_end); 24 | gtk_text_buffer_insert(text_buff, text_buff_end, "\n", -1); 25 | 26 | return EXIT_SUCCESS; 27 | } 28 | 29 | int parse_fb2_p_inline(APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end) 30 | { 31 | g_return_val_if_fail(parent_node != NULL, EXIT_FAILURE); 32 | g_return_val_if_fail(text_buff_end != NULL, EXIT_FAILURE); 33 | 34 | GtkTextBuffer* text_buff = app->text_buff; 35 | xmlNode* node = parent_node->children; 36 | 37 | parse_fb2_id_attribute(app, parent_node, text_buff_end); 38 | 39 | const char* tag = NULL; 40 | 41 | while(node != NULL) 42 | { 43 | tag = NULL; 44 | 45 | if(node->type == XML_TEXT_NODE) 46 | gtk_text_buffer_insert(text_buff, text_buff_end, (char*)node->content, -1); 47 | else if(node->type == XML_ELEMENT_NODE) 48 | { 49 | if(strcmp((char*)node->name, "strong") == 0) // жирный 50 | tag = "strong_tag"; 51 | else if(strcmp((char*)node->name, "emphasis") == 0) // курсив 52 | tag = "emphasis_tag"; 53 | else if(strcmp((char*)node->name, "style") == 0) // стилевое оформление 54 | parse_fb2_style(app, node, text_buff_end); 55 | else if(strcmp((char*)node->name, "a") == 0) // ссылка 56 | parse_fb2_a(app, node, text_buff_end); 57 | else if(strcmp((char*)node->name, "strikethrough") == 0) // зачеркнутый 58 | tag = "strikethrough_tag"; 59 | else if(strcmp((char*)node->name, "sub") == 0) // нижний индекс 60 | tag = "sub_tag"; 61 | else if(strcmp((char*)node->name, "sup") == 0) // верхний индекс 62 | tag = "sup_tag"; 63 | else if(strcmp((char*)parent_node->name, "code") == 0) // код, моноширинный шрифт 64 | tag = "code_tag"; 65 | else if(strcmp((char*)node->name, "image") == 0) // картинка 66 | parse_fb2_image_inline(app, node, text_buff_end); 67 | } 68 | 69 | 70 | 71 | if(tag != NULL) 72 | { 73 | GtkTextMark* start_tag_mark = gtk_text_buffer_create_mark(text_buff, NULL, text_buff_end, TRUE); 74 | 75 | parse_fb2_p_inline(app, node, text_buff_end); 76 | 77 | GtkTextIter start_tag_iter; 78 | gtk_text_buffer_get_iter_at_mark(text_buff, &start_tag_iter, start_tag_mark); 79 | gtk_text_buffer_delete_mark(text_buff, start_tag_mark); 80 | //g_object_unref(G_OBJECT(start_tag_mark)); 81 | gtk_text_buffer_apply_tag_by_name(text_buff, tag, &start_tag_iter, text_buff_end); 82 | 83 | } 84 | 85 | node = node->next; 86 | } 87 | 88 | //gtk_text_buffer_insert(text_buff, text_buff_end, "\n", -1); 89 | 90 | return EXIT_SUCCESS; 91 | } 92 | -------------------------------------------------------------------------------- /src/formats/fb2/FictionBook/body/section/p/p_chunks.h: -------------------------------------------------------------------------------- 1 | #ifndef FB2_FICTIONBOOK_BODY_SECTION_P_P_CHUNKS_H_ 2 | #define FB2_FICTIONBOOK_BODY_SECTION_P_P_CHUNKS_H_ 3 | 4 | #include "../section_chunks.h" 5 | 6 | int parse_fb2_p_no_tab (APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end); 7 | int parse_fb2_p_inline (APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end); 8 | int parse_fb2_p_get_text (xmlNode* parent_node, GString* buff); 9 | int parse_fb2_p_get_length (xmlNode* parent_node, glong* len); 10 | int parse_fb2_p (APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end); 11 | 12 | #endif /* FB2_FICTIONBOOK_BODY_SECTION_P_P_CHUNKS_H_ */ 13 | -------------------------------------------------------------------------------- /src/formats/fb2/FictionBook/body/section/p/p_length.c: -------------------------------------------------------------------------------- 1 | #include "p_chunks.h" 2 | 3 | int parse_fb2_p_get_length(xmlNode* parent_node, glong* len) 4 | { 5 | g_return_val_if_fail(parent_node != NULL, EXIT_FAILURE); 6 | g_return_val_if_fail(len != NULL, EXIT_FAILURE); 7 | 8 | xmlNode* node = parent_node->children; 9 | 10 | while(node != NULL) 11 | { 12 | if(node->type == XML_TEXT_NODE) 13 | { 14 | *len += g_utf8_strlen((char*)node->content, -1); 15 | } 16 | else if(node->type == XML_ELEMENT_NODE) 17 | { 18 | if(strcmp((char*)node->name, "strong") == 0) // жирный 19 | parse_fb2_p_get_length(node, len); 20 | else if(strcmp((char*)node->name, "emphasis") == 0) // курсив 21 | parse_fb2_p_get_length(node, len); 22 | else if(strcmp((char*)node->name, "a") == 0) // ссылка 23 | parse_fb2_p_get_length(node, len); 24 | else if(strcmp((char*)node->name, "strikethrough") == 0) // зачеркнутый 25 | parse_fb2_p_get_length(node, len); 26 | else if(strcmp((char*)node->name, "sub") == 0) // нижний индекс 27 | parse_fb2_p_get_length(node, len); 28 | else if(strcmp((char*)node->name, "sup") == 0) // верхний индекс 29 | parse_fb2_p_get_length(node, len); 30 | else if(strcmp((char*)node->name, "code") == 0) // код, моноширинный шрифт 31 | parse_fb2_p_get_length(node, len); 32 | else if(strcmp((char*)node->name, "image") == 0) // картинка 33 | parse_fb2_p_get_length(node, len); 34 | else if(strcmp((char*)node->name, "style") == 0) // стилевое оформление 35 | parse_fb2_p_get_length(node, len); 36 | } 37 | node = node->next; 38 | } 39 | 40 | return EXIT_SUCCESS; 41 | } 42 | -------------------------------------------------------------------------------- /src/formats/fb2/FictionBook/body/section/p/p_text.c: -------------------------------------------------------------------------------- 1 | #include "p_chunks.h" 2 | 3 | int parse_fb2_p_get_text(xmlNode* parent_node, GString* buff) 4 | { 5 | g_return_val_if_fail(parent_node != NULL, EXIT_FAILURE);; 6 | g_return_val_if_fail(buff != NULL, EXIT_FAILURE);; 7 | 8 | xmlNode* node = parent_node->children; 9 | 10 | while(node != NULL) 11 | { 12 | if(node->type == XML_TEXT_NODE) 13 | g_string_append(buff, (char*)node->content); 14 | else if(node->type == XML_ELEMENT_NODE) 15 | { 16 | if(strcmp((char*)node->name, "strong") == 0) // жирный 17 | parse_fb2_p_get_text(node, buff); 18 | else if(strcmp((char*)node->name, "emphasis") == 0) // курсив 19 | parse_fb2_p_get_text(node, buff); 20 | else if(strcmp((char*)node->name, "a") == 0) // ссылка 21 | parse_fb2_p_get_text(node, buff); 22 | else if(strcmp((char*)node->name, "strikethrough") == 0) // зачеркнутый 23 | parse_fb2_p_get_text(node, buff); 24 | else if(strcmp((char*)node->name, "sub") == 0) // нижний индекс 25 | parse_fb2_p_get_text(node, buff); 26 | else if(strcmp((char*)node->name, "sup") == 0) // верхний индекс 27 | parse_fb2_p_get_text(node, buff); 28 | else if(strcmp((char*)node->name, "code") == 0) // код, моноширинный шрифт 29 | parse_fb2_p_get_text(node, buff); 30 | else if(strcmp((char*)node->name, "image") == 0) // картинка 31 | parse_fb2_p_get_text(node, buff); 32 | else if(strcmp((char*)node->name, "style") == 0) // стилевое оформление 33 | parse_fb2_p_get_text(node, buff); 34 | } 35 | node = node->next; 36 | } 37 | 38 | 39 | return EXIT_SUCCESS; 40 | } 41 | -------------------------------------------------------------------------------- /src/formats/fb2/FictionBook/body/section/poem.c: -------------------------------------------------------------------------------- 1 | #include "section_chunks.h" 2 | 3 | int parse_fb2_poem(APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end) 4 | { 5 | g_return_val_if_fail(parent_node != NULL, EXIT_FAILURE); 6 | g_return_val_if_fail(text_buff_end != NULL, EXIT_FAILURE); 7 | 8 | //GtkTextBuffer* text_buff = app->text_buff; 9 | xmlNode* node = parent_node->children; 10 | 11 | parse_fb2_id_attribute(app, parent_node, text_buff_end); 12 | 13 | 14 | //gtk_text_buffer_insert(text_buff, text_buff_end, "\n", -1); 15 | 16 | while(node != NULL) 17 | { 18 | if(node->type == XML_ELEMENT_NODE) 19 | { 20 | if(strcmp((char*)node->name, "title") == 0) 21 | parse_fb2_title(app, node, text_buff_end); 22 | else if(strcmp((char*)node->name, "epigraph") == 0) 23 | parse_fb2_epigraph(app, node, text_buff_end); 24 | else if(strcmp((char*)node->name, "stanza") == 0) 25 | parse_fb2_stanza(app, node, text_buff_end); 26 | else if(strcmp((char*)node->name, "text-author") == 0) 27 | parse_fb2_text_autor(app, node, text_buff_end); 28 | else if(strcmp((char*)node->name, "date") == 0) 29 | parse_fb2_date(app, node, text_buff_end); 30 | } 31 | 32 | node = node->next; 33 | } 34 | 35 | return EXIT_SUCCESS; 36 | } 37 | -------------------------------------------------------------------------------- /src/formats/fb2/FictionBook/body/section/poem/poem.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef POEM_H_ 3 | #define POEM_H_ 4 | 5 | #include "../section_chunks.h" 6 | 7 | int parse_fb2_poem (APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end); 8 | int parse_fb2_v (APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end); 9 | 10 | #endif /* POEM_H_ */ 11 | -------------------------------------------------------------------------------- /src/formats/fb2/FictionBook/body/section/poem/stanza.c: -------------------------------------------------------------------------------- 1 | #include "poem.h" 2 | 3 | int parse_fb2_stanza(APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end) 4 | { 5 | g_return_val_if_fail(parent_node != NULL, EXIT_FAILURE); 6 | g_return_val_if_fail(text_buff_end != NULL, EXIT_FAILURE); 7 | 8 | GtkTextBuffer* text_buff = app->text_buff; 9 | xmlNode* node = parent_node->children; 10 | 11 | gtk_text_buffer_insert(text_buff, text_buff_end, "\n", -1); 12 | 13 | GtkTextMark* start_tag_mark = gtk_text_buffer_create_mark(text_buff, NULL, text_buff_end, TRUE); 14 | 15 | while(node != NULL) 16 | { 17 | if(node->type == XML_ELEMENT_NODE) 18 | { 19 | if(strcmp((char*)node->name, "title") == 0) 20 | parse_fb2_title(app, node, text_buff_end); 21 | else if(strcmp((char*)node->name, "subtitle") == 0) 22 | parse_fb2_subtitle(app, node, text_buff_end); 23 | else if(strcmp((char*)node->name, "v") == 0) 24 | { 25 | parse_fb2_v(app, node, text_buff_end); 26 | //gtk_text_buffer_insert(text_buff, text_buff_end, "\n", -1); 27 | } 28 | 29 | } 30 | 31 | node = node->next; 32 | } 33 | 34 | //gtk_text_buffer_insert(text_buff, text_buff_end, "\n", -1); 35 | 36 | GtkTextIter start_tag_iter; 37 | gtk_text_buffer_get_iter_at_mark(text_buff, &start_tag_iter, start_tag_mark); 38 | gtk_text_buffer_delete_mark(text_buff, start_tag_mark); 39 | //g_object_unref(G_OBJECT(start_tag_mark)); 40 | gtk_text_buffer_apply_tag_by_name(text_buff, "stanza_tag", &start_tag_iter, text_buff_end); 41 | 42 | return EXIT_SUCCESS; 43 | } 44 | -------------------------------------------------------------------------------- /src/formats/fb2/FictionBook/body/section/poem/v.c: -------------------------------------------------------------------------------- 1 | #include "poem.h" 2 | 3 | int parse_fb2_v(APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end) 4 | { 5 | g_return_val_if_fail(parent_node != NULL, EXIT_FAILURE); 6 | g_return_val_if_fail(text_buff_end != NULL, EXIT_FAILURE); 7 | 8 | //GtkTextBuffer* text_buff = app->text_buff; 9 | 10 | parse_fb2_p_no_tab(app, parent_node, text_buff_end); 11 | //gtk_text_buffer_insert(text_buff, text_buff_end, "\n", -1); 12 | 13 | return EXIT_SUCCESS; 14 | } 15 | -------------------------------------------------------------------------------- /src/formats/fb2/FictionBook/body/section/section.c: -------------------------------------------------------------------------------- 1 | #include "section_chunks.h" 2 | 3 | int parse_fb2_section(APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end, GtkTreeIter* tree_iter) 4 | { 5 | g_return_val_if_fail(parent_node != NULL, EXIT_FAILURE); 6 | g_return_val_if_fail(text_buff_end != NULL, EXIT_FAILURE); 7 | 8 | xmlNode* node = parent_node->children; 9 | GtkTreeStore* sections_treestore = app->sections_treestore; 10 | 11 | parse_fb2_id_attribute(app, parent_node, text_buff_end); 12 | 13 | 14 | GtkTreeIter section_iter; 15 | gtk_tree_store_append(sections_treestore, §ion_iter, tree_iter); 16 | gint cur_line = gtk_text_iter_get_line(text_buff_end); 17 | gtk_tree_store_set(sections_treestore, §ion_iter, SECTION_STRING_COLUMN, cur_line, 18 | SECTION_NAME_COLUMN, _C("Section without title"),-1); 19 | 20 | while(node != NULL) 21 | { 22 | if(node->type == XML_ELEMENT_NODE) 23 | { 24 | if(strcmp((char*)node->name, "title") == 0) 25 | { 26 | parse_fb2_navigation_set_chapter_by_title(app, node, §ion_iter); 27 | parse_fb2_title(app, node, text_buff_end); 28 | } 29 | else if(strcmp((char*)node->name, "epigraph") == 0) 30 | parse_fb2_epigraph(app, node, text_buff_end); 31 | else if(strcmp((char*)node->name, "annotation") == 0) 32 | parse_fb2_annotation(app, node, text_buff_end); 33 | else if(strcmp((char*)node->name, "section") == 0) 34 | parse_fb2_section(app, node, text_buff_end, §ion_iter); 35 | else if(strcmp((char*)node->name, "p") == 0) 36 | parse_fb2_p(app, node, text_buff_end); 37 | else if(strcmp((char*)node->name, "empty-line") == 0) 38 | parse_fb2_empty_line(app, node, text_buff_end); 39 | else if(strcmp((char*)node->name, "image") == 0) 40 | parse_fb2_image(app, node, text_buff_end); 41 | else if(strcmp((char*)node->name, "poem") == 0) 42 | parse_fb2_poem(app, node, text_buff_end); 43 | else if(strcmp((char*)node->name, "subtitle") == 0) 44 | parse_fb2_subtitle(app, node, text_buff_end); 45 | else if(strcmp((char*)node->name, "cite") == 0) 46 | parse_fb2_cite(app, node, text_buff_end); 47 | else if(strcmp((char*)node->name, "table") == 0) 48 | parse_fb2_table(app, node, text_buff_end); 49 | } 50 | 51 | node = node->next; 52 | } 53 | 54 | return EXIT_SUCCESS; 55 | } 56 | -------------------------------------------------------------------------------- /src/formats/fb2/FictionBook/body/section/section_chunks.h: -------------------------------------------------------------------------------- 1 | #ifndef SECTION_CHUNKS_H_ 2 | #define SECTION_CHUNKS_H_ 3 | 4 | #include "../body_chunks.h" 5 | #include "p/p_chunks.h" 6 | #include "table/table_chunks.h" 7 | #include "poem/poem.h" 8 | 9 | int parse_fb2_section (APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end, GtkTreeIter* tree_iter); 10 | int parse_fb2_a (APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end); 11 | int parse_fb2_cite (APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end); 12 | int parse_fb2_date (APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end); 13 | int parse_fb2_empty_line (APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end); 14 | int parse_fb2_image_inline (APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end); 15 | int parse_fb2_poem (APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end); 16 | int parse_fb2_style (APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end); 17 | int parse_fb2_subtitle (APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end); 18 | int parse_fb2_stanza (APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end); 19 | 20 | int parse_fb2_text_autor (APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end); 21 | 22 | int parse_fb2_navigation_set_chapter_by_title(APP* app, xmlNode* parent_node, GtkTreeIter* cur_tree_iter); 23 | 24 | #endif /* SECTION_CHUNKS_H_ */ 25 | -------------------------------------------------------------------------------- /src/formats/fb2/FictionBook/body/section/style.c: -------------------------------------------------------------------------------- 1 | #include "section_chunks.h" 2 | 3 | int parse_fb2_style(APP* app, xmlNode* parent_node, GtkTextIter* text_buff_end) 4 | { 5 | g_return_val_if_fail(parent_node != NULL, EXIT_FAILURE); 6 | g_return_val_if_fail(text_buff_end != NULL, EXIT_FAILURE); 7 | 8 | xmlNode* node = parent_node;//parent_node->children; 9 | //GtkTextBuffer* text_buff = app->text_buff; 10 | 11 | g_log(NULL, G_LOG_LEVEL_WARNING, "Tag