void zathura_document_get_cell_size(zathura_document_t* document, unsigned int* height, unsigned int* width) { g_return_if_fail(document != NULL && height != NULL && width != NULL); unsigned int number_of_pages = zathura_document_get_number_of_pages(document); *width = 0; *height = 0; /* Get the size of each cell of the table/grid, assuming it is homogeneous * (i.e. each cell has the same dimensions. */ for (unsigned int page_id = 0; page_id < number_of_pages; page_id++) { zathura_page_t* page = zathura_document_get_page(document, page_id); if (page == NULL) continue; unsigned int page_width = 0, page_height = 0; page_calc_height_width(page, &page_height, &page_width, true); if (*width < page_width) *width = page_width; if (*height < page_height) *height = page_height; } }
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); } }
/* Helper function; see sc_display_link and sc_follow. */ static bool draw_links(zathura_t* zathura) { /* set pages to draw links */ bool show_links = false; unsigned int page_offset = 0; const 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++) { zathura_page_t* page = zathura_document_get_page(zathura->document, page_id); if (page == NULL) { continue; } GtkWidget* page_widget = zathura_page_get_widget(zathura, page); GObject* obj_page_widget = G_OBJECT(page_widget); g_object_set(obj_page_widget, "draw-search-results", FALSE, NULL); if (zathura_page_get_visibility(page) == true) { g_object_set(obj_page_widget, "draw-links", TRUE, NULL); int number_of_links = 0; g_object_get(obj_page_widget, "number-of-links", &number_of_links, NULL); if (number_of_links != 0) { show_links = true; } g_object_set(obj_page_widget, "offset-links", page_offset, NULL); page_offset += number_of_links; } else { g_object_set(obj_page_widget, "draw-links", FALSE, NULL); } } return show_links; }
bool sc_abort(girara_session_t* session, girara_argument_t* UNUSED(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; bool clear_search = true; girara_setting_get(session, "abort-clear-search", &clear_search); if (zathura->document != NULL) { 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) { zathura_page_t* page = zathura_document_get_page(zathura->document, page_id); if (page == NULL) { continue; } GtkWidget* page_widget = zathura_page_get_widget(zathura, page); g_object_set(page_widget, "draw-links", FALSE, NULL); if (clear_search == true) { g_object_set(page_widget, "draw-search-results", FALSE, NULL); } } } /* Setting the mode back here has not worked for ages. We need another way to * do this. Let's disable this for now. */ /* girara_mode_set(session, session->modes.normal); */ girara_sc_abort(session, NULL, NULL, 0); return false; }
void cb_refresh_view(GtkWidget* GIRARA_UNUSED(view), gpointer data) { zathura_t* zathura = data; if (zathura == NULL || zathura->document == NULL) { return; } unsigned int page_id = zathura_document_get_current_page_number(zathura->document); zathura_page_t* page = zathura_document_get_page(zathura->document, page_id); if (page == NULL) { return; } GtkAdjustment* vadj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view)); GtkAdjustment* hadj = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view)); double position_x = zathura_document_get_position_x(zathura->document); double position_y = zathura_document_get_position_y(zathura->document); zathura_adjustment_set_value_from_ratio(vadj, position_y); zathura_adjustment_set_value_from_ratio(hadj, position_x); statusbar_page_number_update(zathura); }
bool sc_abort(girara_session_t* session, girara_argument_t* UNUSED(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; bool clear_search = true; girara_setting_get(session, "abort-clear-search", &clear_search); if (zathura->document != NULL) { 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) { zathura_page_t* page = zathura_document_get_page(zathura->document, page_id); if (page == NULL) { continue; } g_object_set(zathura_page_get_widget(zathura, page), "draw-links", FALSE, NULL); if (clear_search == true) { g_object_set(zathura_page_get_widget(zathura, page), "search-results", NULL, NULL); } } } girara_mode_set(session, session->modes.normal); girara_sc_abort(session, NULL, NULL, 0); return false; }
void cb_view_vadjustment_value_changed(GtkAdjustment* GIRARA_UNUSED(adjustment), gpointer data) { zathura_t* zathura = data; if (zathura == NULL || zathura->document == NULL || zathura->ui.page_widget == NULL) { return; } GtkAdjustment* view_vadjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view)); GtkAdjustment* view_hadjustment = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view)); GdkRectangle view_rect; /* get current adjustment values */ view_rect.y = 0; view_rect.height = gtk_adjustment_get_page_size(view_vadjustment); view_rect.x = 0; view_rect.width = gtk_adjustment_get_page_size(view_hadjustment); int page_padding = 1; girara_setting_get(zathura->ui.session, "page-padding", &page_padding); GdkRectangle center; center.x = (view_rect.width + 1) / 2; center.y = (view_rect.height + 1) / 2; center.height = center.width = (2 * page_padding) + 1; unsigned int number_of_pages = zathura_document_get_number_of_pages(zathura->document); double scale = zathura_document_get_scale(zathura->document); bool updated = false; /* find page that fits */ for (unsigned int page_id = 0; page_id < number_of_pages; page_id++) { zathura_page_t* page = zathura_document_get_page(zathura->document, page_id); GdkRectangle page_rect; GtkWidget* page_widget = zathura_page_get_widget(zathura, page); gtk_widget_translate_coordinates(page_widget, zathura->ui.session->gtk.view, 0, 0, &page_rect.x, &page_rect.y); page_rect.width = zathura_page_get_width(page) * scale; page_rect.height = zathura_page_get_height(page) * scale; if (gdk_rectangle_intersect(&view_rect, &page_rect, NULL) == TRUE) { zathura_page_set_visibility(page, true); if (zathura->global.update_page_number == true && updated == false && gdk_rectangle_intersect(¢er, &page_rect, NULL) == TRUE) { zathura_document_set_current_page_number(zathura->document, page_id); updated = true; } } else { zathura_page_set_visibility(page, false); } zathura_page_widget_update_view_time(ZATHURA_PAGE(page_widget)); } statusbar_page_number_update(zathura); }
bool cb_sc_follow(GtkEntry* entry, girara_session_t* session) { g_return_val_if_fail(session != NULL, FALSE); g_return_val_if_fail(session->global.data != NULL, FALSE); zathura_t* zathura = session->global.data; bool eval = true; char* input = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1); if (input == NULL || strlen(input) == 0) { eval = false; } int index = 0; if (eval == true) { index = atoi(input); if (index == 0 && g_strcmp0(input, "0") != 0) { girara_notify(session, GIRARA_WARNING, _("Invalid input '%s' given."), input); eval = false; } index = index - 1; } /* set pages to draw links */ bool invalid_index = true; 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++) { zathura_page_t* page = zathura_document_get_page(zathura->document, page_id); if (page == NULL || zathura_page_get_visibility(page) == false) { continue; } GtkWidget* page_widget = zathura_page_get_widget(zathura, page); g_object_set(page_widget, "draw-links", FALSE, NULL); if (eval == true) { zathura_link_t* link = zathura_page_widget_link_get(ZATHURA_PAGE(page_widget), index); if (link != NULL) { zathura_link_evaluate(zathura, link); invalid_index = false; } } } if (eval == true && invalid_index == true) { girara_notify(session, GIRARA_WARNING, _("Invalid index '%s' given."), input); } g_free(input); return (eval == TRUE) ? TRUE : FALSE; }
static void cb_print_request_page_setup(GtkPrintOperation* UNUSED(print_operation), GtkPrintContext* UNUSED(context), gint page_number, GtkPageSetup* setup, zathura_t* zathura) { if (zathura == NULL || zathura->document == NULL) { return; } zathura_page_t* page = zathura_document_get_page(zathura->document, page_number); double width = zathura_page_get_width(page); double height = zathura_page_get_height(page); if (width > height) { gtk_page_setup_set_orientation(setup, GTK_PAGE_ORIENTATION_LANDSCAPE); } else { gtk_page_setup_set_orientation(setup, GTK_PAGE_ORIENTATION_PORTRAIT); } }
void render_all(zathura_t* zathura) { if (zathura == NULL || zathura->document == NULL) { return; } /* unmark all pages */ 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++) { zathura_page_t* page = zathura_document_get_page(zathura->document, page_id); unsigned int page_height = 0, page_width = 0; page_calc_height_width(page, &page_height, &page_width, true); GtkWidget* widget = zathura_page_get_widget(zathura, page); gtk_widget_set_size_request(widget, page_width, page_height); gtk_widget_queue_resize(widget); } }
void update_visible_pages(zathura_t* zathura) { const 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++) { zathura_page_t* page = zathura_document_get_page(zathura->document, page_id); GtkWidget* page_widget = zathura_page_get_widget(zathura, page); ZathuraPage* zathura_page_widget = ZATHURA_PAGE(page_widget); if (page_is_visible(zathura->document, page_id) == true) { /* make page visible */ if (zathura_page_get_visibility(page) == false) { zathura_page_set_visibility(page, true); zathura_page_widget_update_view_time(zathura_page_widget); zathura_renderer_page_cache_add(zathura->sync.render_thread, zathura_page_get_index(page)); } } else { /* make page invisible */ if (zathura_page_get_visibility(page) == true) { zathura_page_set_visibility(page, false); /* If a page becomes invisible, abort the render request. */ zathura_page_widget_abort_render_request(zathura_page_widget); } /* reset current search result */ girara_list_t* results = NULL; GObject* obj_page_widget = G_OBJECT(page_widget); g_object_get(obj_page_widget, "search-results", &results, NULL); if (results != NULL) { g_object_set(obj_page_widget, "search-current", 0, NULL); } } } }
bool cmd_search(girara_session_t* session, const char* input, girara_argument_t* argument) { g_return_val_if_fail(session != NULL, false); g_return_val_if_fail(input != NULL, false); g_return_val_if_fail(argument != NULL, false); g_return_val_if_fail(session->global.data != NULL, false); zathura_t* zathura = session->global.data; if (zathura->document == NULL || strlen(input) == 0) { return false; } zathura_error_t error = ZATHURA_ERROR_OK; /* set search direction */ zathura->global.search_direction = argument->n; unsigned int number_of_pages = zathura_document_get_number_of_pages(zathura->document); unsigned int current_page_number = zathura_document_get_current_page_number(zathura->document); /* reset search highlighting */ bool nohlsearch = false; girara_setting_get(session, "nohlsearch", &nohlsearch); /* search pages */ for (unsigned int page_id = 0; page_id < number_of_pages; ++page_id) { unsigned int index = (page_id + current_page_number) % number_of_pages; zathura_page_t* page = zathura_document_get_page(zathura->document, index); if (page == NULL) { continue; } GtkWidget* page_widget = zathura_page_get_widget(zathura, page); g_object_set(page_widget, "draw-links", FALSE, NULL); zathura_renderer_lock(zathura->sync.render_thread); girara_list_t* result = zathura_page_search_text(page, input, &error); zathura_renderer_unlock(zathura->sync.render_thread); if (result == NULL || girara_list_size(result) == 0) { girara_list_free(result); g_object_set(page_widget, "search-results", NULL, NULL); if (error == ZATHURA_ERROR_NOT_IMPLEMENTED) { break; } else { continue; } } g_object_set(page_widget, "search-results", result, NULL); if (argument->n == BACKWARD) { /* start at bottom hit in page */ g_object_set(page_widget, "search-current", girara_list_size(result) - 1, NULL); } else { g_object_set(page_widget, "search-current", 0, NULL); } } girara_argument_t* arg = g_try_malloc0(sizeof(girara_argument_t)); if (arg == NULL) { return false; } arg->n = FORWARD; sc_search(session, arg, NULL, 0); g_free(arg); return true; }
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 cb_view_vadjustment_value_changed(GtkAdjustment* GIRARA_UNUSED(adjustment), gpointer data) { zathura_t* zathura = data; if (zathura == NULL || zathura->document == NULL || zathura->ui.page_widget == NULL) { return; } GtkAdjustment* view_vadjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view)); GtkAdjustment* view_hadjustment = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view)); /* current adjustment values */ GdkRectangle view_rect = { .x = 0, .y = 0, .width = gtk_adjustment_get_page_size(view_hadjustment), .height = gtk_adjustment_get_page_size(view_vadjustment) }; int page_padding = 1; girara_setting_get(zathura->ui.session, "page-padding", &page_padding); GdkRectangle center = { .x = (view_rect.width + 1) / 2, .y = (view_rect.height + 1) / 2, .width = (2 * page_padding) + 1, .height = (2 * page_padding) + 1 }; unsigned int number_of_pages = zathura_document_get_number_of_pages(zathura->document); double scale = zathura_document_get_scale(zathura->document); bool updated = false; /* find page that fits */ for (unsigned int page_id = 0; page_id < number_of_pages; page_id++) { zathura_page_t* page = zathura_document_get_page(zathura->document, page_id); GdkRectangle page_rect = { .width = zathura_page_get_width(page) * scale, .height = zathura_page_get_height(page) * scale }; GtkWidget* page_widget = zathura_page_get_widget(zathura, page); gtk_widget_translate_coordinates(page_widget, zathura->ui.session->gtk.view, 0, 0, &page_rect.x, &page_rect.y); if (gdk_rectangle_intersect(&view_rect, &page_rect, NULL) == TRUE) { zathura_page_set_visibility(page, true); if (zathura->global.update_page_number == true && updated == false && gdk_rectangle_intersect(¢er, &page_rect, NULL) == TRUE) { zathura_document_set_current_page_number(zathura->document, page_id); updated = true; } } else { zathura_page_set_visibility(page, false); } zathura_page_widget_update_view_time(ZATHURA_PAGE(page_widget)); } statusbar_page_number_update(zathura); } void cb_pages_per_row_value_changed(girara_session_t* session, const char* UNUSED(name), girara_setting_type_t UNUSED(type), void* value, void* UNUSED(data)) { g_return_if_fail(value != NULL); g_return_if_fail(session != NULL); g_return_if_fail(session->global.data != NULL); zathura_t* zathura = session->global.data; int pages_per_row = *(int*) value; if (pages_per_row < 1) { pages_per_row = 1; } unsigned int first_page_column = 1; girara_setting_get(session, "first-page-column", &first_page_column); page_widget_set_mode(zathura, pages_per_row, first_page_column); if (zathura->document != NULL) { unsigned int current_page = zathura_document_get_current_page_number(zathura->document); page_set_delayed(zathura, current_page); } }
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 sc_search(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); g_return_val_if_fail(zathura->document != NULL, false); const int num_pages = zathura_document_get_number_of_pages(zathura->document); const int cur_page = zathura_document_get_current_page_number(zathura->document); int diff = argument->n == FORWARD ? 1 : -1; if (zathura->global.search_direction == BACKWARD) diff = -diff; zathura_page_t* target_page = NULL; int target_idx = 0; for (int page_id = 0; page_id < num_pages; ++page_id) { int tmp = cur_page + diff * page_id; zathura_page_t* page = zathura_document_get_page(zathura->document, (tmp + num_pages) % num_pages); if (page == NULL) { continue; } GtkWidget* page_widget = zathura_page_get_widget(zathura, page); int num_search_results = 0, current = -1; g_object_get(page_widget, "search-current", ¤t, "search-length", &num_search_results, NULL); if (num_search_results == 0 || current == -1) { continue; } if (diff == 1 && current < num_search_results - 1) { /* the next result is on the same page */ target_page = page; target_idx = current + 1; } else if (diff == -1 && current > 0) { target_page = page; target_idx = current - 1; } else { /* the next result is on a different page */ zathura_jumplist_save(zathura); g_object_set(page_widget, "search-current", -1, NULL); for (int npage_id = 1; page_id < num_pages; ++npage_id) { int ntmp = cur_page + diff * (page_id + npage_id); zathura_page_t* npage = zathura_document_get_page(zathura->document, (ntmp + 2*num_pages) % num_pages); zathura_document_set_current_page_number(zathura->document, zathura_page_get_index(npage)); GtkWidget* npage_page_widget = zathura_page_get_widget(zathura, npage); g_object_get(npage_page_widget, "search-length", &num_search_results, NULL); if (num_search_results != 0) { target_page = npage; target_idx = diff == 1 ? 0 : num_search_results - 1; break; } } zathura_jumplist_add(zathura); } break; } if (target_page != NULL) { girara_list_t* results = NULL; GtkWidget* page_widget = zathura_page_get_widget(zathura, target_page); g_object_set(page_widget, "search-current", target_idx, NULL); g_object_get(page_widget, "search-results", &results, NULL); zathura_rectangle_t* rect = girara_list_nth(results, target_idx); zathura_rectangle_t rectangle = recalc_rectangle(target_page, *rect); page_offset_t offset; page_calculate_offset(zathura, target_page, &offset); GtkAdjustment* view_vadjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view)); int y = offset.y - gtk_adjustment_get_page_size(view_vadjustment) / 2 + rectangle.y1; set_adjustment(view_vadjustment, y); bool search_hadjust = true; girara_setting_get(session, "search-hadjust", &search_hadjust); if (search_hadjust == true) { GtkAdjustment* view_hadjustment = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view)); int x = offset.x - gtk_adjustment_get_page_size(view_hadjustment) / 2 + rectangle.x1; set_adjustment(view_hadjustment, x); } } return false; }
bool sc_scroll(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 (zathura->document == NULL) { return false; } GtkAdjustment* adjustment = NULL; if ( (argument->n == LEFT) || (argument->n == FULL_LEFT) || (argument->n == HALF_LEFT) || (argument->n == RIGHT) || (argument->n == FULL_RIGHT) || (argument->n == HALF_RIGHT)) { adjustment = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(session->gtk.view)); } else { adjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(session->gtk.view)); } gdouble view_size = gtk_adjustment_get_page_size(adjustment); gdouble value = gtk_adjustment_get_value(adjustment); gdouble max = gtk_adjustment_get_upper(adjustment) - view_size; zathura->global.update_page_number = true; float scroll_step = 40; girara_setting_get(session, "scroll-step", &scroll_step); float scroll_hstep = -1; girara_setting_get(session, "scroll-hstep", &scroll_hstep); if (scroll_hstep < 0) { scroll_hstep = scroll_step; } float scroll_full_overlap = 0.0; girara_setting_get(session, "scroll-full-overlap", &scroll_full_overlap); bool scroll_page_aware = false; girara_setting_get(session, "scroll-page-aware", &scroll_page_aware); bool scroll_wrap = false; girara_setting_get(session, "scroll-wrap", &scroll_wrap); int padding = 1; girara_setting_get(session, "page-padding", &padding); gdouble new_value; switch(argument->n) { case FULL_UP: case FULL_LEFT: new_value = value - (1.0 - scroll_full_overlap) * view_size - padding; break; case FULL_DOWN: case FULL_RIGHT: new_value = value + (1.0 - scroll_full_overlap) * view_size + padding; break; case HALF_UP: case HALF_LEFT: new_value = value - ((view_size + padding) / 2); break; case HALF_DOWN: case HALF_RIGHT: new_value = value + ((view_size + padding) / 2); break; case LEFT: new_value = value - scroll_hstep; break; case UP: new_value = value - scroll_step; break; case RIGHT: new_value = value + scroll_hstep; break; case DOWN: new_value = value + scroll_step; break; case TOP: new_value = 0; break; case BOTTOM: new_value = max; break; default: new_value = value; } if (scroll_wrap == true) { if (new_value < 0) new_value = max; else if (new_value > max) new_value = 0; } if (scroll_page_aware == true) { int page_offset; double page_size; { unsigned int page_id = zathura_document_get_current_page_number(zathura->document); zathura_page_t* page = zathura_document_get_page(zathura->document, page_id); page_offset_t offset; page_calculate_offset(zathura, page, &offset); double scale = zathura_document_get_scale(zathura->document); if ((argument->n == LEFT) || (argument->n == FULL_LEFT) || (argument->n == HALF_LEFT) || (argument->n == RIGHT) || (argument->n == FULL_RIGHT) || (argument->n == HALF_RIGHT)) { page_offset = offset.x; page_size = zathura_page_get_width(page) * scale; } else { page_offset = offset.y; page_size = zathura_page_get_height(page) * scale; } page_offset -= padding / 2; page_size += padding; } if ((argument->n == FULL_DOWN) || (argument->n == HALF_DOWN) || (argument->n == FULL_RIGHT) || (argument->n == HALF_RIGHT)) { if ((page_offset > value) && (page_offset < value + view_size)) { new_value = page_offset; } else if ((page_offset <= value) && (page_offset + page_size < value + view_size)) { new_value = page_offset + page_size + 1; } else if ((page_offset <= value) && (page_offset + page_size < new_value + view_size)) { new_value = page_offset + page_size - view_size + 1; } } else if ((argument->n == FULL_UP) || (argument->n == HALF_UP) || (argument->n == FULL_LEFT) || (argument->n == HALF_LEFT)) { if ((page_offset + 1 >= value) && (page_offset < value + view_size)) { new_value = page_offset - view_size; } else if ((page_offset <= value) && (page_offset + page_size + 1 < value + view_size)) { new_value = page_offset + page_size - view_size; } else if ((page_offset <= value) && (page_offset > new_value)) { new_value = page_offset; } } } set_adjustment(adjustment, new_value); return false; }
bool sc_search(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); 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); GtkWidget *cur_page_widget = zathura_page_get_widget(zathura, zathura_document_get_page(zathura->document, cur_page)); bool nohlsearch, first_time_after_abort; gboolean draw; nohlsearch = first_time_after_abort = false; draw = FALSE; girara_setting_get(session, "nohlsearch", &nohlsearch); if (nohlsearch == false) { g_object_get(G_OBJECT(cur_page_widget), "draw-search-results", &draw, NULL); if (draw == false) { first_time_after_abort = true; } document_draw_search_results(zathura, true); } int diff = argument->n == FORWARD ? 1 : -1; if (zathura->global.search_direction == BACKWARD) diff = -diff; zathura_page_t* target_page = NULL; int target_idx = 0; for (unsigned int page_id = 0; page_id < num_pages; ++page_id) { int tmp = cur_page + diff * page_id; zathura_page_t* page = zathura_document_get_page(zathura->document, (tmp + num_pages) % num_pages); if (page == NULL) { continue; } GtkWidget* page_widget = zathura_page_get_widget(zathura, page); int num_search_results = 0, current = -1; g_object_get(G_OBJECT(page_widget), "search-current", ¤t, "search-length", &num_search_results, NULL); if (num_search_results == 0 || current == -1) { continue; } if (first_time_after_abort == true || (tmp + num_pages) % num_pages != cur_page) { target_page = page; target_idx = diff == 1 ? 0 : num_search_results - 1; break; } if (diff == 1 && current < num_search_results - 1) { /* the next result is on the same page */ target_page = page; target_idx = current + 1; } else if (diff == -1 && current > 0) { target_page = page; target_idx = current - 1; } else { /* the next result is on a different page */ g_object_set(G_OBJECT(page_widget), "search-current", -1, NULL); for (int npage_id = 1; page_id < num_pages; ++npage_id) { int ntmp = cur_page + diff * (page_id + npage_id); zathura_page_t* npage = zathura_document_get_page(zathura->document, (ntmp + 2*num_pages) % num_pages); GtkWidget* npage_page_widget = zathura_page_get_widget(zathura, npage); g_object_get(G_OBJECT(npage_page_widget), "search-length", &num_search_results, NULL); if (num_search_results != 0) { target_page = npage; target_idx = diff == 1 ? 0 : num_search_results - 1; break; } } } break; } if (target_page != NULL) { girara_list_t* results = NULL; GtkWidget* page_widget = zathura_page_get_widget(zathura, target_page); GObject* obj_page_widget = G_OBJECT(page_widget); g_object_set(obj_page_widget, "search-current", target_idx, NULL); g_object_get(obj_page_widget, "search-results", &results, NULL); /* Need to adjust rectangle to page scale and orientation */ zathura_rectangle_t* rect = girara_list_nth(results, target_idx); zathura_rectangle_t rectangle = recalc_rectangle(target_page, *rect); bool search_hadjust = true; girara_setting_get(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, zathura_page_get_index(target_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); /* 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 */ zathura_jumplist_add(zathura); position_set(zathura, pos_x, pos_y); zathura_jumplist_add(zathura); } return false; }
bool cmd_export(girara_session_t* session, girara_list_t* argument_list) { g_return_val_if_fail(session != NULL, false); g_return_val_if_fail(session->global.data != NULL, false); zathura_t* zathura = session->global.data; if (zathura->document == NULL) { girara_notify(session, GIRARA_ERROR, _("No document opened.")); return false; } if (girara_list_size(argument_list) != 2) { girara_notify(session, GIRARA_ERROR, _("Invalid number of arguments given.")); return false; } const char* file_identifier = girara_list_nth(argument_list, 0); const char* file_name = girara_list_nth(argument_list, 1); if (file_name == NULL || file_identifier == NULL) { return false; } char* export_path = girara_fix_path(file_name); if (export_path == NULL) { return false; } /* attachment */ if (strncmp(file_identifier, "attachment-", strlen("attachment-")) == 0) { if (zathura_document_attachment_save(zathura->document, file_identifier + strlen("attachment-"), export_path) == false) { girara_notify(session, GIRARA_ERROR, _("Couldn't write attachment '%s' to '%s'."), file_identifier, file_name); } else { girara_notify(session, GIRARA_INFO, _("Wrote attachment '%s' to '%s'."), file_identifier, export_path); } /* image */ } else if (strncmp(file_identifier, "image-p", strlen("image-p")) == 0 && strlen(file_identifier) >= 10) { /* parse page id */ const char* input = file_identifier + strlen("image-p"); int page_id = atoi(input); if (page_id == 0) { goto image_error; } /* parse image id */ input = strstr(input, "-"); if (input == NULL) { goto image_error; } int image_id = atoi(input + 1); if (image_id == 0) { goto image_error; } /* get image */ zathura_page_t* page = zathura_document_get_page(zathura->document, page_id - 1); if (page == NULL) { goto image_error; } girara_list_t* images = zathura_page_images_get(page, NULL); if (images == NULL) { goto image_error; } zathura_image_t* image = girara_list_nth(images, image_id - 1); if (image == NULL) { goto image_error; } cairo_surface_t* surface = zathura_page_image_get_cairo(page, image, NULL); if (surface == NULL) { goto image_error; } if (cairo_surface_write_to_png(surface, export_path) == CAIRO_STATUS_SUCCESS) { girara_notify(session, GIRARA_INFO, _("Wrote image '%s' to '%s'."), file_identifier, export_path); } else { girara_notify(session, GIRARA_ERROR, _("Couldn't write image '%s' to '%s'."), file_identifier, file_name); } goto error_ret; image_error: girara_notify(session, GIRARA_ERROR, _("Unknown image '%s'."), file_identifier); goto error_ret; /* unknown */ } else { girara_notify(session, GIRARA_ERROR, _("Unknown attachment or image '%s'."), file_identifier); } error_ret: g_free(export_path); return true; }