synctex.c 3.36 KB
Newer Older
1
2
/* See LICENSE file for license and copyright information */

Moritz Lipp's avatar
Moritz Lipp committed
3
#include <glib.h>
4
#include <girara/utils.h>
Moritz Lipp's avatar
Moritz Lipp committed
5

6
7
8
9
#include "synctex.h"
#include "zathura.h"
#include "page.h"
#include "document.h"
Moritz Lipp's avatar
Moritz Lipp committed
10
#include "utils.h"
11

12
#include "synctex/synctex_parser.h"
Moritz Lipp's avatar
Moritz Lipp committed
13

14
15
16
void
synctex_edit(zathura_t* zathura, zathura_page_t* page, int x, int y)
{
Moritz Lipp's avatar
Moritz Lipp committed
17
18
19
  if (zathura == NULL || page == NULL) {
    return;
  }
20

Moritz Lipp's avatar
Moritz Lipp committed
21
22
  zathura_document_t* document = zathura_page_get_document(page);
  if (document == NULL) {
23
    return;
Moritz Lipp's avatar
Moritz Lipp committed
24
25
26
27
28
29
30
  }

  const char *filename = zathura_document_get_path(document);
  if (filename == NULL) {
    return;
  }

31
  char** argv = g_try_malloc0(sizeof(char*) * (zathura->synctex.editor != NULL ?
32
      7 : 5));
33
34
35
36
  if (argv == NULL) {
    return;
  }

37
38
39
  argv[0] = g_strdup("synctex");
  argv[1] = g_strdup("edit");
  argv[2] = g_strdup("-o");
40
41
  argv[3] = g_strdup_printf("%d:%d:%d:%s", zathura_page_get_index(page) + 1, x,
      y, filename);
Moritz Lipp's avatar
Moritz Lipp committed
42
  if (zathura->synctex.editor != NULL) {
43
44
    argv[4] = g_strdup("-x");
    argv[5] = g_strdup(zathura->synctex.editor);
45
46
  }

47
48
  g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL);
  g_strfreev(argv);
49
}
Moritz Lipp's avatar
Moritz Lipp committed
50

51
girara_list_t*
52
53
synctex_rectangles_from_position(const char* filename, const char* input_file,
                                 int line, int column, unsigned int* page,
54
                                 girara_list_t** secondary_rects)
Moritz Lipp's avatar
Moritz Lipp committed
55
{
56
  if (filename == NULL || input_file == NULL || page == NULL) {
57
    return NULL;
58
59
  }

60
61
62
  synctex_scanner_t scanner = synctex_scanner_new_with_output_file(filename, NULL, 1);
  if (scanner == NULL) {
    girara_debug("Failed to create synctex scanner.");
63
64
65
    return NULL;
  }

66
67
68
69
70
  synctex_scanner_t temp = synctex_scanner_parse(scanner);
  if (temp == NULL) {
    girara_debug("Failed to parse synctex file.");
    synctex_scanner_free(scanner);
    return NULL;
Moritz Lipp's avatar
Moritz Lipp committed
71
72
  }

73
  girara_list_t* hitlist     = girara_list_new2(g_free);
74
  girara_list_t* other_rects = girara_list_new2(g_free);
Moritz Lipp's avatar
Moritz Lipp committed
75

76
77
78
  if (synctex_display_query(scanner, input_file, line, column) > 0) {
    synctex_node_t node        = NULL;
    bool got_page              = false;
Moritz Lipp's avatar
Moritz Lipp committed
79

80
81
82
83
84
85
    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;
      }
Moritz Lipp's avatar
Moritz Lipp committed
86

87
88
89
90
91
      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;
Moritz Lipp's avatar
Moritz Lipp committed
92

93
94
95
96
      if (*page == current_page) {
        zathura_rectangle_t* real_rect = g_try_malloc(sizeof(zathura_rectangle_t));
        if (real_rect == NULL) {
          continue;
Moritz Lipp's avatar
Moritz Lipp committed
97
98
        }

99
        *real_rect = rect;
100
        girara_list_append(hitlist, real_rect);
101
102
103
104
105
106
      } else {
        synctex_page_rect_t* page_rect = g_try_malloc(sizeof(synctex_page_rect_t));
        if (page_rect == NULL) {
          continue;
        }

107
        page_rect->page = current_page;
108
109
        page_rect->rect = rect;

110
111
        girara_list_append(other_rects, page_rect);
      }
112
    }
Moritz Lipp's avatar
Moritz Lipp committed
113
114
  }

115
  synctex_scanner_free(scanner);
Moritz Lipp's avatar
Moritz Lipp committed
116

117
118
119
120
121
122
  if (secondary_rects != NULL) {
    *secondary_rects = other_rects;
  } else {
    girara_list_free(other_rects);
  }

123
  return hitlist;
Moritz Lipp's avatar
Moritz Lipp committed
124
}