utils.c 7.93 KB
Newer Older
1
/* SPDX-License-Identifier: Zlib */
2 3

#include <stdlib.h>
Moritz Lipp's avatar
Moritz Lipp committed
4
#include <stdarg.h>
Moritz Lipp's avatar
Moritz Lipp committed
5
#include <string.h>
6
#include <stdio.h>
Moritz Lipp's avatar
Moritz Lipp committed
7
#include <math.h>
Moritz Lipp's avatar
Moritz Lipp committed
8
#include <gtk/gtk.h>
9
#include <girara/datastructures.h>
Moritz Lipp's avatar
Moritz Lipp committed
10
#include <girara/session.h>
Julian Orth's avatar
Julian Orth committed
11
#include <girara/settings.h>
12
#include <girara/utils.h>
13

Moritz Lipp's avatar
Moritz Lipp committed
14
#include "links.h"
15
#include "utils.h"
16
#include "zathura.h"
17
#include "internal.h"
18
#include "document.h"
Moritz Lipp's avatar
Moritz Lipp committed
19
#include "page.h"
20
#include "plugin.h"
21
#include "content-type.h"
22

23
double
24
zathura_correct_zoom_value(girara_session_t* session, const double zoom)
25 26
{
  if (session == NULL) {
27
    return zoom;
28 29 30 31 32 33 34 35 36 37 38
  }

  /* zoom limitations */
  int zoom_min_int = 10;
  int zoom_max_int = 1000;
  girara_setting_get(session, "zoom-min", &zoom_min_int);
  girara_setting_get(session, "zoom-max", &zoom_max_int);

  const double zoom_min = zoom_min_int * 0.01;
  const double zoom_max = zoom_max_int * 0.01;

39
  if (zoom < zoom_min) {
40
    return zoom_min;
41
  } else if (zoom > zoom_max) {
42 43
    return zoom_max;
  } else {
44
    return zoom;
45 46 47
  }
}

48 49 50
bool
file_valid_extension(zathura_t* zathura, const char* path)
{
51
  if (zathura == NULL || path == NULL || zathura->plugins.manager == NULL) {
52 53 54
    return false;
  }

Sebastian Ramacher's avatar
Sebastian Ramacher committed
55
  char* content_type = zathura_content_type_guess(zathura->content_type_context, path);
56
  if (content_type == NULL) {
57 58 59
    return false;
  }

Sebastian Ramacher's avatar
Sebastian Ramacher committed
60 61
  zathura_plugin_t* plugin = zathura_plugin_manager_get_plugin(zathura->plugins.manager, content_type);
  g_free(content_type);
Moritz Lipp's avatar
Moritz Lipp committed
62 63

  return (plugin == NULL) ? false : true;
64 65
}

66 67 68 69 70 71 72
static void
index_element_free(void* data, GObject* UNUSED(object))
{
  zathura_index_element_t* element = data;
  zathura_index_element_free(element);
}

73
void
Sebastian Ramacher's avatar
Sebastian Ramacher committed
74
document_index_build(GtkTreeModel* model, GtkTreeIter* parent,
Moritz Lipp's avatar
Moritz Lipp committed
75
                     girara_tree_node_t* tree)
76
{
Sebastian Ramacher's avatar
Sebastian Ramacher committed
77 78
  girara_list_t* list = girara_node_get_children(tree);

79
  GIRARA_LIST_FOREACH_BODY(list, girara_tree_node_t*, node,
80
    zathura_index_element_t* index_element = girara_node_get_data(node);
Sebastian Ramacher's avatar
Sebastian Ramacher committed
81 82 83 84 85 86 87 88 89 90 91 92 93

    zathura_link_type_t type     = zathura_link_get_type(index_element->link);
    zathura_link_target_t target = zathura_link_get_target(index_element->link);

    gchar* description = NULL;
    if (type == ZATHURA_LINK_GOTO_DEST) {
      description = g_strdup_printf("Page %d", target.page_number + 1);
    } else {
      description = g_strdup(target.value);
    }

    GtkTreeIter tree_iter;
    gtk_tree_store_append(GTK_TREE_STORE(model), &tree_iter, parent);
94 95 96
    gchar* markup = g_markup_escape_text(index_element->title, -1);
    gtk_tree_store_set(GTK_TREE_STORE(model), &tree_iter, 0, markup, 1, description, 2, index_element, -1);
    g_free(markup);
97
    g_object_weak_ref(G_OBJECT(model), index_element_free, index_element);
Sebastian Ramacher's avatar
Sebastian Ramacher committed
98 99 100 101 102
    g_free(description);

    if (girara_node_get_num_children(node) > 0) {
      document_index_build(model, &tree_iter, node);
    }
103
  );
104
}
Moritz Lipp's avatar
Moritz Lipp committed
105

