static void cb_print_draw_page(GtkPrintOperation* print_operation, GtkPrintContext* context, gint page_number, zathura_t* zathura) { if (context == NULL || zathura == NULL || zathura->document == NULL || zathura->ui.session == NULL || zathura->ui.statusbar.file == NULL) { gtk_print_operation_cancel(print_operation); return; } /* Update statusbar. */ char* tmp = g_strdup_printf(_("Printing page %d ..."), page_number); girara_statusbar_item_set_text(zathura->ui.session, zathura->ui.statusbar.file, tmp); g_free(tmp); /* Get the page and cairo handle. */ cairo_t* cairo = gtk_print_context_get_cairo_context(context); zathura_page_t* page = zathura_document_get_page(zathura->document, page_number); if (cairo == NULL || page == NULL) { gtk_print_operation_cancel(print_operation); return; } girara_debug("printing page %d ...", page_number); if (draw_page_cairo(cairo, zathura, page) == true) { return; } girara_debug("printing page %d (fallback) ...", page_number); if (draw_page_image(cairo, context, zathura, page) == false) { gtk_print_operation_cancel(print_operation); } }
static void init_database(zathura_t* zathura) { char* database = NULL; girara_setting_get(zathura->ui.session, "database", &database); if (g_strcmp0(database, "plain") == 0) { girara_debug("Using plain database backend."); zathura->database = zathura_plaindatabase_new(zathura->config.data_dir); #ifdef WITH_SQLITE } else if (g_strcmp0(database, "sqlite") == 0) { girara_debug("Using sqlite database backend."); char* tmp = g_build_filename(zathura->config.data_dir, "bookmarks.sqlite", NULL); zathura->database = zathura_sqldatabase_new(tmp); g_free(tmp); #endif } else if (g_strcmp0(database, "null") != 0) { girara_error("Database backend '%s' is not supported.", database); } if (zathura->database == NULL && g_strcmp0(database, "null") != 0) { girara_error( "Unable to initialize database. Bookmarks won't be available."); } else { g_object_set(G_OBJECT(zathura->ui.session->command_history), "io", zathura->database, NULL); } g_free(database); }
static const char* guess_type_glib(const char* path) { gboolean uncertain = FALSE; const char* content_type = g_content_type_guess(path, NULL, 0, &uncertain); if (content_type == NULL) { girara_debug("g_content_type failed\n"); } else { if (uncertain == FALSE) { girara_debug("g_content_type detected filetype: %s", content_type); return content_type; } girara_debug("g_content_type is uncertain, guess: %s", content_type); } FILE* f = fopen(path, "rb"); if (f == NULL) { return NULL; } const int fd = fileno(f); guchar* content = NULL; size_t length = 0u; ssize_t bytes_read = -1; while (uncertain == TRUE && length < GT_MAX_READ && bytes_read != 0) { g_free((void*)content_type); content_type = NULL; guchar* temp_content = g_try_realloc(content, length + BUFSIZ); if (temp_content == NULL) { break; } content = temp_content; bytes_read = read(fd, content + length, BUFSIZ); if (bytes_read == -1) { break; } length += bytes_read; content_type = g_content_type_guess(NULL, content, length, &uncertain); girara_debug("new guess: %s uncertain: %d, read: %zu", content_type, uncertain, length); } fclose(f); g_free(content); if (uncertain == FALSE) { return content_type; } g_free((void*)content_type); return NULL; }
bool sc_zoom(girara_session_t* session, girara_argument_t* argument, girara_event_t* event, unsigned int t) { g_return_val_if_fail(session != NULL, false); g_return_val_if_fail(session->global.data != NULL, false); zathura_t* zathura = session->global.data; g_return_val_if_fail(argument != NULL, false); g_return_val_if_fail(zathura->document != NULL, false); zathura_document_set_adjust_mode(zathura->document, ZATHURA_ADJUST_NONE); /* retrieve zoom step value */ int value = 1; girara_setting_get(zathura->ui.session, "zoom-step", &value); const int nt = (t == 0) ? 1 : t; const double zoom_step = 1.0 + value / 100.0 * nt; const double old_zoom = zathura_document_get_scale(zathura->document); /* specify new zoom value */ if (argument->n == ZOOM_IN) { girara_debug("Increasing zoom by %f.", zoom_step - 1.0); zathura_document_set_scale(zathura->document, old_zoom * zoom_step); } else if (argument->n == ZOOM_OUT) { girara_debug("Decreasing zoom by %f.", zoom_step - 1.0); zathura_document_set_scale(zathura->document, old_zoom / zoom_step); } else if (argument->n == ZOOM_SPECIFIC) { if (t == 0) { girara_debug("Setting zoom to 1."); zathura_document_set_scale(zathura->document, 1.0); } else { girara_debug("Setting zoom to %f.", t / 100.0); zathura_document_set_scale(zathura->document, t / 100.0); } } else if (argument->n == ZOOM_SMOOTH) { const double dy = (event != NULL) ? event->y : 1.0; girara_debug("Increasing zoom by %f.", zoom_step * dy - 1.0); zathura_document_set_scale(zathura->document, old_zoom + zoom_step * dy); } else { girara_debug("Setting zoom to 1."); zathura_document_set_scale(zathura->document, 1.0); } /* zoom limitations */ const double scale = zathura_document_get_scale(zathura->document); zathura_document_set_scale(zathura->document, zathura_correct_scale_value(session, scale)); const double new_zoom = zathura_document_get_scale(zathura->document); if (fabs(new_zoom - old_zoom) <= DBL_EPSILON) { girara_debug("New and old zoom level are too close: %f vs. %f, diff = %f", new_zoom, old_zoom, fabs(new_zoom - old_zoom)); return false; } girara_debug("Re-rendering with new zoom level %f.", new_zoom); render_all(zathura); refresh_view(zathura); return false; }
void cb_widget_screen_changed(GtkWidget* widget, GdkScreen* previous_screen, gpointer data) { girara_debug("called"); zathura_t* zathura = data; if (widget == NULL || zathura == NULL) { return; } /* disconnect previous screen handler if present */ if (previous_screen != NULL && zathura->signals.monitors_changed_handler > 0) { g_signal_handler_disconnect(previous_screen, zathura->signals.monitors_changed_handler); zathura->signals.monitors_changed_handler = 0; } if (gtk_widget_has_screen(widget)) { GdkScreen* screen = gtk_widget_get_screen(widget); /* connect to new screen */ zathura->signals.monitors_changed_handler = g_signal_connect(G_OBJECT(screen), "monitors-changed", G_CALLBACK(cb_monitors_changed), zathura); } zathura_update_view_ppi(zathura); }
} END_TEST static void critical_print(const gchar* GIRARA_UNUSED(log_domain), GLogLevelFlags GIRARA_UNUSED(log_level), const gchar* message, gpointer GIRARA_UNUSED(user_data)) { girara_debug("expected glib critical: %s", message); }
bool synctex_get_input_line_column(const char* filename, unsigned int page, int x, int y, char** input_file, unsigned int* line, unsigned int* column) { if (filename == NULL) { return false; } synctex_scanner_t scanner = synctex_scanner_new_with_output_file(filename, NULL, 1); if (scanner == NULL) { girara_debug("Failed to create synctex scanner."); return false; } synctex_scanner_t temp = synctex_scanner_parse(scanner); if (temp == NULL) { girara_debug("Failed to parse synctex file."); synctex_scanner_free(scanner); return false; } bool ret = false; if (synctex_edit_query(scanner, page + 1u, x, y) > 0) { /* Assume that a backward search returns at most one result. */ synctex_node_t node = synctex_next_result(scanner); if (node != NULL) { if (input_file != NULL) { *input_file = g_strdup(synctex_scanner_get_name(scanner, synctex_node_tag(node))); } if (line != NULL) { *line = synctex_node_line(node); } if (column != NULL) { *column = synctex_node_column(node); } ret = true; } } synctex_scanner_free(scanner); return ret; }
static const char* guess_type_magic(const char* path) { const char* mime_type = NULL; /* creat magic cookie */ const int flags = MAGIC_MIME_TYPE | MAGIC_SYMLINK | MAGIC_NO_CHECK_APPTYPE | MAGIC_NO_CHECK_CDF | MAGIC_NO_CHECK_ELF | MAGIC_NO_CHECK_ENCODING; magic_t magic = magic_open(flags); if (magic == NULL) { girara_debug("failed creating the magic cookie"); goto cleanup; } /* ... and load mime database */ if (magic_load(magic, NULL) < 0) { girara_debug("failed loading the magic database: %s", magic_error(magic)); goto cleanup; } /* get the mime type */ mime_type = magic_file(magic, path); if (mime_type == NULL) { girara_debug("failed guessing filetype: %s", magic_error(magic)); goto cleanup; } /* dup so we own the memory */ mime_type = g_strdup(mime_type); girara_debug("magic detected filetype: %s", mime_type); cleanup: if (magic != NULL) { magic_close(magic); } return mime_type; }
static char* guess_type_magic(zathura_content_type_context_t* context, const char* path) { if (context == NULL || context->magic == NULL) { return NULL; } const char* mime_type = NULL; /* get the mime type */ mime_type = magic_file(context->magic, path); if (mime_type == NULL) { girara_debug("failed guessing filetype: %s", magic_error(context->magic)); return NULL; } girara_debug("magic detected filetype: %s", mime_type); /* dup so we own the memory */ return g_strdup(mime_type);; }
void cb_monitors_changed(GdkScreen* screen, gpointer data) { girara_debug("signal received"); zathura_t* zathura = data; if (screen == NULL || zathura == NULL) { return; } zathura_update_view_ppi(zathura); }
static void render_job(void* data, void* user_data) { zathura_page_t* page = data; zathura_t* zathura = user_data; if (page == NULL || zathura == NULL) { return; } girara_debug("rendering page %d ...", zathura_page_get_index(page)); if (render(zathura, page) != true) { girara_error("Rendering failed (page %d)\n", zathura_page_get_index(page)); } }
void cb_scale_factor(GObject* object, GParamSpec* UNUSED(pspec), gpointer data) { zathura_t* zathura = data; if (zathura == NULL || zathura->document == NULL) { return; } int new_factor = gtk_widget_get_scale_factor(GTK_WIDGET(object)); if (new_factor == 0) { girara_debug("Ignoring new device scale factor = 0"); return; } zathura_device_factors_t current = zathura_document_get_device_factors(zathura->document); if (fabs(new_factor - current.x) >= DBL_EPSILON || fabs(new_factor - current.y) >= DBL_EPSILON) { zathura_document_set_device_factors(zathura->document, new_factor, new_factor); girara_debug("New device scale factor: %d", new_factor); zathura_update_view_ppi(zathura); render_all(zathura); } }
void cb_window_update_icon(ZathuraRenderRequest* GIRARA_UNUSED(request), cairo_surface_t* surface, void* data) { zathura_t* zathura = data; girara_debug("updating window icon"); GdkPixbuf* pixbuf = gdk_pixbuf_get_from_surface(surface, 0, 0, cairo_image_surface_get_width(surface), cairo_image_surface_get_height(surface)); if (pixbuf == NULL) { girara_error("Unable to convert cairo surface to Gdk Pixbuf."); } gtk_window_set_icon(GTK_WINDOW(zathura->ui.session->gtk.window), pixbuf); g_object_unref(pixbuf); }
zathura_content_type_context_t* zathura_content_type_new(void) { zathura_content_type_context_t* context = g_try_malloc0(sizeof(zathura_content_type_context_t)); if (context == NULL) { return NULL; } #ifdef WITH_MAGIC /* creat magic cookie */ const int flags = MAGIC_MIME_TYPE | MAGIC_SYMLINK | MAGIC_NO_CHECK_APPTYPE | MAGIC_NO_CHECK_CDF | MAGIC_NO_CHECK_ELF | MAGIC_NO_CHECK_ENCODING; magic_t magic = magic_open(flags); if (magic == NULL) { girara_debug("failed creating the magic cookie"); return context; } /* ... and load mime database */ if (magic_load(magic, NULL) < 0) { girara_debug("failed loading the magic database: %s", magic_error(magic)); magic_close(magic); return context; } context->magic = magic; #endif return context; }
bool sc_adjust_window(girara_session_t* session, girara_argument_t* argument, girara_event_t* UNUSED(event), unsigned int UNUSED(t)) { g_return_val_if_fail(session != NULL, false); g_return_val_if_fail(session->global.data != NULL, false); zathura_t* zathura = session->global.data; g_return_val_if_fail(argument != NULL, false); if (argument->n < ZATHURA_ADJUST_NONE || argument->n >= ZATHURA_ADJUST_MODE_NUMBER) { girara_error("Invalid adjust mode: %d", argument->n); girara_notify(session, GIRARA_ERROR, _("Invalid adjust mode: %d"), argument->n); } else { girara_debug("Setting adjust mode to: %d", argument->n); zathura_document_set_adjust_mode(zathura->document, argument->n); adjust_view(zathura); } return false; }
void cb_page_widget_scaled_button_release(ZathuraPage* page_widget, GdkEventButton* event, void* data) { zathura_t* zathura = data; zathura_page_t* page = zathura_page_widget_get_page(page_widget); /* set page number (but don't scroll there. it was clicked on, so it's visible) */ if (event->button == GDK_BUTTON_PRIMARY) { zathura_document_set_current_page_number(zathura->document, zathura_page_get_index(page)); refresh_view(zathura); } if (event->button != GDK_BUTTON_PRIMARY || !(event->state & GDK_CONTROL_MASK)) { return; } bool synctex = false; girara_setting_get(zathura->ui.session, "synctex", &synctex); if (synctex == false) { return; } if (zathura->dbus != NULL) { zathura_dbus_edit(zathura->dbus, zathura_page_get_index(page), event->x, event->y); } char* editor = NULL; girara_setting_get(zathura->ui.session, "synctex-editor-command", &editor); if (editor == NULL || *editor == '\0') { girara_debug("No SyncTeX editor specified."); g_free(editor); return; } synctex_edit(editor, page, event->x, event->y); g_free(editor); }
bool sc_bisect(girara_session_t* session, girara_argument_t* argument, girara_event_t* UNUSED(event), unsigned int t) { g_return_val_if_fail(session != NULL, false); g_return_val_if_fail(session->global.data != NULL, false); zathura_t* zathura = session->global.data; g_return_val_if_fail(argument != NULL, false); g_return_val_if_fail(zathura->document != NULL, false); const unsigned int num_pages = zathura_document_get_number_of_pages(zathura->document); const unsigned int cur_page = zathura_document_get_current_page_number(zathura->document); /* process arguments */ int direction; if (t > 0 && t <= num_pages) { /* bisect between cur_page and t */ t -= 1; if (t == cur_page) { /* nothing to do */ return false; } else if (t > cur_page) { zathura->bisect.start = cur_page; zathura->bisect.end = t; direction = BACKWARD; } else { zathura->bisect.start = t; zathura->bisect.end = cur_page; direction = FORWARD; } } else if (argument != NULL) { direction = argument->n; /* setup initial bisect range */ zathura_jump_t* jump = zathura_jumplist_current(zathura); if (jump == NULL) { girara_debug("bisecting between first and last page because there are no jumps"); zathura->bisect.start = 0; zathura->bisect.end = num_pages - 1; } else if (jump->page != cur_page || jump->page != zathura->bisect.last_jump) { girara_debug("last jump doesn't match up, starting new bisecting"); zathura->bisect.start = 0; zathura->bisect.end = num_pages - 1; unsigned int prev_page; if (direction == FORWARD) { prev_page = num_pages - 1; } else { prev_page = 0; } /* check if we have previous jumps */ if (zathura_jumplist_has_previous(zathura) == true) { zathura_jumplist_backward(zathura); jump = zathura_jumplist_current(zathura); if (jump != NULL) { prev_page = jump->page; } zathura_jumplist_forward(zathura); } zathura->bisect.start = MIN(prev_page, cur_page); zathura->bisect.end = MAX(prev_page, cur_page); zathura->bisect.last_jump = cur_page; } } else { return false; } girara_debug("bisecting between %d and %d, at %d", zathura->bisect.start, zathura->bisect.end, cur_page); if (zathura->bisect.start == zathura->bisect.end) { /* nothing to do */ return false; } unsigned int next_page = cur_page; unsigned int next_start = zathura->bisect.start; unsigned int next_end = zathura->bisect.end; /* here we have next_start <= next_page <= next_end */ /* bisect step */ switch(direction) { case FORWARD: if (cur_page != zathura->bisect.end) { next_page = (cur_page + zathura->bisect.end) / 2; if (next_page == cur_page) { ++next_page; } next_start = cur_page; } break; case BACKWARD: if (cur_page != zathura->bisect.start) { next_page = (cur_page + zathura->bisect.start) / 2; if (next_page == cur_page) { --next_page; } next_end = cur_page; } break; } if (next_page == cur_page) { /* nothing to do */ return false; } girara_debug("bisecting between %d and %d, jumping to %d", zathura->bisect.start, zathura->bisect.end, next_page); zathura->bisect.last_jump = next_page; zathura->bisect.start = next_start; zathura->bisect.end = next_end; zathura_jumplist_add(zathura); page_set(zathura, next_page); zathura_jumplist_add(zathura); return false; }
static void cb_print_draw_page(GtkPrintOperation* print_operation, GtkPrintContext* context, gint page_number, zathura_t* zathura) { if (context == NULL || zathura == NULL || zathura->document == NULL || zathura->ui.session == NULL || zathura->ui.statusbar.file == NULL) { gtk_print_operation_cancel(print_operation); return; } /* Update statusbar. */ char* tmp = g_strdup_printf("Printing %d...", page_number); girara_statusbar_item_set_text(zathura->ui.session, zathura->ui.statusbar.file, tmp); g_free(tmp); /* Get the page and cairo handle. */ cairo_t* cairo = gtk_print_context_get_cairo_context(context); zathura_page_t* page = zathura_document_get_page(zathura->document, page_number); if (cairo == NULL || page == NULL) { gtk_print_operation_cancel(print_operation); return; } /* Try to render the page without a temporary surface. This only works with * plugins that support rendering to any surface. */ girara_debug("printing page %d ...", page_number); zathura_renderer_lock(zathura->sync.render_thread); int err = zathura_page_render(page, cairo, true); zathura_renderer_unlock(zathura->sync.render_thread); if (err == ZATHURA_ERROR_OK) { return; } /* Try to render the page on a temporary image surface. */ const gdouble width = gtk_print_context_get_width(context); const gdouble height = gtk_print_context_get_height(context); /* Render to a surface that is 5 times larger to workaround quality issues. */ const double page_height = zathura_page_get_height(page) * 5; const double page_width = zathura_page_get_width(page) * 5; cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, page_width, page_height); if (surface == NULL) { gtk_print_operation_cancel(print_operation); return; } cairo_t* temp_cairo = cairo_create(surface); if (cairo == NULL) { gtk_print_operation_cancel(print_operation); cairo_surface_destroy(surface); return; } /* Draw a white background. */ cairo_save(temp_cairo); cairo_set_source_rgb(temp_cairo, 1, 1, 1); cairo_rectangle(temp_cairo, 0, 0, page_width, page_height); cairo_fill(temp_cairo); cairo_restore(temp_cairo); /* Render the page to the temporary surface */ girara_debug("printing page %d (fallback) ...", page_number); zathura_renderer_lock(zathura->sync.render_thread); err = zathura_page_render(page, temp_cairo, true); zathura_renderer_unlock(zathura->sync.render_thread); if (err != ZATHURA_ERROR_OK) { cairo_destroy(temp_cairo); cairo_surface_destroy(surface); gtk_print_operation_cancel(print_operation); return; } /* Rescale the page and keep the aspect ratio */ const gdouble scale = MIN(width / page_width, height / page_height); cairo_scale(cairo, scale, scale); /* Blit temporary surface to original cairo object. */ cairo_set_source_surface(cairo, surface, 0.0, 0.0); cairo_paint(cairo); cairo_destroy(temp_cairo); cairo_surface_destroy(surface); }
bool zathura_init(zathura_t* zathura) { if (zathura == NULL) { return false; } /* create zathura (config/data) directory */ if (g_mkdir_with_parents(zathura->config.config_dir, 0771) == -1) { girara_error("Could not create '%s': %s", zathura->config.config_dir, strerror(errno)); } if (g_mkdir_with_parents(zathura->config.data_dir, 0771) == -1) { girara_error("Could not create '%s': %s", zathura->config.data_dir, strerror(errno)); } /* load plugins */ zathura_plugin_manager_load(zathura->plugins.manager); /* configuration */ config_load_default(zathura); /* load global configuration files */ char* config_path = girara_get_xdg_path(XDG_CONFIG_DIRS); girara_list_t* config_dirs = girara_split_path_array(config_path); ssize_t size = girara_list_size(config_dirs) - 1; for (; size >= 0; --size) { const char* dir = girara_list_nth(config_dirs, size); char* file = g_build_filename(dir, ZATHURA_RC, NULL); config_load_file(zathura, file); g_free(file); } girara_list_free(config_dirs); g_free(config_path); config_load_file(zathura, GLOBAL_RC); /* load local configuration files */ char* configuration_file = g_build_filename(zathura->config.config_dir, ZATHURA_RC, NULL); config_load_file(zathura, configuration_file); g_free(configuration_file); /* UI */ if (girara_session_init(zathura->ui.session, "zathura") == false) { goto error_free; } /* girara events */ zathura->ui.session->events.buffer_changed = cb_buffer_changed; zathura->ui.session->events.unknown_command = cb_unknown_command; /* zathura signals */ zathura->signals.refresh_view = g_signal_new("refresh-view", GTK_TYPE_WIDGET, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, G_TYPE_POINTER); g_signal_connect(G_OBJECT(zathura->ui.session->gtk.view), "refresh-view", G_CALLBACK(cb_refresh_view), zathura); /* page view */ #if (GTK_MAJOR_VERSION == 3) zathura->ui.page_widget = gtk_grid_new(); gtk_grid_set_row_homogeneous(GTK_GRID(zathura->ui.page_widget), TRUE); gtk_grid_set_column_homogeneous(GTK_GRID(zathura->ui.page_widget), TRUE); #else zathura->ui.page_widget = gtk_table_new(0, 0, TRUE); #endif if (zathura->ui.page_widget == NULL) { goto error_free; } g_signal_connect(G_OBJECT(zathura->ui.session->gtk.window), "size-allocate", G_CALLBACK(cb_view_resized), zathura); GtkAdjustment* hadjustment = gtk_scrolled_window_get_hadjustment( GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view)); /* Connect hadjustment signals */ g_signal_connect(G_OBJECT(hadjustment), "value-changed", G_CALLBACK(cb_view_hadjustment_value_changed), zathura); g_signal_connect(G_OBJECT(hadjustment), "changed", G_CALLBACK(cb_view_hadjustment_changed), zathura); GtkAdjustment* vadjustment = gtk_scrolled_window_get_vadjustment( GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view)); /* Connect vadjustment signals */ g_signal_connect(G_OBJECT(vadjustment), "value-changed", G_CALLBACK(cb_view_vadjustment_value_changed), zathura); g_signal_connect(G_OBJECT(vadjustment), "changed", G_CALLBACK(cb_view_vadjustment_changed), zathura); /* page view alignment */ zathura->ui.page_widget_alignment = gtk_alignment_new(0.5, 0.5, 0, 0); if (zathura->ui.page_widget_alignment == NULL) { goto error_free; } gtk_container_add(GTK_CONTAINER(zathura->ui.page_widget_alignment), zathura->ui.page_widget); #if (GTK_MAJOR_VERSION == 3) gtk_widget_set_hexpand_set(zathura->ui.page_widget_alignment, TRUE); gtk_widget_set_hexpand(zathura->ui.page_widget_alignment, FALSE); gtk_widget_set_vexpand_set(zathura->ui.page_widget_alignment, TRUE); gtk_widget_set_vexpand(zathura->ui.page_widget_alignment, FALSE); #endif gtk_widget_show(zathura->ui.page_widget); /* statusbar */ zathura->ui.statusbar.file = girara_statusbar_item_add(zathura->ui.session, TRUE, TRUE, TRUE, NULL); if (zathura->ui.statusbar.file == NULL) { goto error_free; } zathura->ui.statusbar.buffer = girara_statusbar_item_add(zathura->ui.session, FALSE, FALSE, FALSE, NULL); if (zathura->ui.statusbar.buffer == NULL) { goto error_free; } zathura->ui.statusbar.page_number = girara_statusbar_item_add(zathura->ui.session, FALSE, FALSE, FALSE, NULL); if (zathura->ui.statusbar.page_number == NULL) { goto error_free; } girara_statusbar_item_set_text(zathura->ui.session, zathura->ui.statusbar.file, _("[No name]")); /* signals */ g_signal_connect(G_OBJECT(zathura->ui.session->gtk.window), "destroy", G_CALLBACK(cb_destroy), zathura); /* database */ char* database = NULL; girara_setting_get(zathura->ui.session, "database", &database); if (g_strcmp0(database, "plain") == 0) { girara_debug("Using plain database backend."); zathura->database = zathura_plaindatabase_new(zathura->config.data_dir); #ifdef WITH_SQLITE } else if (g_strcmp0(database, "sqlite") == 0) { girara_debug("Using sqlite database backend."); char* tmp = g_build_filename(zathura->config.data_dir, "bookmarks.sqlite", NULL); zathura->database = zathura_sqldatabase_new(tmp); g_free(tmp); #endif } else { girara_error("Database backend '%s' is not supported.", database); } g_free(database); if (zathura->database == NULL) { girara_error("Unable to initialize database. Bookmarks won't be available."); } else { g_object_set(zathura->ui.session->command_history, "io", zathura->database, NULL); } /* bookmarks */ zathura->bookmarks.bookmarks = girara_sorted_list_new2((girara_compare_function_t) zathura_bookmarks_compare, (girara_free_function_t) zathura_bookmark_free); /* jumplist */ int jumplist_size = 20; girara_setting_get(zathura->ui.session, "jumplist-size", &jumplist_size); zathura->jumplist.max_size = jumplist_size < 0 ? 0 : jumplist_size; zathura->jumplist.list = NULL; zathura->jumplist.size = 0; zathura->jumplist.cur = NULL; return true; error_free: if (zathura->ui.page_widget != NULL) { g_object_unref(zathura->ui.page_widget); } if (zathura->ui.page_widget_alignment != NULL) { g_object_unref(zathura->ui.page_widget_alignment); } return false; }
void zathura_plugin_manager_load(zathura_plugin_manager_t* plugin_manager) { if (plugin_manager == NULL || plugin_manager->path == NULL) { return; } GIRARA_LIST_FOREACH(plugin_manager->path, char*, iter, plugindir) /* read all files in the plugin directory */ GDir* dir = g_dir_open(plugindir, 0, NULL); if (dir == NULL) { girara_error("could not open plugin directory: %s", plugindir); girara_list_iterator_next(iter); continue; } char* name = NULL; while ((name = (char*) g_dir_read_name(dir)) != NULL) { char* path = g_build_filename(plugindir, name, NULL); if (g_file_test(path, G_FILE_TEST_IS_REGULAR) == 0) { girara_debug("%s is not a regular file. Skipping.", path); g_free(path); continue; } if (check_suffix(path) == false) { girara_debug("%s is not a plugin file. Skipping.", path); g_free(path); continue; } zathura_plugin_t* plugin = NULL; /* load plugin */ GModule* handle = g_module_open(path, G_MODULE_BIND_LOCAL); if (handle == NULL) { girara_error("could not load plugin %s (%s)", path, g_module_error()); g_free(path); continue; } /* resolve symbols and check API and ABI version*/ zathura_plugin_api_version_t api_version = NULL; if (g_module_symbol(handle, PLUGIN_API_VERSION_FUNCTION, (gpointer*) &api_version) == FALSE || api_version == NULL) { girara_error("could not find '%s' function in plugin %s", PLUGIN_API_VERSION_FUNCTION, path); g_free(path); g_module_close(handle); continue; } if (api_version() != ZATHURA_API_VERSION) { girara_error("plugin %s has been built againt zathura with a different API version (plugin: %d, zathura: %d)", path, api_version(), ZATHURA_API_VERSION); g_free(path); g_module_close(handle); continue; } zathura_plugin_abi_version_t abi_version = NULL; if (g_module_symbol(handle, PLUGIN_ABI_VERSION_FUNCTION, (gpointer*) &abi_version) == FALSE || abi_version == NULL) { girara_error("could not find '%s' function in plugin %s", PLUGIN_ABI_VERSION_FUNCTION, path); g_free(path); g_module_close(handle); continue; } if (abi_version() != ZATHURA_ABI_VERSION) { girara_error("plugin %s has been built againt zathura with a different ABI version (plugin: %d, zathura: %d)", path, abi_version(), ZATHURA_ABI_VERSION); g_free(path); g_module_close(handle); continue; } zathura_plugin_register_service_t register_service = NULL; if (g_module_symbol(handle, PLUGIN_REGISTER_FUNCTION, (gpointer*) ®ister_service) == FALSE || register_service == NULL) { girara_error("could not find '%s' function in plugin %s", PLUGIN_REGISTER_FUNCTION, path); g_free(path); g_module_close(handle); continue; } plugin = g_try_malloc0(sizeof(zathura_plugin_t)); if (plugin == NULL) { girara_error("Failed to allocate memory for plugin."); g_free(path); g_module_close(handle); continue; } plugin->content_types = girara_list_new2(g_free); plugin->handle = handle; register_service(plugin); /* register functions */ if (plugin->register_function == NULL) { girara_error("plugin has no document functions register function"); g_free(path); g_free(plugin); g_module_close(handle); continue; } plugin->register_function(&(plugin->functions)); plugin->path = path; bool ret = register_plugin(plugin_manager, plugin); if (ret == false) { girara_error("could not register plugin %s", path); zathura_plugin_free(plugin); } else { girara_debug("successfully loaded plugin %s", path); zathura_plugin_version_function_t plugin_major = NULL, plugin_minor = NULL, plugin_rev = NULL; g_module_symbol(handle, PLUGIN_VERSION_MAJOR_FUNCTION, (gpointer*) &plugin_major); g_module_symbol(handle, PLUGIN_VERSION_MINOR_FUNCTION, (gpointer*) &plugin_minor); g_module_symbol(handle, PLUGIN_VERSION_REVISION_FUNCTION, (gpointer*) &plugin_rev); if (plugin_major != NULL && plugin_minor != NULL && plugin_rev != NULL) { plugin->version.major = plugin_major(); plugin->version.minor = plugin_minor(); plugin->version.rev = plugin_rev(); girara_debug("plugin '%s': version %u.%u.%u", path, plugin->version.major, plugin->version.minor, plugin->version.rev); } } } g_dir_close(dir); GIRARA_LIST_FOREACH_END(zathura->plugins.path, char*, iter, plugindir); }
void synctex_highlight_rects(zathura_t* zathura, unsigned int page, girara_list_t** rectangles) { const unsigned int number_of_pages = zathura_document_get_number_of_pages(zathura->document); for (unsigned int p = 0; p != number_of_pages; ++p) { GObject* widget = G_OBJECT(zathura->pages[p]); g_object_set(widget, "draw-links", FALSE, "search-results", rectangles[p], NULL); if (p == page) { g_object_set(widget, "search-current", 0, NULL); } } document_draw_search_results(zathura, true); girara_list_t* rect_list = rectangles[page]; if (rect_list == NULL || girara_list_size(rect_list) == 0) { girara_debug("No rectangles for the given page. Jumping to page %u.", page); page_set(zathura, page); return; } bool search_hadjust = true; girara_setting_get(zathura->ui.session, "search-hadjust", &search_hadjust); /* compute the position of the center of the page */ double pos_x = 0; double pos_y = 0; page_number_to_position(zathura->document, page, 0.5, 0.5, &pos_x, &pos_y); /* correction to center the current result */ /* NOTE: rectangle is in viewport units, already scaled and rotated */ unsigned int cell_height = 0; unsigned int cell_width = 0; zathura_document_get_cell_size(zathura->document, &cell_height, &cell_width); unsigned int doc_height = 0; unsigned int doc_width = 0; zathura_document_get_document_size(zathura->document, &doc_height, &doc_width); /* Need to adjust rectangle to page scale and orientation */ zathura_page_t* doc_page = zathura_document_get_page(zathura->document, page); zathura_rectangle_t* rect = girara_list_nth(rect_list, 0); if (rect == NULL) { girara_debug("List of rectangles is broken. Jumping to page %u.", page); page_set(zathura, page); return; } zathura_rectangle_t rectangle = recalc_rectangle(doc_page, *rect); /* compute the center of the rectangle, which will be aligned to the center of the viewport */ double center_x = (rectangle.x1 + rectangle.x2) / 2; double center_y = (rectangle.y1 + rectangle.y2) / 2; pos_y += (center_y - (double)cell_height/2) / (double)doc_height; if (search_hadjust == true) { pos_x += (center_x - (double)cell_width/2) / (double)doc_width; } /* move to position */ girara_debug("Jumping to page %u position (%f, %f).", page, pos_x, pos_y); zathura_jumplist_add(zathura); position_set(zathura, pos_x, pos_y); zathura_jumplist_add(zathura); }
void synctex_edit(zathura_t* zathura, zathura_page_t* page, int x, int y) { if (zathura == NULL || page == NULL || zathura->synctex.editor == NULL) { return; } zathura_document_t* document = zathura_page_get_document(page); if (document == NULL) { return; } const char *filename = zathura_document_get_path(document); if (filename == NULL) { return; } synctex_scanner_t scanner = synctex_scanner_new_with_output_file(filename, NULL, 1); if (scanner == NULL) { girara_debug("Failed to create synctex scanner."); return; } synctex_scanner_t temp = synctex_scanner_parse(scanner); if (temp == NULL) { girara_debug("Failed to parse synctex file."); synctex_scanner_free(scanner); return; } if (synctex_edit_query(scanner, zathura_page_get_index(page) + 1, x, y) > 0) { /* Assume that a backward search returns either at most one result. */ synctex_node_t node = synctex_next_result(scanner); if (node != NULL) { const char* input_file = synctex_scanner_get_name(scanner, synctex_node_tag(node)); const int line = synctex_node_line(node); const int column = synctex_node_column (node); char* linestr = g_strdup_printf("%d", line); char* columnstr = g_strdup_printf("%d", column); gchar** argv = NULL; gint argc = 0; if (g_shell_parse_argv(zathura->synctex.editor, &argc, &argv, NULL) == TRUE) { for (gint i = 0; i != argc; ++i) { char* temp = girara_replace_substring(argv[i], "%{line}", linestr); g_free(argv[i]); argv[i] = temp; temp = girara_replace_substring(argv[i], "%{column}", columnstr); g_free(argv[i]); argv[i] = temp; temp = girara_replace_substring(argv[i], "%{input}", input_file); g_free(argv[i]); argv[i] = temp; } g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL); g_strfreev(argv); } g_free(linestr); g_free(columnstr); } } synctex_scanner_free(scanner); }
static const gchar* guess_type(const char* path) { gboolean uncertain; const gchar* content_type = g_content_type_guess(path, NULL, 0, &uncertain); if (content_type == NULL) { return NULL; } if (uncertain == FALSE) { return content_type; } girara_debug("g_content_type is uncertain, guess: %s\n", content_type); FILE* f = fopen(path, "rb"); if (f == NULL) { return NULL; } const int fd = fileno(f); guchar* content = NULL; size_t length = 0u; ssize_t bytes_read = -1; while (uncertain == TRUE && length < GT_MAX_READ && bytes_read != 0) { g_free((void*)content_type); content_type = NULL; content = g_realloc(content, length + BUFSIZ); bytes_read = read(fd, content + length, BUFSIZ); if (bytes_read == -1) { break; } length += bytes_read; content_type = g_content_type_guess(NULL, content, length, &uncertain); girara_debug("new guess: %s uncertain: %d, read: %zu\n", content_type, uncertain, length); } fclose(f); g_free(content); if (uncertain == FALSE) { return content_type; } g_free((void*)content_type); content_type = NULL; girara_debug("falling back to file"); GString* command = g_string_new("file -b --mime-type "); char* tmp = g_shell_quote(path); g_string_append(command, tmp); g_free(tmp); GError* error = NULL; char* out = NULL; int ret = 0; g_spawn_command_line_sync(command->str, &out, NULL, &ret, &error); g_string_free(command, TRUE); if (error != NULL) { girara_warning("failed to execute command: %s", error->message); g_error_free(error); g_free(out); return NULL; } if (WEXITSTATUS(ret) != 0) { girara_warning("file failed with error code: %d", WEXITSTATUS(ret)); g_free(out); return NULL; } g_strdelimit(out, "\n\r", '\0'); return out; }
static const gchar* guess_type(const char* path) { const gchar* content_type = NULL; #ifdef WITH_MAGIC const char* mime_type = NULL; /* creat magic cookie */ const int flags = MAGIC_MIME_TYPE | MAGIC_SYMLINK | MAGIC_NO_CHECK_APPTYPE | MAGIC_NO_CHECK_CDF | MAGIC_NO_CHECK_ELF | MAGIC_NO_CHECK_ENCODING; magic_t magic = magic_open(flags); if (magic == NULL) { girara_debug("failed creating the magic cookie"); goto cleanup; } /* ... and load mime database */ if (magic_load(magic, NULL) < 0) { girara_debug("failed loading the magic database: %s", magic_error(magic)); goto cleanup; } /* get the mime type */ mime_type = magic_file(magic, path); if (mime_type == NULL) { girara_debug("failed guessing filetype: %s", magic_error(magic)); goto cleanup; } girara_debug("magic detected filetype: %s", mime_type); content_type = g_strdup(mime_type); cleanup: if (magic != NULL) { magic_close(magic); } if (content_type != NULL) { return content_type; } /* else fallback to g_content_type_guess method */ #endif /*WITH_MAGIC*/ gboolean uncertain = FALSE; content_type = g_content_type_guess(path, NULL, 0, &uncertain); if (content_type == NULL) { girara_debug("g_content_type failed\n"); } else { if (uncertain == FALSE) { girara_debug("g_content_type detected filetype: %s", content_type); return content_type; } girara_debug("g_content_type is uncertain, guess: %s", content_type); } FILE* f = fopen(path, "rb"); if (f == NULL) { return NULL; } const int fd = fileno(f); guchar* content = NULL; size_t length = 0u; ssize_t bytes_read = -1; while (uncertain == TRUE && length < GT_MAX_READ && bytes_read != 0) { g_free((void*)content_type); content_type = NULL; content = g_realloc(content, length + BUFSIZ); bytes_read = read(fd, content + length, BUFSIZ); if (bytes_read == -1) { break; } length += bytes_read; content_type = g_content_type_guess(NULL, content, length, &uncertain); girara_debug("new guess: %s uncertain: %d, read: %zu", content_type, uncertain, length); } fclose(f); g_free(content); if (uncertain == FALSE) { return content_type; } g_free((void*)content_type); content_type = NULL; girara_debug("falling back to file"); GString* command = g_string_new("file -b --mime-type "); char* tmp = g_shell_quote(path); g_string_append(command, tmp); g_free(tmp); GError* error = NULL; char* out = NULL; int ret = 0; g_spawn_command_line_sync(command->str, &out, NULL, &ret, &error); g_string_free(command, TRUE); if (error != NULL) { girara_warning("failed to execute command: %s", error->message); g_error_free(error); g_free(out); return NULL; } if (WEXITSTATUS(ret) != 0) { girara_warning("file failed with error code: %d", WEXITSTATUS(ret)); g_free(out); return NULL; } g_strdelimit(out, "\n\r", '\0'); return out; }
girara_list_t* synctex_rectangles_from_position(const char* filename, const char* input_file, int line, int column, unsigned int* page, girara_list_t** secondary_rects) { if (filename == NULL || input_file == NULL || page == NULL) { return NULL; } synctex_scanner_t scanner = synctex_scanner_new_with_output_file(filename, NULL, 1); if (scanner == NULL) { girara_debug("Failed to create synctex scanner."); return NULL; } synctex_scanner_t temp = synctex_scanner_parse(scanner); if (temp == NULL) { girara_debug("Failed to parse synctex file."); synctex_scanner_free(scanner); return NULL; } girara_list_t* hitlist = girara_list_new2(g_free); girara_list_t* other_rects = girara_list_new2(g_free); if (synctex_display_query(scanner, input_file, line, column) > 0) { synctex_node_t node = NULL; bool got_page = false; while ((node = synctex_next_result (scanner)) != NULL) { const unsigned int current_page = synctex_node_page(node) - 1; if (got_page == false) { got_page = true; *page = current_page; } zathura_rectangle_t rect = { 0, 0, 0, 0 }; rect.x1 = synctex_node_box_visible_h(node); rect.y1 = synctex_node_box_visible_v(node) - synctex_node_box_visible_height(node); rect.x2 = rect.x1 + synctex_node_box_visible_width(node); rect.y2 = synctex_node_box_visible_depth(node) + synctex_node_box_visible_height (node) + rect.y1; if (*page == current_page) { zathura_rectangle_t* real_rect = g_try_malloc(sizeof(zathura_rectangle_t)); if (real_rect == NULL) { continue; } *real_rect = rect; girara_list_append(hitlist, real_rect); } else { synctex_page_rect_t* page_rect = g_try_malloc(sizeof(synctex_page_rect_t)); if (page_rect == NULL) { continue; } page_rect->page = current_page; page_rect->rect = rect; girara_list_append(other_rects, page_rect); } } } synctex_scanner_free(scanner); if (secondary_rects != NULL) { *secondary_rects = other_rects; } else { girara_list_free(other_rects); } return hitlist; }
bool zathura_init(zathura_t* zathura) { if (zathura == NULL) { return false; } /* create zathura (config/data) directory */ if (g_mkdir_with_parents(zathura->config.config_dir, 0771) == -1) { girara_error("Could not create '%s': %s", zathura->config.config_dir, strerror(errno)); } if (g_mkdir_with_parents(zathura->config.data_dir, 0771) == -1) { girara_error("Could not create '%s': %s", zathura->config.data_dir, strerror(errno)); } /* load plugins */ zathura_plugin_manager_load(zathura->plugins.manager); /* configuration */ config_load_default(zathura); /* load global configuration files */ char* config_path = girara_get_xdg_path(XDG_CONFIG_DIRS); girara_list_t* config_dirs = girara_split_path_array(config_path); ssize_t size = girara_list_size(config_dirs) - 1; for (; size >= 0; --size) { const char* dir = girara_list_nth(config_dirs, size); char* file = g_build_filename(dir, ZATHURA_RC, NULL); config_load_file(zathura, file); g_free(file); } girara_list_free(config_dirs); g_free(config_path); config_load_file(zathura, GLOBAL_RC); /* load local configuration files */ char* configuration_file = g_build_filename(zathura->config.config_dir, ZATHURA_RC, NULL); config_load_file(zathura, configuration_file); g_free(configuration_file); /* UI */ if (girara_session_init(zathura->ui.session, "zathura") == false) { goto error_free; } /* girara events */ zathura->ui.session->events.buffer_changed = cb_buffer_changed; zathura->ui.session->events.unknown_command = cb_unknown_command; /* page view */ #if (GTK_MAJOR_VERSION == 3) zathura->ui.page_widget = gtk_grid_new(); gtk_grid_set_row_homogeneous(GTK_GRID(zathura->ui.page_widget), TRUE); gtk_grid_set_column_homogeneous(GTK_GRID(zathura->ui.page_widget), TRUE); #else zathura->ui.page_widget = gtk_table_new(0, 0, TRUE); #endif if (zathura->ui.page_widget == NULL) { goto error_free; } g_signal_connect(G_OBJECT(zathura->ui.session->gtk.window), "size-allocate", G_CALLBACK(cb_view_resized), zathura); /* Setup hadjustment tracker */ GtkAdjustment* hadjustment = gtk_scrolled_window_get_hadjustment( GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view)); zathura->ui.hadjustment = zathura_adjustment_clone(hadjustment); g_object_ref_sink(zathura->ui.hadjustment); /* Connect hadjustment signals */ g_signal_connect(G_OBJECT(hadjustment), "value-changed", G_CALLBACK(cb_view_vadjustment_value_changed), zathura); g_signal_connect(G_OBJECT(hadjustment), "value-changed", G_CALLBACK(cb_adjustment_track_value), zathura->ui.hadjustment); g_signal_connect(G_OBJECT(hadjustment), "changed", G_CALLBACK(cb_view_hadjustment_changed), zathura); g_signal_connect(G_OBJECT(hadjustment), "changed", G_CALLBACK(cb_adjustment_track_bounds), zathura->ui.hadjustment); /* Setup vadjustment tracker */ GtkAdjustment* vadjustment = gtk_scrolled_window_get_vadjustment( GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view)); zathura->ui.vadjustment = zathura_adjustment_clone(vadjustment); g_object_ref_sink(zathura->ui.vadjustment); /* Connect vadjustment signals */ g_signal_connect(G_OBJECT(vadjustment), "value-changed", G_CALLBACK(cb_view_vadjustment_value_changed), zathura); g_signal_connect(G_OBJECT(vadjustment), "value-changed", G_CALLBACK(cb_adjustment_track_value), zathura->ui.vadjustment); g_signal_connect(G_OBJECT(vadjustment), "changed", G_CALLBACK(cb_view_vadjustment_changed), zathura); g_signal_connect(G_OBJECT(vadjustment), "changed", G_CALLBACK(cb_adjustment_track_bounds), zathura->ui.vadjustment); /* page view alignment */ zathura->ui.page_widget_alignment = gtk_alignment_new(0.5, 0.5, 0, 0); if (zathura->ui.page_widget_alignment == NULL) { goto error_free; } gtk_container_add(GTK_CONTAINER(zathura->ui.page_widget_alignment), zathura->ui.page_widget); #if (GTK_MAJOR_VERSION == 3) gtk_widget_set_hexpand_set(zathura->ui.page_widget_alignment, TRUE); gtk_widget_set_hexpand(zathura->ui.page_widget_alignment, FALSE); gtk_widget_set_vexpand_set(zathura->ui.page_widget_alignment, TRUE); gtk_widget_set_vexpand(zathura->ui.page_widget_alignment, FALSE); #endif gtk_widget_show(zathura->ui.page_widget); /* statusbar */ zathura->ui.statusbar.file = girara_statusbar_item_add(zathura->ui.session, TRUE, TRUE, TRUE, NULL); if (zathura->ui.statusbar.file == NULL) { goto error_free; } zathura->ui.statusbar.buffer = girara_statusbar_item_add(zathura->ui.session, FALSE, FALSE, FALSE, NULL); if (zathura->ui.statusbar.buffer == NULL) { goto error_free; } zathura->ui.statusbar.page_number = girara_statusbar_item_add(zathura->ui.session, FALSE, FALSE, FALSE, NULL); if (zathura->ui.statusbar.page_number == NULL) { goto error_free; } girara_statusbar_item_set_text(zathura->ui.session, zathura->ui.statusbar.file, _("[No name]")); /* signals */ g_signal_connect(G_OBJECT(zathura->ui.session->gtk.window), "destroy", G_CALLBACK(cb_destroy), zathura); /* set page padding */ int page_padding = 1; girara_setting_get(zathura->ui.session, "page-padding", &page_padding); #if (GTK_MAJOR_VERSION == 3) gtk_grid_set_row_spacing(GTK_GRID(zathura->ui.page_widget), page_padding); gtk_grid_set_column_spacing(GTK_GRID(zathura->ui.page_widget), page_padding); #else gtk_table_set_row_spacings(GTK_TABLE(zathura->ui.page_widget), page_padding); gtk_table_set_col_spacings(GTK_TABLE(zathura->ui.page_widget), page_padding); #endif /* database */ char* database = NULL; girara_setting_get(zathura->ui.session, "database", &database); if (g_strcmp0(database, "plain") == 0) { girara_debug("Using plain database backend."); zathura->database = zathura_plaindatabase_new(zathura->config.data_dir); #ifdef WITH_SQLITE } else if (g_strcmp0(database, "sqlite") == 0) { girara_debug("Using sqlite database backend."); char* tmp = g_build_filename(zathura->config.data_dir, "bookmarks.sqlite", NULL); zathura->database = zathura_sqldatabase_new(tmp); g_free(tmp); #endif } else { girara_error("Database backend '%s' is not supported.", database); } g_free(database); if (zathura->database == NULL) { girara_error("Unable to initialize database. Bookmarks won't be available."); } else { g_object_set(zathura->ui.session->command_history, "io", zathura->database, NULL); } /* bookmarks */ zathura->bookmarks.bookmarks = girara_sorted_list_new2((girara_compare_function_t) zathura_bookmarks_compare, (girara_free_function_t) zathura_bookmark_free); /* jumplist */ zathura->jumplist.max_size = 20; girara_setting_get(zathura->ui.session, "jumplist-size", &(zathura->jumplist.max_size)); zathura->jumplist.list = girara_list_new2(g_free); zathura->jumplist.size = 0; zathura->jumplist.cur = NULL; zathura_jumplist_append_jump(zathura); zathura->jumplist.cur = girara_list_iterator(zathura->jumplist.list); /* page cache */ int cache_size = 0; girara_setting_get(zathura->ui.session, "page-cache-size", &cache_size); if (cache_size <= 0) { girara_warning("page-cache-size is not positive, using %d instead", ZATHURA_PAGE_CACHE_DEFAULT_SIZE); zathura->page_cache.size = ZATHURA_PAGE_CACHE_DEFAULT_SIZE; } else { zathura->page_cache.size = cache_size; } zathura->page_cache.cache = g_malloc(zathura->page_cache.size * sizeof(int)); zathura_page_cache_invalidate_all(zathura); return true; error_free: if (zathura->ui.page_widget != NULL) { g_object_unref(zathura->ui.page_widget); } if (zathura->ui.page_widget_alignment != NULL) { g_object_unref(zathura->ui.page_widget_alignment); } return false; }
bool zathura_init(zathura_t* zathura) { if (zathura == NULL) { return false; } /* create zathura (config/data) directory */ if (g_mkdir_with_parents(zathura->config.config_dir, 0771) == -1) { girara_error("Could not create '%s': %s", zathura->config.config_dir, strerror(errno)); } if (g_mkdir_with_parents(zathura->config.data_dir, 0771) == -1) { girara_error("Could not create '%s': %s", zathura->config.data_dir, strerror(errno)); } /* load plugins */ zathura_plugin_manager_load(zathura->plugins.manager); /* configuration */ config_load_default(zathura); config_load_files(zathura); /* UI */ if (girara_session_init(zathura->ui.session, "zathura") == false) { goto error_free; } /* girara events */ zathura->ui.session->events.buffer_changed = cb_buffer_changed; zathura->ui.session->events.unknown_command = cb_unknown_command; /* zathura signals */ zathura->signals.refresh_view = g_signal_new("refresh-view", GTK_TYPE_WIDGET, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, G_TYPE_POINTER); g_signal_connect(G_OBJECT(zathura->ui.session->gtk.view), "refresh-view", G_CALLBACK(cb_refresh_view), zathura); /* page view */ zathura->ui.page_widget = gtk_grid_new(); gtk_grid_set_row_homogeneous(GTK_GRID(zathura->ui.page_widget), TRUE); gtk_grid_set_column_homogeneous(GTK_GRID(zathura->ui.page_widget), TRUE); if (zathura->ui.page_widget == NULL) { goto error_free; } g_signal_connect(G_OBJECT(zathura->ui.session->gtk.window), "size-allocate", G_CALLBACK(cb_view_resized), zathura); GtkAdjustment* hadjustment = gtk_scrolled_window_get_hadjustment( GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view)); /* Connect hadjustment signals */ g_signal_connect(G_OBJECT(hadjustment), "value-changed", G_CALLBACK(cb_view_hadjustment_value_changed), zathura); g_signal_connect(G_OBJECT(hadjustment), "changed", G_CALLBACK(cb_view_hadjustment_changed), zathura); GtkAdjustment* vadjustment = gtk_scrolled_window_get_vadjustment( GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view)); /* Connect vadjustment signals */ g_signal_connect(G_OBJECT(vadjustment), "value-changed", G_CALLBACK(cb_view_vadjustment_value_changed), zathura); g_signal_connect(G_OBJECT(vadjustment), "changed", G_CALLBACK(cb_view_vadjustment_changed), zathura); /* page view alignment */ gtk_widget_set_halign(zathura->ui.page_widget, GTK_ALIGN_CENTER); gtk_widget_set_valign(zathura->ui.page_widget, GTK_ALIGN_CENTER); gtk_widget_set_hexpand_set(zathura->ui.page_widget, TRUE); gtk_widget_set_hexpand(zathura->ui.page_widget, FALSE); gtk_widget_set_vexpand_set(zathura->ui.page_widget, TRUE); gtk_widget_set_vexpand(zathura->ui.page_widget, FALSE); gtk_widget_show(zathura->ui.page_widget); /* statusbar */ zathura->ui.statusbar.file = girara_statusbar_item_add(zathura->ui.session, TRUE, TRUE, TRUE, NULL); if (zathura->ui.statusbar.file == NULL) { goto error_free; } zathura->ui.statusbar.buffer = girara_statusbar_item_add(zathura->ui.session, FALSE, FALSE, FALSE, NULL); if (zathura->ui.statusbar.buffer == NULL) { goto error_free; } zathura->ui.statusbar.page_number = girara_statusbar_item_add(zathura->ui.session, FALSE, FALSE, FALSE, NULL); if (zathura->ui.statusbar.page_number == NULL) { goto error_free; } girara_statusbar_item_set_text(zathura->ui.session, zathura->ui.statusbar.file, _("[No name]")); /* signals */ g_signal_connect(G_OBJECT(zathura->ui.session->gtk.window), "destroy", G_CALLBACK(cb_destroy), zathura); /* database */ char* database = NULL; girara_setting_get(zathura->ui.session, "database", &database); if (g_strcmp0(database, "plain") == 0) { girara_debug("Using plain database backend."); zathura->database = zathura_plaindatabase_new(zathura->config.data_dir); #ifdef WITH_SQLITE } else if (g_strcmp0(database, "sqlite") == 0) { girara_debug("Using sqlite database backend."); char* tmp = g_build_filename(zathura->config.data_dir, "bookmarks.sqlite", NULL); zathura->database = zathura_sqldatabase_new(tmp); g_free(tmp); #endif } else if (g_strcmp0(database, "null") != 0) { girara_error("Database backend '%s' is not supported.", database); } if (zathura->database == NULL && g_strcmp0(database, "null") != 0) { girara_error("Unable to initialize database. Bookmarks won't be available."); } else { g_object_set(G_OBJECT(zathura->ui.session->command_history), "io", zathura->database, NULL); } g_free(database); /* bookmarks */ zathura->bookmarks.bookmarks = girara_sorted_list_new2((girara_compare_function_t) zathura_bookmarks_compare, (girara_free_function_t) zathura_bookmark_free); /* jumplist */ int jumplist_size = 20; girara_setting_get(zathura->ui.session, "jumplist-size", &jumplist_size); zathura->jumplist.max_size = jumplist_size < 0 ? 0 : jumplist_size; zathura->jumplist.list = NULL; zathura->jumplist.size = 0; zathura->jumplist.cur = NULL; /* CSS for index mode */ GiraraTemplate* csstemplate = girara_session_get_template(zathura->ui.session); static const char* index_settings[] = { "index-fg", "index-bg", "index-active-fg", "index-active-bg" }; for (size_t s = 0; s < LENGTH(index_settings); ++s) { girara_template_add_variable(csstemplate, index_settings[s]); char* tmp_value = NULL; GdkRGBA rgba = { 0, 0, 0, 0 }; girara_setting_get(zathura->ui.session, index_settings[s], &tmp_value); if (tmp_value != NULL) { gdk_rgba_parse(&rgba, tmp_value); g_free(tmp_value); } char* color = gdk_rgba_to_string(&rgba); girara_template_set_variable_value(csstemplate, index_settings[s], color); g_free(color); } char* css = g_strdup_printf("%s\n%s", girara_template_get_base(csstemplate), CSS_TEMPLATE_INDEX); girara_template_set_base(csstemplate, css); g_free(css); /* Start D-Bus service */ bool dbus = true; girara_setting_get(zathura->ui.session, "dbus-service", &dbus); if (dbus == true) { zathura->dbus = zathura_dbus_new(zathura); } return true; error_free: if (zathura->ui.page_widget != NULL) { g_object_unref(zathura->ui.page_widget); } return false; }