From c86fea736694b17beb9fb621fceac7e2970afe08 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Campos Date: Wed, 27 Aug 2008 09:01:41 +0000 Subject: Removed 2008-08-27 Carlos Garcia Campos * backend/djvu/Makefile.am: * backend/djvu/djvu-document-private.h: * backend/djvu/djvu-document.c: (djvu_document_find_find_text), (djvu_document_find_iface_init): * backend/djvu/djvu-text-page.[ch]: * backend/djvu/djvu-text.[ch]: Removed * backend/pdf/ev-poppler.cc: (pdf_document_find_find_text), (pdf_document_find_iface_init): * libdocument/ev-document-find.[ch]: (ev_document_find_find_text): * shell/ev-jobs.[ch]: (ev_job_find_init), (ev_job_find_dispose), (ev_job_find_run), (ev_job_find_class_init), (ev_job_find_new), (ev_job_find_get_n_results), (ev_job_find_get_progress), (ev_job_find_has_results), (ev_job_find_get_results): * shell/ev-view-private.h: * shell/ev-view.[ch]: (ev_view_expose_event), (highlight_find_results), (ev_view_finalize), (ev_view_get_property), (ev_view_class_init), (page_changed_cb), (ev_view_set_document), (ev_view_find_get_n_results), (ev_view_find_get_result), (jump_to_find_result), (jump_to_find_page), (ev_view_find_changed), (ev_view_find_next), (ev_view_find_previous), (ev_view_find_search_changed), (ev_view_find_set_highlight_search), (ev_view_find_cancel): * shell/ev-window.c: (ev_window_update_actions), (page_changed_cb), (ev_window_setup_document), (ev_window_update_find_status_message), (ev_window_find_job_finished_cb), (ev_window_find_job_updated_cb), (ev_window_clear_find_job), (find_bar_close_cb), (find_bar_search_changed_cb), (find_bar_visibility_changed_cb), (ev_window_dispose), (ev_window_init): Rework find interface. The find logic has been moved from backends to the shell avoiding a lot of duplicated code in the backends and making easier to implement the find interface in the backends. svn path=/trunk/; revision=3123 --- diff --git a/ChangeLog b/ChangeLog index 289bbea..6eaf507 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,39 @@ +2008-08-27 Carlos Garcia Campos + + * backend/djvu/Makefile.am: + * backend/djvu/djvu-document-private.h: + * backend/djvu/djvu-document.c: (djvu_document_find_find_text), + (djvu_document_find_iface_init): + * backend/djvu/djvu-text-page.[ch]: + * backend/djvu/djvu-text.[ch]: Removed + * backend/pdf/ev-poppler.cc: (pdf_document_find_find_text), + (pdf_document_find_iface_init): + * libdocument/ev-document-find.[ch]: (ev_document_find_find_text): + * shell/ev-jobs.[ch]: (ev_job_find_init), (ev_job_find_dispose), + (ev_job_find_run), (ev_job_find_class_init), (ev_job_find_new), + (ev_job_find_get_n_results), (ev_job_find_get_progress), + (ev_job_find_has_results), (ev_job_find_get_results): + * shell/ev-view-private.h: + * shell/ev-view.[ch]: (ev_view_expose_event), + (highlight_find_results), (ev_view_finalize), + (ev_view_get_property), (ev_view_class_init), (page_changed_cb), + (ev_view_set_document), (ev_view_find_get_n_results), + (ev_view_find_get_result), (jump_to_find_result), + (jump_to_find_page), (ev_view_find_changed), (ev_view_find_next), + (ev_view_find_previous), (ev_view_find_search_changed), + (ev_view_find_set_highlight_search), (ev_view_find_cancel): + * shell/ev-window.c: (ev_window_update_actions), + (page_changed_cb), (ev_window_setup_document), + (ev_window_update_find_status_message), + (ev_window_find_job_finished_cb), (ev_window_find_job_updated_cb), + (ev_window_clear_find_job), (find_bar_close_cb), + (find_bar_search_changed_cb), (find_bar_visibility_changed_cb), + (ev_window_dispose), (ev_window_init): + + Rework find interface. The find logic has been moved from backends + to the shell avoiding a lot of duplicated code in the backends and + making easier to implement the find interface in the backends. + 2008-08-25 Carlos Garcia Campos * backend/pdf/ev-poppler.cc: diff --git a/backend/djvu/Makefile.am b/backend/djvu/Makefile.am index 956259b..4cd22f5 100644 --- a/backend/djvu/Makefile.am +++ b/backend/djvu/Makefile.am @@ -18,8 +18,6 @@ libdjvudocument_la_SOURCES = \ djvu-document-private.h \ djvu-links.c \ djvu-links.h \ - djvu-text.c \ - djvu-text.h \ djvu-text-page.c \ djvu-text-page.h diff --git a/backend/djvu/djvu-document-private.h b/backend/djvu/djvu-document-private.h index 30810bb..a110e15 100644 --- a/backend/djvu/djvu-document-private.h +++ b/backend/djvu/djvu-document-private.h @@ -22,7 +22,6 @@ #define __DJVU_DOCUMENT_INTERNAL_H__ #include "djvu-document.h" -#include "djvu-text.h" #include @@ -36,8 +35,6 @@ struct _DjvuDocument { gchar *uri; - DjvuText *search; - /* PS exporter */ gchar *ps_filename; GString *opts; diff --git a/backend/djvu/djvu-document.c b/backend/djvu/djvu-document.c index 5f59a8e..40950c7 100644 --- a/backend/djvu/djvu-document.c +++ b/backend/djvu/djvu-document.c @@ -21,7 +21,7 @@ #include #include "djvu-document.h" -#include "djvu-text.h" +#include "djvu-text-page.h" #include "djvu-links.h" #include "djvu-document-private.h" #include "ev-document-thumbnails.h" @@ -388,9 +388,6 @@ djvu_document_finalize (GObject *object) { DjvuDocument *djvu_document = DJVU_DOCUMENT (object); - if (djvu_document->search) - djvu_text_free (djvu_document->search); - if (djvu_document->d_document) ddjvu_document_release (djvu_document->d_document); @@ -438,6 +435,30 @@ djvu_document_document_iface_init (EvDocumentIface *iface) } static gchar * +djvu_text_copy (DjvuDocument *djvu_document, + gint page, + EvRectangle *rectangle) +{ + miniexp_t page_text; + gchar *text = NULL; + + while ((page_text = + ddjvu_document_get_pagetext (djvu_document->d_document, + page, "char")) == miniexp_dummy) + djvu_handle_events (djvu_document, TRUE, NULL); + + if (page_text != miniexp_nil) { + DjvuTextPage *page = djvu_text_page_new (page_text); + + text = djvu_text_page_copy (page, rectangle); + djvu_text_page_free (page); + ddjvu_miniexp_release (djvu_document->d_document, page_text); + } + + return text; +} + +static gchar * djvu_selection_get_selected_text (EvSelection *selection, EvRenderContext *rc, EvSelectionStyle style, @@ -627,107 +648,62 @@ djvu_document_init (DjvuDocument *djvu_document) djvu_document->d_document = NULL; } -static void -djvu_document_find_begin (EvDocumentFind *document, - int page, - const char *search_string, - gboolean case_sensitive) +static GList * +djvu_document_find_find_text (EvDocumentFind *document, + EvPage *page, + const char *text, + gboolean case_sensitive) { DjvuDocument *djvu_document = DJVU_DOCUMENT (document); + miniexp_t page_text; + gdouble width, height; + GList *matches = NULL, *l; - if (djvu_document->search && - strcmp (search_string, djvu_text_get_text (djvu_document->search)) == 0) - return; - - if (djvu_document->search) - djvu_text_free (djvu_document->search); + g_return_val_if_fail (text != NULL, NULL); - djvu_document->search = djvu_text_new (djvu_document, - page, - case_sensitive, - search_string); -} - -static int -djvu_document_find_get_n_results (EvDocumentFind *document_find, int page) -{ - DjvuText *search = DJVU_DOCUMENT (document_find)->search; + while ((page_text = ddjvu_document_get_pagetext (djvu_document->d_document, + page->index, + "char")) == miniexp_dummy) + djvu_handle_events (djvu_document, TRUE, NULL); - if (search) { - return djvu_text_n_results (search, page); - } else { - return 0; + if (page_text != miniexp_nil) { + DjvuTextPage *tpage = djvu_text_page_new (page_text); + + djvu_text_page_prepare_search (tpage, case_sensitive); + if (tpage->links->len > 0) { + djvu_text_page_search (tpage, text); + matches = tpage->results; + } + djvu_text_page_free (tpage); + ddjvu_miniexp_release (djvu_document->d_document, page_text); } -} -static gboolean -djvu_document_find_get_result (EvDocumentFind *document_find, - int page, - int n_result, - EvRectangle *rectangle) -{ - DjvuDocument *djvu_document = DJVU_DOCUMENT (document_find); - DjvuText *search = djvu_document->search; - EvRectangle *r; - double width, height; - - if (search == NULL) - return FALSE; + if (!matches) + return NULL; - r = djvu_text_get_result (search, page, n_result); - if (r == NULL) - return FALSE; + document_get_page_size (djvu_document, page->index, &width, &height); + for (l = matches; l && l->data; l = g_list_next (l)) { + EvRectangle *r = (EvRectangle *)l->data; + gdouble tmp; - document_get_page_size (djvu_document, page, &width, &height); - rectangle->x1 = r->x1 * SCALE_FACTOR; - rectangle->y1 = height - r->y2 * SCALE_FACTOR; - rectangle->x2 = r->x2 * SCALE_FACTOR; - rectangle->y2 = height - r->y1 * SCALE_FACTOR; + tmp = r->y1; - return TRUE; -} - -static int -djvu_document_find_page_has_results (EvDocumentFind *document_find, - int page) -{ - DjvuText *search = DJVU_DOCUMENT (document_find)->search; - - return search && djvu_text_has_results (search, page); -} + r->x1 *= SCALE_FACTOR; + r->x2 *= SCALE_FACTOR; -static double -djvu_document_find_get_progress (EvDocumentFind *document_find) -{ - DjvuText *search = DJVU_DOCUMENT (document_find)->search; - - if (search == NULL) { - return 0; + tmp = r->y1; + r->y1 = height - r->y2 * SCALE_FACTOR; + r->y2 = height - tmp * SCALE_FACTOR; } + - return djvu_text_get_progress (search); -} - -static void -djvu_document_find_cancel (EvDocumentFind *document) -{ - DjvuDocument *djvu_document = DJVU_DOCUMENT (document); - - if (djvu_document->search) { - djvu_text_free (djvu_document->search); - djvu_document->search = NULL; - } + return matches; } static void djvu_document_find_iface_init (EvDocumentFindIface *iface) { - iface->begin = djvu_document_find_begin; - iface->get_n_results = djvu_document_find_get_n_results; - iface->get_result = djvu_document_find_get_result; - iface->page_has_results = djvu_document_find_page_has_results; - iface->get_progress = djvu_document_find_get_progress; - iface->cancel = djvu_document_find_cancel; + iface->find_text = djvu_document_find_find_text; } static GList * diff --git a/backend/djvu/djvu-text-page.c b/backend/djvu/djvu-text-page.c index f0b2809..696cec7 100644 --- a/backend/djvu/djvu-text-page.c +++ b/backend/djvu/djvu-text-page.c @@ -371,7 +371,7 @@ djvu_text_page_append_text (DjvuTextPage *page, */ void djvu_text_page_search (DjvuTextPage *page, - char *text) + const char *text) { char *haystack = page->text; int search_len; diff --git a/backend/djvu/djvu-text-page.h b/backend/djvu/djvu-text-page.h index 61325af..5d2134c 100644 --- a/backend/djvu/djvu-text-page.h +++ b/backend/djvu/djvu-text-page.h @@ -23,6 +23,7 @@ #include #include +#include typedef struct _DjvuTextPage DjvuTextPage; @@ -50,8 +51,8 @@ char * djvu_text_page_copy (DjvuTextPage *page, void djvu_text_page_prepare_search (DjvuTextPage *page, gboolean case_sensitive); void djvu_text_page_search (DjvuTextPage *page, - char *text); -DjvuTextPage* djvu_text_page_new (miniexp_t text); + const char *text); +DjvuTextPage* djvu_text_page_new (miniexp_t text); void djvu_text_page_free (DjvuTextPage *page); #endif /* __DJVU_TEXT_PAGE_H__ */ diff --git a/backend/djvu/djvu-text.c b/backend/djvu/djvu-text.c deleted file mode 100644 index e87dbb1..0000000 --- a/backend/djvu/djvu-text.c +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Implements search and copy functionality for Djvu files. - * Copyright (C) 2006 Michael Hofmann - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include -#include -#include -#include - -#include "djvu-document-private.h" -#include "djvu-document.h" -#include "djvu-text.h" -#include "djvu-text-page.h" -#include "ev-document-find.h" -#include "ev-document.h" - - - -struct _DjvuText { - DjvuDocument *document; - gboolean case_sensitive; - char *text; - GList **pages; - guint idle; - int start_page; - int search_page; -}; - -/** - * djvu_text_idle_callback: - * @data: #DjvuText instance - * - * Idle callback that processes one page at a time. - * - * Returns: whether there are more pages to be processed - */ -static gboolean -djvu_text_idle_callback (void *data) -{ - DjvuText *djvu_text = (DjvuText *) data; - DjvuDocument *djvu_document = djvu_text->document; - int n_pages; - miniexp_t page_text; - - ev_document_doc_mutex_lock (); - while ((page_text = - ddjvu_document_get_pagetext (djvu_document->d_document, - djvu_text->search_page, - "char")) == miniexp_dummy) - djvu_handle_events (djvu_document, TRUE, NULL); - - if (page_text != miniexp_nil) { - DjvuTextPage *page = djvu_text_page_new (page_text); - djvu_text_page_prepare_search (page, djvu_text->case_sensitive); - if (page->links->len > 0) { - djvu_text_page_search (page, djvu_text->text); - djvu_text->pages[djvu_text->search_page] = page->results; - ev_document_find_changed (EV_DOCUMENT_FIND - (djvu_document), - djvu_text->search_page); - } - djvu_text_page_free (page); - ddjvu_miniexp_release (djvu_document->d_document, - page_text); - } - ev_document_doc_mutex_unlock (); - - n_pages = - djvu_document_get_n_pages (EV_DOCUMENT (djvu_text->document)); - djvu_text->search_page += 1; - if (djvu_text->search_page == n_pages) { - /* wrap around */ - djvu_text->search_page = 0; - } - - if (djvu_text->search_page != djvu_text->start_page) - return TRUE; - - /* We're done. */ - djvu_text->idle = 0; - /* will return FALSE to remove */ - return FALSE; -} - -/** - * djvu_text_new: - * @djvu_document: document to search - * @start_page: first page to search - * @case_sensitive: uses g_utf8_case_fold() to enable case-insensitive - * searching - * @text: text to search - * - * Creates a new #DjvuText instance to enable searching. An idle call - * is used to process all pages starting from @start_page. - * - * Returns: newly created instance - */ -DjvuText * -djvu_text_new (DjvuDocument *djvu_document, - int start_page, - gboolean case_sensitive, - const char *text) -{ - DjvuText *djvu_text; - int n_pages; - int i; - - n_pages = djvu_document_get_n_pages (EV_DOCUMENT (djvu_document)); - - djvu_text = g_new0 (DjvuText, 1); - - if (case_sensitive) - djvu_text->text = g_strdup (text); - else - djvu_text->text = g_utf8_casefold (text, -1); - djvu_text->pages = g_new0 (GList *, n_pages); - for (i = 0; i < n_pages; i++) { - djvu_text->pages[i] = NULL; - } - - djvu_text->document = djvu_document; - - /* We add at low priority so the progress bar repaints */ - djvu_text->idle = g_idle_add_full (G_PRIORITY_LOW, - djvu_text_idle_callback, - djvu_text, NULL); - - djvu_text->case_sensitive = case_sensitive; - djvu_text->start_page = start_page; - djvu_text->search_page = start_page; - - return djvu_text; -} - -/** - * djvu_text_copy: - * @djvu_document: document to search - * @page: page to search - * @rectangle: rectangle to copy - * - * Copies and returns the text in the given rectangle. - * - * Returns: newly allocated text or NULL of none is available - */ -char * -djvu_text_copy (DjvuDocument *djvu_document, - int page, - EvRectangle *rectangle) -{ - miniexp_t page_text; - char* text = NULL; - - while ((page_text = - ddjvu_document_get_pagetext (djvu_document->d_document, - page, "char")) == miniexp_dummy) - djvu_handle_events (djvu_document, TRUE, NULL); - - if (page_text != miniexp_nil) { - DjvuTextPage *page = djvu_text_page_new (page_text); - text = djvu_text_page_copy (page, rectangle); - djvu_text_page_free (page); - ddjvu_miniexp_release (djvu_document->d_document, page_text); - } - - return text; -} - -/** - * djvu_text_free: - * @djvu_text: instance to free - * - * Frees the given #DjvuText instance. - */ -void djvu_text_free (DjvuText * djvu_text) -{ - DjvuDocument *djvu_document = djvu_text->document; - int n_pages; - int i; - - if (djvu_text->idle != 0) - g_source_remove (djvu_text->idle); - - n_pages = djvu_document_get_n_pages (EV_DOCUMENT (djvu_document)); - for (i = 0; i < n_pages; i++) { - g_list_foreach (djvu_text->pages[i], (GFunc) g_free, NULL); - g_list_free (djvu_text->pages[i]); - } - - g_free (djvu_text->text); -} - -/** - * djvu_text_get_text: - * @djvu_text: #DjvuText instance - * - * Returns the search text. This is mainly to be able to avoid reinstantiation - * for the same search text. - * - * Returns: the text this instance of #DjvuText is looking for - */ -const char * -djvu_text_get_text (DjvuText *djvu_text) -{ - return djvu_text->text; -} - -/** - * djvu_text_n_results: - * @djvu_text: #DjvuText instance - * @page: page number - * - * Returns the number of search results available for the given page. - * - * Returns: number of search results - */ -int -djvu_text_n_results (DjvuText *djvu_text, - int page) -{ - return g_list_length (djvu_text->pages[page]); -} - -/** - * djvu_text_has_results: - * @djvu_text: #DjvuText instance - * @page: page number - * - * Returns whether there are search results available for the given page. - * This method executes faster than djvu_text_n_results(). - * - * Returns: whether there are search results - */ -int -djvu_text_has_results (DjvuText *djvu_text, - int page) -{ - return djvu_text->pages[page] != NULL; -} - -/** - * djvu_text_get_result: - * @djvu_text: #DjvuText instance - * @page: page number - * @n_result: result number - * - * Returns the n-th search result of a given page. The coordinates are - * Djvu-specific and need to be processed to be compatible with the Evince - * coordinate system. The result may span several lines! - * - * Returns: the rectangle for the search result - */ -EvRectangle * -djvu_text_get_result (DjvuText *djvu_text, - int page, - int n_result) -{ - return (EvRectangle *) g_list_nth_data (djvu_text->pages[page], - n_result); -} - -/** - * djvu_text_get_progress: - * @djvu_text: #DjvuText instance - * - * Returns the percentage of pages done searching. - * - * Returns: the progress as value between 0 and 1 - */ -double -djvu_text_get_progress (DjvuText *djvu_text) -{ - int pages_done; - int n_pages; - - n_pages = - djvu_document_get_n_pages (EV_DOCUMENT (djvu_text->document)); - if (djvu_text->search_page > djvu_text->start_page) { - pages_done = djvu_text->search_page - djvu_text->start_page + 1; - } else if (djvu_text->search_page == djvu_text->start_page) { - pages_done = n_pages; - } else { - pages_done = - n_pages - djvu_text->start_page + djvu_text->search_page; - } - return pages_done / (double) n_pages; -} - diff --git a/backend/djvu/djvu-text.h b/backend/djvu/djvu-text.h deleted file mode 100644 index b7371df..0000000 --- a/backend/djvu/djvu-text.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2006 Michael Hofmann - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __DJVU_TEXT_H__ -#define __DJVU_TEXT_H__ - -#include "ev-document.h" - -#include - -typedef struct _DjvuText DjvuText; - -DjvuText *djvu_text_new (DjvuDocument *djvu_document, - int start_page, - gboolean case_sensitive, - const char *text); -void djvu_text_free (DjvuText *djvu_text); -const char *djvu_text_get_text (DjvuText *djvu_text); -int djvu_text_n_results (DjvuText *djvu_text, - int page); -EvRectangle *djvu_text_get_result (DjvuText *djvu_text, - int page, - int n_result); -int djvu_text_has_results (DjvuText *djvu_text, - int page); -double djvu_text_get_progress (DjvuText *djvu_text); -char *djvu_text_copy (DjvuDocument *djvu_document, - int page, - EvRectangle *rectangle); - -#endif /* __DJVU_TEXT_H__ */ diff --git a/backend/pdf/ev-poppler.cc b/backend/pdf/ev-poppler.cc index 4687ac2..983298e 100644 --- a/backend/pdf/ev-poppler.cc +++ b/backend/pdf/ev-poppler.cc @@ -1364,195 +1364,42 @@ pdf_document_document_thumbnails_iface_init (EvDocumentThumbnailsIface *iface) } -static gboolean -pdf_document_search_idle_callback (void *data) -{ - PdfDocumentSearch *search = (PdfDocumentSearch*) data; - PdfDocument *pdf_document = search->document; - int n_pages; - GList *matches; - PopplerPage *page; - - page = poppler_document_get_page (search->document->document, - search->search_page); - - ev_document_doc_mutex_lock (); - matches = poppler_page_find_text (page, search->text); - ev_document_doc_mutex_unlock (); - - g_object_unref (page); - - search->pages[search->search_page] = matches; - ev_document_find_changed (EV_DOCUMENT_FIND (pdf_document), - search->search_page); - - n_pages = pdf_document_get_n_pages (EV_DOCUMENT (search->document)); - search->search_page += 1; - if (search->search_page == n_pages) { - /* wrap around */ - search->search_page = 0; - } - - if (search->search_page != search->start_page) { - return TRUE; - } - - /* We're done. */ - search->idle = 0; /* will return FALSE to remove */ - return FALSE; -} - - -static PdfDocumentSearch * -pdf_document_search_new (PdfDocument *pdf_document, - int start_page, - const char *text) -{ - PdfDocumentSearch *search; - int n_pages; - int i; - - n_pages = pdf_document_get_n_pages (EV_DOCUMENT (pdf_document)); - - search = g_new0 (PdfDocumentSearch, 1); - - search->text = g_strdup (text); - search->pages = g_new0 (GList *, n_pages); - search->document = pdf_document; - - /* We add at low priority so the progress bar repaints */ - search->idle = g_idle_add_full (G_PRIORITY_LOW, - pdf_document_search_idle_callback, - search, - NULL); - - search->start_page = start_page; - search->search_page = start_page; - - return search; -} - -static void -pdf_document_find_begin (EvDocumentFind *document, - int page, - const char *search_string, - gboolean case_sensitive) -{ - PdfDocument *pdf_document = PDF_DOCUMENT (document); - - /* FIXME handle case_sensitive (right now XPDF - * code is always case insensitive for ASCII - * and case sensitive for all other languaages) - */ - - if (pdf_document->search && - strcmp (search_string, pdf_document->search->text) == 0) - return; - - if (pdf_document->search) - pdf_document_search_free (pdf_document->search); - - pdf_document->search = pdf_document_search_new (pdf_document, - page, - search_string); -} - -static int -pdf_document_find_get_n_results (EvDocumentFind *document_find, int page) -{ - PdfDocumentSearch *search = PDF_DOCUMENT (document_find)->search; - - if (search) { - return g_list_length (search->pages[page]); - } else { - return 0; - } -} - -static gboolean -pdf_document_find_get_result (EvDocumentFind *document_find, - int page, - int n_result, - EvRectangle *rectangle) +static GList * +pdf_document_find_find_text (EvDocumentFind *document_find, + EvPage *page, + const gchar *text, + gboolean case_sensitive) { - PdfDocument *pdf_document = PDF_DOCUMENT (document_find); - PdfDocumentSearch *search = pdf_document->search; + GList *matches, *l; PopplerPage *poppler_page; - PopplerRectangle *r; - double height; - - if (search == NULL) - return FALSE; + gdouble height; + + g_return_val_if_fail (POPPLER_IS_PAGE (page->backend_page), NULL); + g_return_val_if_fail (text != NULL, NULL); - r = (PopplerRectangle *) g_list_nth_data (search->pages[page], - n_result); - if (r == NULL) - return FALSE; + poppler_page = POPPLER_PAGE (page->backend_page); + + matches = poppler_page_find_text (poppler_page, text); + if (!matches) + return NULL; - poppler_page = poppler_document_get_page (pdf_document->document, page); poppler_page_get_size (poppler_page, NULL, &height); - rectangle->x1 = r->x1; - rectangle->y1 = height - r->y2; - rectangle->x2 = r->x2; - rectangle->y2 = height - r->y1; - g_object_unref (poppler_page); - - return TRUE; -} - -static int -pdf_document_find_page_has_results (EvDocumentFind *document_find, - int page) -{ - PdfDocumentSearch *search = PDF_DOCUMENT (document_find)->search; + for (l = matches; l && l->data; l = g_list_next (l)) { + PopplerRectangle *rect = (PopplerRectangle *)l->data; + gdouble tmp; - return search && search->pages[page] != NULL; -} - -static double -pdf_document_find_get_progress (EvDocumentFind *document_find) -{ - PdfDocumentSearch *search; - int n_pages, pages_done; - - search = PDF_DOCUMENT (document_find)->search; - - if (search == NULL) { - return 0; - } - - n_pages = pdf_document_get_n_pages (EV_DOCUMENT (document_find)); - if (search->search_page > search->start_page) { - pages_done = search->search_page - search->start_page + 1; - } else if (search->search_page == search->start_page) { - pages_done = n_pages; - } else { - pages_done = n_pages - search->start_page + search->search_page; - } - - return pages_done / (double) n_pages; -} - -static void -pdf_document_find_cancel (EvDocumentFind *document) -{ - PdfDocument *pdf_document = PDF_DOCUMENT (document); - - if (pdf_document->search) { - pdf_document_search_free (pdf_document->search); - pdf_document->search = NULL; + tmp = rect->y1; + rect->y1 = height - rect->y2; + rect->y2 = height - tmp; } + + return matches; } static void pdf_document_find_iface_init (EvDocumentFindIface *iface) { - iface->begin = pdf_document_find_begin; - iface->get_n_results = pdf_document_find_get_n_results; - iface->get_result = pdf_document_find_get_result; - iface->page_has_results = pdf_document_find_page_has_results; - iface->get_progress = pdf_document_find_get_progress; - iface->cancel = pdf_document_find_cancel; + iface->find_text = pdf_document_find_find_text; } static void diff --git a/libdocument/ev-document-find.c b/libdocument/ev-document-find.c index 02fbae2..59b8755 100644 --- a/libdocument/ev-document-find.c +++ b/libdocument/ev-document-find.c @@ -21,9 +21,6 @@ #include "config.h" #include "ev-document-find.h" -#include "ev-backend-marshalers.h" - -static void ev_document_find_base_init (gpointer g_class); GType ev_document_find_get_type (void) @@ -35,7 +32,7 @@ ev_document_find_get_type (void) const GTypeInfo our_info = { sizeof (EvDocumentFindIface), - ev_document_find_base_init, + NULL, NULL, }; @@ -47,80 +44,14 @@ ev_document_find_get_type (void) return type; } -static void -ev_document_find_base_init (gpointer g_class) -{ - static gboolean initialized = FALSE; - - if (!initialized) { - g_signal_new ("find_changed", - EV_TYPE_DOCUMENT_FIND, - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EvDocumentFindIface, find_changed), - NULL, NULL, - g_cclosure_marshal_VOID__INT, - G_TYPE_NONE, 1, - G_TYPE_INT); - - initialized = TRUE; - } -} - -void -ev_document_find_begin (EvDocumentFind *document_find, - int page, - const char *search_string, - gboolean case_sensitive) +GList * +ev_document_find_find_text (EvDocumentFind *document_find, + EvPage *page, + const gchar *text, + gboolean case_sensitive) { EvDocumentFindIface *iface = EV_DOCUMENT_FIND_GET_IFACE (document_find); - - g_return_if_fail (search_string != NULL); - - iface->begin (document_find, page, search_string, case_sensitive); -} - -void -ev_document_find_cancel (EvDocumentFind *document_find) -{ - EvDocumentFindIface *iface = EV_DOCUMENT_FIND_GET_IFACE (document_find); - iface->cancel (document_find); + + return iface->find_text (document_find, page, text, case_sensitive); } -int -ev_document_find_page_has_results (EvDocumentFind *document_find, - int page) -{ - EvDocumentFindIface *iface = EV_DOCUMENT_FIND_GET_IFACE (document_find); - return iface->page_has_results (document_find, page); -} - -int -ev_document_find_get_n_results (EvDocumentFind *document_find, - int page) -{ - EvDocumentFindIface *iface = EV_DOCUMENT_FIND_GET_IFACE (document_find); - return iface->get_n_results (document_find, page); -} - -gboolean -ev_document_find_get_result (EvDocumentFind *document_find, - int page, - int n_result, - EvRectangle *rectangle) -{ - EvDocumentFindIface *iface = EV_DOCUMENT_FIND_GET_IFACE (document_find); - return iface->get_result (document_find, page, n_result, rectangle); -} - -double -ev_document_find_get_progress (EvDocumentFind *document_find) -{ - EvDocumentFindIface *iface = EV_DOCUMENT_FIND_GET_IFACE (document_find); - return iface->get_progress (document_find); -} - -void -ev_document_find_changed (EvDocumentFind *document_find, int page) -{ - g_signal_emit_by_name (document_find, "find_changed", page); -} diff --git a/libdocument/ev-document-find.h b/libdocument/ev-document-find.h index f365df1..40db017 100644 --- a/libdocument/ev-document-find.h +++ b/libdocument/ev-document-find.h @@ -24,9 +24,8 @@ #include #include -#include -#include "ev-document.h" /* For EvRectangle */ +#include "ev-document.h" G_BEGIN_DECLS @@ -37,62 +36,26 @@ G_BEGIN_DECLS #define EV_IS_DOCUMENT_FIND_IFACE(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EV_TYPE_DOCUMENT_FIND)) #define EV_DOCUMENT_FIND_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), EV_TYPE_DOCUMENT_FIND, EvDocumentFindIface)) -typedef struct _EvDocumentFind EvDocumentFind; -typedef struct _EvDocumentFindIface EvDocumentFindIface; +typedef struct _EvDocumentFind EvDocumentFind; +typedef struct _EvDocumentFindIface EvDocumentFindIface; struct _EvDocumentFindIface { GTypeInterface base_iface; /* Methods */ - - void (* begin) (EvDocumentFind *document_find, - int page, - const char *search_string, - gboolean case_sensitive); - void (* cancel) (EvDocumentFind *document_find); - int (* page_has_results) (EvDocumentFind *document_find, - int page); - int (* get_n_results) (EvDocumentFind *document_find, - int page); - gboolean (* get_result) (EvDocumentFind *document_find, - int page, - int n_result, - EvRectangle *rectangle); - double (* get_progress) (EvDocumentFind *document_find); - - /* Signals */ - - void (* find_changed) (EvDocumentFind *document_find, - int page); + GList *(* find_text) (EvDocumentFind *document_find, + EvPage *page, + const gchar *text, + gboolean case_sensitive); }; -GType ev_document_find_get_type (void); -void ev_document_find_begin (EvDocumentFind *document_find, - int page, - const char *search_string, - gboolean case_sensitive); -void ev_document_find_cancel (EvDocumentFind *document_find); -int ev_document_find_page_has_results (EvDocumentFind *document_find, - int page); -int ev_document_find_get_n_results (EvDocumentFind *document_find, - int page); -gboolean ev_document_find_get_result (EvDocumentFind *document_find, - int page, - int n_result, - EvRectangle *rectangle); -double ev_document_find_get_progress (EvDocumentFind *document_find); -void ev_document_find_changed (EvDocumentFind *document_find, - int page); - -/* How this interface works: - * - * begin() begins a new search, canceling any previous search. - * - * cancel() cancels a search if any, otherwise does nothing. - * - */ +GType ev_document_find_get_type (void) G_GNUC_CONST; +GList *ev_document_find_find_text (EvDocumentFind *document_find, + EvPage *page, + const gchar *text, + gboolean case_sensitive); G_END_DECLS -#endif +#endif /* EV_DOCUMENT_FIND_H */ diff --git a/shell/ev-jobs.c b/shell/ev-jobs.c index fb967cc..6e1e3f1 100644 --- a/shell/ev-jobs.c +++ b/shell/ev-jobs.c @@ -31,6 +31,7 @@ #include "ev-file-helpers.h" #include "ev-document-fonts.h" #include "ev-document-security.h" +#include "ev-document-find.h" #include "ev-debug.h" #include @@ -54,6 +55,8 @@ static void ev_job_save_init (EvJobSave *job); static void ev_job_save_class_init (EvJobSaveClass *class); static void ev_job_print_init (EvJobPrint *job); static void ev_job_print_class_init (EvJobPrintClass *class); +static void ev_job_find_init (EvJobFind *job); +static void ev_job_find_class_init (EvJobFindClass *class); enum { CANCELLED, @@ -67,13 +70,19 @@ enum { }; enum { - UPDATED, + FONTS_UPDATED, FONTS_LAST_SIGNAL }; +enum { + FIND_UPDATED, + FIND_LAST_SIGNAL +}; + static guint job_signals[LAST_SIGNAL] = { 0 }; static guint job_render_signals[RENDER_LAST_SIGNAL] = { 0 }; static guint job_fonts_signals[FONTS_LAST_SIGNAL] = { 0 }; +static guint job_find_signals[FIND_LAST_SIGNAL] = { 0 }; G_DEFINE_ABSTRACT_TYPE (EvJob, ev_job, G_TYPE_OBJECT) G_DEFINE_TYPE (EvJobLinks, ev_job_links, EV_TYPE_JOB) @@ -84,6 +93,7 @@ G_DEFINE_TYPE (EvJobFonts, ev_job_fonts, EV_TYPE_JOB) G_DEFINE_TYPE (EvJobLoad, ev_job_load, EV_TYPE_JOB) G_DEFINE_TYPE (EvJobSave, ev_job_save, EV_TYPE_JOB) G_DEFINE_TYPE (EvJobPrint, ev_job_print, EV_TYPE_JOB) +G_DEFINE_TYPE (EvJobFind, ev_job_find, EV_TYPE_JOB) /* EvJob */ static void @@ -721,7 +731,7 @@ ev_job_fonts_run (EvJob *job) #endif job_fonts->scan_completed = !ev_document_fonts_scan (fonts, 20); - g_signal_emit (job_fonts, job_fonts_signals[UPDATED], 0, + g_signal_emit (job_fonts, job_fonts_signals[FONTS_UPDATED], 0, ev_document_fonts_get_progress (fonts)); ev_document_fc_mutex_unlock (); @@ -740,7 +750,7 @@ ev_job_fonts_class_init (EvJobFontsClass *class) job_class->run = ev_job_fonts_run; - job_fonts_signals[UPDATED] = + job_fonts_signals[FONTS_UPDATED] = g_signal_new ("updated", EV_TYPE_JOB_FONTS, G_SIGNAL_RUN_LAST, @@ -1366,3 +1376,163 @@ ev_job_print_new (EvDocument *document, return EV_JOB (job); } +/* EvJobFind */ +static void +ev_job_find_init (EvJobFind *job) +{ + EV_JOB (job)->run_mode = EV_JOB_RUN_MAIN_LOOP; +} + +static void +ev_job_find_dispose (GObject *object) +{ + EvJobFind *job = EV_JOB_FIND (object); + + ev_debug_message (DEBUG_JOBS, NULL); + + if (job->text) { + g_free (job->text); + job->text = NULL; + } + + if (job->pages) { + gint i; + + for (i = 0; i < job->n_pages; i++) { + g_list_foreach (job->pages[i], (GFunc)g_free, NULL); + g_list_free (job->pages[i]); + } + + g_free (job->pages); + job->pages = NULL; + } + + (* G_OBJECT_CLASS (ev_job_find_parent_class)->dispose) (object); +} + +static gboolean +ev_job_find_run (EvJob *job) +{ + EvJobFind *job_find = EV_JOB_FIND (job); + EvDocumentFind *find = EV_DOCUMENT_FIND (job->document); + EvPage *ev_page; + GList *matches; + + ev_debug_message (DEBUG_JOBS, NULL); + + /* Do not block the main loop */ + if (!ev_document_doc_mutex_trylock ()) + return TRUE; + +#ifdef EV_ENABLE_DEBUG + /* We use the #ifdef in this case because of the if */ + if (job_find->current_page == job_find->start_page) + ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job); +#endif + + ev_page = ev_document_get_page (job->document, job_find->current_page); + matches = ev_document_find_find_text (find, ev_page, job_find->text, + job_find->case_sensitive); + g_object_unref (ev_page); + + ev_document_doc_mutex_unlock (); + + if (!job_find->has_results) + job_find->has_results = (matches != NULL); + + job_find->pages[job_find->current_page] = matches; + g_signal_emit (job_find, job_find_signals[FIND_UPDATED], 0, job_find->current_page); + + job_find->current_page = (job_find->current_page + 1) % job_find->n_pages; + if (job_find->current_page == job_find->start_page) { + ev_job_succeeded (job); + + return FALSE; + } + + return TRUE; +} + +static void +ev_job_find_class_init (EvJobFindClass *class) +{ + EvJobClass *job_class = EV_JOB_CLASS (class); + GObjectClass *gobject_class = G_OBJECT_CLASS (class); + + job_class->run = ev_job_find_run; + gobject_class->dispose = ev_job_find_dispose; + + job_find_signals[FIND_UPDATED] = + g_signal_new ("updated", + EV_TYPE_JOB_FIND, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EvJobFindClass, updated), + NULL, NULL, + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, + 1, G_TYPE_INT); +} + +EvJob * +ev_job_find_new (EvDocument *document, + gint start_page, + gint n_pages, + const gchar *text, + gboolean case_sensitive) +{ + EvJobFind *job; + + ev_debug_message (DEBUG_JOBS, NULL); + + job = g_object_new (EV_TYPE_JOB_FIND, NULL); + + EV_JOB (job)->document = g_object_ref (document); + job->start_page = start_page; + job->current_page = start_page; + job->n_pages = n_pages; + job->pages = g_new0 (GList *, n_pages); + job->text = g_strdup (text); + job->case_sensitive = case_sensitive; + job->has_results = FALSE; + + return EV_JOB (job); +} + +gint +ev_job_find_get_n_results (EvJobFind *job, + gint page) +{ + return g_list_length (job->pages[page]); +} + +gdouble +ev_job_find_get_progress (EvJobFind *job) +{ + gint pages_done; + + if (ev_job_is_finished (EV_JOB (job))) + return 1.0; + + if (job->current_page > job->start_page) { + pages_done = job->current_page - job->start_page + 1; + } else if (job->current_page == job->start_page) { + pages_done = job->n_pages; + } else { + pages_done = job->n_pages - job->start_page + job->current_page; + } + + return pages_done / (gdouble) job->n_pages; +} + +gboolean +ev_job_find_has_results (EvJobFind *job) +{ + return job->has_results; +} + +GList ** +ev_job_find_get_results (EvJobFind *job) +{ + return job->pages; +} + diff --git a/shell/ev-jobs.h b/shell/ev-jobs.h index e89f646..188759e 100644 --- a/shell/ev-jobs.h +++ b/shell/ev-jobs.h @@ -57,6 +57,9 @@ typedef struct _EvJobSaveClass EvJobSaveClass; typedef struct _EvJobPrint EvJobPrint; typedef struct _EvJobPrintClass EvJobPrintClass; +typedef struct _EvJobFind EvJobFind; +typedef struct _EvJobFindClass EvJobFindClass; + #define EV_TYPE_JOB (ev_job_get_type()) #define EV_JOB(object) (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_JOB, EvJob)) #define EV_JOB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_JOB, EvJobClass)) @@ -103,6 +106,11 @@ typedef struct _EvJobPrintClass EvJobPrintClass; #define EV_JOB_PRINT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_JOB_PRINT, EvJobPrintClass)) #define EV_IS_JOB_PRINT(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_JOB_PRINT)) +#define EV_TYPE_JOB_FIND (ev_job_find_get_type()) +#define EV_JOB_FIND(object) (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_JOB_FIND, EvJobFind)) +#define EV_JOB_FIND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_JOB_FIND, EvJobFindClass)) +#define EV_IS_JOB_FIND(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_JOB_FIND)) + typedef enum { EV_JOB_RUN_THREAD, EV_JOB_RUN_MAIN_LOOP @@ -235,7 +243,8 @@ struct _EvJobFontsClass EvJobClass parent_class; /* Signals */ - void (* updated) (EvJobFonts *job); + void (* updated) (EvJobFonts *job, + gdouble progress); }; struct _EvJobLoad @@ -289,6 +298,28 @@ struct _EvJobPrintClass EvJobClass parent_class; }; +struct _EvJobFind +{ + EvJob parent; + + gint start_page; + gint current_page; + gint n_pages; + GList **pages; + gchar *text; + gboolean case_sensitive; + gboolean has_results; +}; + +struct _EvJobFindClass +{ + EvJobClass parent_class; + + /* Signals */ + void (* updated) (EvJobFind *job, + gint page); +}; + /* Base job class */ GType ev_job_get_type (void) G_GNUC_CONST; gboolean ev_job_run (EvJob *job); @@ -370,6 +401,18 @@ EvJob *ev_job_print_new (EvDocument *document, gint copies, gdouble collate, gdouble reverse); +/* EvJobFind */ +GType ev_job_find_get_type (void) G_GNUC_CONST; +EvJob *ev_job_find_new (EvDocument *document, + gint start_page, + gint n_pages, + const gchar *text, + gboolean case_sensitive); +gint ev_job_find_get_n_results (EvJobFind *job, + gint pages); +gdouble ev_job_find_get_progress (EvJobFind *job); +gboolean ev_job_find_has_results (EvJobFind *job); +GList **ev_job_find_get_results (EvJobFind *job); G_END_DECLS diff --git a/shell/ev-view-private.h b/shell/ev-view-private.h index 1618417..547d165 100644 --- a/shell/ev-view-private.h +++ b/shell/ev-view-private.h @@ -97,8 +97,9 @@ struct _EvView { EvDocument *document; - char *find_status; - int find_result; + /* Find */ + GList **find_pages; + gint find_result; gboolean jump_to_find_result; gboolean highlight_find_results; diff --git a/shell/ev-view.c b/shell/ev-view.c index 2524d11..d00f98c 100644 --- a/shell/ev-view.c +++ b/shell/ev-view.c @@ -29,7 +29,6 @@ #include #include "ev-application.h" -#include "ev-document-find.h" #include "ev-document-forms.h" #include "ev-document-images.h" #include "ev-document-links.h" @@ -53,7 +52,6 @@ enum { PROP_0, - PROP_FIND_STATUS, PROP_CONTINUOUS, PROP_DUAL_PAGE, PROP_FULLSCREEN, @@ -228,9 +226,6 @@ static void draw_loading_text (EvView *view, GdkRectangle *expose_area); /*** Callbacks ***/ -static void find_changed_cb (EvDocument *document, - int page, - EvView *view); static void job_finished_cb (EvPixbufCache *pixbuf_cache, GdkRegion *region, EvView *view); @@ -303,10 +298,11 @@ static void ev_view_handle_cursor_over_xy (EvView *view, gint y); /*** Find ***/ -static void update_find_status_message (EvView *view, - gboolean this_page); -static void ev_view_set_find_status (EvView *view, - const char *message); +static gint ev_view_find_get_n_results (EvView *view, + gint page); +static EvRectangle *ev_view_find_get_result (EvView *view, + gint page, + gint result); static void jump_to_find_result (EvView *view); static void jump_to_find_page (EvView *view, EvViewFindDirection direction, @@ -2547,7 +2543,7 @@ ev_view_expose_event (GtkWidget *widget, draw_one_page (view, i, cr, &page_area, &border, &(event->area), &page_ready); - if (page_ready && EV_IS_DOCUMENT_FIND (view->document) && view->highlight_find_results) + if (page_ready && view->find_pages && view->highlight_find_results) highlight_find_results (view, i); } @@ -3608,15 +3604,12 @@ draw_rubberband (GtkWidget *widget, GdkWindow *window, static void highlight_find_results (EvView *view, int page) { - EvDocumentFind *find; - int i, results = 0; + gint i, n_results = 0; - find = EV_DOCUMENT_FIND (view->document); + n_results = ev_view_find_get_n_results (view, page); - results = ev_document_find_get_n_results (find, page); - - for (i = 0; i < results; i++) { - EvRectangle rectangle; + for (i = 0; i < n_results; i++) { + EvRectangle *rectangle; GdkRectangle view_rectangle; guchar alpha; @@ -3626,8 +3619,8 @@ highlight_find_results (EvView *view, int page) alpha = 0x20; } - ev_document_find_get_result (find, page, i, &rectangle); - doc_rect_to_view_rect (view, page, &rectangle, &view_rectangle); + rectangle = ev_view_find_get_result (view, page, i); + doc_rect_to_view_rect (view, page, rectangle, &view_rectangle); draw_rubberband (GTK_WIDGET (view), view->layout.bin_window, &view_rectangle, alpha); } @@ -3822,8 +3815,6 @@ ev_view_finalize (GObject *object) { EvView *view = EV_VIEW (object); - g_free (view->find_status); - clear_selection (view); clear_link_selected (view); @@ -3973,9 +3964,6 @@ ev_view_get_property (GObject *object, EvView *view = EV_VIEW (object); switch (prop_id) { - case PROP_FIND_STATUS: - g_value_set_string (value, view->find_status); - break; case PROP_CONTINUOUS: g_value_set_boolean (value, view->continuous); break; @@ -4092,14 +4080,6 @@ ev_view_class_init (EvViewClass *class) g_object_class_install_property (object_class, - PROP_FIND_STATUS, - g_param_spec_string ("find-status", - "Find Status Message", - "The find status message", - NULL, - G_PARAM_READABLE)); - - g_object_class_install_property (object_class, PROP_CONTINUOUS, g_param_spec_boolean ("continuous", "Continuous", @@ -4224,25 +4204,6 @@ ev_view_init (EvView *view) /*** Callbacks ***/ static void -find_changed_cb (EvDocument *document, int page, EvView *view) -{ - double percent; - int n_pages; - - percent = ev_document_find_get_progress - (EV_DOCUMENT_FIND (view->document)); - n_pages = ev_page_cache_get_n_pages (view->page_cache); - - if (view->jump_to_find_result == TRUE) { - jump_to_find_page (view, EV_VIEW_FIND_NEXT, 0); - jump_to_find_result (view); - } - update_find_status_message (view, percent * n_pages >= n_pages - 1 ); - if (view->current_page == page) - gtk_widget_queue_draw (GTK_WIDGET (view)); -} - -static void ev_view_change_page (EvView *view, gint new_page) { @@ -4334,10 +4295,7 @@ page_changed_cb (EvPageCache *page_cache, gtk_widget_queue_draw (GTK_WIDGET (view)); } - if (EV_IS_DOCUMENT_FIND (view->document)) { - view->find_result = 0; - update_find_status_message (view, TRUE); - } + view->find_result = 0; } static void @@ -4519,12 +4477,8 @@ ev_view_set_document (EvView *view, clear_caches (view); if (view->document) { - g_signal_handlers_disconnect_by_func (view->document, - find_changed_cb, - view); g_object_unref (view->document); view->page_cache = NULL; - } view->document = document; @@ -4532,13 +4486,6 @@ ev_view_set_document (EvView *view, if (view->document) { g_object_ref (view->document); - if (EV_IS_DOCUMENT_FIND (view->document)) { - g_signal_connect (view->document, - "find_changed", - G_CALLBACK (find_changed_cb), - view); - } - setup_caches (view); } @@ -5139,71 +5086,32 @@ ev_view_set_zoom_for_size (EvView *view, } /*** Find ***/ -static void -update_find_status_message (EvView *view, gboolean this_page) -{ - char *message; - - if (this_page) { - int results; - - results = ev_document_find_get_n_results - (EV_DOCUMENT_FIND (view->document), - view->current_page); - /* TRANS: Sometimes this could be better translated as - "%d hit(s) on this page". Therefore this string - contains plural cases. */ - message = g_strdup_printf (ngettext ("%d found on this page", - "%d found on this page", - results), - results); - } else { - double percent; - - percent = ev_document_find_get_progress - (EV_DOCUMENT_FIND (view->document)); - message = g_strdup_printf (_("%3d%% remaining to search"), - (int) ((1.0 - percent) * 100)); - - } - ev_view_set_find_status (view, message); - g_free (message); -} - -const char * -ev_view_get_find_status (EvView *view) +static gint +ev_view_find_get_n_results (EvView *view, gint page) { - g_return_val_if_fail (EV_IS_VIEW (view), NULL); - - return view->find_status; + return view->find_pages ? g_list_length (view->find_pages[page]) : 0; } -static void -ev_view_set_find_status (EvView *view, const char *message) +static EvRectangle * +ev_view_find_get_result (EvView *view, gint page, gint result) { - g_return_if_fail (EV_IS_VIEW (view)); - - g_free (view->find_status); - view->find_status = g_strdup (message); - g_object_notify (G_OBJECT (view), "find-status"); + return view->find_pages ? (EvRectangle *) g_list_nth_data (view->find_pages[page], result) : NULL; } static void jump_to_find_result (EvView *view) { - EvDocumentFind *find = EV_DOCUMENT_FIND (view->document); - EvRectangle rect; - GdkRectangle view_rect; - int n_results; - int page = view->current_page; + gint n_results; + gint page = view->current_page; - n_results = ev_document_find_get_n_results (find, page); + n_results = ev_view_find_get_n_results (view, page); - if (n_results > 0 && view->find_result < n_results) { - ev_document_find_get_result - (find, page, view->find_result, &rect); + if (n_results > 0 && view->find_result < n_results) { + EvRectangle *rect; + GdkRectangle view_rect; - doc_rect_to_view_rect (view, page, &rect, &view_rect); + rect = ev_view_find_get_result (view, page, view->find_result); + doc_rect_to_view_rect (view, page, rect, &view_rect); ensure_rectangle_is_visible (view, &view_rect); } } @@ -5226,7 +5134,6 @@ jump_to_find_page (EvView *view, EvViewFindDirection direction, gint shift) n_pages = ev_page_cache_get_n_pages (view->page_cache); for (i = 0; i < n_pages; i++) { - int has_results; int page; if (direction == EV_VIEW_FIND_NEXT) @@ -5237,53 +5144,39 @@ jump_to_find_page (EvView *view, EvViewFindDirection direction, gint shift) if (page >= n_pages) { page = page - n_pages; - } - if (page < 0) + } else if (page < 0) page = page + n_pages; - - has_results = ev_document_find_page_has_results - (EV_DOCUMENT_FIND (view->document), page); - if (has_results == -1) { - break; - } else if (has_results == 1) { + + if (ev_view_find_get_n_results (view, page) > 0) { ev_page_cache_set_current_page (view->page_cache, page); break; } } } -gboolean -ev_view_can_find_next (EvView *view) +void +ev_view_find_changed (EvView *view, GList **results, gint page) { - if (EV_IS_DOCUMENT_FIND (view->document)) { - EvDocumentFind *find = EV_DOCUMENT_FIND (view->document); - int i, n_pages; - - n_pages = ev_page_cache_get_n_pages (view->page_cache); - for (i = 0; i < n_pages; i++) { - if (ev_document_find_get_n_results (find, i) > 0) { - return TRUE; - } - } + view->find_pages = results; + + if (view->jump_to_find_result == TRUE) { + jump_to_find_page (view, EV_VIEW_FIND_NEXT, 0); + jump_to_find_result (view); } - return FALSE; + if (view->current_page == page) + gtk_widget_queue_draw (GTK_WIDGET (view)); } void ev_view_find_next (EvView *view) { - int n_results, n_pages; - EvDocumentFind *find = EV_DOCUMENT_FIND (view->document); - - n_results = ev_document_find_get_n_results (find, view->current_page); - - n_pages = ev_page_cache_get_n_pages (view->page_cache); + gint n_results; + n_results = ev_view_find_get_n_results (view, view->current_page); view->find_result++; if (view->find_result >= n_results) { - view->find_result = 0; jump_to_find_page (view, EV_VIEW_FIND_NEXT, 1); jump_to_find_result (view); @@ -5293,42 +5186,14 @@ ev_view_find_next (EvView *view) } } -gboolean -ev_view_can_find_previous (EvView *view) -{ - if (EV_IS_DOCUMENT_FIND (view->document)) { - EvDocumentFind *find = EV_DOCUMENT_FIND (view->document); - int i, n_pages; - - n_pages = ev_page_cache_get_n_pages (view->page_cache); - for (i = n_pages - 1; i >= 0; i--) { - if (ev_document_find_get_n_results (find, i) > 0) { - return TRUE; - } - } - } - - return FALSE; -} void ev_view_find_previous (EvView *view) { - int n_results, n_pages; - EvDocumentFind *find = EV_DOCUMENT_FIND (view->document); - EvPageCache *page_cache; - - page_cache = ev_page_cache_get (view->document); - - n_results = ev_document_find_get_n_results (find, view->current_page); - - n_pages = ev_page_cache_get_n_pages (page_cache); - view->find_result--; if (view->find_result < 0) { - jump_to_find_page (view, EV_VIEW_FIND_PREV, -1); - view->find_result = ev_document_find_get_n_results (find, view->current_page) - 1; + view->find_result = ev_view_find_get_n_results (view, view->current_page) - 1; jump_to_find_result (view); } else { jump_to_find_result (view); @@ -5337,14 +5202,15 @@ ev_view_find_previous (EvView *view) } void -ev_view_search_changed (EvView *view) +ev_view_find_search_changed (EvView *view) { /* search string has changed, focus on new search result */ view->jump_to_find_result = TRUE; + view->find_pages = NULL; } void -ev_view_set_highlight_search (EvView *view, gboolean value) +ev_view_find_set_highlight_search (EvView *view, gboolean value) { view->highlight_find_results = value; gtk_widget_queue_draw (GTK_WIDGET (view)); @@ -5353,11 +5219,7 @@ ev_view_set_highlight_search (EvView *view, gboolean value) void ev_view_find_cancel (EvView *view) { - if (EV_IS_DOCUMENT_FIND (view->document)) { - EvDocumentFind *find = EV_DOCUMENT_FIND (view->document); - - ev_document_find_cancel (find); - } + view->find_pages = NULL; } /*** Selections ***/ diff --git a/shell/ev-view.h b/shell/ev-view.h index cbcf768..b6e5e82 100644 --- a/shell/ev-view.h +++ b/shell/ev-view.h @@ -117,18 +117,15 @@ void ev_view_set_rotation (EvView *view, int ev_view_get_rotation (EvView *view); /* Find */ -gboolean ev_view_can_find_next (EvView *view); -void ev_view_find_next (EvView *view); -gboolean ev_view_can_find_previous (EvView *view); -void ev_view_find_previous (EvView *view); -void ev_view_search_changed (EvView *view); -void ev_view_set_highlight_search (EvView *view, - gboolean value); -void ev_view_find_cancel (EvView *view); - -/* Status */ -const char *ev_view_get_status (EvView *view); -const char *ev_view_get_find_status (EvView *view); +void ev_view_find_next (EvView *view); +void ev_view_find_previous (EvView *view); +void ev_view_find_search_changed (EvView *view); +void ev_view_find_set_highlight_search (EvView *view, + gboolean value); +void ev_view_find_changed (EvView *view, + GList **results, + gint page); +void ev_view_find_cancel (EvView *view); /* Cursor */ void ev_view_hide_cursor (EvView *view); diff --git a/shell/ev-window.c b/shell/ev-window.c index 7b5a770..65f5d46 100644 --- a/shell/ev-window.c +++ b/shell/ev-window.c @@ -179,6 +179,7 @@ struct _EvWindowPrivate { EvJob *thumbnail_job; EvJob *save_job; EvJob *print_job; + EvJob *find_job; /* Printing */ gboolean print_preview; @@ -275,6 +276,7 @@ static void ev_window_cmd_view_page_width (GtkAction *action, static void view_handle_link_cb (EvView *view, EvLink *link, EvWindow *window); +static void ev_window_update_find_status_message (EvWindow *ev_window); static void ev_window_cmd_edit_find (GtkAction *action, EvWindow *ev_window); static void find_bar_search_changed_cb (EggFindBar *find_bar, @@ -396,6 +398,7 @@ ev_window_update_actions (EvWindow *ev_window) int n_pages = 0, page = -1; gboolean has_pages = FALSE; gboolean presentation_mode; + gboolean can_find_in_page = FALSE; if (ev_window->priv->document && ev_window->priv->page_cache) { page = ev_page_cache_get_current_page (ev_window->priv->page_cache); @@ -403,13 +406,16 @@ ev_window_update_actions (EvWindow *ev_window) has_pages = n_pages > 0; } + can_find_in_page = (ev_window->priv->find_job && + ev_job_find_has_results (EV_JOB_FIND (ev_window->priv->find_job))); + ev_window_set_action_sensitive (ev_window, "EditCopy", has_pages && ev_view_get_has_selection (view)); ev_window_set_action_sensitive (ev_window, "EditFindNext", - ev_view_can_find_next (view)); + has_pages && can_find_in_page); ev_window_set_action_sensitive (ev_window, "EditFindPrevious", - ev_view_can_find_previous (view)); + has_pages && can_find_in_page); presentation_mode = ev_view_get_presentation (view); @@ -688,18 +694,14 @@ ev_window_warning_message (GtkWindow *window, const gchar *msg) } static void -find_changed_cb (EvDocument *document, int page, EvWindow *ev_window) -{ - ev_window_update_actions (ev_window); -} - -static void page_changed_cb (EvPageCache *page_cache, gint page, EvWindow *ev_window) { ev_window_update_actions (ev_window); - + + ev_window_update_find_status_message (ev_window); + if (!ev_window_is_empty (ev_window)) ev_metadata_manager_set_int (ev_window->priv->uri, "page", page); } @@ -1142,13 +1144,6 @@ ev_window_setup_document (EvWindow *ev_window) ev_window->priv->setup_document_idle = 0; - if (EV_IS_DOCUMENT_FIND (document)) { - g_signal_connect_object (G_OBJECT (document), - "find_changed", - G_CALLBACK (find_changed_cb), - ev_window, 0); - } - ev_window_refresh_window_thumbnail (ev_window, 0); ev_window_set_page_mode (ev_window, PAGE_MODE_DOCUMENT); @@ -4019,15 +4014,73 @@ attachment_bar_menu_popup_cb (EvSidebarAttachments *attachbar, } static void -view_find_status_changed_cb (EvView *view, - GParamSpec *pspec, - EvWindow *ev_window) +ev_window_update_find_status_message (EvWindow *ev_window) +{ + gchar *message; + + if (!ev_window->priv->find_job) + return; + + if (ev_job_is_finished (ev_window->priv->find_job)) { + gint n_results; + + n_results = ev_job_find_get_n_results (EV_JOB_FIND (ev_window->priv->find_job), + ev_page_cache_get_current_page (ev_window->priv->page_cache)); + /* TRANS: Sometimes this could be better translated as + "%d hit(s) on this page". Therefore this string + contains plural cases. */ + message = g_strdup_printf (ngettext ("%d found on this page", + "%d found on this page", + n_results), + n_results); + } else { + gdouble percent; + + percent = ev_job_find_get_progress (EV_JOB_FIND (ev_window->priv->find_job)); + message = g_strdup_printf (_("%3d%% remaining to search"), + (gint) ((1.0 - percent) * 100)); + } + + egg_find_bar_set_status_text (EGG_FIND_BAR (ev_window->priv->find_bar), message); + g_free (message); +} + +static void +ev_window_find_job_finished_cb (EvJobFind *job, + EvWindow *ev_window) { - const char *text; + ev_window_update_find_status_message (ev_window); +} - text = ev_view_get_find_status (view); - egg_find_bar_set_status_text (EGG_FIND_BAR (ev_window->priv->find_bar), - text); +static void +ev_window_find_job_updated_cb (EvJobFind *job, + gint page, + EvWindow *ev_window) +{ + ev_window_update_actions (ev_window); + + ev_view_find_changed (EV_VIEW (ev_window->priv->view), + ev_job_find_get_results (job), + page); + ev_window_update_find_status_message (ev_window); +} + +static void +ev_window_clear_find_job (EvWindow *ev_window) +{ + if (ev_window->priv->find_job != NULL) { + if (!ev_job_is_finished (ev_window->priv->find_job)) + ev_job_cancel (ev_window->priv->find_job); + + g_signal_handlers_disconnect_by_func (ev_window->priv->find_job, + ev_window_find_job_finished_cb, + ev_window); + g_signal_handlers_disconnect_by_func (ev_window->priv->find_job, + ev_window_find_job_updated_cb, + ev_window); + g_object_unref (ev_window->priv->find_job); + ev_window->priv->find_job = NULL; + } } static void @@ -4049,6 +4102,7 @@ find_bar_close_cb (EggFindBar *find_bar, EvWindow *ev_window) { ev_view_find_cancel (EV_VIEW (ev_window->priv->view)); + ev_window_clear_find_job (ev_window); update_chrome_flag (ev_window, EV_CHROME_FINDBAR, FALSE); update_chrome_visibility (ev_window); } @@ -4061,39 +4115,42 @@ find_bar_search_changed_cb (EggFindBar *find_bar, gboolean case_sensitive; const char *search_string; + if (!ev_window->priv->document || !EV_IS_DOCUMENT_FIND (ev_window->priv->document)) + return; + /* Either the string or case sensitivity could have changed. */ - case_sensitive = egg_find_bar_get_case_sensitive (find_bar); search_string = egg_find_bar_get_search_string (find_bar); - ev_view_search_changed (EV_VIEW(ev_window->priv->view)); + ev_view_find_search_changed (EV_VIEW (ev_window->priv->view)); - if (ev_window->priv->document && - EV_IS_DOCUMENT_FIND (ev_window->priv->document)) { - if (search_string && search_string[0]) { - ev_document_doc_mutex_lock (); - ev_document_find_begin (EV_DOCUMENT_FIND (ev_window->priv->document), - ev_page_cache_get_current_page (ev_window->priv->page_cache), - search_string, - case_sensitive); - ev_document_doc_mutex_unlock (); - } else { - ev_document_doc_mutex_lock (); - ev_document_find_cancel (EV_DOCUMENT_FIND (ev_window->priv->document)); - ev_document_doc_mutex_unlock (); - - ev_window_update_actions (ev_window); - egg_find_bar_set_status_text (EGG_FIND_BAR (ev_window->priv->find_bar), - NULL); - gtk_widget_queue_draw (GTK_WIDGET (ev_window->priv->view)); - } + ev_window_clear_find_job (ev_window); + + if (search_string && search_string[0]) { + ev_window->priv->find_job = ev_job_find_new (ev_window->priv->document, + ev_page_cache_get_current_page (ev_window->priv->page_cache), + ev_page_cache_get_n_pages (ev_window->priv->page_cache), + search_string, + case_sensitive); + g_signal_connect (ev_window->priv->find_job, "finished", + G_CALLBACK (ev_window_find_job_finished_cb), + ev_window); + g_signal_connect (ev_window->priv->find_job, "updated", + G_CALLBACK (ev_window_find_job_updated_cb), + ev_window); + ev_job_scheduler_push_job (ev_window->priv->find_job, EV_JOB_PRIORITY_NONE); + } else { + ev_window_update_actions (ev_window); + egg_find_bar_set_status_text (EGG_FIND_BAR (ev_window->priv->find_bar), + NULL); + gtk_widget_queue_draw (GTK_WIDGET (ev_window->priv->view)); } } static void find_bar_visibility_changed_cb (EggFindBar *find_bar, - GParamSpec *param, - EvWindow *ev_window) + GParamSpec *param, + EvWindow *ev_window) { gboolean visible; @@ -4101,8 +4158,8 @@ find_bar_visibility_changed_cb (EggFindBar *find_bar, if (ev_window->priv->document && EV_IS_DOCUMENT_FIND (ev_window->priv->document)) { - ev_view_set_highlight_search (EV_VIEW (ev_window->priv->view), visible); - ev_view_search_changed (EV_VIEW (ev_window->priv->view)); + ev_view_find_set_highlight_search (EV_VIEW (ev_window->priv->view), visible); + ev_view_find_search_changed (EV_VIEW (ev_window->priv->view)); ev_window_update_actions (ev_window); if (visible) @@ -4115,7 +4172,7 @@ find_bar_visibility_changed_cb (EggFindBar *find_bar, static void find_bar_scroll(EggFindBar *find_bar, GtkScrollType scroll, EvWindow* ev_window) { - ev_view_scroll(EV_VIEW(ev_window->priv->view), scroll, FALSE); + ev_view_scroll (EV_VIEW (ev_window->priv->view), scroll, FALSE); } static void @@ -4257,6 +4314,10 @@ ev_window_dispose (GObject *object) if (priv->thumbnail_job) { ev_window_clear_thumbnail_job (window); } + + if (priv->find_job) { + ev_window_clear_find_job (window); + } if (priv->local_uri) { ev_window_clear_local_uri (window); @@ -5490,10 +5551,6 @@ ev_window_init (EvWindow *ev_window) ev_window->priv->view); g_signal_connect (ev_window->priv->view, - "notify::find-status", - G_CALLBACK (view_find_status_changed_cb), - ev_window); - g_signal_connect (ev_window->priv->view, "notify::sizing-mode", G_CALLBACK (ev_window_sizing_mode_changed_cb), ev_window); -- cgit v0.9.1