void SynctexHandler::loadData(const QString &fileName) { removeData(); m_fileName = fileName; m_synctexScanner = synctex_scanner_new_with_output_file(m_fileName.toUtf8().data(), 0, 1); }
int SyncTex::RebuildIndex() { synctex_scanner_free(this->scanner); this->scanner = NULL; ScopedMem<char> syncfname(str::conv::ToAnsi(syncfilepath)); if (!syncfname) return PDFSYNCERR_OUTOFMEMORY; scanner = synctex_scanner_new_with_output_file(syncfname, NULL, 1); if (!scanner) return PDFSYNCERR_SYNCFILE_NOTFOUND; // cannot rebuild the index return Synchronizer::RebuildIndex(); }
int SyncTex::RebuildIndex() { synctex_scanner_free(scanner); scanner = nullptr; OwnedData syncfname(str::conv::ToAnsi(syncfilepath)); if (!syncfname.Get()) return PDFSYNCERR_OUTOFMEMORY; scanner = synctex_scanner_new_with_output_file(syncfname.Get(), nullptr, 1); if (!scanner) return PDFSYNCERR_SYNCFILE_NOTFOUND; // cannot rebuild the index return Synchronizer::RebuildIndex(); }
static void ev_document_initialize_synctex (EvDocument *document, const gchar *uri) { EvDocumentPrivate *priv = document->priv; if (_ev_document_support_synctex (document)) { gchar *filename; filename = g_filename_from_uri (uri, NULL, NULL); if (filename != NULL) { priv->synctex_scanner = synctex_scanner_new_with_output_file (filename, NULL, 1); g_free (filename); } } }
bool synctex_get_input_line_column(const char* filename, unsigned int page, int x, int y, char** input_file, unsigned int* line, unsigned int* column) { if (filename == NULL) { return false; } synctex_scanner_t scanner = synctex_scanner_new_with_output_file(filename, NULL, 1); if (scanner == NULL) { girara_debug("Failed to create synctex scanner."); 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 false; } bool ret = false; if (synctex_edit_query(scanner, page + 1u, x, y) > 0) { /* Assume that a backward search returns at most one result. */ synctex_node_t node = synctex_next_result(scanner); if (node != NULL) { if (input_file != NULL) { *input_file = g_strdup(synctex_scanner_get_name(scanner, synctex_node_tag(node))); } if (line != NULL) { *line = synctex_node_line(node); } if (column != NULL) { *column = synctex_node_column(node); } ret = true; } } synctex_scanner_free(scanner); return ret; }
/** * ev_document_load: * @document: a #EvDocument * @uri: the document's URI * @error: a #GError location to store an error, or %NULL * * Loads @document from @uri. * * On failure, %FALSE is returned and @error is filled in. * If the document is encrypted, EV_DEFINE_ERROR_ENCRYPTED is returned. * If the backend cannot load the specific document, EV_DOCUMENT_ERROR_INVALID * is returned. Other errors are possible too, depending on the backend * used to load the document and the URI, e.g. #GIOError, #GFileError, and * #GConvertError. * * Returns: %TRUE on success, or %FALSE on failure. */ gboolean ev_document_load (EvDocument *document, const char *uri, GError **error) { EvDocumentClass *klass = EV_DOCUMENT_GET_CLASS (document); gboolean retval; GError *err = NULL; retval = klass->load (document, uri, &err); if (!retval) { if (err) { g_propagate_error (error, err); } else { g_warning ("%s::EvDocument::load returned FALSE but did not fill in @error; fix the backend!\n", G_OBJECT_TYPE_NAME (document)); /* So upper layers don't crash */ g_set_error_literal (error, EV_DOCUMENT_ERROR, EV_DOCUMENT_ERROR_INVALID, "Internal error in backend"); } } else { EvDocumentPrivate *priv = document->priv; ev_document_setup_cache (document); priv->uri = g_strdup (uri); priv->info = _ev_document_get_info (document); if (_ev_document_support_synctex (document)) { gchar *filename; filename = g_filename_from_uri (uri, NULL, NULL); if (filename != NULL) { priv->synctex_scanner = synctex_scanner_new_with_output_file (filename, NULL, 1); g_free (filename); } } } return retval; }
int synctex_edit_proceed(synctex_edit_params_t * Ps) { synctex_scanner_t scanner = NULL; #if SYNCTEX_DEBUG printf("page:%i\n",Ps->page); printf("x:%f\n",Ps->x); printf("y:%f\n",Ps->y); printf("almost output:%s\n",Ps->output); printf("editor:%s\n",Ps->editor); printf("offset:%i\n",Ps->offset); printf("context:%s\n",Ps->context); printf("cwd:%s\n",getcwd(NULL,0)); #endif scanner = synctex_scanner_new_with_output_file(Ps->output,Ps->directory,1); if(NULL == scanner) { synctex_help_edit("No SyncTeX available for %s",Ps->output); return -1; } if(synctex_edit_query(scanner,Ps->page,Ps->x,Ps->y)) { synctex_node_t node = NULL; const char * input = NULL; if(NULL != (node = synctex_next_result(scanner)) && NULL != (input = synctex_scanner_get_name(scanner,synctex_node_tag(node)))) { /* filtering the command */ if(Ps->editor && strlen(Ps->editor)) { size_t size = 0; char * where = NULL; char * buffer = NULL; char * buffer_cur = NULL; int printed; int status; size = strlen(Ps->editor)+3*sizeof(int)+3*SYNCTEX_STR_SIZE; buffer = malloc(size+1); if(NULL == buffer) { printf("SyncTeX ERROR: No memory available\n"); return -1; } buffer[size]='\0'; /* Replace %{ by &{, then remove all unescaped '%'*/ while((where = strstr(Ps->editor,"%{")) != NULL) { *where = '&'; } where = Ps->editor; while(where &&(where = strstr(where,"%"))) { if(strlen(++where)) { if(*where == '%') { ++where; } else { *(where-1)='&'; } } } buffer_cur = buffer; /* find the next occurrence of a format key */ where = Ps->editor; while(Ps->editor && (where = strstr(Ps->editor,"&{"))) { #define TEST(KEY,FORMAT,WHAT)\ if(!strncmp(where,KEY,strlen(KEY))) {\ printed = where-Ps->editor;\ if(buffer_cur != memcpy(buffer_cur,Ps->editor,(size_t)printed)) {\ synctex_help_edit("Memory copy problem");\ free(buffer);\ return -1;\ }\ buffer_cur += printed;size-=printed;\ printed = snprintf(buffer_cur,size,FORMAT,WHAT);\ if((unsigned)printed >= (unsigned)size) {\ synctex_help_edit("Snprintf problem");\ free(buffer);\ return -1;\ }\ buffer_cur += printed;size-=printed;\ *buffer_cur='\0';\ Ps->editor = where+strlen(KEY);\ continue;\ } TEST("&{output}", "%s",Ps->output); TEST("&{input}", "%s",input); TEST("&{line}", "%i",synctex_node_line(node)); TEST("&{column}", "%i",-1); TEST("&{offset}", "%i",Ps->offset); TEST("&{context}","%s",Ps->context); #undef TEST break; } /* copy the rest of editor into the buffer */ if(buffer_cur != memcpy(buffer_cur,Ps->editor,strlen(Ps->editor))) { fputs("! synctex_edit: Memory copy problem",stderr); free(buffer); return -1; }\ printf("SyncTeX: Executing\n%s\n",buffer); status = system(buffer); free(buffer); buffer = NULL; return status; } else { /* just print out the results */ puts("SyncTeX result begin"); do { printf( "Output:%s\n" "Input:%s\n" "Line:%i\n" "Column:%i\n" "Offset:%i\n" "Context:%s\n", Ps->output, input, synctex_node_line(node), synctex_node_column(node), Ps->offset, (Ps->context?Ps->context:"")); } while((node = synctex_next_result(scanner)) != NULL); puts("SyncTeX result end"); } } } return 0; }
int synctex_view_proceed(synctex_view_params_t * Ps) { synctex_scanner_t scanner = NULL; size_t size = 0; #if SYNCTEX_DEBUG printf("line:%i\n",Ps->line); printf("column:%i\n",Ps->column); printf("input:%s\n",Ps->input); printf("viewer:%s\n",Ps->viewer); printf("before:%s\n",Ps->before); printf("offset:%i\n",Ps->offset); printf("middle:%s\n",Ps->middle); printf("after:%s\n",Ps->after); printf("output:%s\n",Ps->output); printf("cwd:%s\n",getcwd(NULL,0)); #endif /* We assume that viewer is not so big: */ # define SYNCTEX_STR_SIZE 65536 if(Ps->viewer && strlen(Ps->viewer)>=SYNCTEX_STR_SIZE) { synctex_help_view("Viewer command is too long"); return -1; } scanner = synctex_scanner_new_with_output_file(Ps->output,Ps->directory,1); if(scanner && synctex_display_query(scanner,Ps->input,Ps->line,Ps->column)) { synctex_node_t node = NULL; if((node = synctex_next_result(scanner)) != NULL) { /* filtering the command */ if(Ps->viewer && strlen(Ps->viewer)) { char * viewer = Ps->viewer; char * where = NULL; char * buffer = NULL; char * buffer_cur = NULL; int printed = 0; int status = 0; /* Preparing the buffer where everything will be printed */ size = strlen(viewer)+3*sizeof(int)+6*sizeof(float)+4*(SYNCTEX_STR_SIZE); buffer = malloc(size+1); if(NULL == buffer) { synctex_help_view("No memory available"); return -1; } /* Properly terminate the buffer, no bad access for string related functions. */ buffer[size] = '\0'; /* Replace %{ by &{, then remove all unescaped '%'*/ while((where = strstr(viewer,"%{")) != NULL) { *where = '&'; } /* find all the unescaped '%', change to a safe character */ where = viewer; while(where && (where = strstr(where,"%"))) { /* Find the next occurrence of a "%", * if it is not followed by another "%", * replace it by a "&" */ if(strlen(++where)) { if(*where == '%') { ++where; } else { *(where-1)='&'; } } } buffer_cur = buffer; /* find the next occurrence of a format key */ where = viewer; while(viewer && (where = strstr(viewer,"&{"))) { #define TEST(KEY,FORMAT,WHAT)\ if(!strncmp(where,KEY,strlen(KEY))) {\ printed = where-viewer;\ if(buffer_cur != memcpy(buffer_cur,viewer,(size_t)printed)) {\ synctex_help_view("Memory copy problem");\ free(buffer);\ return -1;\ }\ buffer_cur += printed;size-=printed;\ printed = snprintf(buffer_cur,size,FORMAT,WHAT);\ if((unsigned)printed >= (unsigned)size) {\ synctex_help_view("Snprintf problem");\ free(buffer);\ return -1;\ }\ buffer_cur += printed;size-=printed;\ *buffer_cur='\0';\ viewer = where+strlen(KEY);\ continue;\ } TEST("&{output}","%s",synctex_scanner_get_output(scanner)); TEST("&{page}", "%i",synctex_node_page(node)-1); TEST("&{page+1}","%i",synctex_node_page(node)); TEST("&{x}", "%f",synctex_node_visible_h(node)); TEST("&{y}", "%f",synctex_node_visible_v(node)); TEST("&{h}", "%f",synctex_node_box_visible_h(node)); TEST("&{v}", "%f",synctex_node_box_visible_v(node)+synctex_node_box_visible_depth(node)); TEST("&{width}", "%f",fabs(synctex_node_box_visible_width(node))); TEST("&{height}","%f",fmax(synctex_node_box_visible_height(node)+synctex_node_box_visible_depth(node),1)); TEST("&{before}","%s",(Ps->before && strlen(Ps->before)<SYNCTEX_STR_SIZE?Ps->before:"")); TEST("&{offset}","%i",Ps->offset); TEST("&{middle}","%s",(Ps->middle && strlen(Ps->middle)<SYNCTEX_STR_SIZE?Ps->middle:"")); TEST("&{after}", "%s",(Ps->after && strlen(Ps->after)<SYNCTEX_STR_SIZE?Ps->after:"")); #undef TEST break; } /* copy the rest of viewer into the buffer */ if(buffer_cur != strncpy(buffer_cur,viewer,size + 1)) { synctex_help_view("Memory copy problem"); free(buffer); return -1; } buffer_cur[size] = '\0'; printf("SyncTeX: Executing\n%s\n",buffer); status = system(buffer); free(buffer); buffer = NULL; return status; } else { /* just print out the results */ puts("SyncTeX result begin"); do { printf( "Output:%s\n" "Page:%i\n" "x:%f\n" "y:%f\n" "h:%f\n" "v:%f\n" "W:%f\n" "H:%f\n" "before:%s\n" "offset:%i\n" "middle:%s\n" "after:%s\n", Ps->output, synctex_node_page(node), synctex_node_visible_h(node), synctex_node_visible_v(node), synctex_node_box_visible_h(node), synctex_node_box_visible_v(node)+synctex_node_box_visible_depth(node), synctex_node_box_visible_width(node), synctex_node_box_visible_height(node)+synctex_node_box_visible_depth(node), (Ps->before?Ps->before:""), Ps->offset, (Ps->middle?Ps->middle:""), (Ps->after?Ps->after:"")); } while((node = synctex_next_result(scanner)) != NULL); puts("SyncTeX result end"); } } } return 0; }
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; }
void synctex_edit(zathura_t* zathura, zathura_page_t* page, int x, int y) { if (zathura == NULL || page == NULL || zathura->synctex.editor == NULL) { return; } zathura_document_t* document = zathura_page_get_document(page); if (document == NULL) { return; } const char *filename = zathura_document_get_path(document); if (filename == NULL) { return; } synctex_scanner_t scanner = synctex_scanner_new_with_output_file(filename, NULL, 1); if (scanner == NULL) { girara_debug("Failed to create synctex scanner."); return; } synctex_scanner_t temp = synctex_scanner_parse(scanner); if (temp == NULL) { girara_debug("Failed to parse synctex file."); synctex_scanner_free(scanner); return; } if (synctex_edit_query(scanner, zathura_page_get_index(page) + 1, x, y) > 0) { /* Assume that a backward search returns either at most one result. */ synctex_node_t node = synctex_next_result(scanner); if (node != NULL) { const char* input_file = synctex_scanner_get_name(scanner, synctex_node_tag(node)); const int line = synctex_node_line(node); const int column = synctex_node_column (node); char* linestr = g_strdup_printf("%d", line); char* columnstr = g_strdup_printf("%d", column); gchar** argv = NULL; gint argc = 0; if (g_shell_parse_argv(zathura->synctex.editor, &argc, &argv, NULL) == TRUE) { for (gint i = 0; i != argc; ++i) { char* temp = girara_replace_substring(argv[i], "%{line}", linestr); g_free(argv[i]); argv[i] = temp; temp = girara_replace_substring(argv[i], "%{column}", columnstr); g_free(argv[i]); argv[i] = temp; temp = girara_replace_substring(argv[i], "%{input}", input_file); g_free(argv[i]); argv[i] = temp; } g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL); g_strfreev(argv); } g_free(linestr); g_free(columnstr); } } synctex_scanner_free(scanner); }