Compare commits

...

32 Commits

Author SHA1 Message Date
b33b5ff0ce Prevent gtk_widget_error_bell() in clipboard watch
All checks were successful
Arch Linux AUR Success
Alpine 3.22 Success
I'm not sure if the position setting is necessary at all.
2025-11-23 16:42:40 +01:00
c204e4e094 Bump liberty and termo
All checks were successful
Alpine 3.20 Success
Arch Linux AUR Success
2025-04-23 22:00:17 +02:00
16e0ff2188 Make README.adoc a bit less confusing
All checks were successful
Alpine 3.20 Success
Arch Linux AUR Success
2024-12-19 15:29:58 +01:00
2d6855445f Update the screenshot
All checks were successful
Alpine 3.20 Success
Arch Linux AUR Success
2024-12-19 15:24:53 +01:00
531f18d827 GUI: add basic configuration
It is simply not feasible to write the text file by hand on Windows.
2024-12-19 14:38:19 +01:00
862cde36ae CMakeLists.txt: quote more paths 2024-12-07 22:50:53 +01:00
661dc85d45 Fix macOS build
All checks were successful
Alpine 3.20 Success
Arch Linux AUR Success
2024-12-04 18:10:35 +01:00
2fe846f09f Fix running tests in Windows builds
All checks were successful
Arch Linux AUR Success
Alpine 3.19 Success
2024-04-10 12:48:05 +02:00
33426992ec Bump liberty, moving the Win64 toolchain file
All checks were successful
Arch Linux AUR Success
2024-04-09 17:04:45 +02:00
197d071160 Enable cross-compiled tests
All checks were successful
Arch Linux AUR Success
2024-04-09 13:04:32 +02:00
fafac22d60 Bump liberty
All checks were successful
Arch Linux AUR Success
2024-02-10 05:46:13 +01:00
58f7ba55b3 CMakeLists.txt: declare compatibility with 3.27
Sadly, the 3.5 deprecation warning doesn't go away after this.
2023-08-01 03:09:31 +02:00
d2cfc2ee81 Deduplicate CMake scripts 2023-07-24 11:47:33 +02:00
5a9a446b9c Fix build on OpenIndiana 2023-07-24 08:24:52 +02:00
39e2fc5142 Find ncursesw on OpenIndiana 2023-07-24 08:07:26 +02:00
f94bb77091 Reflect the recent renaming of tabfile in scripts 2023-07-07 12:15:37 +02:00
d3cfb12e16 README.adoc: update package information 2023-07-01 22:00:54 +02:00
9aac2511d3 Win64Depends.sh: only extract what we need
In case the packages directory has been preloaded or symlinked.
2023-06-26 20:57:56 +02:00
8af337c83c CMakeLists.txt: fix dependencies after renaming 2023-06-22 00:23:29 +02:00
951208c15b Test SVG and desktop file validity 2023-06-15 16:24:16 +02:00
74d9acecb5 Bump termo 2023-06-14 16:24:27 +02:00
d1ce97010e Update the manual page 2023-06-11 18:14:46 +02:00
e7be281b58 Reflect upstream URL rename 2023-06-11 18:12:12 +02:00
2aa6390146 Update translations 2023-06-11 18:08:03 +02:00
c77d994dc4 Rename tools, make them installable 2023-06-11 18:08:03 +02:00
238e7a2bb9 Merge TUI and GUI binaries, using a new name
The appropriate interface will be chosen automatically.
2023-06-11 18:08:03 +02:00
7bcbc04b04 Bump liberty
This improves the still-imperfect fallback manpage output.
2023-06-11 10:11:54 +02:00
59d7c4af17 Improve manpage AsciiDoc compatibility 2023-06-10 15:05:12 +02:00
2ed1c005c9 Import liberty for its manpage generator
It cannot parse the page well, so it's just a convenience fallback.
2023-06-10 12:12:42 +02:00
26e73711b1 Improve GLib version compatibility 2023-06-10 12:12:41 +02:00
d13b4a793d Prevent undefined behaviour 2022-09-24 18:42:59 +02:00
0570a4d050 sdtui: measure the "search" prompt properly 2022-09-24 18:42:30 +02:00
34 changed files with 825 additions and 447 deletions

12
.gitignore vendored
View File

@@ -3,9 +3,9 @@
# Qt Creator files # Qt Creator files
/CMakeLists.txt.user* /CMakeLists.txt.user*
/sdtui.cflags /tdv.cflags
/sdtui.cxxflags /tdv.cxxflags
/sdtui.config /tdv.config
/sdtui.files /tdv.files
/sdtui.creator* /tdv.creator*
/sdtui.includes /tdv.includes

3
.gitmodules vendored
View File

@@ -1,3 +1,6 @@
[submodule "termo"] [submodule "termo"]
path = termo path = termo
url = https://git.janouch.name/p/termo.git url = https://git.janouch.name/p/termo.git
[submodule "liberty"]
path = liberty
url = https://git.janouch.name/p/liberty.git

View File

