|
Packit |
116408 |
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
|
|
Packit |
116408 |
/*
|
|
Packit |
116408 |
* Copyright (C) 2001 Mikael Hallendal <micke@imendio.com>
|
|
Packit |
116408 |
* Copyright (C) 2004, 2008 Imendio AB
|
|
Packit |
116408 |
* Copyright (C) 2015, 2017, 2018 Sébastien Wilmet <swilmet@gnome.org>
|
|
Packit |
116408 |
*
|
|
Packit |
116408 |
* This program is free software; you can redistribute it and/or
|
|
Packit |
116408 |
* modify it under the terms of the GNU General Public License as
|
|
Packit |
116408 |
* published by the Free Software Foundation; either version 2 of the
|
|
Packit |
116408 |
* License, or (at your option) any later version.
|
|
Packit |
116408 |
*
|
|
Packit |
116408 |
* This program is distributed in the hope that it will be useful,
|
|
Packit |
116408 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
116408 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
116408 |
* General Public License for more details.
|
|
Packit |
116408 |
*
|
|
Packit |
116408 |
* You should have received a copy of the GNU General Public License
|
|
Packit |
116408 |
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
116408 |
*/
|
|
Packit |
116408 |
|
|
Packit |
116408 |
#include "dh-util.h"
|
|
Packit |
116408 |
#include "dh-link.h"
|
|
Packit |
116408 |
|
|
Packit |
116408 |
gchar *
|
|
Packit |
116408 |
dh_util_build_data_filename (const gchar *first_part,
|
|
Packit |
116408 |
...)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
gchar *datadir = NULL;
|
|
Packit |
116408 |
va_list args;
|
|
Packit |
116408 |
const gchar *part;
|
|
Packit |
116408 |
gchar **strv;
|
|
Packit |
116408 |
gint i;
|
|
Packit |
116408 |
gchar *ret;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
va_start (args, first_part);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if (datadir == NULL) {
|
|
Packit |
116408 |
datadir = g_strdup (DATADIR);
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* 2 = 1 initial component + terminating NULL element. */
|
|
Packit |
116408 |
strv = g_malloc (sizeof (gchar *) * 2);
|
|
Packit |
116408 |
strv[0] = (gchar *) datadir;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
i = 1;
|
|
Packit |
116408 |
for (part = first_part; part; part = va_arg (args, char *), i++) {
|
|
Packit |
116408 |
/* +2 = 1 new element + terminating NULL element. */
|
|
Packit |
116408 |
strv = g_realloc (strv, sizeof (gchar*) * (i + 2));
|
|
Packit |
116408 |
strv[i] = (gchar *) part;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
strv[i] = NULL;
|
|
Packit |
116408 |
ret = g_build_filenamev (strv);
|
|
Packit |
116408 |
g_free (strv);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
g_free (datadir);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
va_end (args);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
return ret;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* We're only going to expect ASCII strings here, so there's no point in
|
|
Packit |
116408 |
* playing with g_unichar_totitle() and such.
|
|
Packit |
116408 |
* Note that we modify the string in place.
|
|
Packit |
116408 |
*/
|
|
Packit |
116408 |
void
|
|
Packit |
116408 |
dh_util_ascii_strtitle (gchar *str)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
gboolean word_start;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if (str == NULL)
|
|
Packit |
116408 |
return;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
word_start = TRUE;
|
|
Packit |
116408 |
while (*str != '\0') {
|
|
Packit |
116408 |
if (g_ascii_isalpha (*str)) {
|
|
Packit |
116408 |
*str = (word_start ?
|
|
Packit |
116408 |
g_ascii_toupper (*str) :
|
|
Packit |
116408 |
g_ascii_tolower (*str));
|
|
Packit |
116408 |
word_start = FALSE;
|
|
Packit |
116408 |
} else {
|
|
Packit |
116408 |
word_start = TRUE;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
str++;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
gchar *
|
|
Packit |
116408 |
dh_util_create_data_uri_for_filename (const gchar *filename,
|
|
Packit |
116408 |
const gchar *mime_type)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
gchar *data;
|
|
Packit |
116408 |
gsize data_length;
|
|
Packit |
116408 |
gchar *base64;
|
|
Packit |
116408 |
gchar *uri;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if (!g_file_get_contents (filename, &data, &data_length, NULL))
|
|
Packit |
116408 |
return NULL;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
base64 = g_base64_encode ((const guchar *)data, data_length);
|
|
Packit |
116408 |
g_free (data);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
uri = g_strdup_printf ("data:%s;charset=utf8;base64,%s", mime_type, base64);
|
|
Packit |
116408 |
g_free(base64);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
return uri;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* Set the given fonts on the given view. */
|
|
Packit |
116408 |
void
|
|
Packit |
116408 |
dh_util_view_set_font (WebKitWebView *view,
|
|
Packit |
116408 |
const gchar *font_name_fixed,
|
|
Packit |
116408 |
const gchar *font_name_variable)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
PangoFontDescription *font_desc_fixed;
|
|
Packit |
116408 |
PangoFontDescription *font_desc_variable;
|
|
Packit |
116408 |
guint font_size_fixed;
|
|
Packit |
116408 |
guint font_size_variable;
|
|
Packit |
116408 |
guint font_size_fixed_px;
|
|
Packit |
116408 |
guint font_size_variable_px;
|
|
Packit |
116408 |
WebKitSettings *settings;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
g_return_if_fail (WEBKIT_IS_WEB_VIEW (view));
|
|
Packit |
116408 |
g_return_if_fail (font_name_fixed != NULL);
|
|
Packit |
116408 |
g_return_if_fail (font_name_variable != NULL);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* Get the font size. */
|
|
Packit |
116408 |
font_desc_fixed = pango_font_description_from_string (font_name_fixed);
|
|
Packit |
116408 |
font_desc_variable = pango_font_description_from_string (font_name_variable);
|
|
Packit |
116408 |
font_size_fixed = pango_font_description_get_size (font_desc_fixed) / PANGO_SCALE;
|
|
Packit |
116408 |
font_size_variable = pango_font_description_get_size (font_desc_variable) / PANGO_SCALE;
|
|
Packit |
116408 |
font_size_fixed_px = webkit_settings_font_size_to_pixels (font_size_fixed);
|
|
Packit |
116408 |
font_size_variable_px = webkit_settings_font_size_to_pixels (font_size_variable);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* Set the fonts. */
|
|
Packit |
116408 |
settings = webkit_web_view_get_settings (view);
|
|
Packit |
116408 |
webkit_settings_set_zoom_text_only (settings, TRUE);
|
|
Packit |
116408 |
webkit_settings_set_monospace_font_family (settings, font_name_fixed);
|
|
Packit |
116408 |
webkit_settings_set_default_monospace_font_size (settings, font_size_fixed_px);
|
|
Packit |
116408 |
webkit_settings_set_serif_font_family (settings, font_name_variable);
|
|
Packit |
116408 |
webkit_settings_set_default_font_size (settings, font_size_variable_px);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
g_debug ("Set font-fixed to '%s' (%i) and font-variable to '%s' (%i).",
|
|
Packit |
116408 |
font_name_fixed, font_size_fixed_px, font_name_variable, font_size_variable_px);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
pango_font_description_free (font_desc_fixed);
|
|
Packit |
116408 |
pango_font_description_free (font_desc_variable);
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
static void
|
|
Packit |
116408 |
introspect_window_gsettings (GSettings *window_settings,
|
|
Packit |
116408 |
gboolean *has_required_keys,
|
|
Packit |
116408 |
gboolean *has_maximized_key)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
GSettingsSchema *schema = NULL;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
g_object_get (window_settings,
|
|
Packit |
116408 |
"settings-schema", &schema,
|
|
Packit |
116408 |
NULL);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
*has_required_keys = (g_settings_schema_has_key (schema, "width") &&
|
|
Packit |
116408 |
g_settings_schema_has_key (schema, "height"));
|
|
Packit |
116408 |
|
|
Packit |
116408 |
*has_maximized_key = g_settings_schema_has_key (schema, "maximized");
|
|
Packit |
116408 |
|
|
Packit |
116408 |
g_settings_schema_unref (schema);
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
void
|
|
Packit |
116408 |
dh_util_window_settings_save (GtkWindow *window,
|
|
Packit |
116408 |
GSettings *settings)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
gboolean has_required_keys;
|
|
Packit |
116408 |
gboolean has_maximized_key;
|
|
Packit |
116408 |
gint width;
|
|
Packit |
116408 |
gint height;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
g_return_if_fail (GTK_IS_WINDOW (window));
|
|
Packit |
116408 |
g_return_if_fail (G_IS_SETTINGS (settings));
|
|
Packit |
116408 |
|
|
Packit |
116408 |
introspect_window_gsettings (settings, &has_required_keys, &has_maximized_key);
|
|
Packit |
116408 |
g_return_if_fail (has_required_keys);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if (has_maximized_key) {
|
|
Packit |
116408 |
GdkWindowState state;
|
|
Packit |
116408 |
gboolean maximized;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
state = gdk_window_get_state (gtk_widget_get_window (GTK_WIDGET (window)));
|
|
Packit |
116408 |
maximized = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
g_settings_set_boolean (settings, "maximized", maximized);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* If maximized don't save the size. */
|
|
Packit |
116408 |
if (maximized)
|
|
Packit |
116408 |
return;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* Store the dimensions */
|
|
Packit |
116408 |
gtk_window_get_size (GTK_WINDOW (window), &width, &height);
|
|
Packit |
116408 |
g_settings_set_int (settings, "width", width);
|
|
Packit |
116408 |
g_settings_set_int (settings, "height", height);
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* This should be called when @gtk_window is realized (i.e. its GdkWindow is
|
|
Packit |
116408 |
* created) but not yet mapped (i.e. gtk_widget_show() has not yet been called,
|
|
Packit |
116408 |
* so that when it is shown it already has the good size).
|
|
Packit |
116408 |
*/
|
|
Packit |
116408 |
void
|
|
Packit |
116408 |
dh_util_window_settings_restore (GtkWindow *gtk_window,
|
|
Packit |
116408 |
GSettings *settings)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
gboolean has_required_keys;
|
|
Packit |
116408 |
gboolean has_maximized_key;
|
|
Packit |
116408 |
gint width;
|
|
Packit |
116408 |
gint height;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
g_return_if_fail (GTK_IS_WINDOW (gtk_window));
|
|
Packit |
116408 |
g_return_if_fail (gtk_widget_get_realized (GTK_WIDGET (gtk_window)));
|
|
Packit |
116408 |
g_return_if_fail (G_IS_SETTINGS (settings));
|
|
Packit |
116408 |
|
|
Packit |
116408 |
introspect_window_gsettings (settings, &has_required_keys, &has_maximized_key);
|
|
Packit |
116408 |
g_return_if_fail (has_required_keys);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
width = g_settings_get_int (settings, "width");
|
|
Packit |
116408 |
height = g_settings_get_int (settings, "height");
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if (width > 1 && height > 1) {
|
|
Packit |
116408 |
GdkDisplay *display;
|
|
Packit |
116408 |
GdkWindow *gdk_window;
|
|
Packit |
116408 |
GdkMonitor *monitor;
|
|
Packit |
116408 |
GdkRectangle monitor_workarea;
|
|
Packit |
116408 |
gint max_width;
|
|
Packit |
116408 |
gint max_height;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
display = gtk_widget_get_display (GTK_WIDGET (gtk_window));
|
|
Packit |
116408 |
/* To get the GdkWindow the widget must be realized. */
|
|
Packit |
116408 |
gdk_window = gtk_widget_get_window (GTK_WIDGET (gtk_window));
|
|
Packit |
116408 |
monitor = gdk_display_get_monitor_at_window (display, gdk_window);
|
|
Packit |
116408 |
gdk_monitor_get_workarea (monitor, &monitor_workarea);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
max_width = monitor_workarea.width;
|
|
Packit |
116408 |
max_height = monitor_workarea.height;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
width = CLAMP (width, 0, max_width);
|
|
Packit |
116408 |
height = CLAMP (height, 0, max_height);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
gtk_window_set_default_size (gtk_window, width, height);
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if (has_maximized_key && g_settings_get_boolean (settings, "maximized"))
|
|
Packit |
116408 |
gtk_window_maximize (gtk_window);
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* Adds q2 onto the end of q1, and frees q2. */
|
|
Packit |
116408 |
void
|
|
Packit |
116408 |
dh_util_queue_concat (GQueue *q1,
|
|
Packit |
116408 |
GQueue *q2)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
g_return_if_fail (q1 != NULL);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if (q2 == NULL)
|
|
Packit |
116408 |
return;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
if (q1->head == NULL) {
|
|
Packit |
116408 |
g_assert_cmpint (q1->length, ==, 0);
|
|
Packit |
116408 |
g_assert (q1->tail == NULL);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
q1->head = q2->head;
|
|
Packit |
116408 |
q1->tail = q2->tail;
|
|
Packit |
116408 |
q1->length = q2->length;
|
|
Packit |
116408 |
} else if (q2->head != NULL) {
|
|
Packit |
116408 |
g_assert_cmpint (q1->length, >, 0);
|
|
Packit |
116408 |
g_assert_cmpint (q2->length, >, 0);
|
|
Packit |
116408 |
g_assert (q1->tail != NULL);
|
|
Packit |
116408 |
g_assert (q2->tail != NULL);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
q1->tail->next = q2->head;
|
|
Packit |
116408 |
q2->head->prev = q1->tail;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
q1->tail = q2->tail;
|
|
Packit |
116408 |
q1->length += q2->length;
|
|
Packit |
116408 |
} else {
|
|
Packit |
116408 |
g_assert_cmpint (q2->length, ==, 0);
|
|
Packit |
116408 |
g_assert (q2->tail == NULL);
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
q2->head = NULL;
|
|
Packit |
116408 |
q2->tail = NULL;
|
|
Packit |
116408 |
q2->length = 0;
|
|
Packit |
116408 |
g_queue_free (q2);
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
static gboolean
|
|
Packit |
116408 |
unref_node_link (GNode *node,
|
|
Packit |
116408 |
gpointer data)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
dh_link_unref (node->data);
|
|
Packit |
116408 |
return FALSE;
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
void
|
|
Packit |
116408 |
_dh_util_free_book_tree (GNode *book_tree)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
if (book_tree == NULL)
|
|
Packit |
116408 |
return;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
g_node_traverse (book_tree,
|
|
Packit |
116408 |
G_IN_ORDER,
|
|
Packit |
116408 |
G_TRAVERSE_ALL,
|
|
Packit |
116408 |
-1,
|
|
Packit |
116408 |
unref_node_link,
|
|
Packit |
116408 |
NULL);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
g_node_destroy (book_tree);
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* Returns: (transfer full) (element-type GFile): the list of possible Devhelp
|
|
Packit |
116408 |
* index files in @book_directory, in order of preference.
|
|
Packit |
116408 |
*/
|
|
Packit |
116408 |
GSList *
|
|
Packit |
116408 |
_dh_util_get_possible_index_files (GFile *book_directory)
|
|
Packit |
116408 |
{
|
|
Packit |
116408 |
const gchar *extensions[] = {
|
|
Packit |
116408 |
".devhelp2",
|
|
Packit |
116408 |
".devhelp2.gz",
|
|
Packit |
116408 |
".devhelp",
|
|
Packit |
116408 |
".devhelp.gz",
|
|
Packit |
116408 |
NULL
|
|
Packit |
116408 |
};
|
|
Packit |
116408 |
gchar *directory_name;
|
|
Packit |
116408 |
GSList *list = NULL;
|
|
Packit |
116408 |
gint i;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
g_return_val_if_fail (G_IS_FILE (book_directory), NULL);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
directory_name = g_file_get_basename (book_directory);
|
|
Packit |
116408 |
g_return_val_if_fail (directory_name != NULL, NULL);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
for (i = 0; extensions[i] != NULL; i++) {
|
|
Packit |
116408 |
const gchar *cur_extension = extensions[i];
|
|
Packit |
116408 |
gchar *index_file_name;
|
|
Packit |
116408 |
GFile *index_file;
|
|
Packit |
116408 |
|
|
Packit |
116408 |
/* The name of the directory the index file is in and the name
|
|
Packit |
116408 |
* of the index file (minus the extension) must match.
|
|
Packit |
116408 |
*/
|
|
Packit |
116408 |
index_file_name = g_strconcat (directory_name, cur_extension, NULL);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
index_file = g_file_get_child (book_directory, index_file_name);
|
|
Packit |
116408 |
list = g_slist_prepend (list, index_file);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
g_free (index_file_name);
|
|
Packit |
116408 |
}
|
|
Packit |
116408 |
|
|
Packit |
116408 |
list = g_slist_reverse (list);
|
|
Packit |
116408 |
|
|
Packit |
116408 |
g_free (directory_name);
|
|
Packit |
116408 |
return list;
|
|
Packit |
116408 |
}
|