106 107
zathura_rectangle_t
rotate_rectangle(zathura_rectangle_t rectangle, unsigned int degree, double height, double width)
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
{
  zathura_rectangle_t tmp;
  switch (degree) {
    case 90:
      tmp.x1 = height - rectangle.y2;
      tmp.x2 = height - rectangle.y1;
      tmp.y1 = rectangle.x1;
      tmp.y2 = rectangle.x2;
      break;
    case 180:
      tmp.x1 = width - rectangle.x2;
      tmp.x2 = width - rectangle.x1;
      tmp.y1 = height - rectangle.y2;
      tmp.y2 = height - rectangle.y1;
      break;
    case 270:
      tmp.x1 = rectangle.y1;
      tmp.x2 = rectangle.y2;
      tmp.y1 = width - rectangle.x2;
      tmp.y2 = width - rectangle.x1;
      break;
    default:
      tmp.x1 = rectangle.x1;
      tmp.x2 = rectangle.x2;
      tmp.y1 = rectangle.y1;
      tmp.y2 = rectangle.y2;
  }

  return tmp;
}

Moritz Lipp's avatar
Moritz Lipp committed
139 140 141
zathura_rectangle_t
recalc_rectangle(zathura_page_t* page, zathura_rectangle_t rectangle)
{
Moritz Lipp's avatar
Moritz Lipp committed
142 143
  if (page == NULL) {
    goto error_ret;
Moritz Lipp's avatar
Moritz Lipp committed
144 145
  }

Moritz Lipp's avatar
Moritz Lipp committed
146 147 148 149 150 151 152 153
  zathura_document_t* document = zathura_page_get_document(page);

  if (document == NULL) {
    goto error_ret;
  }

  double page_height = zathura_page_get_height(page);
  double page_width  = zathura_page_get_width(page);
154
  double scale       = zathura_document_get_scale(document);
Moritz Lipp's avatar
Moritz Lipp committed
155

156 157 158 159 160
  zathura_rectangle_t tmp = rotate_rectangle(rectangle, zathura_document_get_rotation(document), page_height, page_width);
  tmp.x1 *= scale;
  tmp.x2 *= scale;
  tmp.y1 *= scale;
  tmp.y2 *= scale;
Moritz Lipp's avatar
Moritz Lipp committed
161 162

  return tmp;
Moritz Lipp's avatar
Moritz Lipp committed
163 164 165 166

error_ret:

  return rectangle;
Moritz Lipp's avatar
Moritz Lipp committed
167
}
168

169 170 171 172 173 174 175 176 177 178 179
GtkWidget*
zathura_page_get_widget(zathura_t* zathura, zathura_page_t* page)
{
  if (zathura == NULL || page == NULL || zathura->pages == NULL) {
    return NULL;
  }

  unsigned int page_number = zathura_page_get_index(page);

  return zathura->pages[page_number];
}
Moritz Lipp's avatar
Moritz Lipp committed
180

181 182 183 184 185 186 187 188 189 190 191 192
void
document_draw_search_results(zathura_t* zathura, bool value)
{
  if (zathura == NULL || zathura->document == NULL || zathura->pages == NULL) {
    return;
  }

  unsigned int number_of_pages = zathura_document_get_number_of_pages(zathura->document);
  for (unsigned int page_id = 0; page_id < number_of_pages; page_id++) {
    g_object_set(zathura->pages[page_id], "draw-search-results", (value == true) ? TRUE : FALSE, NULL);
  }
}
193 194 195 196