@@ -1,15 +1,18 @@
cmake_minimum_required (VERSION 3.0) cmake_minimum_required (VERSION 3.0...3.27)
project (sdtui VERSION 0.1.0 LANGUAGES C) project (tdv VERSION 0.1.0 LANGUAGES C)
# Moar warnings # Adjust warnings
if ("${CMAKE_C_COMPILER_ID}" MATCHES "GNU" OR CMAKE_COMPILER_IS_GNUCC) if ("${CMAKE_C_COMPILER_ID}" MATCHES "GNU" OR CMAKE_COMPILER_IS_GNUCC)
set (ignores "-Wno-missing-field-initializers -Wno-cast-function-type") set (ignores "-Wno-missing-field-initializers -Wno-cast-function-type")
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 ${ignores}") set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 ${ignores}")
set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wall -Wextra") set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wall -Wextra")
endif () endif ()
add_definitions (-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_38)
# For custom modules # For custom modules
set (CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) set (CMAKE_MODULE_PATH
"${PROJECT_SOURCE_DIR}/cmake;${PROJECT_SOURCE_DIR}/liberty/cmake")
# Cross-compilation for Windows, as a proof-of-concept pulled in from logdiag # Cross-compilation for Windows, as a proof-of-concept pulled in from logdiag
if (WIN32) if (WIN32)
@@ -75,7 +78,7 @@ if (USE_SYSTEM_TERMO)
if (NOT Termo_FOUND) if (NOT Termo_FOUND)
message (FATAL_ERROR "System termo library not found") message (FATAL_ERROR "System termo library not found")
endif () endif ()
else () elseif (NOT WIN32)
# We don't want the library to install, but EXCLUDE_FROM_ALL ignores tests # We don't want the library to install, but EXCLUDE_FROM_ALL ignores tests
add_subdirectory (termo EXCLUDE_FROM_ALL) add_subdirectory (termo EXCLUDE_FROM_ALL)
file (WRITE ${PROJECT_BINARY_DIR}/CTestCustom.cmake file (WRITE ${PROJECT_BINARY_DIR}/CTestCustom.cmake
@@ -108,6 +111,7 @@ if (WITH_GUI)
message (FATAL_ERROR "GTK+ not found") message (FATAL_ERROR "GTK+ not found")
endif () endif ()
include_directories (${gtk_INCLUDE_DIRS})
link_directories (${gtk_LIBRARY_DIRS}) link_directories (${gtk_LIBRARY_DIRS})
endif () endif ()
@@ -123,23 +127,24 @@ CHECK_FUNCTION_EXISTS ("resizeterm" HAVE_RESIZETERM)
# Localization # Localization
find_package (Gettext REQUIRED) find_package (Gettext REQUIRED)
file (GLOB project_PO_FILES ${PROJECT_SOURCE_DIR}/po/*.po) file (GLOB project_PO_FILES "${PROJECT_SOURCE_DIR}/po/*.po")
GETTEXT_CREATE_TRANSLATIONS ( GETTEXT_CREATE_TRANSLATIONS (
${PROJECT_SOURCE_DIR}/po/${PROJECT_NAME}.pot "${PROJECT_SOURCE_DIR}/po/${PROJECT_NAME}.pot"
ALL ${project_PO_FILES}) ALL ${project_PO_FILES})
# Documentation # Documentation
find_program (ASCIIDOCTOR_EXECUTABLE asciidoctor) find_program (ASCIIDOCTOR_EXECUTABLE asciidoctor)
find_program (A2X_EXECUTABLE a2x) find_program (A2X_EXECUTABLE a2x)
if (NOT ASCIIDOCTOR_EXECUTABLE AND NOT A2X_EXECUTABLE) if (NOT ASCIIDOCTOR_EXECUTABLE AND NOT A2X_EXECUTABLE)
message (FATAL_ERROR "Neither asciidoctor nor a2x were found") message (WARNING "Neither asciidoctor nor a2x were found, "
"falling back to a substandard manual page generator")
endif () endif ()
foreach (page "${PROJECT_NAME}.1") foreach (page "${PROJECT_NAME}.1")
set (page_output "${PROJECT_BINARY_DIR}/${page}") set (page_output "${PROJECT_BINARY_DIR}/${page}")
list (APPEND project_MAN_PAGES "${page_output}") list (APPEND project_MAN_PAGES "${page_output}")
if (ASCIIDOCTOR_EXECUTABLE) if (ASCIIDOCTOR_EXECUTABLE)
add_custom_command (OUTPUT ${page_output} add_custom_command (OUTPUT "${page_output}"
COMMAND ${ASCIIDOCTOR_EXECUTABLE} -b manpage COMMAND ${ASCIIDOCTOR_EXECUTABLE} -b manpage
-a release-version=${PROJECT_VERSION} -a release-version=${PROJECT_VERSION}
-o "${page_output}" -o "${page_output}"
@@ -147,13 +152,21 @@ foreach (page "${PROJECT_NAME}.1")
DEPENDS "docs/${page}.adoc" DEPENDS "docs/${page}.adoc"
COMMENT "Generating man page for ${page}" VERBATIM) COMMENT "Generating man page for ${page}" VERBATIM)
elseif (A2X_EXECUTABLE) elseif (A2X_EXECUTABLE)
add_custom_command (OUTPUT ${page_output} add_custom_command (OUTPUT "${page_output}"
COMMAND ${A2X_EXECUTABLE} --doctype manpage --format manpage COMMAND ${A2X_EXECUTABLE} --doctype manpage --format manpage
-a release-version=${PROJECT_VERSION} -a release-version=${PROJECT_VERSION}
-D "${PROJECT_BINARY_DIR}" -D "${PROJECT_BINARY_DIR}"
"${PROJECT_SOURCE_DIR}/docs/${page}.adoc" "${PROJECT_SOURCE_DIR}/docs/${page}.adoc"
DEPENDS "docs/${page}.adoc" DEPENDS "docs/${page}.adoc"
COMMENT "Generating man page for ${page}" VERBATIM) COMMENT "Generating man page for ${page}" VERBATIM)
else ()
set (ASCIIMAN ${PROJECT_SOURCE_DIR}/liberty/tools/asciiman.awk)
add_custom_command (OUTPUT "${page_output}"
COMMAND env LC_ALL=C asciidoc-release-version=${PROJECT_VERSION}
awk -f ${ASCIIMAN} "${PROJECT_SOURCE_DIR}/docs/${page}.adoc"
> "${page_output}"
DEPENDS "docs/${page}.adoc" ${ASCIIMAN}
COMMENT "Generating man page for ${page}" VERBATIM)
endif () endif ()
endforeach () endforeach ()
@@ -168,7 +181,7 @@ if (WIN32)
endif (WIN32) endif (WIN32)
set (project_common_headers set (project_common_headers
${PROJECT_BINARY_DIR}/config.h "${PROJECT_BINARY_DIR}/config.h"
src/dictzip-input-stream.h src/dictzip-input-stream.h
src/stardict.h src/stardict.h
src/stardict-private.h src/stardict-private.h
@@ -185,100 +198,80 @@ add_library (stardict OBJECT
set (project_common_sources $<TARGET_OBJECTS:stardict>) set (project_common_sources $<TARGET_OBJECTS:stardict>)
# Generate a configuration file # Generate a configuration file
configure_file (${PROJECT_SOURCE_DIR}/config.h.in configure_file ("${PROJECT_SOURCE_DIR}/config.h.in"
${PROJECT_BINARY_DIR}/config.h) "${PROJECT_BINARY_DIR}/config.h")
include_directories (${PROJECT_SOURCE_DIR} ${PROJECT_BINARY_DIR}) include_directories ("${PROJECT_SOURCE_DIR}" "${PROJECT_BINARY_DIR}")
# Primary target source files # Build the main executable and link it
set (project_libraries
${project_common_libraries})
set (project_sources set (project_sources
${project_common_sources}
src/${PROJECT_NAME}.c) src/${PROJECT_NAME}.c)
set (project_headers set (project_headers
${project_common_headers}) ${project_common_headers})
# Build the main executable and link it
add_definitions (-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_38)
if (NOT WIN32)
add_executable (${PROJECT_NAME}
${project_sources} ${project_headers} ${project_common_sources})
target_link_libraries (${PROJECT_NAME} ${project_common_libraries}
${Ncursesw_LIBRARIES} termo-static)
if (WITH_X11)
target_link_libraries (${PROJECT_NAME} ${xcb_LIBRARIES})
endif ()
endif (NOT WIN32)
# The same for the alternative GTK+ UI
if (NOT ${CMAKE_VERSION} VERSION_LESS 3.18.0)
set (find_program_REQUIRE REQUIRED)
endif ()
function (icon_to_png svg size output_dir output)
set (_dimensions ${size}x${size})
set (_png_path ${output_dir}/hicolor/${_dimensions}/apps)
set (_png ${_png_path}/sdgui.png)
set (${output} ${_png} PARENT_SCOPE)
find_program (rsvg_convert_EXECUTABLE rsvg-convert ${find_program_REQUIRE})
add_custom_command (OUTPUT ${_png}
COMMAND ${CMAKE_COMMAND} -E make_directory ${_png_path}
COMMAND ${rsvg_convert_EXECUTABLE} --output=${_png}
--width=${size} --height=${size} ${svg}
DEPENDS ${svg}
COMMENT "Generating ${_dimensions} application icon" VERBATIM)
endfunction ()
function (icon_for_win32 pngs ico)
find_program (icotool_EXECUTABLE icotool ${find_program_REQUIRE})
add_custom_command (OUTPUT ${ico}
COMMAND ${icotool_EXECUTABLE} -c -o ${ico} ${pngs}
DEPENDS ${pngs}
COMMENT "Generating Windows program icon" VERBATIM)
endfunction ()
if (WITH_GUI) if (WITH_GUI)
set (icon_svg ${PROJECT_SOURCE_DIR}/sdgui.svg) include (IconUtils)
set (icon_base ${PROJECT_BINARY_DIR}/icons)
# The largest size is mainly for an appropriately sized Windows icon # The largest size is mainly for an appropriately sized Windows icon
set (icon_base "${PROJECT_BINARY_DIR}/icons")
set (icon_png_list) set (icon_png_list)
foreach (icon_size 16 32 48 256) foreach (icon_size 16 32 48 256)
icon_to_png (${icon_svg} ${icon_size} ${icon_base} icon_png) icon_to_png (${PROJECT_NAME} "${PROJECT_SOURCE_DIR}/${PROJECT_NAME}.svg"
list (APPEND icon_png_list ${icon_png}) ${icon_size} "${icon_base}" icon_png)
list (APPEND icon_png_list "${icon_png}")
endforeach () endforeach ()
add_custom_target (sdgui-icons ALL DEPENDS ${icon_png_list})
set (sdgui_sources add_custom_target (icons ALL DEPENDS ${icon_png_list})
src/sdgui.c
src/stardict-view.c
${project_common_sources})
if (WIN32)
set (icon_ico ${PROJECT_BINARY_DIR}/sdgui.ico)
icon_for_win32 ("${icon_png_list}" ${icon_ico})
set (resource_file ${PROJECT_BINARY_DIR}/sdgui.rc)
list (APPEND sdgui_sources ${resource_file})
add_custom_command (OUTPUT ${resource_file}
COMMAND ${CMAKE_COMMAND} -E echo "1 ICON \"sdgui.ico\""
> ${resource_file} VERBATIM)
set_property (SOURCE ${resource_file}
APPEND PROPERTY OBJECT_DEPENDS ${icon_ico})
endif ()
add_executable (sdgui WIN32 ${sdgui_sources})
target_include_directories (sdgui PUBLIC ${gtk_INCLUDE_DIRS})
target_link_libraries (sdgui ${project_common_libraries} ${gtk_LIBRARIES})
endif () endif ()
if (WIN32)
list (REMOVE_ITEM icon_png_list "${icon_png}")
set (icon_ico "${PROJECT_BINARY_DIR}/${PROJECT_NAME}.ico")
icon_for_win32 ("${icon_ico}" "${icon_png_list}" "${icon_png}")
set (resource_file "${PROJECT_BINARY_DIR}/${PROJECT_NAME}.rc")
list (APPEND project_sources "${resource_file}")
add_custom_command (OUTPUT "${resource_file}"
COMMAND ${CMAKE_COMMAND} -E echo "1 ICON \"${PROJECT_NAME}.ico\""
> "${resource_file}" VERBATIM)
set_property (SOURCE "${resource_file}"
APPEND PROPERTY OBJECT_DEPENDS "${icon_ico}")
else ()
list (APPEND project_libraries ${Ncursesw_LIBRARIES} ${Termo_LIBRARIES})
list (APPEND project_sources
src/${PROJECT_NAME}-tui.c)
endif ()
if (WITH_X11)
list (APPEND project_libraries ${xcb_LIBRARIES})
endif ()
if (WITH_GUI)
list (APPEND project_libraries ${gtk_LIBRARIES})
list (APPEND project_sources
src/${PROJECT_NAME}-gui.c
src/stardict-view.c)
add_executable (${PROJECT_NAME} WIN32 ${project_sources} ${project_headers})
else ()
add_executable (${PROJECT_NAME} ${project_sources} ${project_headers})
endif ()
target_link_libraries (${PROJECT_NAME} ${project_libraries})
# Tools # Tools
set (tools tabfile add-pronunciation query-tool transform) set (tools tdv-tabfile tdv-add-pronunciation tdv-query-tool tdv-transform)
foreach (tool ${tools}) foreach (tool ${tools})
add_executable (${tool} EXCLUDE_FROM_ALL add_executable (${tool} EXCLUDE_FROM_ALL
src/${tool}.c ${project_common_sources}) src/${tool}.c ${project_common_sources})
target_link_libraries (${tool} ${project_common_libraries}) target_link_libraries (${tool} ${project_common_libraries})
endforeach () endforeach ()
add_custom_target (tools DEPENDS ${tools}) option (WITH_TOOLS "Build and install some StarDict tools" ${UNIX})
if (WITH_TOOLS)
add_custom_target (tools ALL DEPENDS ${tools})
endif ()
# Example dictionaries # Example dictionaries
file (GLOB dicts_scripts "${PROJECT_SOURCE_DIR}/dicts/*.*") file (GLOB dicts_scripts "${PROJECT_SOURCE_DIR}/dicts/*.*")
@@ -288,7 +281,7 @@ foreach (dict_script ${dicts_scripts})
list (APPEND dicts_targets "dicts-${dict_name}") list (APPEND dicts_targets "dicts-${dict_name}")
add_custom_target (dicts-${dict_name} add_custom_target (dicts-${dict_name}
COMMAND sh -c "PATH=.:$PATH \"$0\"" "${dict_script}" COMMAND sh -c "PATH=.:$PATH \"$0\"" "${dict_script}"
DEPENDS tabfile DEPENDS tdv-tabfile
COMMENT "Generating sample dictionary ${dict_name}" COMMENT "Generating sample dictionary ${dict_name}"
VERBATIM) VERBATIM)
endforeach () endforeach ()
@@ -301,15 +294,17 @@ if (NOT WIN32)
install (TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR}) install (TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})
install (FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR}) install (FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR})
if (WITH_TOOLS)
install (TARGETS ${tools} DESTINATION ${CMAKE_INSTALL_BINDIR})
endif ()
if (WITH_GUI) if (WITH_GUI)
install (TARGETS sdgui DESTINATION ${CMAKE_INSTALL_BINDIR}) install (FILES ${PROJECT_NAME}.svg
install (FILES sdgui.svg
DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/scalable/apps) DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/scalable/apps)
install (DIRECTORY ${PROJECT_BINARY_DIR}/icons install (DIRECTORY ${icon_base}
DESTINATION ${CMAKE_INSTALL_DATADIR}) DESTINATION ${CMAKE_INSTALL_DATADIR})
install (FILES sdgui.desktop install (FILES ${PROJECT_NAME}.desktop
DESTINATION ${CMAKE_INSTALL_DATADIR}/applications) DESTINATION ${CMAKE_INSTALL_DATADIR}/applications)
install (FILES sdgui.xml install (FILES ${PROJECT_NAME}.xml
DESTINATION ${CMAKE_INSTALL_DATADIR}/mime/packages) DESTINATION ${CMAKE_INSTALL_DATADIR}/mime/packages)
endif () endif ()
@@ -320,7 +315,7 @@ if (NOT WIN32)
endforeach () endforeach ()
elseif (WITH_GUI) elseif (WITH_GUI)
# This rather crude filter has been mostly copied over from logdiag # This rather crude filter has been mostly copied over from logdiag
install (TARGETS sdgui DESTINATION .) install (TARGETS ${PROJECT_NAME} DESTINATION .)
install (DIRECTORY install (DIRECTORY
${win32_deps_prefix}/bin/ ${win32_deps_prefix}/bin/
DESTINATION . DESTINATION .
@@ -342,7 +337,7 @@ elseif (WITH_GUI)
install (FILES install (FILES
${win32_deps_prefix}/share/icons/hicolor/index.theme ${win32_deps_prefix}/share/icons/hicolor/index.theme
DESTINATION share/icons/hicolor) DESTINATION share/icons/hicolor)
install (DIRECTORY ${icon_base} DESTINATION share) install (DIRECTORY "${icon_base}" DESTINATION share)
install (SCRIPT cmake/Win32Cleanup.cmake) install (SCRIPT cmake/Win32Cleanup.cmake)
@@ -361,34 +356,40 @@ endif ()
# Do some unit tests # Do some unit tests
option (BUILD_TESTING "Build tests" OFF) option (BUILD_TESTING "Build tests" OFF)
set (project_tests stardict)
if (BUILD_TESTING) if (BUILD_TESTING)
enable_testing () enable_testing ()
find_program (xmlwf_EXECUTABLE xmlwf) find_program (xmlwf_EXECUTABLE xmlwf)
find_program (xmllint_EXECUTABLE xmllint) find_program (xmllint_EXECUTABLE xmllint)
foreach (xml sdgui.xml) foreach (xml ${PROJECT_NAME}.xml ${PROJECT_NAME}.svg)
if (xmlwf_EXECUTABLE) if (xmlwf_EXECUTABLE)
add_test (test-xmlwf-${xml} ${xmlwf_EXECUTABLE} add_test (test-xmlwf-${xml} ${xmlwf_EXECUTABLE}
${PROJECT_SOURCE_DIR}/${xml}) "${PROJECT_SOURCE_DIR}/${xml}")
endif () endif ()
if (xmllint_EXECUTABLE) if (xmllint_EXECUTABLE)
add_test (test-xmllint-${xml} ${xmllint_EXECUTABLE} --noout add_test (test-xmllint-${xml} ${xmllint_EXECUTABLE} --noout
${PROJECT_SOURCE_DIR}/${xml}) "${PROJECT_SOURCE_DIR}/${xml}")
endif () endif ()
endforeach () endforeach ()
foreach (name ${project_tests}) find_program (dfv_EXECUTABLE desktop-file-validate)
if (dfv_EXECUTABLE)
foreach (df ${PROJECT_NAME}.desktop)
add_test (test-dfv-${df} ${dfv_EXECUTABLE}
"${PROJECT_SOURCE_DIR}/${df}")
endforeach ()
endif ()
foreach (name stardict)
add_executable (test-${name} add_executable (test-${name}
src/test-${name}.c ${project_common_sources}) src/test-${name}.c ${project_common_sources})
target_link_libraries (test-${name} ${project_common_libraries}) target_link_libraries (test-${name} ${project_common_libraries})
add_test (test-${name} test-${name}) add_test (NAME test-${name} COMMAND test-${name})
endforeach () endforeach ()
endif () endif ()
# CPack # CPack
set (CPACK_PACKAGE_DESCRIPTION_SUMMARY "StarDict TUI and GUI") set (CPACK_PACKAGE_DESCRIPTION_SUMMARY "Translation dictionary viewer")
set (CPACK_PACKAGE_VENDOR "Premysl Eric Janouch") set (CPACK_PACKAGE_VENDOR "Premysl Eric Janouch")
set (CPACK_PACKAGE_CONTACT "Přemysl Eric Janouch <p@janouch.name>") set (CPACK_PACKAGE_CONTACT "Přemysl Eric Janouch <p@janouch.name>")
set (CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE") set (CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE")
@@ -404,17 +405,17 @@ set (CPACK_SOURCE_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}")
set (CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON) set (CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON)
set (CPACK_PACKAGE_INSTALL_REGISTRY_KEY "${PROJECT_NAME}") set (CPACK_PACKAGE_INSTALL_REGISTRY_KEY "${PROJECT_NAME}")
set (CPACK_NSIS_INSTALLED_ICON_NAME sdgui.exe) set (CPACK_NSIS_INSTALLED_ICON_NAME ${PROJECT_NAME}.exe)
set (CPACK_PACKAGE_EXECUTABLES sdgui sdgui) set (CPACK_PACKAGE_EXECUTABLES ${PROJECT_NAME} ${PROJECT_NAME})
set (CPACK_NSIS_EXECUTABLES_DIRECTORY .) set (CPACK_NSIS_EXECUTABLES_DIRECTORY .)
set (CPACK_NSIS_EXTRA_INSTALL_COMMANDS [[ set (CPACK_NSIS_EXTRA_INSTALL_COMMANDS [[
WriteRegStr HKCR '.ifo' '' 'sdgui.Dictionary' WriteRegStr HKCR '.ifo' '' 'tdv.Dictionary'
WriteRegStr HKCR 'sdgui.Dictionary' '' 'StarDict Dictionary' WriteRegStr HKCR 'tdv.Dictionary' '' 'StarDict Dictionary'
WriteRegStr HKCR 'sdgui.Dictionary\\shell\\open\\command' '' '\"$INSTDIR\\sdgui.exe\" \"%1\"' WriteRegStr HKCR 'tdv.Dictionary\\shell\\open\\command' '' '\"$INSTDIR\\tdv.exe\" \"%1\"'
System::Call 'shell32::SHChangeNotify(i,i,i,i) (0x08000000, 0x1000, 0, 0)' System::Call 'shell32::SHChangeNotify(i,i,i,i) (0x08000000, 0x1000, 0, 0)'
]]) ]])
set (CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS [[ set (CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS [[
DeleteRegKey HKCR 'sdgui.Dictionary' DeleteRegKey HKCR 'tdv.Dictionary'
System::Call 'shell32::SHChangeNotify(i,i,i,i) (0x08000000, 0x1000, 0, 0)' System::Call 'shell32::SHChangeNotify(i,i,i,i) (0x08000000, 0x1000, 0, 0)'
]]) ]])

View File

@@ -1,4 +1,4 @@
Copyright (c) 2013 - 2022, Přemysl Eric Janouch <p@janouch.name> Copyright (c) 2013 - 2024, Přemysl Eric Janouch <p@janouch.name>
Permission to use, copy, modify, and/or distribute this software for any Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted. purpose with or without fee is hereby granted.

View File

@@ -1,29 +1,33 @@
StarDict Terminal and Graphical UI Translation dictionary viewer
================================== =============================
'sdtui' aims to provide an easy way of viewing translation as well as other 'tdv' aims to provide an easy way of viewing translation as well as other kinds
kinds of dictionaries in your terminal, and is inspired by the dictionary of StarDict dictionaries, and is inspired by the dictionary component
component of PC Translator. I wasn't successful in finding any free software of PC Translator. I was unsuccessful in finding any free software of this kind,
of this kind, GUI or not, and thus decided to write my own. and thus decided to write my own.
The program offers both a terminal user interface, and a GTK+ 3 based UI.
The styling of the latter will follow your theme, and may be customized
from 'gtk.css'.
The project is covered by a permissive license, unlike vast majority of other The project is covered by a permissive license, unlike vast majority of other
similar projects, and can serve as a base for implementing other dictionary similar projects, and can serve as a base for implementing other dictionary
software. software.
image::sdtui.png[align="center"] Screenshot
----------
As a recent addition, there is now an alternative GTK+ 3 based frontend as well, image::tdv.png[align="center"]
called 'sdgui'. It shares its dictionary list with 'sdtui', but styling will
follow your theme, and may be customized from 'gtk.css'.
Packages Packages
-------- --------
Regular releases are sporadic. git master should be stable enough. You can get Regular releases are sporadic. git master should be stable enough.
a package with the latest development version from Archlinux's AUR. You can get a package with the latest development version using Arch Linux's
https://aur.archlinux.org/packages/tdv-git[AUR],
or as a https://git.janouch.name/p/nixexprs[Nix derivation].
Documentation Documentation
------------- -------------
See the link:docs/sdtui.1.adoc[man page] for information about usage. See the link:docs/tdv.1.adoc[man page] for information about usage.
The rest of this README will concern itself with externalities. The rest of this README will concern itself with externalities.
Building and Running Building and Running
@@ -37,9 +41,9 @@ Runtime dependencies:
Optional runtime dependencies: Optional runtime dependencies:
xcb, xcb-xfixes (the first two for the TUI), gtk+-3.0 (for the GUI) xcb, xcb-xfixes (the first two for the TUI), gtk+-3.0 (for the GUI)
$ git clone --recursive https://git.janouch.name/p/sdtui.git $ git clone --recursive https://git.janouch.name/p/tdv.git
$ mkdir sdtui/build $ mkdir tdv/build
$ cd sdtui/build $ cd tdv/build
$ cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug \ $ cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug \
-DWITH_X11=ON -DWITH_GUI=ON -DWITH_X11=ON -DWITH_GUI=ON
$ make $ make
@@ -51,22 +55,22 @@ To install the application, you can do either the usual:
Or you can try telling CMake to make a package for you. For Debian it is: Or you can try telling CMake to make a package for you. For Debian it is:
$ cpack -G DEB $ cpack -G DEB
# dpkg -i sdtui-*.deb # dpkg -i tdv-*.deb
Having the program installed, simply run it with a StarDict '.ifo' file as Having the program installed, simply run it with a StarDict '.ifo' file as
an argument. It is, however, preferable to an argument. It is, however, preferable to
link:docs/sdtui.1.adoc#_configuration[configure it] to load your dictionaries link:docs/tdv.1.adoc#_configuration[configure it] to load your dictionaries
automatically. automatically.
Windows Windows
~~~~~~~ ~~~~~~~
With the help of Mingw-w64 and WINE, 'sdgui' will successfully cross-compile With the help of Mingw-w64 and WINE, 'tdv' will successfully cross-compile
for Windows. It isn't particularly usable on that system, if only because for Windows. It isn't particularly usable on that system, if only because
selection watching is a very X11/Wayland-specific feature. Beware that build selection watching is a very X11/Wayland-specific feature. Beware that build
dependencies take up almost a gigabyte of disk space. dependencies take up almost a gigabyte of disk space.
$ sh -e cmake/Win64Depends.sh $ sh -e cmake/Win64Depends.sh
$ cmake -DCMAKE_TOOLCHAIN_FILE=cmake/Win64CrossToolchain.cmake \ $ cmake -DCMAKE_TOOLCHAIN_FILE=liberty/cmake/toolchains/MinGW-w64-x64.cmake \
-DCMAKE_BUILD_TYPE=Release -B build -DCMAKE_BUILD_TYPE=Release -B build
$ cmake --build build -- package $ cmake --build build -- package
@@ -82,27 +86,21 @@ The `make dicts` command will build some examples from freely available sources:
- Czech foreign words (the site's export is broken as of 2022/08, no response) - Czech foreign words (the site's export is broken as of 2022/08, no response)
- Czech WordNet 1.9 PDT (synonyms, hypernyms, hyponyms) - Czech WordNet 1.9 PDT (synonyms, hypernyms, hyponyms)
You can use the included 'transform' tool to convert already existing StarDict You can use the included 'tdv-transform' tool to convert already existing
dictionaries that are nearly good as they are. Remember that you can change StarDict dictionaries that are nearly good as they are. Remember that you can
the `sametypesequence` of the resulting '.ifo' file to another format, or run change the `sametypesequence` of the resulting '.ifo' file to another format,
'dictzip' on '.dict' files to make them compact. or run 'dictzip' on '.dict' files to make them compact.
https://mega.co.nz/#!axtD0QRK!sbtBgizksyfkPqKvKEgr8GQ11rsWhtqyRgUUV0B7pwg[CZ <--> EN/DE/PL/RU dictionaries] https://mega.co.nz/#!axtD0QRK!sbtBgizksyfkPqKvKEgr8GQ11rsWhtqyRgUUV0B7pwg[CZ <--> EN/DE/PL/RU dictionaries]
Further Development Further Development
------------------- -------------------
While I've been successfully using 'sdtui' for many years now, some issues Lacking configuration, standard StarDict locations should be scanned.
should be addressed before including the software in regular Linux and/or We should try harder to display arbitrary dictionaries sensibly.
BSD distributions:
- The GUI is awkward to configure.
- Lacking configuration, standard StarDict locations should be scanned.
Given all issues with the file format, it might be better to start anew.
Contributing and Support Contributing and Support
------------------------ ------------------------
Use https://git.janouch.name/p/sdtui to report any bugs, request features, Use https://git.janouch.name/p/tdv to report any bugs, request features,
or submit pull requests. `git send-email` is tolerated. If you want to discuss or submit pull requests. `git send-email` is tolerated. If you want to discuss
the project, feel free to join me at ircs://irc.janouch.name, channel #dev. the project, feel free to join me at ircs://irc.janouch.name, channel #dev.

View File

@@ -1,17 +0,0 @@
# Public Domain
find_package (PkgConfig REQUIRED)
pkg_check_modules (Ncursesw QUIET ncursesw)
# OpenBSD doesn't provide a pkg-config file
set (required_vars Ncursesw_LIBRARIES)
if (NOT Ncursesw_FOUND)
find_library (Ncursesw_LIBRARIES NAMES ncursesw)
find_path (Ncursesw_INCLUDE_DIRS ncurses.h)
list (APPEND required_vars Ncursesw_INCLUDE_DIRS)
endif (NOT Ncursesw_FOUND)
include (FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS (Ncursesw DEFAULT_MSG ${required_vars})
mark_as_advanced (Ncursesw_LIBRARIES Ncursesw_INCLUDE_DIRS)

View File

@@ -1,15 +0,0 @@
set (CMAKE_SYSTEM_NAME "Windows")
set (CMAKE_SYSTEM_PROCESSOR "x86_64")
set (CMAKE_C_COMPILER "x86_64-w64-mingw32-gcc")
set (CMAKE_CXX_COMPILER "x86_64-w64-mingw32-g++")
set (CMAKE_RC_COMPILER "x86_64-w64-mingw32-windres")
# Not needed to crosscompile an installation package
#set (CMAKE_CROSSCOMPILING_EMULATOR "wine64")
set (CMAKE_FIND_ROOT_PATH "/usr/x86_64-w64-mingw32")
set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

View File

@@ -27,7 +27,8 @@ fetch() {
} BEGIN { while ((getline < "db.tsv") > 0) { } BEGIN { while ((getline < "db.tsv") > 0) {
filenames[$1] = $2; deps[$1] = ""; for (i = 3; i <= NF; i++) { filenames[$1] = $2; deps[$1] = ""; for (i = 3; i <= NF; i++) {
gsub(/[<=>].*/, "", $i); deps[$1] = deps[$1] $i FS } gsub(/[<=>].*/, "", $i); deps[$1] = deps[$1] $i FS }
} for (i = 0; i < ARGC; i++) get(ARGV[i]) }' "$@" | while IFS= read -r name } for (i = 0; i < ARGC; i++) get(ARGV[i]) }' "$@" | tee db.want | \
while IFS= read -r name
do do
status Fetching "$name" status Fetching "$name"
[ -f "packages/$name" ] || curl -#o "packages/$name" "$repository/$name" [ -f "packages/$name" ] || curl -#o "packages/$name" "$repository/$name"
@@ -44,9 +45,9 @@ extract() {
for subdir in * for subdir in *
do [ -d "$subdir" -a "$subdir" != packages ] && rm -rf -- "$subdir" do [ -d "$subdir" -a "$subdir" != packages ] && rm -rf -- "$subdir"
done done
for i in packages/* while IFS= read -r name
do bsdtar -xf "$i" --strip-components 1 mingw64 do bsdtar -xf "packages/$name" --strip-components 1
done done < db.want
} }
configure() { configure() {

View File

@@ -8,6 +8,7 @@
#define GETTEXT_DIRNAME "${CMAKE_INSTALL_PREFIX}/share/locale" #define GETTEXT_DIRNAME "${CMAKE_INSTALL_PREFIX}/share/locale"
#cmakedefine WITH_X11 #cmakedefine WITH_X11
#cmakedefine WITH_GUI
#cmakedefine HAVE_RESIZETERM #cmakedefine HAVE_RESIZETERM
#endif // ! CONFIG_H #endif // ! CONFIG_H

View File

@@ -55,7 +55,7 @@ while (my ($id, $synset) = each %synsets) {
# Output synsets exploded to individual words, with expanded relationships # Output synsets exploded to individual words, with expanded relationships
close($doc) or die $?; close($doc) or die $?;
open(my $tabfile, '|-', 'tabfile', 'czech-wordnet', open(my $tabfile, '|-', 'tdv-tabfile', 'czech-wordnet',
'--book-name=Czech WordNet 1.9 PDT', "--website=$base/$path", '--book-name=Czech WordNet 1.9 PDT', "--website=$base/$path",
'--date=2011-01-24', '--collation=cs_CZ') or die $!; '--date=2011-01-24', '--collation=cs_CZ') or die $!;

View File

@@ -9,7 +9,7 @@ grep -v ^# | sed 's/\\//g' | perl -CSD -F\\t -le '
sub tabesc { shift =~ s/\\/\\\\/gr =~ s/\n/\\n/gr =~ s/\t/\\t/gr } sub tabesc { shift =~ s/\\/\\\\/gr =~ s/\n/\\n/gr =~ s/\t/\\t/gr }
sub w { sub w {
my ($name, $dict, $collation) = @_; my ($name, $dict, $collation) = @_;
open(my $f, "|-", "tabfile", "--pango", "--collation=$collation", open(my $f, "|-", "tdv-tabfile", "--pango", "--collation=$collation",
"--website=https://gnu.nemeckoceskyslovnik.cz", "--website=https://gnu.nemeckoceskyslovnik.cz",
"gnu-fdl-$name") or die $!; "gnu-fdl-$name") or die $!;
print $f tabesc($keyword) . "\t" . tabesc(join("\n", @$defs)) print $f tabesc($keyword) . "\t" . tabesc(join("\n", @$defs))

View File

@@ -5,7 +5,7 @@ zcat | grep -v ^# | sed 's/\\//g' | perl -CSD -F\\t -le '
sub tabesc { shift =~ s/\\/\\\\/gr =~ s/\n/\\n/gr =~ s/\t/\\t/gr } sub tabesc { shift =~ s/\\/\\\\/gr =~ s/\n/\\n/gr =~ s/\t/\\t/gr }
sub w { sub w {
my ($name, $dict, $collation) = @_; my ($name, $dict, $collation) = @_;
open(my $f, "|-", "tabfile", "--pango", "--collation=$collation", open(my $f, "|-", "tdv-tabfile", "--pango", "--collation=$collation",
"--website=https://www.svobodneslovniky.cz", "--website=https://www.svobodneslovniky.cz",
"gnu-fdl-$name") or die $!; "gnu-fdl-$name") or die $!;
print $f tabesc($keyword) . "\t" . tabesc(join("\n", @$defs)) print $f tabesc($keyword) . "\t" . tabesc(join("\n", @$defs))

View File

@@ -4,7 +4,7 @@
curl -Lo- https://slovnik-cizich-slov.abz.cz/export.php | \ curl -Lo- https://slovnik-cizich-slov.abz.cz/export.php | \
iconv -f latin2 -t UTF-8 | perl -CSD -F\\\| -le ' iconv -f latin2 -t UTF-8 | perl -CSD -F\\\| -le '
print "$_\t" . $F[2] =~ s/\\/\\\\/gr =~ s/; /\\n/gr for split(", ", $F[0]) print "$_\t" . $F[2] =~ s/\\/\\\\/gr =~ s/; /\\n/gr for split(", ", $F[0])
' | sort -u | tabfile slovnik-cizich-slov \ ' | sort -u | tdv-tabfile slovnik-cizich-slov \
--book-name="Slovník cizích slov" \ --book-name="Slovník cizích slov" \
--website=https://slovnik-cizich-slov.abz.cz \ --website=https://slovnik-cizich-slov.abz.cz \
--date="$(date +%F)" \ --date="$(date +%F)" \

View File

@@ -1,21 +1,21 @@
sdtui(1) tdv(1)
======== ======
:doctype: manpage :doctype: manpage
:manmanual: sdtui Manual :manmanual: tdv Manual
:mansource: sdtui {release-version} :mansource: tdv {release-version}
Name Name
---- ----
sdtui - StarDict terminal UI tdv - Translation dictionary viewer
Synopsis Synopsis
-------- --------
*sdtui* [_OPTION_]... [_DICTIONARY_.ifo]... *tdv* [_OPTION_]... [_DICTIONARY_.ifo]...
Description Description
----------- -----------
*sdtui* is a StarDict dictionary viewer, custom-tailored for translation *tdv* is a StarDict dictionary viewer, custom-tailored for translation
dictionaries, with a simple curses-based terminal UI. dictionaries, with a simple curses-based terminal UI, and a GTK+ graphical UI.
Without any command line arguments, the program expects to find a list of Without any command line arguments, the program expects to find a list of
dictionaries to load on start-up in its configuration file. The _.ifo_ files dictionaries to load on start-up in its configuration file. The _.ifo_ files
@@ -24,6 +24,9 @@ database files.
Options Options
------- -------
*--gui*::
Launch the GUI even when run from a terminal.
*-h*, *--help*:: *-h*, *--help*::
Display a help message and exit. Display a help message and exit.
@@ -32,7 +35,7 @@ Options
Configuration Configuration
------------- -------------
You can start your _sdtui.conf_ file with the following snippet: You can start your _tdv.conf_ file with the following snippet:
[Settings] [Settings]
center-search = true # Ensure visibility of preceding entries? center-search = true # Ensure visibility of preceding entries?
@@ -75,21 +78,21 @@ Extensions
---------- ----------
Because the StarDict file format is a bit of a clusterfuck with regard to Because the StarDict file format is a bit of a clusterfuck with regard to
collation of dictionary entries, this software introduces an additional, collation of dictionary entries, this software introduces an additional,
optional "collation" field into the '.ifo' file. When *sdtui* discovers this optional "collation" field into the _.ifo_ file. When *tdv* discovers this
field while reading a dictionary, it automatically reorders the index according field while reading a dictionary, it automatically reorders the index according
to that locale (e.g., "cs_CZ"). This operation may take a little while, to that locale (e.g., "cs_CZ"). This operation may take a little while,
in the order of seconds. in the order of seconds.
Files Files
----- -----
*sdtui* follows the XDG Base Directory Specification. *tdv* follows the XDG Base Directory Specification.
_~/.config/sdtui/sdtui.conf_:: _~/.config/tdv/tdv.conf_::
The configuration file. The configuration file.
Reporting bugs Reporting bugs
-------------- --------------
Use https://git.janouch.name/p/sdtui to report bugs, request features, Use https://git.janouch.name/p/tdv to report bugs, request features,
or submit pull requests. or submit pull requests.
See also See also

1
liberty Submodule

Submodule liberty added at 0f20cce9c8

102
po/cs.po
View File

@@ -1,84 +1,95 @@
# SOME DESCRIPTIVE TITLE. # SOME DESCRIPTIVE TITLE.
# Copyright (C) 2013 Přemysl Eric Janouch # Copyright (C) 2013 Přemysl Eric Janouch
# This file is distributed under the same license as the sdtui package. # This file is distributed under the same license as the tdv package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: sdtui 0.1.0\n" "Project-Id-Version: tdv 0.1.0\n"
"Report-Msgid-Bugs-To: https://git.janouch.name/p/sdtui/issues\n" "Report-Msgid-Bugs-To: https://git.janouch.name/p/tdv/issues\n"
"POT-Creation-Date: 2021-10-11 21:10+0200\n" "POT-Creation-Date: 2023-06-11 17:47+0200\n"
"PO-Revision-Date: 2016-09-28 16:15+0200\n" "PO-Revision-Date: 2023-06-11 17:53+0200\n"
"Last-Translator: Přemysl Eric Janouch <p@janouch.name>\n" "Last-Translator: Přemysl Eric Janouch <p@janouch.name>\n"
"Language-Team: Czech <translation-team-cs@lists.sourceforge.net>\n" "Language-Team: Czech <translation-team-cs@lists.sourceforge.net>\n"
"Language: cs\n" "Language: cs\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.8.9\n" "X-Generator: Poedit 3.3.1\n"
#: ../src/sdgtk.c:304 #: ../src/tdv-tui.c:572
msgid "- StarDict GTK+ UI"
msgstr ""
#: ../src/sdtui.c:726
msgid "Cannot load configuration" msgid "Cannot load configuration"
msgstr "Nemohu načíst konfiguraci" msgstr "Nemohu načíst konfiguraci"
#: ../src/sdtui.c:2497 #: ../src/tdv.c:77
msgid "Error" msgid "Error"
msgstr "Chyba" msgstr "Chyba"
#: ../src/sdtui.c:745 #: ../src/tdv-tui.c:592
msgid "Error loading dictionary" msgid "Error loading dictionary"
msgstr "Chyba při načítání slovníku" msgstr "Chyba při načítání slovníku"
#: ../src/sdgtk.c:299 #: ../src/tdv.c:60
msgid "FILE..." msgid "Launch the GUI even when run from a terminal"
msgstr "" msgstr "Spustit GUI i při běhu z terminálu"
#: ../src/sdgtk.c:355 #: ../src/tdv-gui.c:467 ../src/tdv-tui.c:597
msgid "Follow selection" msgid "No dictionaries found either in the configuration or on the command line"
msgstr ""
#: ../src/sdtui.c:750
msgid ""
"No dictionaries found either in the configuration or on the command line"
msgstr "V konfiguraci ani na příkazové řádce nebyly nalezeny žádné slovníky" msgstr "V konfiguraci ani na příkazové řádce nebyly nalezeny žádné slovníky"
#: ../src/sdtui.c:2476 #: ../src/tdv-gui.c:367
msgid "Open dictionary"
msgstr "Otevřít slovník"
#: ../src/tdv.c:55
msgid "Output version information and exit" msgid "Output version information and exit"
msgstr "Vypíše informace o verzi a ukončí se" msgstr "Vypíše informace o verzi a ukončí se"
#: ../src/sdtui.c:700 #: ../src/tdv-tui.c:555
msgid "Search" msgid "Search"
msgstr "Hledat" msgstr "Hledat"
#: ../src/sdtui.c:1114 #: ../src/tdv-tui.c:1068
msgid "Terminal UI for StarDict dictionaries" msgid "Terminal UI for StarDict dictionaries"
msgstr "Terminálové UI pro stardictové slovníky" msgstr "Terminálové UI pro stardictové slovníky"
#: ../src/sdtui.c:1117 #: ../src/tdv-tui.c:1071
msgid "Type to search" msgid "Type to search"
msgstr "Zadejte vyhledávaný výraz" msgstr "Zadejte vyhledávaný výraz"
#: ../src/sdgtk.c:289 ../src/sdtui.c:2481 #: ../src/tdv.c:39
msgid "Warning" msgid "Warning"
msgstr "Varování" msgstr "Varování"
#: ../src/sdtui.c:2095 #: ../src/tdv-tui.c:2071
#, c-format #, c-format
msgid "X11 connection failed (error code %d)" msgid "X11 connection failed (error code %d)"
msgstr "" msgstr "Spojení s X11 selhalo (chybový kód %d)"
#: ../src/sdtui.c:2241 #: ../src/tdv-tui.c:2217
#, c-format #, c-format
msgid "X11 request error (%d, major %d, minor %d)" msgid "X11 request error (%d, major %d, minor %d)"
msgstr "" msgstr "Chyba X11 požadavku (%d, major %d, minor %d)"
#: ../src/sdtui.c:2489 #: ../src/tdv.c:67
msgid "[dictionary.ifo...] - StarDict terminal UI" msgid "[dictionary.ifo...] - Translation dictionary viewer"
msgstr "[slovník.ifo...] - terminálové UI pro StarDict" msgstr "[slovník.ifo...] - Prohlížeč překladových slovníků"
#: ../src/tdv-gui.c:369
msgid "_Cancel"
msgstr "_Storno"
#: ../src/tdv-gui.c:509
msgid "_Follow selection"
msgstr "_Sledovat výběr"
#: ../src/tdv-gui.c:370
msgid "_Open"
msgstr "_Otevřít"
#: ../src/tdv-gui.c:504
msgid "_Open..."
msgstr "_Otevřít..."
#: ../src/stardict.c:850 #: ../src/stardict.c:850
msgid "cannot find .dict file" msgid "cannot find .dict file"
@@ -88,19 +99,19 @@ msgstr "nemohu najít .dict soubor"
msgid "cannot find .idx file" msgid "cannot find .idx file"
msgstr "nemohu najít .idx soubor" msgstr "nemohu najít .idx soubor"
#: ../src/sdtui.c:320 #: ../src/tdv-tui.c:258
msgid "error in entry" msgid "error in entry"
msgstr "chyba v záznamu" msgstr "chyba v záznamu"
#: ../src/sdgtk.c:289 ../src/sdtui.c:2481 #: ../src/tdv.c:39
msgid "failed to set the locale" msgid "failed to set the locale"
msgstr "selhalo nastavení locale" msgstr "selhalo nastavení locale"
#: ../src/stardict.c:330 #: ../src/stardict.c:328
msgid "index file size not specified" msgid "index file size not specified"
msgstr "nebyla určena velikost rejstříku" msgstr "nebyla určena velikost rejstříku"
#: ../src/stardict.c:1153 ../src/stardict.c:1178 #: ../src/stardict.c:1157 ../src/stardict.c:1182
msgid "invalid data entry" msgid "invalid data entry"
msgstr "neplatná datová položka" msgstr "neplatná datová položka"
@@ -112,7 +123,7 @@ msgstr "neplatné kódování, musí být validní UTF-8"
msgid "invalid header format" msgid "invalid header format"
msgstr "neplatný formát hlavičky" msgstr "neplatný formát hlavičky"
#: ../src/stardict.c:339 #: ../src/stardict.c:337
msgid "invalid index offset bits" msgid "invalid index offset bits"
msgstr "neplatný počet bitů pro offset v rejstříku" msgstr "neplatný počet bitů pro offset v rejstříku"
@@ -124,11 +135,11 @@ msgstr "neplatné číslo"
msgid "invalid version" msgid "invalid version"
msgstr "neplatná verze" msgstr "neplatná verze"
#: ../src/stardict.c:318 #: ../src/stardict.c:316
msgid "no book name specified" msgid "no book name specified"
msgstr "nebyl určen název knihy" msgstr "nebyl určen název knihy"
#: ../src/sdtui.c:415 #: ../src/stardict-view.c:96 ../src/tdv-tui.c:340
msgid "no usable field found" msgid "no usable field found"
msgstr "nenalezeno žádné použitelné pole" msgstr "nenalezeno žádné použitelné pole"
@@ -136,7 +147,7 @@ msgstr "nenalezeno žádné použitelné pole"
msgid "option format error" msgid "option format error"
msgstr "chyba v zápisu volby" msgstr "chyba v zápisu volby"
#: ../src/sdtui.c:2497 #: ../src/tdv.c:77
msgid "option parsing failed" msgid "option parsing failed"
msgstr "zpracování přepínačů selhalo" msgstr "zpracování přepínačů selhalo"
@@ -148,6 +159,9 @@ msgstr "neznámý klíč, ignoruji"
msgid "version not specified" msgid "version not specified"
msgstr "nebyla určena verze" msgstr "nebyla určena verze"
#: ../src/stardict.c:324 #: ../src/stardict.c:322
msgid "word count not specified" msgid "word count not specified"
msgstr "nebyl určen počet slov" msgstr "nebyl určen počet slov"
#~ msgid "FILE..."
#~ msgstr "SOUBOR..."

View File

@@ -1,14 +1,14 @@
# SOME DESCRIPTIVE TITLE. # SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR Přemysl Eric Janouch # Copyright (C) YEAR Přemysl Eric Janouch
# This file is distributed under the same license as the sdtui package. # This file is distributed under the same license as the tdv package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
# #
#, fuzzy #, fuzzy
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: sdtui 0.1.0\n" "Project-Id-Version: tdv 0.1.0\n"
"Report-Msgid-Bugs-To: https://git.janouch.name/p/sdtui/issues\n" "Report-Msgid-Bugs-To: https://git.janouch.name/p/tdv/issues\n"
"POT-Creation-Date: 2021-10-11 21:10+0200\n" "POT-Creation-Date: 2023-06-11 17:47+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,85 +17,10 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
#: ../src/sdgtk.c:289 ../src/sdtui.c:2481 #: ../src/stardict-view.c:96 ../src/tdv-tui.c:340
msgid "Warning"
msgstr ""
#: ../src/sdgtk.c:289 ../src/sdtui.c:2481
msgid "failed to set the locale"
msgstr ""
#: ../src/sdgtk.c:299
msgid "FILE..."
msgstr ""
#: ../src/sdgtk.c:304
msgid "- StarDict GTK+ UI"
msgstr ""
#: ../src/sdgtk.c:355
msgid "Follow selection"
msgstr ""
#: ../src/sdtui.c:320
msgid "error in entry"
msgstr ""
#: ../src/sdtui.c:415
msgid "no usable field found" msgid "no usable field found"
msgstr "" msgstr ""
#: ../src/sdtui.c:700
msgid "Search"
msgstr ""
#: ../src/sdtui.c:726
msgid "Cannot load configuration"
msgstr ""
#: ../src/sdtui.c:745
msgid "Error loading dictionary"
msgstr ""
#: ../src/sdtui.c:750
msgid ""
"No dictionaries found either in the configuration or on the command line"
msgstr ""
#: ../src/sdtui.c:1114
msgid "Terminal UI for StarDict dictionaries"
msgstr ""
#: ../src/sdtui.c:1117
msgid "Type to search"
msgstr ""
#: ../src/sdtui.c:2095
#, c-format
msgid "X11 connection failed (error code %d)"
msgstr ""
#: ../src/sdtui.c:2241
#, c-format
msgid "X11 request error (%d, major %d, minor %d)"
msgstr ""
#: ../src/sdtui.c:2476
msgid "Output version information and exit"
msgstr ""
#: ../src/sdtui.c:2489
msgid "[dictionary.ifo...] - StarDict terminal UI"
msgstr ""
#: ../src/sdtui.c:2497
msgid "Error"
msgstr ""
#: ../src/sdtui.c:2497
msgid "option parsing failed"
msgstr ""
#: ../src/stardict.c:89 #: ../src/stardict.c:89
msgid "invalid header format" msgid "invalid header format"
msgstr "" msgstr ""
@@ -124,19 +49,19 @@ msgstr ""
msgid "option format error" msgid "option format error"
msgstr "" msgstr ""
#: ../src/stardict.c:318 #: ../src/stardict.c:316
msgid "no book name specified" msgid "no book name specified"
msgstr "" msgstr ""
#: ../src/stardict.c:324 #: ../src/stardict.c:322
msgid "word count not specified" msgid "word count not specified"
msgstr "" msgstr ""
#: ../src/stardict.c:330 #: ../src/stardict.c:328
msgid "index file size not specified" msgid "index file size not specified"
msgstr "" msgstr ""
#: ../src/stardict.c:339 #: ../src/stardict.c:337
msgid "invalid index offset bits" msgid "invalid index offset bits"
msgstr "" msgstr ""
@@ -148,6 +73,93 @@ msgstr ""
msgid "cannot find .dict file" msgid "cannot find .dict file"
msgstr "" msgstr ""
#: ../src/stardict.c:1153 ../src/stardict.c:1178 #: ../src/stardict.c:1157 ../src/stardict.c:1182
msgid "invalid data entry" msgid "invalid data entry"
msgstr "" msgstr ""
#: ../src/tdv-gui.c:367
msgid "Open dictionary"
msgstr ""
#: ../src/tdv-gui.c:369
msgid "_Cancel"
msgstr ""
#: ../src/tdv-gui.c:370
msgid "_Open"
msgstr ""
#: ../src/tdv-gui.c:467 ../src/tdv-tui.c:597
msgid ""
"No dictionaries found either in the configuration or on the command line"
msgstr ""
#: ../src/tdv-gui.c:504
msgid "_Open..."
msgstr ""
#: ../src/tdv-gui.c:509
msgid "_Follow selection"
msgstr ""
#: ../src/tdv-tui.c:258
msgid "error in entry"
msgstr ""
#: ../src/tdv-tui.c:555
msgid "Search"
msgstr ""
#: ../src/tdv-tui.c:572
msgid "Cannot load configuration"
msgstr ""
#: ../src/tdv-tui.c:592
msgid "Error loading dictionary"
msgstr ""
#: ../src/tdv-tui.c:1068
msgid "Terminal UI for StarDict dictionaries"
msgstr ""
#: ../src/tdv-tui.c:1071
msgid "Type to search"
msgstr ""
#: ../src/tdv-tui.c:2071
#, c-format
msgid "X11 connection failed (error code %d)"
msgstr ""
#: ../src/tdv-tui.c:2217
#, c-format
msgid "X11 request error (%d, major %d, minor %d)"
msgstr ""
#: ../src/tdv.c:39
msgid "Warning"
msgstr ""
#: ../src/tdv.c:39
msgid "failed to set the locale"
msgstr ""
#: ../src/tdv.c:55
msgid "Output version information and exit"
msgstr ""
#: ../src/tdv.c:60
msgid "Launch the GUI even when run from a terminal"
msgstr ""
#: ../src/tdv.c:67
msgid "[dictionary.ifo...] - Translation dictionary viewer"
msgstr ""
#: ../src/tdv.c:77
msgid "Error"
msgstr ""
#: ../src/tdv.c:77
msgid "option parsing failed"
msgstr ""

BIN
sdtui.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

View File

@@ -357,6 +357,20 @@ error:
return ret_val; return ret_val;
} }
/// Read an .ifo file.
/// @return StardictInfo *. Deallocate with stardict_info_free();
StardictInfo *
stardict_info_new (const gchar *filename, GError **error)
{
StardictInfo *ifo = g_new (StardictInfo, 1);
if (!load_ifo (ifo, filename, error))
{
g_free (ifo);
return NULL;
}
return ifo;
}
/// List all dictionary files located in a path. /// List all dictionary files located in a path.
/// @return GList<StardictInfo *>. Deallocate the list with: /// @return GList<StardictInfo *>. Deallocate the list with:
/// @code /// @code
@@ -377,12 +391,10 @@ stardict_list_dictionaries (const gchar *path)
continue; continue;
gchar *filename = g_build_filename (path, name, NULL); gchar *filename = g_build_filename (path, name, NULL);
StardictInfo *ifo = g_new (StardictInfo, 1); StardictInfo *ifo = stardict_info_new (filename, NULL);
if (load_ifo (ifo, filename, NULL))
dicts = g_list_append (dicts, ifo);
else
g_free (ifo);
g_free (filename); g_free (filename);
if (ifo)
dicts = g_list_append (dicts, ifo);
} }
g_dir_close (dir); g_dir_close (dir);
g_pattern_spec_free (ps); g_pattern_spec_free (ps);
@@ -1014,6 +1026,10 @@ stardict_longest_common_collation_prefix (StardictDict *sd,
u_strFromUTF8 (NULL, 0, &uc2_len, s2, -1, &error); u_strFromUTF8 (NULL, 0, &uc2_len, s2, -1, &error);
error = U_ZERO_ERROR; error = U_ZERO_ERROR;
// Prevent undefined behaviour with VLAs.
if (!uc1_len || !uc2_len)
return 0;
UChar uc1[uc1_len]; UChar uc1[uc1_len];
UChar uc2[uc2_len]; UChar uc2[uc2_len];
u_strFromUTF8 (uc1, uc1_len, NULL, s1, -1, &error); u_strFromUTF8 (uc1, uc1_len, NULL, s1, -1, &error);

View File

@@ -108,6 +108,7 @@ GQuark stardict_error_quark (void);
// --- Dictionary information -------------------------------------------------- // --- Dictionary information --------------------------------------------------
StardictInfo *stardict_info_new (const gchar *filename, GError **error);
const gchar *stardict_info_get_path (StardictInfo *sdi) G_GNUC_PURE; const gchar *stardict_info_get_path (StardictInfo *sdi) G_GNUC_PURE;
const gchar *stardict_info_get_book_name (StardictInfo *sdi) G_GNUC_PURE; const gchar *stardict_info_get_book_name (StardictInfo *sdi) G_GNUC_PURE;
gsize stardict_info_get_word_count (StardictInfo *sd) G_GNUC_PURE; gsize stardict_info_get_word_count (StardictInfo *sd) G_GNUC_PURE;

View File

@@ -1,7 +1,7 @@
/* /*
* StarDict GTK+ UI * StarDict GTK+ UI
* *
* Copyright (c) 2020 - 2022, Přemysl Eric Janouch <p@janouch.name> * Copyright (c) 2020 - 2024, Přemysl Eric Janouch <p@janouch.name>
* *
* Permission to use, copy, modify, and/or distribute this software for any * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted. * purpose with or without fee is hereby granted.
@@ -19,7 +19,6 @@
#include <gtk/gtk.h> #include <gtk/gtk.h>
#include <glib/gi18n.h> #include <glib/gi18n.h>
#include <locale.h>
#include <stdlib.h> #include <stdlib.h>
#include "config.h" #include "config.h"
@@ -27,9 +26,6 @@
#include "utils.h" #include "utils.h"
#include "stardict-view.h" #include "stardict-view.h"
#undef PROJECT_NAME
#define PROJECT_NAME "sdgui"
static struct static struct
{ {
GtkWidget *window; ///< Top-level window GtkWidget *window; ///< Top-level window
@@ -150,8 +146,8 @@ on_selection_received (G_GNUC_UNUSED GtkClipboard *clipboard, const gchar *text,
gchar *trimmed = g_strstrip (g_strdup (text)); gchar *trimmed = g_strstrip (g_strdup (text));
gtk_entry_set_text (GTK_ENTRY (g.entry), trimmed); gtk_entry_set_text (GTK_ENTRY (g.entry), trimmed);
g_free (trimmed); g_free (trimmed);
g_signal_emit_by_name (g.entry,
"move-cursor", GTK_MOVEMENT_BUFFER_ENDS, 1, FALSE); gtk_editable_set_position (GTK_EDITABLE (g.entry), -1);
} }
static void static void
@@ -299,6 +295,8 @@ show_error_dialog (GError *error)
g_error_free (error); g_error_free (error);
} }
// --- Loading -----------------------------------------------------------------
static void static void
on_new_dictionaries_loaded (G_GNUC_UNUSED GObject* source_object, on_new_dictionaries_loaded (G_GNUC_UNUSED GObject* source_object,
GAsyncResult* res, G_GNUC_UNUSED gpointer user_data) GAsyncResult* res, G_GNUC_UNUSED gpointer user_data)
@@ -364,8 +362,8 @@ reload_dictionaries (GPtrArray *new_dictionaries, GError **error)
return TRUE; return TRUE;
} }
static void static GtkWidget *
on_open (G_GNUC_UNUSED GtkMenuItem *item, G_GNUC_UNUSED gpointer data) new_open_dialog (void)
{ {
// The default is local-only. Paths are returned absolute. // The default is local-only. Paths are returned absolute.
GtkWidget *dialog = gtk_file_chooser_dialog_new (_("Open dictionary"), GtkWidget *dialog = gtk_file_chooser_dialog_new (_("Open dictionary"),
@@ -379,7 +377,14 @@ on_open (G_GNUC_UNUSED GtkMenuItem *item, G_GNUC_UNUSED gpointer data)
GtkFileChooser *chooser = GTK_FILE_CHOOSER (dialog); GtkFileChooser *chooser = GTK_FILE_CHOOSER (dialog);
gtk_file_chooser_add_filter (chooser, filter); gtk_file_chooser_add_filter (chooser, filter);
gtk_file_chooser_set_select_multiple (chooser, TRUE); gtk_file_chooser_set_select_multiple (chooser, TRUE);
return dialog;
}
static void
on_open (G_GNUC_UNUSED GtkMenuItem *item, G_GNUC_UNUSED gpointer data)
{
GtkWidget *dialog = new_open_dialog ();
GtkFileChooser *chooser = GTK_FILE_CHOOSER (dialog);
GPtrArray *new_dictionaries = GPtrArray *new_dictionaries =
g_ptr_array_new_with_free_func ((GDestroyNotify) dictionary_destroy); g_ptr_array_new_with_free_func ((GDestroyNotify) dictionary_destroy);
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
@@ -435,6 +440,280 @@ on_drag_data_received (G_GNUC_UNUSED GtkWidget *widget, GdkDragContext *context,
show_error_dialog (error); show_error_dialog (error);
} }
// --- Settings ----------------------------------------------------------------
typedef struct settings_data SettingsData;
enum
{
SETTINGS_COLUMN_NAME,
SETTINGS_COLUMN_PATH,
SETTINGS_COLUMN_COUNT
};
struct settings_data
{
GKeyFile *key_file; ///< Configuration file
GtkTreeModel *model; ///< GtkListStore
};
static void
settings_load (SettingsData *data)
{
// We want to keep original comments, as well as any other data.
GError *error = NULL;
data->key_file = load_project_config_file (&error);
if (!data->key_file)
{
if (error)
show_error_dialog (error);
data->key_file = g_key_file_new ();
}
GtkListStore *list_store = gtk_list_store_new (SETTINGS_COLUMN_COUNT,
G_TYPE_STRING, G_TYPE_STRING);
data->model = GTK_TREE_MODEL (list_store);
const gchar *dictionaries = "Dictionaries";
gchar **names =
g_key_file_get_keys (data->key_file, dictionaries, NULL, NULL);
if (!names)
return;
for (gsize i = 0; names[i]; i++)
{
gchar *path = g_key_file_get_string (data->key_file,
dictionaries, names[i], NULL);
if (!path)
continue;
GtkTreeIter iter = { 0 };
gtk_list_store_append (list_store, &iter);
gtk_list_store_set (list_store, &iter,
SETTINGS_COLUMN_NAME, names[i], SETTINGS_COLUMN_PATH, path, -1);
g_free (path);
}
g_strfreev (names);
}
static void
settings_save (SettingsData *data)
{
const gchar *dictionaries = "Dictionaries";
g_key_file_remove_group (data->key_file, dictionaries, NULL);
GtkTreeIter iter = { 0 };
gboolean valid = gtk_tree_model_get_iter_first (data->model, &iter);
while (valid)
{
gchar *name = NULL, *path = NULL;
gtk_tree_model_get (data->model, &iter,
SETTINGS_COLUMN_NAME, &name, SETTINGS_COLUMN_PATH, &path, -1);
if (name && path)
g_key_file_set_string (data->key_file, dictionaries, name, path);
g_free (name);
g_free (path);
valid = gtk_tree_model_iter_next (data->model, &iter);
}
GError *e = NULL;
if (!save_project_config_file (data->key_file, &e))
show_error_dialog (e);
}
static void
on_settings_name_edited (G_GNUC_UNUSED GtkCellRendererText *cell,
const gchar *path_string, const gchar *new_text, gpointer data)
{
GtkTreeModel *model = GTK_TREE_MODEL (data);
GtkTreePath *path = gtk_tree_path_new_from_string (path_string);
GtkTreeIter iter = { 0 };
gtk_tree_model_get_iter (model, &iter, path);
gtk_list_store_set (GTK_LIST_STORE (model), &iter,
SETTINGS_COLUMN_NAME, new_text, -1);
gtk_tree_path_free (path);
}
static void
on_settings_path_edited (G_GNUC_UNUSED GtkCellRendererText *cell,
const gchar *path_string, const gchar *new_text, gpointer data)
{
GtkTreeModel *model = GTK_TREE_MODEL (data);
GtkTreePath *path = gtk_tree_path_new_from_string (path_string);
GtkTreeIter iter = { 0 };
gtk_tree_model_get_iter (model, &iter, path);
gtk_list_store_set (GTK_LIST_STORE (model), &iter,
SETTINGS_COLUMN_PATH, new_text, -1);
gtk_tree_path_free (path);
}
static void
on_settings_add (G_GNUC_UNUSED GtkButton *button, gpointer user_data)
{
GtkWidget *dialog = new_open_dialog ();
GtkFileChooser *chooser = GTK_FILE_CHOOSER (dialog);
GSList *paths = NULL;
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
paths = gtk_file_chooser_get_filenames (chooser);
gtk_widget_destroy (dialog);
// When the dialog is aborted, we simply add an empty list.
GtkTreeView *tree_view = GTK_TREE_VIEW (user_data);
gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (tree_view));
GtkTreeModel *model = gtk_tree_view_get_model (tree_view);
GtkListStore *list_store = GTK_LIST_STORE (model);
const gchar *home = g_get_home_dir ();
for (GSList *iter = paths; iter; iter = iter->next)
{
GError *error = NULL;
StardictInfo *ifo = stardict_info_new (iter->data, &error);
g_free (iter->data);
if (!ifo)
{
show_error_dialog (error);
continue;
}
// We also expand tildes, even on Windows, so no problem there.
const gchar *path = stardict_info_get_path (ifo);
gchar *tildified = g_str_has_prefix (stardict_info_get_path (ifo), home)
? g_strdup_printf ("~%s", path + strlen (home))
: g_strdup (path);
GtkTreeIter iter = { 0 };
gtk_list_store_append (list_store, &iter);
gtk_list_store_set (list_store, &iter,
SETTINGS_COLUMN_NAME, stardict_info_get_book_name (ifo),
SETTINGS_COLUMN_PATH, tildified, -1);
g_free (tildified);
stardict_info_free (ifo);
}
g_slist_free (paths);
}
static void
on_settings_remove (G_GNUC_UNUSED GtkButton *button, gpointer user_data)
{
GtkTreeView *tree_view = GTK_TREE_VIEW (user_data);
GtkTreeSelection *selection = gtk_tree_view_get_selection (tree_view);
GtkTreeModel *model = gtk_tree_view_get_model (tree_view);
GtkListStore *list_store = GTK_LIST_STORE (model);
GList *selected = gtk_tree_selection_get_selected_rows (selection, &model);
for (GList *iter = selected; iter; iter = iter->next)
{
GtkTreePath *path = iter->data;
iter->data = gtk_tree_row_reference_new (model, path);
gtk_tree_path_free (path);
}
for (GList *iter = selected; iter; iter = iter->next)
{
GtkTreePath *path = gtk_tree_row_reference_get_path (iter->data);
if (path)
{
GtkTreeIter tree_iter = { 0 };
if (gtk_tree_model_get_iter (model, &tree_iter, path))
gtk_list_store_remove (list_store, &tree_iter);
gtk_tree_path_free (path);
}
}
g_list_free_full (selected, (GDestroyNotify) gtk_tree_row_reference_free);
}
static void
on_settings_selection_changed
(GtkTreeSelection* selection, gpointer user_data)
{
GtkWidget *remove = GTK_WIDGET (user_data);
gtk_widget_set_sensitive (remove,
gtk_tree_selection_count_selected_rows (selection) > 0);
}
static void
on_settings (G_GNUC_UNUSED GtkMenuItem *item, G_GNUC_UNUSED gpointer data)
{
SettingsData sd = {};
settings_load (&sd);
GtkWidget *treeview = gtk_tree_view_new_with_model (sd.model);
gtk_tree_view_set_reorderable (GTK_TREE_VIEW (treeview), TRUE);
g_object_unref (sd.model);
GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
g_object_set (renderer, "editable", TRUE, NULL);
g_signal_connect (renderer, "edited",
G_CALLBACK (on_settings_name_edited), sd.model);
GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes
(_("Name"), renderer, "text", SETTINGS_COLUMN_NAME, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
renderer = gtk_cell_renderer_text_new ();
g_object_set (renderer, "editable", TRUE, NULL);
g_signal_connect (renderer, "edited",
G_CALLBACK (on_settings_path_edited), sd.model);
column = gtk_tree_view_column_new_with_attributes
(_("Path"), renderer, "text", SETTINGS_COLUMN_PATH, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
GtkWidget *scrolled = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_shadow_type
(GTK_SCROLLED_WINDOW (scrolled), GTK_SHADOW_ETCHED_IN);
gtk_container_add (GTK_CONTAINER (scrolled), treeview);
GtkWidget *dialog = gtk_dialog_new_with_buttons (_("Settings"),
GTK_WINDOW (g.window),
GTK_DIALOG_MODAL,
_("_Cancel"), GTK_RESPONSE_CANCEL,
_("_Save"), GTK_RESPONSE_ACCEPT,
NULL);
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
gtk_window_set_default_size (GTK_WINDOW (dialog), 600, 400);
GtkWidget *remove = gtk_button_new_with_mnemonic (_("_Remove"));
gtk_widget_set_sensitive (remove, FALSE);
g_signal_connect (remove, "clicked",
G_CALLBACK (on_settings_remove), treeview);
GtkWidget *add = gtk_button_new_with_mnemonic (_("_Add..."));
g_signal_connect (add, "clicked",
G_CALLBACK (on_settings_add), treeview);
GtkTreeSelection *selection =
gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
g_signal_connect (selection, "changed",
G_CALLBACK (on_settings_selection_changed), remove);
GtkWidget *box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
gtk_box_pack_start (GTK_BOX (box),
gtk_label_new (_("Here you can configure the default dictionaries.")),
FALSE, FALSE, 0);
gtk_box_pack_end (GTK_BOX (box), remove, FALSE, FALSE, 0);
gtk_box_pack_end (GTK_BOX (box), add, FALSE, FALSE, 0);
GtkWidget *content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
g_object_set (content_area, "margin", 12, NULL);
gtk_box_pack_start (GTK_BOX (content_area), box, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (content_area), scrolled, TRUE, TRUE, 12);
gtk_widget_show_all (dialog);
switch (gtk_dialog_run (GTK_DIALOG (dialog)))
{
case GTK_RESPONSE_NONE:
break;
case GTK_RESPONSE_ACCEPT:
settings_save (&sd);
// Fall through
default:
gtk_widget_destroy (dialog);
}
g_key_file_free (sd.key_file);
}
// --- Main --------------------------------------------------------------------
static void static void
on_destroy (G_GNUC_UNUSED GtkWidget *widget, G_GNUC_UNUSED gpointer data) on_destroy (G_GNUC_UNUSED GtkWidget *widget, G_GNUC_UNUSED gpointer data)
{ {
@@ -452,48 +731,35 @@ die_with_dialog (const gchar *message)
} }
int int
main (int argc, char *argv[]) gui_main (char *argv[])
{ {
if (!setlocale (LC_ALL, "")) // Just like with GtkApplication, argv has been parsed by the option group.
g_printerr ("%s: %s\n", _("Warning"), _("failed to set the locale")); gtk_init (NULL, NULL);
bindtextdomain (GETTEXT_PACKAGE, GETTEXT_DIRNAME);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE);
gchar **filenames = NULL;
GOptionEntry option_entries[] =
{
{G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames,
NULL, N_("[FILE]...")},
{},
};
GError *error = NULL;
gtk_init_with_args (&argc, &argv, N_("- StarDict GTK+ UI"),
option_entries, GETTEXT_PACKAGE, &error);
if (error)
{
g_warning ("%s", error->message);
g_error_free (error);
return 1;
}
gtk_window_set_default_icon_name (PROJECT_NAME); gtk_window_set_default_icon_name (PROJECT_NAME);
GError *error = NULL;
GPtrArray *new_dictionaries = GPtrArray *new_dictionaries =
g_ptr_array_new_with_free_func ((GDestroyNotify) dictionary_destroy); g_ptr_array_new_with_free_func ((GDestroyNotify) dictionary_destroy);
if (filenames) if (argv[0])
{ load_from_filenames (new_dictionaries, argv);
load_from_filenames (new_dictionaries, filenames);
g_strfreev (filenames);
}
else if (!load_from_config (new_dictionaries, &error) && error) else if (!load_from_config (new_dictionaries, &error) && error)
die_with_dialog (error->message); die_with_dialog (error->message);
if (!new_dictionaries->len) if (!new_dictionaries->len)
die_with_dialog (_("No dictionaries found either in " {
GtkWidget *dialog = gtk_message_dialog_new (NULL, 0,
GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s",
_("No dictionaries found either in "
"the configuration or on the command line")); "the configuration or on the command line"));
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
// This is better than nothing.
// Our GtkNotebook action widget would be invisible without any tabs.
on_settings (NULL, NULL);
exit (EXIT_SUCCESS);
}
// Some Adwaita stupidity, plus defaults for our own widget. // Some Adwaita stupidity, plus defaults for our own widget.
// All the named colours have been there since GNOME 3.4 // All the named colours have been there since GNOME 3.4
@@ -532,6 +798,10 @@ main (int argc, char *argv[])
GtkWidget *item_open = gtk_menu_item_new_with_mnemonic (_("_Open...")); GtkWidget *item_open = gtk_menu_item_new_with_mnemonic (_("_Open..."));
g_signal_connect (item_open, "activate", G_CALLBACK (on_open), NULL); g_signal_connect (item_open, "activate", G_CALLBACK (on_open), NULL);
GtkWidget *item_settings = gtk_menu_item_new_with_mnemonic (_("_Settings"));
g_signal_connect (item_settings, "activate",
G_CALLBACK (on_settings), NULL);
g.watch_selection = TRUE; g.watch_selection = TRUE;
GtkWidget *item_selection = GtkWidget *item_selection =
gtk_check_menu_item_new_with_mnemonic (_("_Follow selection")); gtk_check_menu_item_new_with_mnemonic (_("_Follow selection"));
@@ -543,6 +813,7 @@ main (int argc, char *argv[])
GtkWidget *menu = gtk_menu_new (); GtkWidget *menu = gtk_menu_new ();
gtk_widget_set_halign (menu, GTK_ALIGN_END); gtk_widget_set_halign (menu, GTK_ALIGN_END);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item_open); gtk_menu_shell_append (GTK_MENU_SHELL (menu), item_open);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item_settings);
#ifndef G_OS_WIN32 #ifndef G_OS_WIN32
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item_selection); gtk_menu_shell_append (GTK_MENU_SHELL (menu), item_selection);
#endif // ! G_OS_WIN32 #endif // ! G_OS_WIN32

View File

@@ -6,7 +6,7 @@
* finalised with an empty line. Newlines are escaped with `\n', * finalised with an empty line. Newlines are escaped with `\n',
* backslashes with `\\'. * backslashes with `\\'.
* *
* So far only the `m', `g`, and `x` fields are supported, as in sdtui. * So far only the `m', `g`, and `x` fields are supported, as in tdv.
* *
* Copyright (c) 2013 - 2021, Přemysl Eric Janouch <p@janouch.name> * Copyright (c) 2013 - 2021, Přemysl Eric Janouch <p@janouch.name>
* *

View File

@@ -3,7 +3,7 @@
* *
* The external filter needs to process NUL-separated textual entries. * The external filter needs to process NUL-separated textual entries.
* *
* Example: transform input.ifo output -- perl -p0e s/bullshit/soykaf/g * Example: tdv-transform input.ifo output -- perl -p0e s/bullshit/soykaf/g
* *
* Copyright (c) 2020, Přemysl Eric Janouch <p@janouch.name> * Copyright (c) 2020, Přemysl Eric Janouch <p@janouch.name>
* *

View File

@@ -18,16 +18,15 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <locale.h>
#include <stdarg.h> #include <stdarg.h>
#include <limits.h> #include <limits.h>
#include <string.h> #include <string.h>
#include <glib.h> #include <glib.h>
#include <glib-unix.h> #include <glib-unix.h>
#include <glib/gi18n.h>
#include <gio/gio.h> #include <gio/gio.h>
#include <pango/pango.h> #include <pango/pango.h>
#include <glib/gi18n.h>
#include <unistd.h> #include <unistd.h>
#include <poll.h> #include <poll.h>
@@ -166,6 +165,7 @@ struct application
GPtrArray * entries; ///< ViewEntry-s within the view GPtrArray * entries; ///< ViewEntry-s within the view
gchar * search_label; ///< Text of the "Search" label gchar * search_label; ///< Text of the "Search" label
gsize search_label_width; ///< Visible width of "search_label"
GArray * input; ///< The current search input GArray * input; ///< The current search input
guint input_pos; ///< Cursor position within input guint input_pos; ///< Cursor position within input
guint input_offset; ///< Render offset in codepoints guint input_offset; ///< Render offset in codepoints
@@ -206,6 +206,10 @@ app_char_width (Application *app, gunichar c)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#if !GLIB_CHECK_VERSION(2, 68, 0)
#define g_memdup2 g_memdup
#endif
/// Splits the entry and adds it to a pointer array. /// Splits the entry and adds it to a pointer array.
static void static void
view_entry_split_add (ViewEntry *ve, const gchar *text, const chtype *attrs) view_entry_split_add (ViewEntry *ve, const gchar *text, const chtype *attrs)
@@ -486,6 +490,17 @@ app_init_attrs (Application *self)
#undef XX #undef XX
} }
static gsize
app_utf8_width (Application *self, const char *utf8)
{
gsize width = 0;
gunichar *ucs4 = g_utf8_to_ucs4_fast (utf8, -1, NULL);
for (gunichar *it = ucs4; *it; it++)
width += app_char_width (self, *it);
g_free (ucs4);
return width;
}
static gboolean static gboolean
app_load_dictionaries (Application *self, GError **e) app_load_dictionaries (Application *self, GError **e)
{ {
@@ -500,11 +515,7 @@ app_load_dictionaries (Application *self, GError **e)
gchar *tmp = g_strdup_printf (" %s ", dict->super.name); gchar *tmp = g_strdup_printf (" %s ", dict->super.name);
g_free (dict->super.name); g_free (dict->super.name);
dict->super.name = tmp; dict->super.name = tmp;
dict->name_width = app_utf8_width (self, dict->super.name);
gunichar *ucs4 = g_utf8_to_ucs4_fast (dict->super.name, -1, NULL);
for (gunichar *it = ucs4; *it; it++)
dict->name_width += app_char_width (self, *it);
g_free (ucs4);
} }
return TRUE; return TRUE;
} }
@@ -520,6 +531,15 @@ app_init (Application *self, char **filenames)
self->tk = NULL; self->tk = NULL;
self->tk_timer = 0; self->tk_timer = 0;
const char *charset = NULL;
self->locale_is_utf8 = g_get_charset (&charset);
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
self->ucs4_to_locale = g_iconv_open (charset, "UTF-32LE");
#else // G_BYTE_ORDER != G_LITTLE_ENDIAN
self->ucs4_to_locale = g_iconv_open (charset, "UTF-32BE");
#endif // G_BYTE_ORDER != G_LITTLE_ENDIAN
self->focused = TRUE;
self->show_help = TRUE; self->show_help = TRUE;
self->center_search = TRUE; self->center_search = TRUE;
self->underline_last = TRUE; self->underline_last = TRUE;
@@ -533,6 +553,7 @@ app_init (Application *self, char **filenames)
((GDestroyNotify) view_entry_free); ((GDestroyNotify) view_entry_free);
self->search_label = g_strdup_printf ("%s: ", _("Search")); self->search_label = g_strdup_printf ("%s: ", _("Search"));
self->search_label_width = app_utf8_width (self, self->search_label);
self->input = g_array_new (TRUE, FALSE, sizeof (gunichar)); self->input = g_array_new (TRUE, FALSE, sizeof (gunichar));
self->input_pos = self->input_offset = 0; self->input_pos = self->input_offset = 0;
@@ -540,15 +561,6 @@ app_init (Application *self, char **filenames)
self->division = 0.5; self->division = 0.5;
const char *charset;
self->locale_is_utf8 = g_get_charset (&charset);
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
self->ucs4_to_locale = g_iconv_open (charset, "UTF-32LE");
#else // G_BYTE_ORDER != G_LITTLE_ENDIAN
self->ucs4_to_locale = g_iconv_open (charset, "UTF-32BE");
#endif // G_BYTE_ORDER != G_LITTLE_ENDIAN
self->focused = TRUE;
app_init_attrs (self); app_init_attrs (self);
self->dictionaries = self->dictionaries =
g_ptr_array_new_with_free_func ((GDestroyNotify) dictionary_destroy); g_ptr_array_new_with_free_func ((GDestroyNotify) dictionary_destroy);
@@ -1922,10 +1934,7 @@ app_process_left_mouse_click (Application *self, int line, int column)
} }
else if (line == 1) else if (line == 1)
{ {
// FIXME: this is only an approximation gint pos = column - self->search_label_width;
glong label_width = g_utf8_strlen (self->search_label, -1);
gint pos = column - label_width;
if (pos >= 0) if (pos >= 0)
{ {
// On clicking the left arrow, go to that invisible character // On clicking the left arrow, go to that invisible character
@@ -2428,53 +2437,10 @@ log_handler (const gchar *domain, GLogLevelFlags level,
} }
int int
main (int argc, char *argv[]) tui_main (char *argv[])
{ {
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
if (glib_check_version (2, 36, 0))
g_type_init ();
G_GNUC_END_IGNORE_DEPRECATIONS
gboolean show_version = FALSE;
GOptionEntry entries[] =
{
{ "version", 0, G_OPTION_FLAG_IN_MAIN,
G_OPTION_ARG_NONE, &show_version,
N_("Output version information and exit"), NULL },
{ NULL }
};
if (!setlocale (LC_ALL, ""))
g_printerr ("%s: %s\n", _("Warning"), _("failed to set the locale"));
bindtextdomain (GETTEXT_PACKAGE, GETTEXT_DIRNAME);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE);
GError *error = NULL;
GOptionContext *ctx = g_option_context_new
(N_("[dictionary.ifo...] - StarDict terminal UI"));
GOptionGroup *group = g_option_group_new ("", "", "", NULL, NULL);
g_option_group_add_entries (group, entries);
g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
g_option_context_add_group (ctx, group);
g_option_context_set_translation_domain (ctx, GETTEXT_PACKAGE);
if (!g_option_context_parse (ctx, &argc, &argv, &error))
{
g_printerr ("%s: %s: %s\n", _("Error"), _("option parsing failed"),
error->message);
exit (EXIT_FAILURE);
}
g_option_context_free (ctx);
if (show_version)
{
g_print (PROJECT_NAME " " PROJECT_VERSION "\n");
exit (EXIT_SUCCESS);
}
Application app; Application app;
app_init (&app, argv + 1); app_init (&app, argv);
app_init_terminal (&app); app_init_terminal (&app);
app_redraw (&app); app_redraw (&app);
@@ -2518,4 +2484,3 @@ G_GNUC_END_IGNORE_DEPRECATIONS
return 0; return 0;
} }

98
src/tdv.c Normal file
View File

@@ -0,0 +1,98 @@
/*
* Translation dictionary viewer
*
* Copyright (c) 2023, Přemysl Eric Janouch <p@janouch.name>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#include "config.h"
#include <glib.h>
#include <glib/gi18n.h>
#ifdef WITH_GUI
#include <gtk/gtk.h>
#endif
#include <locale.h>
#ifndef G_OS_WIN32
#include <unistd.h>
#endif
int tui_main (char *[]);
int gui_main (char *[]);
int
main (int argc, char *argv[])
{
if (!setlocale (LC_ALL, ""))
g_printerr ("%s: %s\n", _("Warning"), _("failed to set the locale"));
bindtextdomain (GETTEXT_PACKAGE, GETTEXT_DIRNAME);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE);
gboolean show_version = FALSE;
#ifdef WITH_GUI
# ifndef G_OS_WIN32
gboolean gui = FALSE;
# endif
#endif
GOptionEntry entries[] =
{
{ "version", 0, G_OPTION_FLAG_IN_MAIN,
G_OPTION_ARG_NONE, &show_version,
N_("Output version information and exit"), NULL },
#ifdef WITH_GUI
# ifndef G_OS_WIN32
{ "gui", 0, G_OPTION_FLAG_IN_MAIN,
G_OPTION_ARG_NONE, &gui,
N_("Launch the GUI even when run from a terminal"), NULL },
# endif
#endif
{ },
};
GOptionContext *ctx = g_option_context_new
(N_("[dictionary.ifo...] - Translation dictionary viewer"));
g_option_context_add_main_entries (ctx, entries, GETTEXT_PACKAGE);
#ifdef WITH_GUI
g_option_context_add_group (ctx, gtk_get_option_group (FALSE));
#endif
g_option_context_set_translation_domain (ctx, GETTEXT_PACKAGE);
GError *error = NULL;
if (!g_option_context_parse (ctx, &argc, &argv, &error))
{
g_printerr ("%s: %s: %s\n", _("Error"), _("option parsing failed"),
error->message);
exit (EXIT_FAILURE);
}
g_option_context_free (ctx);
if (show_version)
{
g_print (PROJECT_NAME " " PROJECT_VERSION "\n");
exit (EXIT_SUCCESS);
}
#ifdef WITH_GUI
# ifndef G_OS_WIN32
if (gui || !isatty (STDIN_FILENO))
# endif
return gui_main (argv + 1);
#endif
#ifndef G_OS_WIN32
return tui_main (argv + 1);
#endif
}

View File

@@ -16,6 +16,11 @@
* *
*/ */
// getpwnam_r, _SC_GETPW_R_SIZE_MAX
#ifndef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200112L
#endif
#include <glib.h> #include <glib.h>
#include <glib/gprintf.h> #include <glib/gprintf.h>
#include <gio/gio.h> #include <gio/gio.h>
@@ -217,7 +222,7 @@ load_project_config_file (GError **error)
// which is completely undocumented // which is completely undocumented
g_key_file_load_from_dirs (key_file, g_key_file_load_from_dirs (key_file,
PROJECT_NAME G_DIR_SEPARATOR_S PROJECT_NAME ".conf", PROJECT_NAME G_DIR_SEPARATOR_S PROJECT_NAME ".conf",
paths, NULL, 0, &e); paths, NULL, G_KEY_FILE_KEEP_COMMENTS, &e);
g_free (paths); g_free (paths);
if (!e) if (!e)
return key_file; return key_file;
@@ -231,6 +236,25 @@ load_project_config_file (GError **error)
return NULL; return NULL;
} }
gboolean
save_project_config_file (GKeyFile *key_file, GError **error)
{
gchar *dirname =
g_build_filename (g_get_user_config_dir (), PROJECT_NAME, NULL);
(void) g_mkdir_with_parents (dirname, 0755);
gchar *path = g_build_filename (dirname, PROJECT_NAME ".conf", NULL);
g_free (dirname);
gsize length = 0;
gchar *data = g_key_file_to_data (key_file, &length, error);
if (!data)
return FALSE;
gboolean result = g_file_set_contents (path, data, length, error);
g_free (data);
return result;
}
// --- Loading ----------------------------------------------------------------- // --- Loading -----------------------------------------------------------------
void void

View File

@@ -54,6 +54,7 @@ gchar *resolve_relative_config_filename (const gchar *filename);
gchar *resolve_filename gchar *resolve_filename
(const gchar *filename, gchar *(*relative_cb) (const char *)); (const gchar *filename, gchar *(*relative_cb) (const char *));
GKeyFile *load_project_config_file (GError **error); GKeyFile *load_project_config_file (GError **error);
gboolean save_project_config_file (GKeyFile *key_file, GError **error);
// --- Loading ----------------------------------------------------------------- // --- Loading -----------------------------------------------------------------

View File

@@ -1,9 +1,9 @@
[Desktop Entry] [Desktop Entry]
Type=Application Type=Application
Name=sdgui Name=tdv
GenericName=StarDict GUI GenericName=Translation dictionary viewer
Icon=sdgui Icon=tdv
Exec=sdgui %F Exec=tdv %F
StartupNotify=true StartupNotify=true
MimeType=application/x-stardict-ifo; MimeType=application/x-stardict-ifo;
Categories=Office;Dictionary;GTK; Categories=Office;Dictionary;GTK;

BIN
tdv.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

2
termo

Submodule termo updated: 8265f075b1...f9a102456f