void zathura_free(zathura_t* zathura) { if (zathura == NULL) { return; } document_close(zathura, false); if (zathura->ui.session != NULL) { girara_session_destroy(zathura->ui.session); } /* stdin support */ if (zathura->stdin_support.file != NULL) { g_unlink(zathura->stdin_support.file); g_free(zathura->stdin_support.file); } /* bookmarks */ girara_list_free(zathura->bookmarks.bookmarks); /* database */ if (zathura->database != NULL) { g_object_unref(G_OBJECT(zathura->database)); } /* free print settings */ if (zathura->print.settings != NULL) { g_object_unref(zathura->print.settings); } if (zathura->print.page_setup != NULL) { g_object_unref(zathura->print.page_setup); } /* free registered plugins */ zathura_plugin_manager_free(zathura->plugins.manager); /* free config variables */ g_free(zathura->config.config_dir); g_free(zathura->config.data_dir); /* free jumplist */ if (zathura->jumplist.list != NULL) { girara_list_free(zathura->jumplist.list); } if (zathura->jumplist.cur != NULL) { girara_list_iterator_free(zathura->jumplist.cur); } g_free(zathura); }
} END_TEST START_TEST(test_datastructures_sorted_list) { girara_list_t* list = girara_sorted_list_new2((girara_compare_function_t) g_strcmp0, (girara_free_function_t) g_free); fail_unless((list != NULL), NULL); girara_list_t* unsorted_list = girara_list_new2((girara_free_function_t) g_free); fail_unless((unsorted_list != NULL), NULL); static const char* test_strings[] = { "A", "C", "Baa", "Za", "Bba", "Bab", NULL }; static const char* test_strings_sorted[] = { "A", "Baa", "Bab", "Bba", "C", "Za", NULL }; // append for (const char** p = test_strings; *p != NULL; ++p) { girara_list_append(list, (void*)g_strdup(*p)); girara_list_append(unsorted_list, (void*)g_strdup(*p)); } fail_unless((girara_list_size(list) == sizeof(test_strings) / sizeof(char*) - 1), NULL); fail_unless((girara_list_size(unsorted_list) == sizeof(test_strings) / sizeof(char*) - 1), NULL); // check sorting const char** p = test_strings_sorted; GIRARA_LIST_FOREACH(list, const char*, iter, value) fail_unless((g_strcmp0(value, *p) == 0), NULL); ++p; GIRARA_LIST_FOREACH_END(list, const char*, iter, value); girara_list_sort(unsorted_list, (girara_compare_function_t) g_strcmp0); p = test_strings_sorted; GIRARA_LIST_FOREACH(unsorted_list, const char*, iter, value) fail_unless((g_strcmp0(value, *p) == 0), NULL); ++p; GIRARA_LIST_FOREACH_END(unsorted_list, const char*, iter, value); girara_list_free(list); girara_list_free(unsorted_list); } END_TEST
} END_TEST START_TEST(test_fix_path_extended) { gchar* oldenv = g_getenv("HOME") ? g_strdup(g_getenv("HOME")) : NULL; g_unsetenv("HOME"); girara_list_t* list = read_pwd_info(); GIRARA_LIST_FOREACH(list, pwd_info_t*, iter, pwdinfo) gchar* path = g_strdup_printf("~%s/test", pwdinfo->name); gchar* eres = g_build_filename(pwdinfo->dir, "test", NULL); gchar* result = girara_fix_path(path); fail_unless(g_strcmp0(result, eres) == 0, "Fix path result does not match (got: %s, expected %s)", result, eres, NULL); g_free(result); g_free(eres); g_free(path); GIRARA_LIST_FOREACH_END(list, pwd_info_t*, iter, pwdinfo); girara_list_free(list); if (oldenv) { g_setenv("HOME", oldenv, TRUE); g_free(oldenv); } } END_TEST
} END_TEST START_TEST(test_datastructures_sorted_list_basic) { girara_list_t* list = girara_sorted_list_new(NULL); fail_unless((list != NULL), NULL); girara_list_free(list); } END_TEST
} END_TEST START_TEST(test_datastructures_list_free_empty) { // free empty list girara_list_t* list = girara_list_new(); fail_unless((list != NULL), NULL); girara_list_free(list); list = girara_list_new2(NULL); fail_unless((list != NULL), NULL); girara_list_free(list); list = girara_list_new2(g_free); fail_unless((list != NULL), NULL); girara_list_free(list); } END_TEST
} END_TEST START_TEST(test_split_path) { fail_unless(girara_split_path_array(NULL) == NULL, NULL); fail_unless(girara_split_path_array("") == NULL, NULL); girara_list_t* res = girara_split_path_array("one/path"); fail_unless(res != NULL, NULL); fail_unless(girara_list_size(res) == 1, NULL); fail_unless(g_strcmp0(girara_list_nth(res, 0), "one/path") == 0, NULL); girara_list_free(res); res = girara_split_path_array("first/path:second/path"); fail_unless(res != NULL, NULL); fail_unless(girara_list_size(res) == 2, NULL); fail_unless(g_strcmp0(girara_list_nth(res, 0), "first/path") == 0, NULL); fail_unless(g_strcmp0(girara_list_nth(res, 1), "second/path") == 0, NULL); girara_list_free(res); } END_TEST
void zathura_plugin_manager_free(zathura_plugin_manager_t* plugin_manager) { if (plugin_manager == NULL) { return; } if (plugin_manager->plugins != NULL) { girara_list_free(plugin_manager->plugins); } if (plugin_manager->path != NULL) { girara_list_free(plugin_manager->path); } if (plugin_manager->type_plugin_mapping != NULL) { girara_list_free(plugin_manager->type_plugin_mapping); } g_free(plugin_manager); }
} END_TEST START_TEST(test_datastructures_list_prepend) { girara_list_t* list = girara_list_new(); fail_unless((list != NULL), NULL); /* test parameters */ girara_list_prepend(list, NULL); fail_unless((girara_list_size(list) != 0), NULL); girara_list_free(list); } END_TEST
} END_TEST START_TEST(test_datastructures_list_free_free_function) { // free function girara_list_t* list = girara_list_new(); list_free_called = 0; fail_unless((list != NULL), NULL); girara_list_set_free_function(list, list_free); girara_list_append(list, (void*) 0xDEAD); girara_list_free(list); fail_unless((list_free_called == 1), NULL); } END_TEST
} END_TEST START_TEST(test_datastructures_list_free_already_cleared) { // free cleared list girara_list_t* list = girara_list_new(); fail_unless((list != NULL), NULL); girara_list_append(list, (void*) 0xDEAD); fail_unless((girara_list_size(list) == 1), NULL); girara_list_clear(list); fail_unless((girara_list_size(list) == 0), NULL); girara_list_free(list); } END_TEST
void zathura_set_plugin_dir(zathura_t* zathura, const char* dir) { g_return_if_fail(zathura != NULL); g_return_if_fail(zathura->plugins.manager != NULL); if (dir != NULL) { girara_list_t* paths = girara_split_path_array(dir); GIRARA_LIST_FOREACH(paths, char*, iter, path) zathura_plugin_manager_add_dir(zathura->plugins.manager, path); GIRARA_LIST_FOREACH_END(paths, char*, iter, path); girara_list_free(paths); } else {
} END_TEST START_TEST(test_datastructures_list_free_free_function_remove) { // remove with free function list_free_called = 0; girara_list_t* list = girara_list_new2(list_free); fail_unless((list != NULL), NULL); girara_list_append(list, (void*)0xDEAD); girara_list_remove(list, (void*)0xDEAD); fail_unless((girara_list_size(list) == 0), NULL); girara_list_free(list); fail_unless((list_free_called == 1), NULL); } END_TEST
} END_TEST START_TEST(test_datastructures_list_merge) { girara_list_t* list1 = girara_list_new(); girara_list_t* list2 = girara_list_new(); fail_unless((list1 != NULL), NULL); fail_unless((list2 != NULL), NULL); fail_unless((girara_list_merge(NULL, NULL) == NULL), NULL); fail_unless((girara_list_merge(list1, NULL) == list1), NULL); fail_unless((girara_list_merge(NULL, list2) == NULL), NULL); girara_list_append(list1, (void*)0); girara_list_append(list2, (void*)1); girara_list_t* list3 = girara_list_merge(list1, list2); fail_unless((list3 == list1), NULL); fail_unless((girara_list_nth(list3, 0) == (void*)0), NULL); fail_unless((girara_list_nth(list3, 1) == (void*)1), NULL); girara_list_free(list1); girara_list_free(list2); } END_TEST
bool synctex_view(zathura_t* zathura, const char* input_file, unsigned int line, unsigned int column) { if (zathura == NULL || input_file == NULL) { return false; } const unsigned int number_of_pages = zathura_document_get_number_of_pages(zathura->document); unsigned int page = 0; girara_list_t* secondary_rects = NULL; girara_list_t* rectangles = synctex_rectangles_from_position( zathura_document_get_path(zathura->document), input_file, line, column, &page, &secondary_rects); if (rectangles == NULL) { return false; } girara_list_t** all_rectangles = g_try_malloc0(number_of_pages * sizeof(girara_list_t*)); if (all_rectangles == NULL) { girara_list_free(rectangles); return false; } for (unsigned int p = 0; p != number_of_pages; ++p) { if (p == page) { all_rectangles[p] = rectangles; } else { all_rectangles[p] = girara_list_new2(g_free); } } if (secondary_rects != NULL) { GIRARA_LIST_FOREACH(secondary_rects, synctex_page_rect_t*, iter, rect) zathura_rectangle_t* newrect = g_try_malloc0(sizeof(zathura_rectangle_t)); if (newrect != NULL) { *newrect = rect->rect; girara_list_append(all_rectangles[rect->page], newrect); } GIRARA_LIST_FOREACH_END(secondary_rects, synctex_page_rect_t*, iter, rect); }
bool zathura_bookmarks_load(zathura_t* zathura, const gchar* file) { g_return_val_if_fail(zathura, false); g_return_val_if_fail(file, false); if (zathura->database == NULL) { return false; } girara_list_t* bookmarks = zathura_db_load_bookmarks(zathura->database, file); if (bookmarks == NULL) { return false; } girara_list_free(zathura->bookmarks.bookmarks); zathura->bookmarks.bookmarks = bookmarks; return true; }
static void zathura_plugin_free(zathura_plugin_t* plugin) { if (plugin == NULL) { return; } if (plugin->name != NULL) { g_free(plugin->name); } if (plugin->path != NULL) { g_free(plugin->path); } g_module_close(plugin->handle); girara_list_free(plugin->content_types); g_free(plugin); }
void config_load_files(zathura_t* zathura) { /* load global configuration files */ char* config_path = girara_get_xdg_path(XDG_CONFIG_DIRS); girara_list_t* config_dirs = girara_split_path_array(config_path); ssize_t size = girara_list_size(config_dirs) - 1; for (; size >= 0; --size) { const char* dir = girara_list_nth(config_dirs, size); char* file = g_build_filename(dir, ZATHURA_RC, NULL); girara_config_parse(zathura->ui.session, file); g_free(file); } girara_list_free(config_dirs); g_free(config_path); girara_config_parse(zathura->ui.session, GLOBAL_RC); /* load local configuration files */ char* configuration_file = g_build_filename(zathura->config.config_dir, ZATHURA_RC, NULL); girara_config_parse(zathura->ui.session, configuration_file); g_free(configuration_file); }
girara_list_t* djvu_page_links_get(zathura_page_t* page, void* UNUSED(data), zathura_error_t* error) { if (page == NULL) { if (error != NULL) { *error = ZATHURA_ERROR_INVALID_ARGUMENTS; } goto error_ret; } zathura_document_t* document = zathura_page_get_document(page); if (document == NULL) { goto error_ret; } girara_list_t* list = girara_list_new2((girara_free_function_t) zathura_link_free); if (list == NULL) { if (error != NULL) { *error = ZATHURA_ERROR_OUT_OF_MEMORY; } goto error_ret; } djvu_document_t* djvu_document = zathura_document_get_data(document); miniexp_t annotations = miniexp_nil; while ((annotations = ddjvu_document_get_pageanno(djvu_document->document, zathura_page_get_index(page))) == miniexp_dummy) { handle_messages(djvu_document, true); } if (annotations == miniexp_nil) { goto error_free; } miniexp_t* hyperlinks = ddjvu_anno_get_hyperlinks(annotations); for (miniexp_t* iter = hyperlinks; *iter != NULL; iter++) { if (miniexp_car(*iter) != miniexp_symbol("maparea")) { continue; } miniexp_t inner = miniexp_cdr(*iter); /* extract url information */ const char* target_string = NULL; if (miniexp_caar(inner) == miniexp_symbol("url")) { if (exp_to_str(miniexp_caddr(miniexp_car(inner)), &target_string) == false) { continue; } } else { if (exp_to_str(miniexp_car(inner), &target_string) == false) { continue; } } /* skip comment */ inner = miniexp_cdr(inner); /* extract link area */ inner = miniexp_cdr(inner); zathura_rectangle_t rect = { 0, 0, 0, 0 }; if (exp_to_rect(miniexp_car(inner), &rect) == false) { continue; } /* update rect */ unsigned int page_height = zathura_page_get_height(page) / ZATHURA_DJVU_SCALE; rect.x1 = rect.x1 * ZATHURA_DJVU_SCALE; rect.x2 = rect.x2 * ZATHURA_DJVU_SCALE; double tmp = rect.y1; rect.y1 = (page_height - rect.y2) * ZATHURA_DJVU_SCALE; rect.y2 = (page_height - tmp) * ZATHURA_DJVU_SCALE; /* create zathura link */ zathura_link_type_t type = ZATHURA_LINK_INVALID; zathura_link_target_t target = { ZATHURA_LINK_DESTINATION_UNKNOWN, NULL, 0, -1, -1, -1, -1, 0 };; /* goto page */ if (target_string[0] == '#' && target_string[1] == 'p') { type = ZATHURA_LINK_GOTO_DEST; target.page_number = atoi(target_string + 2) - 1; /* url or other? */ } else if (strstr(target_string, "//") != NULL) { type = ZATHURA_LINK_URI; target.value = (char*) target_string; /* TODO: Parse all different links */ } else { continue; } zathura_link_t* link = zathura_link_new(type, rect, target); if (link != NULL) { girara_list_append(list, link); } } return list; error_free: if (list != NULL) { girara_list_free(list); } error_ret: return NULL; }
void zathura_free(zathura_t* zathura) { if (zathura == NULL) { return; } document_close(zathura, false); /* MIME type detection */ zathura_content_type_free(zathura->content_type_context); #ifdef G_OS_UNIX if (zathura->signals.sigterm > 0) { g_source_remove(zathura->signals.sigterm); zathura->signals.sigterm = 0; } #endif /* stop D-Bus */ if (zathura->dbus != NULL) { g_object_unref(zathura->dbus); zathura->dbus = NULL; } if (zathura->ui.session != NULL) { girara_session_destroy(zathura->ui.session); } /* shortcut */ if (zathura->shortcut.toggle_presentation_mode.first_page_column_list != NULL) { g_free(zathura->shortcut.toggle_presentation_mode.first_page_column_list); } /* stdin support */ if (zathura->stdin_support.file != NULL) { g_unlink(zathura->stdin_support.file); g_free(zathura->stdin_support.file); } /* bookmarks */ girara_list_free(zathura->bookmarks.bookmarks); /* database */ if (zathura->database != NULL) { g_object_unref(G_OBJECT(zathura->database)); } /* free print settings */ if (zathura->print.settings != NULL) { g_object_unref(zathura->print.settings); } if (zathura->print.page_setup != NULL) { g_object_unref(zathura->print.page_setup); } /* free registered plugins */ zathura_plugin_manager_free(zathura->plugins.manager); /* free config variables */ g_free(zathura->config.config_dir); g_free(zathura->config.data_dir); g_free(zathura->config.cache_dir); /* free jumplist */ if (zathura->jumplist.list != NULL) { girara_list_free(zathura->jumplist.list); } if (zathura->jumplist.cur != NULL) { girara_list_iterator_free(zathura->jumplist.cur); } g_free(zathura); }
bool zathura_init(zathura_t* zathura) { if (zathura == NULL) { return false; } /* create zathura (config/data) directory */ if (g_mkdir_with_parents(zathura->config.config_dir, 0771) == -1) { girara_error("Could not create '%s': %s", zathura->config.config_dir, strerror(errno)); } if (g_mkdir_with_parents(zathura->config.data_dir, 0771) == -1) { girara_error("Could not create '%s': %s", zathura->config.data_dir, strerror(errno)); } /* load plugins */ zathura_plugin_manager_load(zathura->plugins.manager); /* configuration */ config_load_default(zathura); /* load global configuration files */ char* config_path = girara_get_xdg_path(XDG_CONFIG_DIRS); girara_list_t* config_dirs = girara_split_path_array(config_path); ssize_t size = girara_list_size(config_dirs) - 1; for (; size >= 0; --size) { const char* dir = girara_list_nth(config_dirs, size); char* file = g_build_filename(dir, ZATHURA_RC, NULL); config_load_file(zathura, file); g_free(file); } girara_list_free(config_dirs); g_free(config_path); config_load_file(zathura, GLOBAL_RC); /* load local configuration files */ char* configuration_file = g_build_filename(zathura->config.config_dir, ZATHURA_RC, NULL); config_load_file(zathura, configuration_file); g_free(configuration_file); /* UI */ if (girara_session_init(zathura->ui.session, "zathura") == false) { goto error_free; } /* girara events */ zathura->ui.session->events.buffer_changed = cb_buffer_changed; zathura->ui.session->events.unknown_command = cb_unknown_command; /* page view */ #if (GTK_MAJOR_VERSION == 3) zathura->ui.page_widget = gtk_grid_new(); gtk_grid_set_row_homogeneous(GTK_GRID(zathura->ui.page_widget), TRUE); gtk_grid_set_column_homogeneous(GTK_GRID(zathura->ui.page_widget), TRUE); #else zathura->ui.page_widget = gtk_table_new(0, 0, TRUE); #endif if (zathura->ui.page_widget == NULL) { goto error_free; } g_signal_connect(G_OBJECT(zathura->ui.session->gtk.window), "size-allocate", G_CALLBACK(cb_view_resized), zathura); /* Setup hadjustment tracker */ GtkAdjustment* hadjustment = gtk_scrolled_window_get_hadjustment( GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view)); zathura->ui.hadjustment = zathura_adjustment_clone(hadjustment); g_object_ref_sink(zathura->ui.hadjustment); /* Connect hadjustment signals */ g_signal_connect(G_OBJECT(hadjustment), "value-changed", G_CALLBACK(cb_view_vadjustment_value_changed), zathura); g_signal_connect(G_OBJECT(hadjustment), "value-changed", G_CALLBACK(cb_adjustment_track_value), zathura->ui.hadjustment); g_signal_connect(G_OBJECT(hadjustment), "changed", G_CALLBACK(cb_view_hadjustment_changed), zathura); g_signal_connect(G_OBJECT(hadjustment), "changed", G_CALLBACK(cb_adjustment_track_bounds), zathura->ui.hadjustment); /* Setup vadjustment tracker */ GtkAdjustment* vadjustment = gtk_scrolled_window_get_vadjustment( GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view)); zathura->ui.vadjustment = zathura_adjustment_clone(vadjustment); g_object_ref_sink(zathura->ui.vadjustment); /* Connect vadjustment signals */ g_signal_connect(G_OBJECT(vadjustment), "value-changed", G_CALLBACK(cb_view_vadjustment_value_changed), zathura); g_signal_connect(G_OBJECT(vadjustment), "value-changed", G_CALLBACK(cb_adjustment_track_value), zathura->ui.vadjustment); g_signal_connect(G_OBJECT(vadjustment), "changed", G_CALLBACK(cb_view_vadjustment_changed), zathura); g_signal_connect(G_OBJECT(vadjustment), "changed", G_CALLBACK(cb_adjustment_track_bounds), zathura->ui.vadjustment); /* page view alignment */ zathura->ui.page_widget_alignment = gtk_alignment_new(0.5, 0.5, 0, 0); if (zathura->ui.page_widget_alignment == NULL) { goto error_free; } gtk_container_add(GTK_CONTAINER(zathura->ui.page_widget_alignment), zathura->ui.page_widget); #if (GTK_MAJOR_VERSION == 3) gtk_widget_set_hexpand_set(zathura->ui.page_widget_alignment, TRUE); gtk_widget_set_hexpand(zathura->ui.page_widget_alignment, FALSE); gtk_widget_set_vexpand_set(zathura->ui.page_widget_alignment, TRUE); gtk_widget_set_vexpand(zathura->ui.page_widget_alignment, FALSE); #endif gtk_widget_show(zathura->ui.page_widget); /* statusbar */ zathura->ui.statusbar.file = girara_statusbar_item_add(zathura->ui.session, TRUE, TRUE, TRUE, NULL); if (zathura->ui.statusbar.file == NULL) { goto error_free; } zathura->ui.statusbar.buffer = girara_statusbar_item_add(zathura->ui.session, FALSE, FALSE, FALSE, NULL); if (zathura->ui.statusbar.buffer == NULL) { goto error_free; } zathura->ui.statusbar.page_number = girara_statusbar_item_add(zathura->ui.session, FALSE, FALSE, FALSE, NULL); if (zathura->ui.statusbar.page_number == NULL) { goto error_free; } girara_statusbar_item_set_text(zathura->ui.session, zathura->ui.statusbar.file, _("[No name]")); /* signals */ g_signal_connect(G_OBJECT(zathura->ui.session->gtk.window), "destroy", G_CALLBACK(cb_destroy), zathura); /* set page padding */ int page_padding = 1; girara_setting_get(zathura->ui.session, "page-padding", &page_padding); #if (GTK_MAJOR_VERSION == 3) gtk_grid_set_row_spacing(GTK_GRID(zathura->ui.page_widget), page_padding); gtk_grid_set_column_spacing(GTK_GRID(zathura->ui.page_widget), page_padding); #else gtk_table_set_row_spacings(GTK_TABLE(zathura->ui.page_widget), page_padding); gtk_table_set_col_spacings(GTK_TABLE(zathura->ui.page_widget), page_padding); #endif /* database */ char* database = NULL; girara_setting_get(zathura->ui.session, "database", &database); if (g_strcmp0(database, "plain") == 0) { girara_debug("Using plain database backend."); zathura->database = zathura_plaindatabase_new(zathura->config.data_dir); #ifdef WITH_SQLITE } else if (g_strcmp0(database, "sqlite") == 0) { girara_debug("Using sqlite database backend."); char* tmp = g_build_filename(zathura->config.data_dir, "bookmarks.sqlite", NULL); zathura->database = zathura_sqldatabase_new(tmp); g_free(tmp); #endif } else { girara_error("Database backend '%s' is not supported.", database); } g_free(database); if (zathura->database == NULL) { girara_error("Unable to initialize database. Bookmarks won't be available."); } else { g_object_set(zathura->ui.session->command_history, "io", zathura->database, NULL); } /* bookmarks */ zathura->bookmarks.bookmarks = girara_sorted_list_new2((girara_compare_function_t) zathura_bookmarks_compare, (girara_free_function_t) zathura_bookmark_free); /* jumplist */ zathura->jumplist.max_size = 20; girara_setting_get(zathura->ui.session, "jumplist-size", &(zathura->jumplist.max_size)); zathura->jumplist.list = girara_list_new2(g_free); zathura->jumplist.size = 0; zathura->jumplist.cur = NULL; zathura_jumplist_append_jump(zathura); zathura->jumplist.cur = girara_list_iterator(zathura->jumplist.list); /* page cache */ int cache_size = 0; girara_setting_get(zathura->ui.session, "page-cache-size", &cache_size); if (cache_size <= 0) { girara_warning("page-cache-size is not positive, using %d instead", ZATHURA_PAGE_CACHE_DEFAULT_SIZE); zathura->page_cache.size = ZATHURA_PAGE_CACHE_DEFAULT_SIZE; } else { zathura->page_cache.size = cache_size; } zathura->page_cache.cache = g_malloc(zathura->page_cache.size * sizeof(int)); zathura_page_cache_invalidate_all(zathura); return true; error_free: if (zathura->ui.page_widget != NULL) { g_object_unref(zathura->ui.page_widget); } if (zathura->ui.page_widget_alignment != NULL) { g_object_unref(zathura->ui.page_widget_alignment); } return false; }
bool 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; }
girara_list_t* pdf_page_images_get(zathura_page_t* page, void* data, zathura_error_t* error) { mupdf_page_t* mupdf_page = data; if (page == NULL) { if (error != NULL) { *error = ZATHURA_ERROR_INVALID_ARGUMENTS; } goto error_ret; } girara_list_t* list = NULL; zathura_document_t* document = zathura_page_get_document(page); if (document == NULL) { goto error_ret; } mupdf_document_t* mupdf_document = zathura_document_get_data(document); /* Setup image list */ list = girara_list_new(); if (list == NULL) { if (error != NULL) { *error = ZATHURA_ERROR_OUT_OF_MEMORY; } goto error_free; } girara_list_set_free_function(list, (girara_free_function_t) pdf_zathura_image_free); /* Extract images */ mupdf_page_extract_text(mupdf_document, mupdf_page); fz_stext_block* block; for (block = mupdf_page->text->first_block; block; block = block->next) { if (block->type == FZ_STEXT_BLOCK_IMAGE) { zathura_image_t* zathura_image = g_malloc(sizeof(zathura_image_t)); zathura_image->position.x1 = block->bbox.x0; zathura_image->position.y1 = block->bbox.y0; zathura_image->position.x2 = block->bbox.x1; zathura_image->position.y2 = block->bbox.y1; zathura_image->data = block->u.i.image; girara_list_append(list, zathura_image); } } return list; error_free: if (error != NULL && *error == ZATHURA_ERROR_OK) { *error = ZATHURA_ERROR_UNKNOWN; } if (list != NULL) { girara_list_free(list); } error_ret: return NULL; }
static girara_list_t* list_files(zathura_t* zathura, const char* current_path, const char* current_file, unsigned int current_file_length, bool is_dir, bool check_file_ext) { if (zathura == NULL || zathura->ui.session == NULL || current_path == NULL) { return NULL; } /* read directory */ GDir* dir = g_dir_open(current_path, 0, NULL); if (dir == NULL) { return NULL; } girara_list_t* res = girara_sorted_list_new2((girara_compare_function_t)compare_case_insensitive, (girara_free_function_t)g_free); bool show_hidden = false; girara_setting_get(zathura->ui.session, "show-hidden", &show_hidden); bool show_directories = true; girara_setting_get(zathura->ui.session, "show-directories", &show_directories); /* read files */ char* name = NULL; while ((name = (char*) g_dir_read_name(dir)) != NULL) { char* e_name = g_filename_display_name(name); if (e_name == NULL) { goto error_free; } size_t e_length = strlen(e_name); if (show_hidden == false && e_name[0] == '.') { g_free(e_name); continue; } if ((current_file_length > e_length) || strncmp(current_file, e_name, current_file_length)) { g_free(e_name); continue; } char* tmp = "/"; if (is_dir == true || g_strcmp0(current_path, "/") == 0) { tmp = ""; }; char* full_path = g_strdup_printf("%s%s%s", current_path, tmp, e_name); if (g_file_test(full_path, G_FILE_TEST_IS_DIR) == true) { if (show_directories == false) { g_free(e_name); g_free(full_path); continue; } girara_list_append(res, full_path); } else if (check_file_ext == false || file_valid_extension(zathura, full_path) == true) { girara_list_append(res, full_path); } else { g_free(full_path); } g_free(e_name); } g_dir_close(dir); if (girara_list_size(res) == 1) { char* path = girara_list_nth(res, 0); if (g_file_test(path, G_FILE_TEST_IS_DIR) == true) { char* newpath = g_strdup_printf("%s/", path); girara_list_clear(res); girara_list_append(res, newpath); } } return res; error_free: girara_list_free(res); return NULL; }
static girara_completion_t* list_files_for_cc(zathura_t* zathura, const char* input, bool check_file_ext) { girara_completion_t* completion = girara_completion_init(); girara_completion_group_t* group = girara_completion_group_create(zathura->ui.session, NULL); gchar* path = NULL; gchar* current_path = NULL; if (completion == NULL || group == NULL) { goto error_free; } path = girara_fix_path(input); if (path == NULL) { goto error_free; } /* If the path does not begin with a slash we update the path with the current * working directory */ if (strlen(path) == 0 || path[0] != '/') { long path_max; #ifdef PATH_MAX path_max = PATH_MAX; #else path_max = pathconf(path,_PC_PATH_MAX); if (path_max <= 0) path_max = 4096; #endif char cwd[path_max]; if (getcwd(cwd, path_max) == NULL) { goto error_free; } char* tmp_path = g_strdup_printf("%s/%s", cwd, path); g_free(path); path = tmp_path; } /* Append a slash if the given argument is a directory */ bool is_dir = (path[strlen(path) - 1] == '/') ? true : false; if ((g_file_test(path, G_FILE_TEST_IS_DIR) == TRUE) && !is_dir) { char* tmp_path = g_strdup_printf("%s/", path); g_free(path); path = tmp_path; is_dir = true; } /* get current path */ char* tmp = g_strdup(path); current_path = is_dir ? g_strdup(tmp) : g_strdup(dirname(tmp)); g_free(tmp); /* get current file */ gchar* current_file = is_dir ? "" : basename(path); int current_file_length = strlen(current_file); /* read directory */ if (g_file_test(current_path, G_FILE_TEST_IS_DIR) == TRUE) { girara_list_t* names = list_files(zathura, current_path, current_file, current_file_length, is_dir, check_file_ext); if (!names) { goto error_free; } GIRARA_LIST_FOREACH(names, const char*, iter, file) girara_completion_group_add_element(group, file, NULL); GIRARA_LIST_FOREACH_END(names, const char*, iter, file); girara_list_free(names); }
bool zathura_init(zathura_t* zathura) { if (zathura == NULL) { return false; } /* create zathura (config/data) directory */ if (g_mkdir_with_parents(zathura->config.config_dir, 0771) == -1) { girara_error("Could not create '%s': %s", zathura->config.config_dir, strerror(errno)); } if (g_mkdir_with_parents(zathura->config.data_dir, 0771) == -1) { girara_error("Could not create '%s': %s", zathura->config.data_dir, strerror(errno)); } /* load plugins */ zathura_plugin_manager_load(zathura->plugins.manager); /* configuration */ config_load_default(zathura); /* load global configuration files */ char* config_path = girara_get_xdg_path(XDG_CONFIG_DIRS); girara_list_t* config_dirs = girara_split_path_array(config_path); ssize_t size = girara_list_size(config_dirs) - 1; for (; size >= 0; --size) { const char* dir = girara_list_nth(config_dirs, size); char* file = g_build_filename(dir, ZATHURA_RC, NULL); config_load_file(zathura, file); g_free(file); } girara_list_free(config_dirs); g_free(config_path); config_load_file(zathura, GLOBAL_RC); /* load local configuration files */ char* configuration_file = g_build_filename(zathura->config.config_dir, ZATHURA_RC, NULL); config_load_file(zathura, configuration_file); g_free(configuration_file); /* UI */ if (girara_session_init(zathura->ui.session, "zathura") == false) { goto error_free; } /* girara events */ zathura->ui.session->events.buffer_changed = cb_buffer_changed; zathura->ui.session->events.unknown_command = cb_unknown_command; /* zathura signals */ zathura->signals.refresh_view = g_signal_new("refresh-view", GTK_TYPE_WIDGET, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 1, G_TYPE_POINTER); g_signal_connect(G_OBJECT(zathura->ui.session->gtk.view), "refresh-view", G_CALLBACK(cb_refresh_view), zathura); /* page view */ #if (GTK_MAJOR_VERSION == 3) zathura->ui.page_widget = gtk_grid_new(); gtk_grid_set_row_homogeneous(GTK_GRID(zathura->ui.page_widget), TRUE); gtk_grid_set_column_homogeneous(GTK_GRID(zathura->ui.page_widget), TRUE); #else zathura->ui.page_widget = gtk_table_new(0, 0, TRUE); #endif if (zathura->ui.page_widget == NULL) { goto error_free; } g_signal_connect(G_OBJECT(zathura->ui.session->gtk.window), "size-allocate", G_CALLBACK(cb_view_resized), zathura); GtkAdjustment* hadjustment = gtk_scrolled_window_get_hadjustment( GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view)); /* Connect hadjustment signals */ g_signal_connect(G_OBJECT(hadjustment), "value-changed", G_CALLBACK(cb_view_hadjustment_value_changed), zathura); g_signal_connect(G_OBJECT(hadjustment), "changed", G_CALLBACK(cb_view_hadjustment_changed), zathura); GtkAdjustment* vadjustment = gtk_scrolled_window_get_vadjustment( GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view)); /* Connect vadjustment signals */ g_signal_connect(G_OBJECT(vadjustment), "value-changed", G_CALLBACK(cb_view_vadjustment_value_changed), zathura); g_signal_connect(G_OBJECT(vadjustment), "changed", G_CALLBACK(cb_view_vadjustment_changed), zathura); /* page view alignment */ zathura->ui.page_widget_alignment = gtk_alignment_new(0.5, 0.5, 0, 0); if (zathura->ui.page_widget_alignment == NULL) { goto error_free; } gtk_container_add(GTK_CONTAINER(zathura->ui.page_widget_alignment), zathura->ui.page_widget); #if (GTK_MAJOR_VERSION == 3) gtk_widget_set_hexpand_set(zathura->ui.page_widget_alignment, TRUE); gtk_widget_set_hexpand(zathura->ui.page_widget_alignment, FALSE); gtk_widget_set_vexpand_set(zathura->ui.page_widget_alignment, TRUE); gtk_widget_set_vexpand(zathura->ui.page_widget_alignment, FALSE); #endif gtk_widget_show(zathura->ui.page_widget); /* statusbar */ zathura->ui.statusbar.file = girara_statusbar_item_add(zathura->ui.session, TRUE, TRUE, TRUE, NULL); if (zathura->ui.statusbar.file == NULL) { goto error_free; } zathura->ui.statusbar.buffer = girara_statusbar_item_add(zathura->ui.session, FALSE, FALSE, FALSE, NULL); if (zathura->ui.statusbar.buffer == NULL) { goto error_free; } zathura->ui.statusbar.page_number = girara_statusbar_item_add(zathura->ui.session, FALSE, FALSE, FALSE, NULL); if (zathura->ui.statusbar.page_number == NULL) { goto error_free; } girara_statusbar_item_set_text(zathura->ui.session, zathura->ui.statusbar.file, _("[No name]")); /* signals */ g_signal_connect(G_OBJECT(zathura->ui.session->gtk.window), "destroy", G_CALLBACK(cb_destroy), zathura); /* database */ char* database = NULL; girara_setting_get(zathura->ui.session, "database", &database); if (g_strcmp0(database, "plain") == 0) { girara_debug("Using plain database backend."); zathura->database = zathura_plaindatabase_new(zathura->config.data_dir); #ifdef WITH_SQLITE } else if (g_strcmp0(database, "sqlite") == 0) { girara_debug("Using sqlite database backend."); char* tmp = g_build_filename(zathura->config.data_dir, "bookmarks.sqlite", NULL); zathura->database = zathura_sqldatabase_new(tmp); g_free(tmp); #endif } else { girara_error("Database backend '%s' is not supported.", database); } g_free(database); if (zathura->database == NULL) { girara_error("Unable to initialize database. Bookmarks won't be available."); } else { g_object_set(zathura->ui.session->command_history, "io", zathura->database, NULL); } /* bookmarks */ zathura->bookmarks.bookmarks = girara_sorted_list_new2((girara_compare_function_t) zathura_bookmarks_compare, (girara_free_function_t) zathura_bookmark_free); /* jumplist */ int jumplist_size = 20; girara_setting_get(zathura->ui.session, "jumplist-size", &jumplist_size); zathura->jumplist.max_size = jumplist_size < 0 ? 0 : jumplist_size; zathura->jumplist.list = NULL; zathura->jumplist.size = 0; zathura->jumplist.cur = NULL; return true; error_free: if (zathura->ui.page_widget != NULL) { g_object_unref(zathura->ui.page_widget); } if (zathura->ui.page_widget_alignment != NULL) { g_object_unref(zathura->ui.page_widget_alignment); } return false; }
girara_list_t* synctex_rectangles_from_position(const char* filename, const char* input_file, int line, int column, unsigned int* page, girara_list_t** secondary_rects) { if (filename == NULL || input_file == NULL || page == NULL) { return NULL; } synctex_scanner_t scanner = synctex_scanner_new_with_output_file(filename, NULL, 1); if (scanner == NULL) { girara_debug("Failed to create synctex scanner."); return NULL; } synctex_scanner_t temp = synctex_scanner_parse(scanner); if (temp == NULL) { girara_debug("Failed to parse synctex file."); synctex_scanner_free(scanner); return NULL; } girara_list_t* hitlist = girara_list_new2(g_free); girara_list_t* other_rects = girara_list_new2(g_free); if (synctex_display_query(scanner, input_file, line, column) > 0) { synctex_node_t node = NULL; bool got_page = false; while ((node = synctex_next_result (scanner)) != NULL) { const unsigned int current_page = synctex_node_page(node) - 1; if (got_page == false) { got_page = true; *page = current_page; } zathura_rectangle_t rect = { 0, 0, 0, 0 }; rect.x1 = synctex_node_box_visible_h(node); rect.y1 = synctex_node_box_visible_v(node) - synctex_node_box_visible_height(node); rect.x2 = rect.x1 + synctex_node_box_visible_width(node); rect.y2 = synctex_node_box_visible_depth(node) + synctex_node_box_visible_height (node) + rect.y1; if (*page == current_page) { zathura_rectangle_t* real_rect = g_try_malloc(sizeof(zathura_rectangle_t)); if (real_rect == NULL) { continue; } *real_rect = rect; girara_list_append(hitlist, real_rect); } else { synctex_page_rect_t* page_rect = g_try_malloc(sizeof(synctex_page_rect_t)); if (page_rect == NULL) { continue; } page_rect->page = current_page; page_rect->rect = rect; girara_list_append(other_rects, page_rect); } } } synctex_scanner_free(scanner); if (secondary_rects != NULL) { *secondary_rects = other_rects; } else { girara_list_free(other_rects); } return hitlist; }