diff --git a/dbus-interface.c b/dbus-interface.c index e9409ab..5e965f6 100644 --- a/dbus-interface.c +++ b/dbus-interface.c @@ -545,17 +545,17 @@ zathura_dbus_goto_page_and_highlight(const char* filename, unsigned int page, } bool -zathura_dbus_synctex_position(const char* filename, const char* position, - pid_t hint) +zathura_dbus_synctex_position(const char* filename, const char* input_file, + int line, int column, pid_t hint) { - if (filename == NULL || position == NULL) { + if (filename == NULL || input_file == NULL) { return false; } unsigned int page = 0; girara_list_t* secondary_rects = NULL; girara_list_t* rectangles = synctex_rectangles_from_position( - filename, position, &page, &secondary_rects); + filename, input_file, line, column, &page, &secondary_rects); if (rectangles == NULL) { return false; } diff --git a/dbus-interface.h b/dbus-interface.h index 4e0f929..1f5b2c5 100644 --- a/dbus-interface.h +++ b/dbus-interface.h @@ -57,7 +57,7 @@ bool zathura_dbus_goto_page_and_highlight(const char* filename, unsigned int page, girara_list_t* rectangles, girara_list_t* secondary_rects, pid_t pidhint); -bool zathura_dbus_synctex_position(const char* filename, const char* position, - pid_t pidhint); +bool zathura_dbus_synctex_position(const char* filename, const char* input_file, + int line, int column, pid_t hint); #endif diff --git a/main.c b/main.c index 002860e..4762371 100644 --- a/main.c +++ b/main.c @@ -106,11 +106,25 @@ main(int argc, char* argv[]) return -1; } - if (zathura_dbus_synctex_position(real_path, synctex_fwd, synctex_pid) == true) { + char** split_fwd = g_strsplit(synctex_fwd, ":", 0); + if (split_fwd == NULL || split_fwd[0] == NULL || split_fwd[1] == NULL || + split_fwd[2] == NULL || split_fwd[3] != NULL) { + girara_error("Failed to parse argument to --synctex-forward."); + free(real_path); + g_strfreev(split_fwd); + return -1; + } + + const int line = MIN(INT_MAX, g_ascii_strtoll(split_fwd[0], NULL, 10)); + const int column = MIN(INT_MAX, g_ascii_strtoll(split_fwd[1], NULL, 10)); + const bool ret = zathura_dbus_synctex_position(real_path, split_fwd[2], line, column, synctex_pid); + g_strfreev(split_fwd); + + if (ret == true) { free(real_path); return 0; } else { - girara_error("Could not find open instance for '%s' or got no usable output from 'synctex view'.", real_path); + girara_error("Could not find open instance for '%s' or got no usable data from synctex.", real_path); free(real_path); return -1; } diff --git a/synctex.c b/synctex.c index 949ac54..d6a8073 100644 --- a/synctex.c +++ b/synctex.c @@ -9,43 +9,7 @@ #include "document.h" #include "utils.h" -enum { - SYNCTEX_RESULT_BEGIN = 1, - SYNCTEX_RESULT_END, - SYNCTEX_PROP_PAGE, - SYNCTEX_PROP_H, - SYNCTEX_PROP_V, - SYNCTEX_PROP_WIDTH, - SYNCTEX_PROP_HEIGHT, -}; - -typedef struct token_s { - const char* name; - guint token; -} token_t; - -static token_t scanner_tokens[] = { - {"SyncTeX result begin", SYNCTEX_RESULT_BEGIN}, - {"SyncTeX result end", SYNCTEX_RESULT_END}, - {"Page:", SYNCTEX_PROP_PAGE}, - {"h:", SYNCTEX_PROP_H}, - {"v:", SYNCTEX_PROP_V}, - {"W:", SYNCTEX_PROP_WIDTH}, - {"H:", SYNCTEX_PROP_HEIGHT}, - {NULL, 0} -}; - -static GScannerConfig scanner_config = { - .cset_skip_characters = "\n\r", - .cset_identifier_first = G_CSET_a_2_z G_CSET_A_2_Z, - .cset_identifier_nth = G_CSET_a_2_z G_CSET_A_2_Z ": ", - .cpair_comment_single = NULL, - .case_sensitive = TRUE, - .scan_identifier = TRUE, - .scan_symbols = TRUE, - .scan_float = TRUE, - .numbers_2_int = TRUE, -}; +#include "synctex/synctex_parser.h" void synctex_edit(zathura_t* zathura, zathura_page_t* page, int x, int y) @@ -84,192 +48,72 @@ synctex_edit(zathura_t* zathura, zathura_page_t* page, int x, int y) g_strfreev(argv); } -static double -scan_float(GScanner* scanner) -{ - switch (g_scanner_get_next_token(scanner)) { - case G_TOKEN_FLOAT: - return g_scanner_cur_value(scanner).v_float; - case G_TOKEN_INT: - return g_scanner_cur_value(scanner).v_int; - default: - return 0.0; - } -} - girara_list_t* -synctex_rectangles_from_position(const char* filename, const char* position, - unsigned int* page, +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 || position == NULL || page == NULL) { + if (filename == NULL || input_file == NULL || page == NULL) { return NULL; } - char** argv = g_try_malloc0(sizeof(char*) * 7); - if (argv == 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; } - argv[0] = g_strdup("synctex"); - argv[1] = g_strdup("view"); - argv[2] = g_strdup("-i"); - argv[3] = g_strdup(position); - argv[4] = g_strdup("-o"); - argv[5] = g_strdup(filename); - - gint output = -1; - bool ret = g_spawn_async_with_pipes(NULL, argv, NULL, - G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL, NULL, NULL, NULL, NULL, - &output, NULL, NULL); - g_strfreev(argv); - - if (ret == false) { - return false; + synctex_scanner_t temp = synctex_scanner_parse(scanner); + if (temp == NULL) { + girara_debug("Failed to parse synctex file."); + synctex_scanner_free(scanner); + return NULL; } - GScanner* scanner = g_scanner_new(&scanner_config); - token_t* tokens = scanner_tokens; - while (tokens->name != NULL) { - g_scanner_add_symbol(scanner, tokens->name, GINT_TO_POINTER(tokens->token)); - tokens++; - } - - g_scanner_input_file(scanner, output); - - bool found_begin = false, found_end = false; - while (found_begin == false && found_end == false) { - switch (g_scanner_get_next_token(scanner)) { - case G_TOKEN_EOF: - found_end = true; - break; - - case G_TOKEN_SYMBOL: - switch (GPOINTER_TO_INT(g_scanner_cur_value(scanner).v_identifier)) { - case SYNCTEX_RESULT_BEGIN: - found_begin = true; - break; - } - break; - - default: - /* skip everything else */ - break; - } - } - - ret = false; - unsigned int rpage = 0; - unsigned int current_page = 0; girara_list_t* hitlist = girara_list_new2(g_free); girara_list_t* other_rects = girara_list_new2(g_free); - bool got_rect = false; - zathura_rectangle_t rectangle; - while (found_end == false) { - switch (g_scanner_get_next_token(scanner)) { - case G_TOKEN_EOF: - found_end = true; - break; + if (synctex_display_query(scanner, input_file, line, column) > 0) { + synctex_node_t node = NULL; + bool got_page = false; - case G_TOKEN_SYMBOL: - switch (GPOINTER_TO_INT(g_scanner_cur_value(scanner).v_identifier)) { - case SYNCTEX_RESULT_END: - found_end = true; - break; - - case SYNCTEX_PROP_PAGE: - if (g_scanner_get_next_token(scanner) == G_TOKEN_INT) { - current_page = g_scanner_cur_value(scanner).v_int - 1; - if (ret == false) { - ret = true; - rpage = current_page; - } - - if (got_rect == false) { - continue; - } - got_rect = false; - - if (*page == current_page) { - zathura_rectangle_t* real_rect = g_try_malloc(sizeof(zathura_rectangle_t)); - if (real_rect == NULL) { - continue; - } - - *real_rect = rectangle; - 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 = rectangle; - - girara_list_append(other_rects, page_rect); - } - } - break; - - case SYNCTEX_PROP_H: - rectangle.x1 = scan_float(scanner); - got_rect = true; - break; - - case SYNCTEX_PROP_V: - rectangle.y2 = scan_float(scanner); - got_rect = true; - break; - - case SYNCTEX_PROP_WIDTH: - rectangle.x2 = rectangle.x1 + scan_float(scanner); - got_rect = true; - break; - - case SYNCTEX_PROP_HEIGHT: - rectangle.y1 = rectangle.y2 - scan_float(scanner); - got_rect = true; - break; - } - break; - - default: - break; - } - } - - if (got_rect == true) { - if (current_page == rpage) { - zathura_rectangle_t* real_rect = g_try_malloc(sizeof(zathura_rectangle_t)); - if (real_rect != NULL) { - *real_rect = rectangle; - girara_list_append(hitlist, real_rect); + 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; } - } else { - synctex_page_rect_t* page_rect = g_try_malloc(sizeof(synctex_page_rect_t)); - if (page_rect != NULL) { + + 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 = rectangle; + page_rect->rect = rect; + girara_list_append(other_rects, page_rect); } } } - g_scanner_destroy(scanner); - close(output); + synctex_scanner_free(scanner); - if (ret == false) { - girara_debug("Got no usable output from running synctex view."); - girara_list_free(hitlist); - girara_list_free(other_rects); - return NULL; - } - - if (page != NULL) { - *page = rpage; - } if (secondary_rects != NULL) { *secondary_rects = other_rects; } else {