mirror of
https://git.pwmt.org/pwmt/zathura.git
synced 2024-11-14 08:53:46 +01:00
Switch forward synchronizaton to synctex_parser
Signed-off-by: Sebastian Ramacher <sebastian+dev@ramacher.at>
This commit is contained in:
parent
1f286ebcb3
commit
79eb7d88c8
@ -545,17 +545,17 @@ zathura_dbus_goto_page_and_highlight(const char* filename, unsigned int page,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
zathura_dbus_synctex_position(const char* filename, const char* position,
|
zathura_dbus_synctex_position(const char* filename, const char* input_file,
|
||||||
pid_t hint)
|
int line, int column, pid_t hint)
|
||||||
{
|
{
|
||||||
if (filename == NULL || position == NULL) {
|
if (filename == NULL || input_file == NULL) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int page = 0;
|
unsigned int page = 0;
|
||||||
girara_list_t* secondary_rects = NULL;
|
girara_list_t* secondary_rects = NULL;
|
||||||
girara_list_t* rectangles = synctex_rectangles_from_position(
|
girara_list_t* rectangles = synctex_rectangles_from_position(
|
||||||
filename, position, &page, &secondary_rects);
|
filename, input_file, line, column, &page, &secondary_rects);
|
||||||
if (rectangles == NULL) {
|
if (rectangles == NULL) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -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,
|
unsigned int page, girara_list_t* rectangles, girara_list_t* secondary_rects,
|
||||||
pid_t pidhint);
|
pid_t pidhint);
|
||||||
|
|
||||||
bool zathura_dbus_synctex_position(const char* filename, const char* position,
|
bool zathura_dbus_synctex_position(const char* filename, const char* input_file,
|
||||||
pid_t pidhint);
|
int line, int column, pid_t hint);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
18
main.c
18
main.c
@ -106,11 +106,25 @@ main(int argc, char* argv[])
|
|||||||
return -1;
|
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);
|
free(real_path);
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} 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);
|
free(real_path);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
212
synctex.c
212
synctex.c
@ -9,43 +9,7 @@
|
|||||||
#include "document.h"
|
#include "document.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
enum {
|
#include "synctex/synctex_parser.h"
|
||||||
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,
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
void
|
||||||
synctex_edit(zathura_t* zathura, zathura_page_t* page, int x, int y)
|
synctex_edit(zathura_t* zathura, zathura_page_t* page, int x, int y)
|
||||||
@ -84,112 +48,47 @@ synctex_edit(zathura_t* zathura, zathura_page_t* page, int x, int y)
|
|||||||
g_strfreev(argv);
|
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*
|
girara_list_t*
|
||||||
synctex_rectangles_from_position(const char* filename, const char* position,
|
synctex_rectangles_from_position(const char* filename, const char* input_file,
|
||||||
unsigned int* page,
|
int line, int column, unsigned int* page,
|
||||||
girara_list_t** secondary_rects)
|
girara_list_t** secondary_rects)
|
||||||
{
|
{
|
||||||
if (filename == NULL || position == NULL || page == NULL) {
|
if (filename == NULL || input_file == NULL || page == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
char** argv = g_try_malloc0(sizeof(char*) * 7);
|
synctex_scanner_t scanner = synctex_scanner_new_with_output_file(filename, NULL, 1);
|
||||||
if (argv == NULL) {
|
if (scanner == NULL) {
|
||||||
|
girara_debug("Failed to create synctex scanner.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
argv[0] = g_strdup("synctex");
|
synctex_scanner_t temp = synctex_scanner_parse(scanner);
|
||||||
argv[1] = g_strdup("view");
|
if (temp == NULL) {
|
||||||
argv[2] = g_strdup("-i");
|
girara_debug("Failed to parse synctex file.");
|
||||||
argv[3] = g_strdup(position);
|
synctex_scanner_free(scanner);
|
||||||
argv[4] = g_strdup("-o");
|
return NULL;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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* hitlist = girara_list_new2(g_free);
|
||||||
girara_list_t* other_rects = 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) {
|
if (synctex_display_query(scanner, input_file, line, column) > 0) {
|
||||||
switch (g_scanner_get_next_token(scanner)) {
|
synctex_node_t node = NULL;
|
||||||
case G_TOKEN_EOF:
|
bool got_page = false;
|
||||||
found_end = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case G_TOKEN_SYMBOL:
|
while ((node = synctex_next_result (scanner)) != NULL) {
|
||||||
switch (GPOINTER_TO_INT(g_scanner_cur_value(scanner).v_identifier)) {
|
const unsigned int current_page = synctex_node_page(node) - 1;
|
||||||
case SYNCTEX_RESULT_END:
|
if (got_page == false) {
|
||||||
found_end = true;
|
got_page = true;
|
||||||
break;
|
*page = current_page;
|
||||||
|
|
||||||
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) {
|
zathura_rectangle_t rect = { 0, 0, 0, 0 };
|
||||||
continue;
|
rect.x1 = synctex_node_box_visible_h(node);
|
||||||
}
|
rect.y1 = synctex_node_box_visible_v(node) - synctex_node_box_visible_height(node);
|
||||||
got_rect = false;
|
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) {
|
if (*page == current_page) {
|
||||||
zathura_rectangle_t* real_rect = g_try_malloc(sizeof(zathura_rectangle_t));
|
zathura_rectangle_t* real_rect = g_try_malloc(sizeof(zathura_rectangle_t));
|
||||||
@ -197,7 +96,7 @@ synctex_rectangles_from_position(const char* filename, const char* position,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
*real_rect = rectangle;
|
*real_rect = rect;
|
||||||
girara_list_append(hitlist, real_rect);
|
girara_list_append(hitlist, real_rect);
|
||||||
} else {
|
} else {
|
||||||
synctex_page_rect_t* page_rect = g_try_malloc(sizeof(synctex_page_rect_t));
|
synctex_page_rect_t* page_rect = g_try_malloc(sizeof(synctex_page_rect_t));
|
||||||
@ -206,70 +105,15 @@ synctex_rectangles_from_position(const char* filename, const char* position,
|
|||||||
}
|
}
|
||||||
|
|
||||||
page_rect->page = current_page;
|
page_rect->page = current_page;
|
||||||
page_rect->rect = rectangle;
|
page_rect->rect = rect;
|
||||||
|
|
||||||
girara_list_append(other_rects, page_rect);
|
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) {
|
synctex_scanner_free(scanner);
|
||||||
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);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
synctex_page_rect_t* page_rect = g_try_malloc(sizeof(synctex_page_rect_t));
|
|
||||||
if (page_rect != NULL) {
|
|
||||||
page_rect->page = current_page;
|
|
||||||
page_rect->rect = rectangle;
|
|
||||||
girara_list_append(other_rects, page_rect);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
g_scanner_destroy(scanner);
|
|
||||||
close(output);
|
|
||||||
|
|
||||||
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) {
|
if (secondary_rects != NULL) {
|
||||||
*secondary_rects = other_rects;
|
*secondary_rects = other_rects;
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user