Beispiel #1
0
/**
 * ev_document_synctex_forward_search:
 * @document: a #EvDocument
 * @source_link: a #EvSourceLink
 *
 * Peforms a Synctex forward search to obtain the area in the document
 * corresponding to the position @line and @column number in the source Tex file
 *
 * Returns: An EvMapping with the page number and area corresponfing to
 * the given line in the source file. It must be free with g_free when done
 */
EvMapping *
ev_document_synctex_forward_search (EvDocument   *document,
				    EvSourceLink *link)
{
        EvMapping        *result = NULL;
        synctex_scanner_t scanner;

        g_return_val_if_fail (EV_IS_DOCUMENT (document), NULL);

        scanner = document->priv->synctex_scanner;
        if (!scanner)
                return NULL;

        if (synctex_display_query (scanner, link->filename, link->line, link->col) > 0) {
                synctex_node_t node;
                gint           page;

                if ((node = synctex_next_result (scanner))) {
                        result = g_new (EvMapping, 1);

                        page = synctex_node_page (node) - 1;
                        result->data = GINT_TO_POINTER (page);

                        result->area.x1 = synctex_node_box_visible_h (node);
                        result->area.y1 = synctex_node_box_visible_v (node) -
                                synctex_node_box_visible_height (node);
                        result->area.x2 = synctex_node_box_visible_width (node) + result->area.x1;
                        result->area.y2 = synctex_node_box_visible_depth (node) +
                                synctex_node_box_visible_height (node) + result->area.y1;
                }
        }

        return result;
}
Beispiel #2
0
QList<SynctexTextBox> SynctexHandler::syncFromSource(const QString &sourceFile, int lineNumber)
{
	QList<SynctexTextBox> textBoxList;

	if (!m_synctexScanner)
		return textBoxList;

	// find the name synctex is using for this file
	const QFileInfo sourceFileInfo(sourceFile);
	const QDir currentDir(QFileInfo(m_fileName).canonicalPath());
	synctex_node_t synctexNode = synctex_scanner_input(m_synctexScanner);
	QString texFileName;
	bool found = false;
	while (synctexNode)
	{
		texFileName = QString::fromUtf8(synctex_scanner_get_name(m_synctexScanner, synctex_node_tag(synctexNode)));
		if (QFileInfo(currentDir, texFileName) == sourceFileInfo)
		{
			found = true;
			break;
		}
		synctexNode = synctex_node_sibling(synctexNode);
	}
	if (!found)
		return textBoxList;

	if (synctex_display_query(m_synctexScanner, texFileName.toUtf8().data(), lineNumber, 0) > 0)
	{
		int pageNumber = -1;
		while ((synctexNode = synctex_next_result(m_synctexScanner)) != 0)
		{
			if (pageNumber < 0)
				pageNumber = synctex_node_page(synctexNode);
			if (synctex_node_page(synctexNode) != pageNumber)
				continue;
			const QRectF textBox(synctex_node_box_visible_h(synctexNode),
			    synctex_node_box_visible_v(synctexNode) - synctex_node_box_visible_height(synctexNode),
			    synctex_node_box_visible_width(synctexNode),
			    synctex_node_box_visible_height(synctexNode));
			SynctexTextBox synctexTextBox;
			synctexTextBox.pageNumber = pageNumber;
			synctexTextBox.textBox = textBox;
			textBoxList << synctexTextBox;
		}
	}
	return textBoxList;
}
Beispiel #3
0
int SyncTex::SourceToDoc(const WCHAR* srcfilename, UINT line, UINT col, UINT *page, Vec<RectI> &rects)
{
    if (IsIndexDiscarded())
        if (RebuildIndex() != PDFSYNCERR_SUCCESS)
            return PDFSYNCERR_SYNCFILE_CANNOT_BE_OPENED;
    assert(this->scanner);

    ScopedMem<WCHAR> srcfilepath;
    // convert the source file to an absolute path
    if (PathIsRelative(srcfilename))
        srcfilepath.Set(PrependDir(srcfilename));
    else
        srcfilepath.Set(str::Dup(srcfilename));
    if (!srcfilepath)
        return PDFSYNCERR_OUTOFMEMORY;

    bool isUtf8 = true;
    char *mb_srcfilepath = str::conv::ToUtf8(srcfilepath);
TryAgainAnsi:
    if (!mb_srcfilepath)
        return PDFSYNCERR_OUTOFMEMORY;
    int ret = synctex_display_query(this->scanner, mb_srcfilepath, line, col);
    free(mb_srcfilepath);
    // recent SyncTeX versions encode in UTF-8 instead of ANSI
    if (isUtf8 && -1 == ret) {
        isUtf8 = false;
        mb_srcfilepath = str::conv::ToAnsi(srcfilepath);
        goto TryAgainAnsi;
    }

    if (-1 == ret)
        return PDFSYNCERR_UNKNOWN_SOURCEFILE;
    if (0 == ret)
        return PDFSYNCERR_NOSYNCPOINT_FOR_LINERECORD;

    synctex_node_t node;
    int firstpage = -1;
    rects.Reset();

    while ((node = synctex_next_result(this->scanner)) != NULL) {
        if (firstpage == -1) {
            firstpage = synctex_node_page(node);
            if (firstpage <= 0 || firstpage > engine->PageCount())
                continue;
            *page = (UINT)firstpage;
        }
        if (synctex_node_page(node) != firstpage)
            continue;

        RectD rc;
        rc.x  = synctex_node_box_visible_h(node);
        rc.y  = synctex_node_box_visible_v(node) - synctex_node_box_visible_height(node);
        rc.dx = synctex_node_box_visible_width(node),
        rc.dy = synctex_node_box_visible_height(node) + synctex_node_box_visible_depth(node);
        rects.Push(rc.Round());
    }

    if (firstpage <= 0)
        return PDFSYNCERR_NOSYNCPOINT_FOR_LINERECORD;
    return PDFSYNCERR_SUCCESS;
}
Beispiel #4
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;
}
Beispiel #5
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;
}