From 573554b9decf74f3b57ab6d26252700132255525 Mon Sep 17 00:00:00 2001
From: Přemysl Eric Janouch
Date: Fri, 15 Oct 2021 12:08:44 +0200
Subject: sdgtk -> sdgui, improve build, mention in README
It's finally not horrible.
---
CMakeLists.txt | 24 +++--
README.adoc | 5 +
src/sdgtk.c | 311 ---------------------------------------------------------
src/sdgui.c | 311 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/sdtui.c | 29 +++++-
src/utils.c | 28 ------
src/utils.h | 1 -
7 files changed, 358 insertions(+), 351 deletions(-)
delete mode 100644 src/sdgtk.c
create mode 100644 src/sdgui.c
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f661cbc..38b0bf7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -78,6 +78,9 @@ if (WITH_X11)
list (APPEND dependencies_LIBRARIES ${xcb_LIBRARIES})
endif ()
+pkg_check_modules (gtk gtk+-3.0)
+option (WITH_GUI "Build a work-in-progress GTK+ UI" ${gtk_FOUND})
+
link_directories (${dependencies_LIBRARY_DIRS})
include_directories (${ZLIB_INCLUDE_DIRS} ${icu_INCLUDE_DIRS}
${dependencies_INCLUDE_DIRS} ${Ncursesw_INCLUDE_DIRS}
@@ -117,7 +120,7 @@ add_custom_target (docs ALL DEPENDS ${project_MAN_PAGES})
# Project libraries
set (project_common_libraries ${ZLIB_LIBRARIES} ${icu_LIBRARIES}
- ${dependencies_LIBRARIES} ${Ncursesw_LIBRARIES} termo-static)
+ ${dependencies_LIBRARIES})
set (project_common_headers
${PROJECT_BINARY_DIR}/config.h
@@ -151,17 +154,17 @@ set (project_headers
add_definitions (-DGLIB_DISABLE_DEPRECATION_WARNINGS)
add_executable (${PROJECT_NAME}
${project_sources} ${project_headers} ${project_common_sources})
-target_link_libraries (${PROJECT_NAME} ${project_common_libraries})
+target_link_libraries (${PROJECT_NAME} ${project_common_libraries}
+ ${Ncursesw_LIBRARIES} termo-static)
-# Experimental GTK+ frontend, we link it with ncurses but we don't care
-pkg_check_modules (gtk gtk+-3.0)
-if (gtk_FOUND)
- add_executable (sdgtk EXCLUDE_FROM_ALL
- src/sdgtk.c
+# The same for the alternative GTK+ UI
+if (WITH_GUI)
+ add_executable (sdgui
+ src/sdgui.c
src/stardict-view.c
${project_common_sources})
- target_include_directories (sdgtk PUBLIC ${gtk_INCLUDE_DIRS})
- target_link_libraries (sdgtk ${gtk_LIBRARIES} ${project_common_libraries})
+ target_include_directories (sdgui PUBLIC ${gtk_INCLUDE_DIRS})
+ target_link_libraries (sdgui ${gtk_LIBRARIES} ${project_common_libraries})
endif ()
# Tools
@@ -193,6 +196,9 @@ add_custom_target (dicts DEPENDS ${dicts_targets})
include (GNUInstallDirs)
install (TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})
install (FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR})
+if (WITH_GUI)
+ install (TARGETS sdgui DESTINATION ${CMAKE_INSTALL_BINDIR})
+endif ()
foreach (page ${project_MAN_PAGES})
string (REGEX MATCH "\\.([0-9])$" manpage_suffix "${page}")
diff --git a/README.adoc b/README.adoc
index 6047f44..727d3a0 100644
--- a/README.adoc
+++ b/README.adoc
@@ -79,6 +79,11 @@ Linux and/or BSD distributions:
Given the entangledness of this codebase, issues with the file format,
and general undesirability of terminal UIs, it might be better to start anew.
+Graphical UI
+------------
+With GTK+ 3 development packages installed, an alternative, work-in-progress
+frontend will be built and installed.
+
Contributing and Support
------------------------
Use https://git.janouch.name/p/sdtui to report any bugs, request features,
diff --git a/src/sdgtk.c b/src/sdgtk.c
deleted file mode 100644
index 3565bc6..0000000
--- a/src/sdgtk.c
+++ /dev/null
@@ -1,311 +0,0 @@
-/*
- * StarDict GTK+ UI
- *
- * Copyright (c) 2020 - 2021, Přemysl Eric Janouch
- *
- * 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
-#include
-
-#include
-
-#include "config.h"
-#include "stardict.h"
-#include "utils.h"
-#include "stardict-view.h"
-
-typedef struct dictionary Dictionary;
-
-struct dictionary
-{
- const gchar *filename; ///< Filename
- StardictDict *dict; ///< Stardict dictionary data
- gchar *name; ///< Name to show
- guint position; ///< Current position
-};
-
-static struct
-{
- GtkWidget *window; ///< Top-level window
- GtkWidget *notebook; ///< Notebook with tabs
- GtkWidget *entry; ///< Search entry widget
- GtkWidget *view; ///< Entries view
-
- gint dictionary; ///< Index of the current dictionary
- Dictionary *dictionaries; ///< All open dictionaries
- gsize dictionaries_len; ///< Total number of dictionaries
-
- gboolean watch_selection; ///< Following X11 PRIMARY?
-}
-g;
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-static gboolean
-dictionary_load (Dictionary *self, gchar *filename, GError **e)
-{
- self->filename = filename;
- if (!(self->dict = stardict_dict_new (self->filename, e)))
- return FALSE;
-
- if (!self->name)
- {
- self->name = g_strdup (stardict_info_get_book_name
- (stardict_dict_get_info (self->dict)));
- }
- return TRUE;
-}
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-static gboolean
-init (gchar **filenames, GError **e)
-{
- while (filenames[g.dictionaries_len])
- g.dictionaries_len++;
-
- g.dictionaries = g_malloc0_n (sizeof *g.dictionaries, g.dictionaries_len);
- for (gsize i = 0; i < g.dictionaries_len; i++)
- {
- Dictionary *dict = &g.dictionaries[i];
- if (!dictionary_load (dict, filenames[i], e))
- return FALSE;
- }
- return TRUE;
-}
-
-static void
-search (Dictionary *dict)
-{
- GtkEntryBuffer *buf = gtk_entry_get_buffer (GTK_ENTRY (g.entry));
- const gchar *input_utf8 = gtk_entry_buffer_get_text (buf);
-
- StardictIterator *iterator =
- stardict_dict_search (dict->dict, input_utf8, NULL);
- dict->position = stardict_iterator_get_offset (iterator);
- g_object_unref (iterator);
-
- stardict_view_set_position (STARDICT_VIEW (g.view),
- dict->dict, dict->position);
- stardict_view_set_matched (STARDICT_VIEW (g.view), input_utf8);
-}
-
-static void
-on_changed (G_GNUC_UNUSED GtkWidget *widget, G_GNUC_UNUSED gpointer data)
-{
- search (&g.dictionaries[g.dictionary]);
-}
-
-static void
-on_selection_received (G_GNUC_UNUSED GtkClipboard *clipboard, const gchar *text,
- G_GNUC_UNUSED gpointer data)
-{
- if (!text)
- return;
-
- gtk_entry_set_text (GTK_ENTRY (g.entry), text);
- g_signal_emit_by_name (g.entry,
- "move-cursor", GTK_MOVEMENT_BUFFER_ENDS, 1, FALSE);
-}
-
-static void
-on_selection (GtkClipboard *clipboard, GdkEvent *event,
- G_GNUC_UNUSED gpointer data)
-{
- if (g.watch_selection
- && !gtk_window_has_toplevel_focus (GTK_WINDOW (g.window))
- && event->owner_change.owner != NULL)
- gtk_clipboard_request_text (clipboard, on_selection_received, NULL);
-}
-
-static void
-on_selection_watch_toggle (GtkCheckMenuItem *item, G_GNUC_UNUSED gpointer data)
-{
- g.watch_selection = gtk_check_menu_item_get_active (item);
-}
-
-static void
-on_switch_page (G_GNUC_UNUSED GtkWidget *widget, G_GNUC_UNUSED GtkWidget *page,
- guint page_num, G_GNUC_UNUSED gpointer data)
-{
- g.dictionary = page_num;
- search (&g.dictionaries[g.dictionary]);
-}
-
-static gboolean
-on_key_press (G_GNUC_UNUSED GtkWidget *widget, GdkEvent *event,
- G_GNUC_UNUSED gpointer data)
-{
- if (event->key.state == GDK_CONTROL_MASK)
- {
- if (event->key.keyval == GDK_KEY_Page_Up)
- {
- gtk_notebook_prev_page (GTK_NOTEBOOK (g.notebook));
- return TRUE;
- }
- if (event->key.keyval == GDK_KEY_Page_Down)
- {
- gtk_notebook_next_page (GTK_NOTEBOOK (g.notebook));
- return TRUE;
- }
- }
- if (event->key.state == GDK_MOD1_MASK)
- {
- if (event->key.keyval >= GDK_KEY_0
- && event->key.keyval <= GDK_KEY_9)
- {
- gint n = event->key.keyval - GDK_KEY_0;
- gtk_notebook_set_current_page
- (GTK_NOTEBOOK (g.notebook), n ? (n - 1) : 10);
- return TRUE;
- }
- }
- return FALSE;
-}
-
-static void
-on_destroy (G_GNUC_UNUSED GtkWidget *widget, G_GNUC_UNUSED gpointer data)
-{
- gtk_main_quit ();
-}
-
-static void
-die_with_dialog (const gchar *message)
-{
- GtkWidget *dialog = gtk_message_dialog_new (NULL, 0,
- GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s", message);
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (dialog);
- exit (EXIT_FAILURE);
-}
-
-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);
-
- 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;
- }
-
- if (!filenames)
- {
- // TODO: eventually just load all dictionaries from configuration
- die_with_dialog ("No arguments have been passed.");
- }
- if (!init (filenames, &error))
- die_with_dialog (error->message);
-
- // Some Adwaita stupidity
- const char *style = "notebook header tab { padding: 2px 8px; margin: 0; }";
-
- GdkScreen *screen = gdk_screen_get_default ();
- GtkCssProvider *provider = gtk_css_provider_new ();
- gtk_css_provider_load_from_data (provider, style, strlen (style), NULL);
- gtk_style_context_add_provider_for_screen (screen,
- GTK_STYLE_PROVIDER (provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
-
- g.notebook = gtk_notebook_new ();
- g_signal_connect (g.notebook, "switch-page",
- G_CALLBACK (on_switch_page), NULL);
- gtk_notebook_set_scrollable (GTK_NOTEBOOK (g.notebook), TRUE);
-
- g.watch_selection = TRUE;
- GtkWidget *item =
- gtk_check_menu_item_new_with_label (_("Follow selection"));
- gtk_check_menu_item_set_active
- (GTK_CHECK_MENU_ITEM (item), g.watch_selection);
- g_signal_connect (item, "toggled",
- G_CALLBACK (on_selection_watch_toggle), NULL);
-
- GtkWidget *menu = gtk_menu_new ();
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
- gtk_widget_show_all (menu);
-
- GtkWidget *hamburger = gtk_menu_button_new ();
- gtk_menu_button_set_direction (GTK_MENU_BUTTON (hamburger), GTK_ARROW_NONE);
- gtk_menu_button_set_popup (GTK_MENU_BUTTON (hamburger), menu);
- gtk_button_set_relief (GTK_BUTTON (hamburger), GTK_RELIEF_NONE);
- gtk_widget_show (hamburger);
-
- gtk_notebook_set_action_widget
- (GTK_NOTEBOOK (g.notebook), hamburger, GTK_PACK_END);
-
- // FIXME: when the clear icon shows, the widget changes in height
- g.entry = gtk_search_entry_new ();
- // TODO: attach to the "key-press-event" signal and implement ^W at least,
- // though ^U is working already! Note that bindings can be done in CSS
- // as well, if we have any extra specially for the editor
- g_signal_connect (g.entry, "changed", G_CALLBACK (on_changed), g.view);
- // TODO: make the entry have a background colour, rather than transparency
- gtk_entry_set_has_frame (GTK_ENTRY (g.entry), FALSE);
-
- // TODO: supposedly attach to "key-press-event" here and react to
- // PageUp/PageDown and up/down arrow keys... either here or in the Entry
- g.window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- gtk_window_set_default_size (GTK_WINDOW (g.window), 300, 600);
- g_signal_connect (g.window, "destroy",
- G_CALLBACK (on_destroy), NULL);
- g_signal_connect (g.window, "key-press-event",
- G_CALLBACK (on_key_press), NULL);
-
- GtkWidget *superbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 1);
- gtk_container_add (GTK_CONTAINER (g.window), superbox);
- gtk_container_add (GTK_CONTAINER (superbox), g.notebook);
- gtk_container_add (GTK_CONTAINER (superbox), g.entry);
- gtk_container_add (GTK_CONTAINER (superbox),
- gtk_separator_new (GTK_ORIENTATION_HORIZONTAL));
-
- g.view = stardict_view_new ();
- gtk_box_pack_end (GTK_BOX (superbox), g.view, TRUE, TRUE, 0);
-
- for (gsize i = 0; i < g.dictionaries_len; i++)
- {
- Dictionary *dict = &g.dictionaries[i];
- GtkWidget *dummy = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
- GtkWidget *label = gtk_label_new (dict->name);
- gtk_notebook_append_page (GTK_NOTEBOOK (g.notebook), dummy, label);
- }
-
- GtkClipboard *clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
- g_signal_connect (clipboard, "owner-change",
- G_CALLBACK (on_selection), NULL);
-
- gtk_widget_grab_focus (g.entry);
- gtk_widget_show_all (g.window);
- gtk_main ();
-
- g_strfreev (filenames);
- return 0;
-}
diff --git a/src/sdgui.c b/src/sdgui.c
new file mode 100644
index 0000000..3565bc6
--- /dev/null
+++ b/src/sdgui.c
@@ -0,0 +1,311 @@
+/*
+ * StarDict GTK+ UI
+ *
+ * Copyright (c) 2020 - 2021, Přemysl Eric Janouch
+ *
+ * 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
+#include
+
+#include
+
+#include "config.h"
+#include "stardict.h"
+#include "utils.h"
+#include "stardict-view.h"
+
+typedef struct dictionary Dictionary;
+
+struct dictionary
+{
+ const gchar *filename; ///< Filename
+ StardictDict *dict; ///< Stardict dictionary data
+ gchar *name; ///< Name to show
+ guint position; ///< Current position
+};
+
+static struct
+{
+ GtkWidget *window; ///< Top-level window
+ GtkWidget *notebook; ///< Notebook with tabs
+ GtkWidget *entry; ///< Search entry widget
+ GtkWidget *view; ///< Entries view
+
+ gint dictionary; ///< Index of the current dictionary
+ Dictionary *dictionaries; ///< All open dictionaries
+ gsize dictionaries_len; ///< Total number of dictionaries
+
+ gboolean watch_selection; ///< Following X11 PRIMARY?
+}
+g;
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+static gboolean
+dictionary_load (Dictionary *self, gchar *filename, GError **e)
+{
+ self->filename = filename;
+ if (!(self->dict = stardict_dict_new (self->filename, e)))
+ return FALSE;
+
+ if (!self->name)
+ {
+ self->name = g_strdup (stardict_info_get_book_name
+ (stardict_dict_get_info (self->dict)));
+ }
+ return TRUE;
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+static gboolean
+init (gchar **filenames, GError **e)
+{
+ while (filenames[g.dictionaries_len])
+ g.dictionaries_len++;
+
+ g.dictionaries = g_malloc0_n (sizeof *g.dictionaries, g.dictionaries_len);
+ for (gsize i = 0; i < g.dictionaries_len; i++)
+ {
+ Dictionary *dict = &g.dictionaries[i];
+ if (!dictionary_load (dict, filenames[i], e))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void
+search (Dictionary *dict)
+{
+ GtkEntryBuffer *buf = gtk_entry_get_buffer (GTK_ENTRY (g.entry));
+ const gchar *input_utf8 = gtk_entry_buffer_get_text (buf);
+
+ StardictIterator *iterator =
+ stardict_dict_search (dict->dict, input_utf8, NULL);
+ dict->position = stardict_iterator_get_offset (iterator);
+ g_object_unref (iterator);
+
+ stardict_view_set_position (STARDICT_VIEW (g.view),
+ dict->dict, dict->position);
+ stardict_view_set_matched (STARDICT_VIEW (g.view), input_utf8);
+}
+
+static void
+on_changed (G_GNUC_UNUSED GtkWidget *widget, G_GNUC_UNUSED gpointer data)
+{
+ search (&g.dictionaries[g.dictionary]);
+}
+
+static void
+on_selection_received (G_GNUC_UNUSED GtkClipboard *clipboard, const gchar *text,
+ G_GNUC_UNUSED gpointer data)
+{
+ if (!text)
+ return;
+
+ gtk_entry_set_text (GTK_ENTRY (g.entry), text);
+ g_signal_emit_by_name (g.entry,
+ "move-cursor", GTK_MOVEMENT_BUFFER_ENDS, 1, FALSE);
+}
+
+static void
+on_selection (GtkClipboard *clipboard, GdkEvent *event,
+ G_GNUC_UNUSED gpointer data)
+{
+ if (g.watch_selection
+ && !gtk_window_has_toplevel_focus (GTK_WINDOW (g.window))
+ && event->owner_change.owner != NULL)
+ gtk_clipboard_request_text (clipboard, on_selection_received, NULL);
+}
+
+static void
+on_selection_watch_toggle (GtkCheckMenuItem *item, G_GNUC_UNUSED gpointer data)
+{
+ g.watch_selection = gtk_check_menu_item_get_active (item);
+}
+
+static void
+on_switch_page (G_GNUC_UNUSED GtkWidget *widget, G_GNUC_UNUSED GtkWidget *page,
+ guint page_num, G_GNUC_UNUSED gpointer data)
+{
+ g.dictionary = page_num;
+ search (&g.dictionaries[g.dictionary]);
+}
+
+static gboolean
+on_key_press (G_GNUC_UNUSED GtkWidget *widget, GdkEvent *event,
+ G_GNUC_UNUSED gpointer data)
+{
+ if (event->key.state == GDK_CONTROL_MASK)
+ {
+ if (event->key.keyval == GDK_KEY_Page_Up)
+ {
+ gtk_notebook_prev_page (GTK_NOTEBOOK (g.notebook));
+ return TRUE;
+ }
+ if (event->key.keyval == GDK_KEY_Page_Down)
+ {
+ gtk_notebook_next_page (GTK_NOTEBOOK (g.notebook));
+ return TRUE;
+ }
+ }
+ if (event->key.state == GDK_MOD1_MASK)
+ {
+ if (event->key.keyval >= GDK_KEY_0
+ && event->key.keyval <= GDK_KEY_9)
+ {
+ gint n = event->key.keyval - GDK_KEY_0;
+ gtk_notebook_set_current_page
+ (GTK_NOTEBOOK (g.notebook), n ? (n - 1) : 10);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static void
+on_destroy (G_GNUC_UNUSED GtkWidget *widget, G_GNUC_UNUSED gpointer data)
+{
+ gtk_main_quit ();
+}
+
+static void
+die_with_dialog (const gchar *message)
+{
+ GtkWidget *dialog = gtk_message_dialog_new (NULL, 0,
+ GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s", message);
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+ exit (EXIT_FAILURE);
+}
+
+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);
+
+ 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;
+ }
+
+ if (!filenames)
+ {
+ // TODO: eventually just load all dictionaries from configuration
+ die_with_dialog ("No arguments have been passed.");
+ }
+ if (!init (filenames, &error))
+ die_with_dialog (error->message);
+
+ // Some Adwaita stupidity
+ const char *style = "notebook header tab { padding: 2px 8px; margin: 0; }";
+
+ GdkScreen *screen = gdk_screen_get_default ();
+ GtkCssProvider *provider = gtk_css_provider_new ();
+ gtk_css_provider_load_from_data (provider, style, strlen (style), NULL);
+ gtk_style_context_add_provider_for_screen (screen,
+ GTK_STYLE_PROVIDER (provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+
+ g.notebook = gtk_notebook_new ();
+ g_signal_connect (g.notebook, "switch-page",
+ G_CALLBACK (on_switch_page), NULL);
+ gtk_notebook_set_scrollable (GTK_NOTEBOOK (g.notebook), TRUE);
+
+ g.watch_selection = TRUE;
+ GtkWidget *item =
+ gtk_check_menu_item_new_with_label (_("Follow selection"));
+ gtk_check_menu_item_set_active
+ (GTK_CHECK_MENU_ITEM (item), g.watch_selection);
+ g_signal_connect (item, "toggled",
+ G_CALLBACK (on_selection_watch_toggle), NULL);
+
+ GtkWidget *menu = gtk_menu_new ();
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show_all (menu);
+
+ GtkWidget *hamburger = gtk_menu_button_new ();
+ gtk_menu_button_set_direction (GTK_MENU_BUTTON (hamburger), GTK_ARROW_NONE);
+ gtk_menu_button_set_popup (GTK_MENU_BUTTON (hamburger), menu);
+ gtk_button_set_relief (GTK_BUTTON (hamburger), GTK_RELIEF_NONE);
+ gtk_widget_show (hamburger);
+
+ gtk_notebook_set_action_widget
+ (GTK_NOTEBOOK (g.notebook), hamburger, GTK_PACK_END);
+
+ // FIXME: when the clear icon shows, the widget changes in height
+ g.entry = gtk_search_entry_new ();
+ // TODO: attach to the "key-press-event" signal and implement ^W at least,
+ // though ^U is working already! Note that bindings can be done in CSS
+ // as well, if we have any extra specially for the editor
+ g_signal_connect (g.entry, "changed", G_CALLBACK (on_changed), g.view);
+ // TODO: make the entry have a background colour, rather than transparency
+ gtk_entry_set_has_frame (GTK_ENTRY (g.entry), FALSE);
+
+ // TODO: supposedly attach to "key-press-event" here and react to
+ // PageUp/PageDown and up/down arrow keys... either here or in the Entry
+ g.window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_default_size (GTK_WINDOW (g.window), 300, 600);
+ g_signal_connect (g.window, "destroy",
+ G_CALLBACK (on_destroy), NULL);
+ g_signal_connect (g.window, "key-press-event",
+ G_CALLBACK (on_key_press), NULL);
+
+ GtkWidget *superbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 1);
+ gtk_container_add (GTK_CONTAINER (g.window), superbox);
+ gtk_container_add (GTK_CONTAINER (superbox), g.notebook);
+ gtk_container_add (GTK_CONTAINER (superbox), g.entry);
+ gtk_container_add (GTK_CONTAINER (superbox),
+ gtk_separator_new (GTK_ORIENTATION_HORIZONTAL));
+
+ g.view = stardict_view_new ();
+ gtk_box_pack_end (GTK_BOX (superbox), g.view, TRUE, TRUE, 0);
+
+ for (gsize i = 0; i < g.dictionaries_len; i++)
+ {
+ Dictionary *dict = &g.dictionaries[i];
+ GtkWidget *dummy = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+ GtkWidget *label = gtk_label_new (dict->name);
+ gtk_notebook_append_page (GTK_NOTEBOOK (g.notebook), dummy, label);
+ }
+
+ GtkClipboard *clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
+ g_signal_connect (clipboard, "owner-change",
+ G_CALLBACK (on_selection), NULL);
+
+ gtk_widget_grab_focus (g.entry);
+ gtk_widget_show_all (g.window);
+ gtk_main ();
+
+ g_strfreev (filenames);
+ return 0;
+}
diff --git a/src/sdtui.c b/src/sdtui.c
index 3be34f4..1158d05 100644
--- a/src/sdtui.c
+++ b/src/sdtui.c
@@ -36,8 +36,12 @@
#include
#include
-#include // input
-#include // output
+#include // input
+#include // output
+#include
+#ifndef TIOCGWINSZ
+#include
+#endif // ! TIOCGWINSZ
#include "config.h"
#include "stardict.h"
@@ -62,6 +66,27 @@ unichar_width (gunichar ch)
return 1 + g_unichar_iswide (ch);
}
+void
+update_curses_terminal_size (void)
+{
+#if defined (HAVE_RESIZETERM) && defined (TIOCGWINSZ)
+ struct winsize size;
+ if (!ioctl (STDOUT_FILENO, TIOCGWINSZ, (char *) &size))
+ {
+ char *row = getenv ("LINES");
+ char *col = getenv ("COLUMNS");
+ unsigned long tmp;
+ resizeterm (
+ (row && xstrtoul (&tmp, row, 10)) ? tmp : size.ws_row,
+ (col && xstrtoul (&tmp, col, 10)) ? tmp : size.ws_col);
+ }
+#else // HAVE_RESIZETERM && TIOCGWINSZ
+ // The standard endwin/refresh sequence makes the terminal flicker.
+ endwin ();
+ refresh ();
+#endif // HAVE_RESIZETERM && TIOCGWINSZ
+}
+
static guint
add_read_watch (int fd, GIOFunc func, gpointer user_data)
{
diff --git a/src/utils.c b/src/utils.c
index 275e4e1..3bba022 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -23,12 +23,6 @@
#include
#include
-#include
-#include
-#ifndef TIOCGWINSZ
-#include
-#endif // ! TIOCGWINSZ
-
#include "config.h"
#include "utils.h"
@@ -101,28 +95,6 @@ xstrtoul (unsigned long *out, const char *s, int base)
return errno == 0 && !*end && end != s;
}
-// Didn't want to have this ugly piece of code in the main source file;
-// the standard endwin/refresh sequence makes the terminal flicker.
-void
-update_curses_terminal_size (void)
-{
-#if defined (HAVE_RESIZETERM) && defined (TIOCGWINSZ)
- struct winsize size;
- if (!ioctl (STDOUT_FILENO, TIOCGWINSZ, (char *) &size))
- {
- char *row = getenv ("LINES");
- char *col = getenv ("COLUMNS");
- unsigned long tmp;
- resizeterm (
- (row && xstrtoul (&tmp, row, 10)) ? tmp : size.ws_row,
- (col && xstrtoul (&tmp, col, 10)) ? tmp : size.ws_col);
- }
-#else // HAVE_RESIZETERM && TIOCGWINSZ
- endwin ();
- refresh ();
-#endif // HAVE_RESIZETERM && TIOCGWINSZ
-}
-
/// Print a fatal error message and terminate the process immediately.
void
fatal (const gchar *format, ...)
diff --git a/src/utils.h b/src/utils.h
index 99ad19a..b47daa9 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -41,7 +41,6 @@ gchar *xdxf_to_pango_markup_with_reduced_effort (const gchar *xml);
gboolean stream_read_all (GByteArray *ba, GInputStream *is, GError **error);
gchar *stream_read_string (GDataInputStream *dis, GError **error);
gboolean xstrtoul (unsigned long *out, const char *s, int base);
-void update_curses_terminal_size (void);
void fatal (const gchar *format, ...) G_GNUC_PRINTF (1, 2) G_GNUC_NORETURN;
#endif // ! UTILS_H
--
cgit v1.2.3-70-g09d2