char*
zathura_get_version_string(zathura_t* zathura, bool markup)
{
Moritz Lipp's avatar
Moritz Lipp committed
197 198 199
  if (zathura == NULL) {
    return NULL;
  }
200 201 202 203

  GString* string = g_string_new(NULL);

  /* zathura version */
204 205
  g_string_append(string, "zathura " ZATHURA_VERSION);
  g_string_append_printf(string, "\ngirara " GIRARA_VERSION " (runtime: %s)", girara_version());
206

Sebastian Ramacher's avatar
Sebastian Ramacher committed
207
  const char* format = (markup == true) ? "\n<i>(plugin)</i> %s (%d.%d.%d) <i>(%s)</i>" : "\n(plugin) %s (%d.%d.%d) (%s)";
208 209 210 211

  /* plugin information */
  girara_list_t* plugins = zathura_plugin_manager_get_plugins(zathura->plugins.manager);
  if (plugins != NULL) {
212
    GIRARA_LIST_FOREACH_BODY(plugins, zathura_plugin_t*, plugin,
Sebastian Ramacher's avatar
Sebastian Ramacher committed
213
      const char* name = zathura_plugin_get_name(plugin);
Sebastian Ramacher's avatar
Sebastian Ramacher committed
214
      zathura_plugin_version_t version = zathura_plugin_get_version(plugin);
215 216 217 218 219 220
      g_string_append_printf(string, format,
                             (name == NULL) ? "-" : name,
                             version.major,
                             version.minor,
                             version.rev,
                             zathura_plugin_get_path(plugin));
221
    );
222 223
  }

Moritz Lipp's avatar
Moritz Lipp committed
224 225
  char* version = string->str;
  g_string_free(string, FALSE);
226

Moritz Lipp's avatar
Moritz Lipp committed
227
  return version;
228
}
Moritz Lipp's avatar
Moritz Lipp committed
229

Sebastian Ramacher's avatar
Sebastian Ramacher committed
230 231
GdkAtom*
get_selection(zathura_t* zathura)
232
{
Sebastian Ramacher's avatar
Sebastian Ramacher committed
233
  g_return_val_if_fail(zathura != NULL, NULL);
234

235
  char* value = NULL;
Sebastian Ramacher's avatar
Sebastian Ramacher committed
236
  girara_setting_get(zathura->ui.session, "selection-clipboard", &value);
237 238 239
  if (value == NULL) {
    return NULL;
  }
240

241 242
  GdkAtom* selection = g_try_malloc(sizeof(GdkAtom));
  if (selection == NULL) {
243
    g_free(selection);
244 245
    return NULL;
  }
246

Sebastian Ramacher's avatar
Sebastian Ramacher committed
247 248 249 250 251 252 253 254
  if (strcmp(value, "primary") == 0) {
    *selection = GDK_SELECTION_PRIMARY;
  } else if (strcmp(value, "clipboard") == 0) {
    *selection = GDK_SELECTION_CLIPBOARD;
  } else {
    girara_error("Invalid value for the selection-clipboard setting");
    g_free(value);
    g_free(selection);
255

Sebastian Ramacher's avatar
Sebastian Ramacher committed
256 257
    return NULL;
  }
258

Sebastian Ramacher's avatar
Sebastian Ramacher committed
259
  g_free(value);
260

Sebastian Ramacher's avatar
Sebastian Ramacher committed
261
  return selection;
262
}
263 264 265 266 267 268 269

unsigned int
find_first_page_column(const char* first_page_column_list,
                       const unsigned int pages_per_row)
{
  /* sanity checks */
  unsigned int first_page_column = 1;
Sebastian Ramacher's avatar
Sebastian Ramacher committed
270 271 272
  g_return_val_if_fail(first_page_column_list != NULL,  first_page_column);
  g_return_val_if_fail(*first_page_column_list != '\0', first_page_column);
  g_return_val_if_fail(pages_per_row > 0,               first_page_column);
273 274

  /* split settings list */
Sebastian Ramacher's avatar
Sebastian Ramacher committed
275
  char** settings = g_strsplit(first_page_column_list, ":", pages_per_row + 1);
Sebastian Ramacher's avatar
Sebastian Ramacher committed
276
  const size_t settings_size = g_strv_length(settings);
277 278 279

  /* read setting value corresponding to the specified pages per row */
  unsigned int index = pages_per_row - 1;
Sebastian Ramacher's avatar
Sebastian Ramacher committed
280
  if (index < settings_size && *settings[index] != '\0') {
281
    first_page_column = atoi(settings[index]);
282 283
  } else if (*settings[settings_size - 1] != '\0') {
    first_page_column = atoi(settings[settings_size - 1]);
284 285 286 287 288 289 290
  }

  /* free buffers */
  g_strfreev(settings);

  return first_page_column;
}
291 292 293 294 295 296 297 298 299 300

bool
parse_color(GdkRGBA* color, const char* str)
{
  if (gdk_rgba_parse(color, str) == FALSE) {
    girara_warning("Failed to parse color string '%s'.", str);
    return false;
  }
  return true;
}