Beispiel #1
0
bool
cb_sc_follow(GtkEntry* entry, girara_session_t* session)
{
  g_return_val_if_fail(session != NULL, FALSE);
  g_return_val_if_fail(session->global.data != NULL, FALSE);

  zathura_t* zathura = session->global.data;
  bool eval = true;

  char* input = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1);
  if (input == NULL || strlen(input) == 0) {
    eval = false;
  }

  int index = 0;
  if (eval == true) {
    index = atoi(input);
    if (index == 0 && g_strcmp0(input, "0") != 0) {
      girara_notify(session, GIRARA_WARNING, _("Invalid input '%s' given."), input);
      eval = false;
    }
    index = index - 1;
  }

  /* set pages to draw links */
  bool invalid_index = true;
  unsigned int number_of_pages = zathura_document_get_number_of_pages(zathura->document);
  for (unsigned int page_id = 0; page_id < number_of_pages; page_id++) {
    zathura_page_t* page = zathura_document_get_page(zathura->document, page_id);
    if (page == NULL || zathura_page_get_visibility(page) == false) {
      continue;
    }

    GtkWidget* page_widget = zathura_page_get_widget(zathura, page);
    g_object_set(page_widget, "draw-links", FALSE, NULL);

    if (eval == true) {
      zathura_link_t* link = zathura_page_widget_link_get(ZATHURA_PAGE(page_widget), index);
      if (link != NULL) {
        zathura_link_evaluate(zathura, link);
        invalid_index = false;
      }
    }
  }

  if (eval == true && invalid_index == true) {
    girara_notify(session, GIRARA_WARNING, _("Invalid index '%s' given."), input);
  }

  g_free(input);

  return (eval == TRUE) ? TRUE : FALSE;
}
Beispiel #2
0
void
document_draw_search_results(zathura_t* zathura, bool value)
{
  if (zathura == NULL || zathura->document == NULL || zathura->pages == NULL) {
    return;
  }

  unsigned int number_of_pages = zathura_document_get_number_of_pages(zathura->document);
  for (unsigned int page_id = 0; page_id < number_of_pages; page_id++) {
    g_object_set(zathura->pages[page_id], "draw-search-results", (value == true) ? TRUE : FALSE, NULL);
  }
}
Beispiel #3
0
void
print(zathura_t* zathura)
{
  g_return_if_fail(zathura           != NULL);
  g_return_if_fail(zathura->document != NULL);

  GtkPrintOperation* print_operation = gtk_print_operation_new();

  /* print operation settings */
  gtk_print_operation_set_job_name(print_operation, zathura_document_get_path(zathura->document));
  gtk_print_operation_set_allow_async(print_operation, TRUE);
  gtk_print_operation_set_n_pages(print_operation, zathura_document_get_number_of_pages(zathura->document));
  gtk_print_operation_set_current_page(print_operation, zathura_document_get_current_page_number(zathura->document));
  gtk_print_operation_set_use_full_page(print_operation, TRUE);

  if (zathura->print.settings != NULL) {
    gtk_print_operation_set_print_settings(print_operation,
                                           zathura->print.settings);
  }

  if (zathura->print.page_setup != NULL) {
    gtk_print_operation_set_default_page_setup(print_operation,
                                               zathura->print.page_setup);
  }
  gtk_print_operation_set_embed_page_setup(print_operation, TRUE);

  /* print operation signals */
  g_signal_connect(print_operation, "draw-page",          G_CALLBACK(cb_print_draw_page),          zathura);
  g_signal_connect(print_operation, "end-print",          G_CALLBACK(cb_print_end),                zathura);
  g_signal_connect(print_operation, "request-page-setup", G_CALLBACK(cb_print_request_page_setup), zathura);

  /* print */
  GError* error = NULL;
  GtkPrintOperationResult result = gtk_print_operation_run(print_operation,
                                   GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
                                   GTK_WINDOW(zathura->ui.session->gtk.window), &error);

  if (result == GTK_PRINT_OPERATION_RESULT_ERROR) {
    girara_notify(zathura->ui.session, GIRARA_ERROR, _("Printing failed: %s"),
                  error->message);
    g_error_free(error);
  } else if (result == GTK_PRINT_OPERATION_RESULT_APPLY) {
    g_clear_object(&zathura->print.settings);
    g_clear_object(&zathura->print.page_setup);

    /* save previous settings */
    zathura->print.settings   = g_object_ref(gtk_print_operation_get_print_settings(print_operation));
    zathura->print.page_setup = g_object_ref(gtk_print_operation_get_default_page_setup(print_operation));
  }

  g_object_unref(print_operation);
}
Beispiel #4
0
bool
sc_navigate(girara_session_t* session, girara_argument_t* argument,
            girara_event_t* UNUSED(event), unsigned int t)
{
  g_return_val_if_fail(session != NULL, false);
  g_return_val_if_fail(session->global.data != NULL, false);
  zathura_t* zathura = session->global.data;
  g_return_val_if_fail(argument != NULL, false);
  g_return_val_if_fail(zathura->document != NULL, false);

  int number_of_pages = zathura_document_get_number_of_pages(zathura->document);
  int new_page        = zathura_document_get_current_page_number(zathura->document);

  bool scroll_wrap = false;
  girara_setting_get(session, "scroll-wrap", &scroll_wrap);

  bool columns_per_row_offset = false;
  girara_setting_get(session, "advance-pages-per-row", &columns_per_row_offset);

  int offset = 1;
  if (columns_per_row_offset == true) {
    girara_setting_get(session, "pages-per-row", &offset);
  }

  t = (t == 0) ? (unsigned int) offset : t;
  if (argument->n == NEXT) {
    if (scroll_wrap == false) {
      new_page = new_page + t;
    } else {
      new_page = (new_page + t) % number_of_pages;
    }
  } else if (argument->n == PREVIOUS) {
    if (scroll_wrap == false) {
      new_page = new_page - t;
    } else {
      new_page = (new_page + number_of_pages - t) % number_of_pages;
    }
  }

  if (!scroll_wrap) {
    if (new_page <= 0) {
      new_page = 0;
    } else if (new_page >= number_of_pages) {
      new_page = number_of_pages - 1;
    }
  }

  page_set(zathura, new_page);

  return false;
}
Beispiel #5
0
bool
sc_navigate(girara_session_t* session, girara_argument_t* argument,
            girara_event_t* UNUSED(event), unsigned int t)
{
  g_return_val_if_fail(session != NULL, false);
  g_return_val_if_fail(session->global.data != NULL, false);
  zathura_t* zathura = session->global.data;
  g_return_val_if_fail(argument != NULL, false);
  g_return_val_if_fail(zathura->document != NULL, false);

  int number_of_pages = zathura_document_get_number_of_pages(zathura->document);
  int new_page        = zathura_document_get_current_page_number(zathura->document);

  bool scroll_wrap = false;
  girara_setting_get(session, "scroll-wrap", &scroll_wrap);

  bool columns_per_row_offset = false;
  girara_setting_get(session, "advance-pages-per-row", &columns_per_row_offset);

  int offset = 1;
  if (columns_per_row_offset == true) {
    girara_setting_get(session, "pages-per-row", &offset);
  }

  t = (t == 0) ? (unsigned int) offset : t;
  if (argument->n == NEXT) {
    if (scroll_wrap == false) {
      new_page = new_page + t;
    } else {
      new_page = (new_page + t) % number_of_pages;
    }
  } else if (argument->n == PREVIOUS) {
    if (scroll_wrap == false) {
      new_page = new_page - t;
    } else {
      new_page = (new_page + number_of_pages - t) % number_of_pages;
    }
  }

  if ((new_page < 0 || new_page >= number_of_pages) && !scroll_wrap) {
    return false;
  }

  page_set(zathura, new_page);

  /* adjust horizontal position */
  GtkAdjustment* hadjustment = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(session->gtk.view));
  cb_view_hadjustment_changed(hadjustment, zathura);

  return false;
}
Beispiel #6
0
void
zathura_document_get_document_size(zathura_document_t* document,
                                   unsigned int* height, unsigned int* width)
{
  g_return_if_fail(document != NULL && height != NULL && width != NULL);

  const unsigned int npag  = zathura_document_get_number_of_pages(document);
  const unsigned int ncol  = zathura_document_get_pages_per_row(document);
  const unsigned int c0    = zathura_document_get_first_page_column(document);
  const unsigned int nrow  = (npag + c0 - 1 + ncol - 1) / ncol;  /* number of rows */
  const unsigned int pad   = zathura_document_get_page_padding(document);

  unsigned int cell_height = 0;
  unsigned int cell_width  = 0;
  zathura_document_get_cell_size(document, &cell_height, &cell_width);

  *width  = ncol * cell_width + (ncol - 1) * pad;
  *height = nrow * cell_height + (nrow - 1) * pad;
}
Beispiel #7
0
bool
synctex_view(zathura_t* zathura, const char* input_file,
             unsigned int line, unsigned int column)
{
  if (zathura == NULL || input_file == NULL) {
    return false;
  }

  const unsigned int number_of_pages = zathura_document_get_number_of_pages(zathura->document);

  unsigned int page = 0;
  girara_list_t* secondary_rects = NULL;
  girara_list_t* rectangles = synctex_rectangles_from_position(
    zathura_document_get_path(zathura->document), input_file, line,
    column, &page, &secondary_rects);

  if (rectangles == NULL) {
    return false;
  }

  girara_list_t** all_rectangles = g_try_malloc0(number_of_pages * sizeof(girara_list_t*));
  if (all_rectangles == NULL) {
    girara_list_free(rectangles);
    return false;
  }

  for (unsigned int p = 0; p != number_of_pages; ++p) {
    if (p == page) {
      all_rectangles[p] = rectangles;
    } else {
      all_rectangles[p] = girara_list_new2(g_free);
    }
  }

  if (secondary_rects != NULL) {
    GIRARA_LIST_FOREACH(secondary_rects, synctex_page_rect_t*, iter, rect)
      zathura_rectangle_t* newrect = g_try_malloc0(sizeof(zathura_rectangle_t));
      if (newrect != NULL) {
        *newrect = rect->rect;
        girara_list_append(all_rectangles[rect->page], newrect);
      }
    GIRARA_LIST_FOREACH_END(secondary_rects, synctex_page_rect_t*, iter, rect);
  }
Beispiel #8
0
void
render_all(zathura_t* zathura)
{
  if (zathura == NULL || zathura->document == NULL) {
    return;
  }

  /* unmark all pages */
  unsigned int number_of_pages = zathura_document_get_number_of_pages(zathura->document);
  for (unsigned int page_id = 0; page_id < number_of_pages; page_id++) {
    zathura_page_t* page = zathura_document_get_page(zathura->document, page_id);
    unsigned int page_height = 0, page_width = 0;
    page_calc_height_width(page, &page_height, &page_width, true);

    GtkWidget* widget = zathura_page_get_widget(zathura, page);
    gtk_widget_set_size_request(widget, page_width, page_height);
    gtk_widget_queue_resize(widget);
  }
}
Beispiel #9
0
void
page_number_to_position(zathura_document_t* document, unsigned int page_number,
                        double xalign, double yalign, double* pos_x,
                        double* pos_y)
{
  g_return_if_fail(document != NULL);

  unsigned int c0   = zathura_document_get_first_page_column(document);
  unsigned int npag = zathura_document_get_number_of_pages(document);
  unsigned int ncol = zathura_document_get_pages_per_row(document);
  unsigned int nrow = (npag + c0 - 1 + ncol - 1) / ncol;   /* number of rows */

  /* row and column for page_number indexed from 0 */
  unsigned int row  = (page_number + c0 - 1) / ncol;
  unsigned int col  = (page_number + c0 - 1) % ncol;

  /* sizes of page cell, viewport and document */
  unsigned int cell_height = 0, cell_width = 0;
  zathura_document_get_cell_size(document, &cell_height, &cell_width);

  unsigned int view_height = 0, view_width = 0;
  zathura_document_get_viewport_size(document, &view_height, &view_width);

  unsigned int doc_height = 0, doc_width = 0;
  zathura_document_get_document_size(document, &doc_height, &doc_width);

  /* compute the shift to align to the viewport. If the page fits to viewport, just center it. */
  double shift_x = 0.5, shift_y = 0.5;
  if (cell_width > view_width) {
    shift_x = 0.5 + (xalign - 0.5) * ((double)cell_width - (double)view_width) / (double)cell_width;
  }

  if (cell_height > view_height) {
    shift_y = 0.5 + (yalign - 0.5) * ((double)cell_height - (double)view_height) / (double)cell_height;
  }

  /* compute the position */
  *pos_x = ((double)col + shift_x) / (double)ncol;
  *pos_y = ((double)row + shift_y) / (double)nrow;
}
Beispiel #10
0
unsigned int
position_to_page_number(zathura_document_t* document, double pos_x,
                        double pos_y)
{
  g_return_val_if_fail(document != NULL, 0);

  unsigned int doc_width, doc_height;
  zathura_document_get_document_size(document, &doc_height, &doc_width);

  unsigned int cell_width, cell_height;
  zathura_document_get_cell_size(document, &cell_height, &cell_width);

  unsigned int c0   = zathura_document_get_first_page_column(document);
  unsigned int npag = zathura_document_get_number_of_pages(document);
  unsigned int ncol = zathura_document_get_pages_per_row(document);
  unsigned int nrow = 0;
  unsigned int pad  = zathura_document_get_page_padding(document);

  if (c0 == 1) {
    /* There is no offset, so this is easy. */
    nrow = (npag + ncol - 1) / ncol;
  } else {
    /* If there is a offset, we handle the first row extra. */
    nrow = 1 + (npag - (ncol - c0 - 1) + (ncol - 1)) / ncol;
  }

  unsigned int col = floor(pos_x * (double)doc_width  / (double)(cell_width + pad));
  unsigned int row = floor(pos_y * (double)doc_height / (double)(cell_height + pad));

  unsigned int page = ncol * (row % nrow) + (col % ncol);
  if (page < c0 - 1) {
    return 0;
  } else {
    return MIN(page - (c0 - 1), npag - 1);
  }
}
Beispiel #11
0
void
zathura_get_document_size(zathura_t* zathura,
                          unsigned int cell_height, unsigned int cell_width,
                          unsigned int* height, unsigned int* width)
{
  g_return_if_fail(zathura != NULL && zathura->document != NULL &&
                   height != NULL && width != NULL);

  unsigned int pages_per_row = 1;
  girara_setting_get(zathura->ui.session, "pages-per-row", &pages_per_row);
  if (pages_per_row == 0)
    pages_per_row = 1;

  unsigned int first_page_column = 1;
  girara_setting_get(zathura->ui.session, "first-page-column", &first_page_column);
  if (first_page_column < 1)
    first_page_column = 1;
  if (first_page_column > pages_per_row)
    first_page_column = (first_page_column - 1) % pages_per_row + 1;

  int padding = 1;
  girara_setting_get(zathura->ui.session, "page-padding", &padding);

  double scale = zathura_document_get_scale(zathura->document);

  cell_height = ceil(cell_height * scale);
  cell_width  = ceil(cell_width * scale);

  *width = pages_per_row * cell_width + (pages_per_row - 1) * padding;
  unsigned int effective_number_of_pages =
    zathura_document_get_number_of_pages(zathura->document) +
    first_page_column - 1;
  unsigned int rows = effective_number_of_pages / pages_per_row +
                     (effective_number_of_pages % pages_per_row ? 1 : 0);
  *height = rows * cell_height + (rows - 1) * padding;
}
Beispiel #12
0
void
update_visible_pages(zathura_t* zathura)
{
  const unsigned int number_of_pages = zathura_document_get_number_of_pages(zathura->document);

  for (unsigned int page_id = 0; page_id < number_of_pages; page_id++) {
    zathura_page_t* page = zathura_document_get_page(zathura->document, page_id);
    GtkWidget* page_widget = zathura_page_get_widget(zathura, page);
    ZathuraPage* zathura_page_widget = ZATHURA_PAGE(page_widget);

    if (page_is_visible(zathura->document, page_id) == true) {
      /* make page visible */
      if (zathura_page_get_visibility(page) == false) {
        zathura_page_set_visibility(page, true);
        zathura_page_widget_update_view_time(zathura_page_widget);
        zathura_renderer_page_cache_add(zathura->sync.render_thread, zathura_page_get_index(page));
      }

    } else {
      /* make page invisible */
      if (zathura_page_get_visibility(page) == true) {
        zathura_page_set_visibility(page, false);
        /* If a page becomes invisible, abort the render request. */
        zathura_page_widget_abort_render_request(zathura_page_widget);
      }

      /* reset current search result */
      girara_list_t* results = NULL;
      GObject* obj_page_widget = G_OBJECT(page_widget);
      g_object_get(obj_page_widget, "search-results", &results, NULL);
      if (results != NULL) {
        g_object_set(obj_page_widget, "search-current", 0, NULL);
      }
    }
  }
}
Beispiel #13
0
bool
sc_abort(girara_session_t* session, girara_argument_t* UNUSED(argument),
         girara_event_t* UNUSED(event), unsigned int UNUSED(t))
{
  g_return_val_if_fail(session != NULL, false);
  g_return_val_if_fail(session->global.data != NULL, false);
  zathura_t* zathura = session->global.data;

  bool clear_search = true;
  girara_setting_get(session, "abort-clear-search", &clear_search);

  if (zathura->document != NULL) {
    const unsigned int number_of_pages = zathura_document_get_number_of_pages(zathura->document);
    for (unsigned int page_id = 0; page_id < number_of_pages; ++page_id) {
      zathura_page_t* page = zathura_document_get_page(zathura->document, page_id);
      if (page == NULL) {
        continue;
      }

      GtkWidget* page_widget = zathura_page_get_widget(zathura, page);
      GObject* obj_page_widget = G_OBJECT(page_widget);
      g_object_set(obj_page_widget, "draw-links", FALSE, NULL);
      if (clear_search == true) {
        g_object_set(obj_page_widget, "draw-search-results", FALSE, NULL);
      }
    }
  }

  /* Setting the mode back here has not worked for ages. We need another way to
   * do this. Let's disable this for now.
   */
  /* girara_mode_set(session, session->modes.normal); */
  girara_sc_abort(session, NULL, NULL, 0);

  return false;
}
Beispiel #14
0
bool
sc_search(girara_session_t* session, girara_argument_t* argument,
          girara_event_t* UNUSED(event), unsigned int UNUSED(t))
{
  g_return_val_if_fail(session != NULL, false);
  g_return_val_if_fail(session->global.data != NULL, false);
  zathura_t* zathura = session->global.data;
  g_return_val_if_fail(argument != NULL, false);
  g_return_val_if_fail(zathura->document != NULL, false);

  const unsigned int num_pages = zathura_document_get_number_of_pages(zathura->document);
  const unsigned int cur_page  = zathura_document_get_current_page_number(zathura->document);
  GtkWidget *cur_page_widget = zathura_page_get_widget(zathura, zathura_document_get_page(zathura->document, cur_page));
  bool nohlsearch, first_time_after_abort;
  gboolean draw;

  nohlsearch = first_time_after_abort = false;
  draw = FALSE;
  girara_setting_get(session, "nohlsearch", &nohlsearch);

  if (nohlsearch == false) {
    g_object_get(G_OBJECT(cur_page_widget), "draw-search-results", &draw, NULL);

    if (draw == false) {
      first_time_after_abort = true;
    }

    document_draw_search_results(zathura, true);
  }

  int diff = argument->n == FORWARD ? 1 : -1;
  if (zathura->global.search_direction == BACKWARD)
    diff = -diff;

  zathura_page_t* target_page = NULL;
  int target_idx = 0;

  for (unsigned int page_id = 0; page_id < num_pages; ++page_id) {
    int tmp = cur_page + diff * page_id;
    zathura_page_t* page = zathura_document_get_page(zathura->document, (tmp + num_pages) % num_pages);
    if (page == NULL) {
      continue;
    }

    GtkWidget* page_widget = zathura_page_get_widget(zathura, page);

    int num_search_results = 0, current = -1;
    g_object_get(G_OBJECT(page_widget), "search-current", &current, "search-length", &num_search_results, NULL);
    if (num_search_results == 0 || current == -1) {
      continue;
    }

    if (first_time_after_abort == true || (tmp + num_pages) % num_pages != cur_page) {
      target_page = page;
      target_idx = diff == 1 ? 0 : num_search_results - 1;
      break;
    }

    if (diff == 1 && current < num_search_results - 1) {
      /* the next result is on the same page */
      target_page = page;
      target_idx = current + 1;
    } else if (diff == -1 && current > 0) {
      target_page = page;
      target_idx = current - 1;
    } else {
      /* the next result is on a different page */
      g_object_set(G_OBJECT(page_widget), "search-current", -1, NULL);

      for (int npage_id = 1; page_id < num_pages; ++npage_id) {
        int ntmp = cur_page + diff * (page_id + npage_id);
        zathura_page_t* npage = zathura_document_get_page(zathura->document, (ntmp + 2*num_pages) % num_pages);
        GtkWidget* npage_page_widget = zathura_page_get_widget(zathura, npage);
        g_object_get(G_OBJECT(npage_page_widget), "search-length", &num_search_results, NULL);
        if (num_search_results != 0) {
          target_page = npage;
          target_idx = diff == 1 ? 0 : num_search_results - 1;
          break;
        }
      }
    }

    break;
  }

  if (target_page != NULL) {
    girara_list_t* results = NULL;
    GtkWidget* page_widget = zathura_page_get_widget(zathura, target_page);
    GObject* obj_page_widget = G_OBJECT(page_widget);
    g_object_set(obj_page_widget, "search-current", target_idx, NULL);
    g_object_get(obj_page_widget, "search-results", &results, NULL);

    /* Need to adjust rectangle to page scale and orientation */
    zathura_rectangle_t* rect = girara_list_nth(results, target_idx);
    zathura_rectangle_t rectangle = recalc_rectangle(target_page, *rect);

    bool search_hadjust = true;
    girara_setting_get(session, "search-hadjust", &search_hadjust);

    /* compute the position of the center of the page */
    double pos_x = 0;
    double pos_y = 0;
    page_number_to_position(zathura->document, zathura_page_get_index(target_page),
                            0.5, 0.5, &pos_x, &pos_y);

    /* correction to center the current result                          */
    /* NOTE: rectangle is in viewport units, already scaled and rotated */
    unsigned int cell_height = 0;
    unsigned int cell_width = 0;
    zathura_document_get_cell_size(zathura->document, &cell_height, &cell_width);

    unsigned int doc_height = 0;
    unsigned int doc_width = 0;
    zathura_document_get_document_size(zathura->document, &doc_height, &doc_width);

    /* compute the center of the rectangle, which will be aligned to the center
       of the viewport */
    double center_x = (rectangle.x1 + rectangle.x2) / 2;
    double center_y = (rectangle.y1 + rectangle.y2) / 2;

    pos_y += (center_y - (double)cell_height/2) / (double)doc_height;
    if (search_hadjust == true) {
      pos_x += (center_x - (double)cell_width/2) / (double)doc_width;
    }

    /* move to position */
    zathura_jumplist_add(zathura);
    position_set(zathura, pos_x, pos_y);
    zathura_jumplist_add(zathura);
  }

  return false;
}
Beispiel #15
0
bool
sc_bisect(girara_session_t* session, girara_argument_t* argument,
          girara_event_t* UNUSED(event), unsigned int t)
{
  g_return_val_if_fail(session != NULL, false);
  g_return_val_if_fail(session->global.data != NULL, false);
  zathura_t* zathura = session->global.data;
  g_return_val_if_fail(argument != NULL, false);
  g_return_val_if_fail(zathura->document != NULL, false);

  const unsigned int num_pages = zathura_document_get_number_of_pages(zathura->document);
  const unsigned int cur_page = zathura_document_get_current_page_number(zathura->document);

  /* process arguments */
  int direction;
  if (t > 0 && t <= num_pages) {
    /* bisect between cur_page and t */
    t -= 1;
    if (t == cur_page) {
      /* nothing to do */
      return false;
    }
    else if (t > cur_page) {
      zathura->bisect.start = cur_page;
      zathura->bisect.end = t;
      direction = BACKWARD;
    } else {
      zathura->bisect.start = t;
      zathura->bisect.end = cur_page;
      direction = FORWARD;
    }
  } else if (argument != NULL)  {
    direction = argument->n;

    /* setup initial bisect range */
    zathura_jump_t* jump = zathura_jumplist_current(zathura);
    if (jump == NULL) {
      girara_debug("bisecting between first and last page because there are no jumps");
      zathura->bisect.start = 0;
      zathura->bisect.end = num_pages - 1;

    } else if (jump->page != cur_page || jump->page != zathura->bisect.last_jump) {
      girara_debug("last jump doesn't match up, starting new bisecting");
      zathura->bisect.start = 0;
      zathura->bisect.end = num_pages - 1;

      unsigned int prev_page;
      if (direction == FORWARD) {
        prev_page = num_pages - 1;
      } else {
        prev_page = 0;
      }

      /* check if we have previous jumps */
      if (zathura_jumplist_has_previous(zathura) == true) {
        zathura_jumplist_backward(zathura);
        jump = zathura_jumplist_current(zathura);
        if (jump != NULL) {
          prev_page = jump->page;
        }
        zathura_jumplist_forward(zathura);
      }

      zathura->bisect.start = MIN(prev_page, cur_page);
      zathura->bisect.end = MAX(prev_page, cur_page);
      zathura->bisect.last_jump = cur_page;
    }
  } else {
    return false;
  }

  girara_debug("bisecting between %d and %d, at %d", zathura->bisect.start, zathura->bisect.end, cur_page);
  if (zathura->bisect.start == zathura->bisect.end) {
    /* nothing to do */
    return false;
  }

  unsigned int next_page = cur_page;
  unsigned int next_start = zathura->bisect.start;
  unsigned int next_end = zathura->bisect.end;

  /* here we have next_start <= next_page <= next_end */

  /* bisect step */
  switch(direction) {
    case FORWARD:
      if (cur_page != zathura->bisect.end) {
        next_page = (cur_page + zathura->bisect.end) / 2;
        if (next_page == cur_page) {
          ++next_page;
        }
        next_start = cur_page;
      }
      break;

    case BACKWARD:
      if (cur_page != zathura->bisect.start) {
        next_page = (cur_page + zathura->bisect.start) / 2;
        if (next_page == cur_page) {
          --next_page;
        }
        next_end = cur_page;
      }
      break;
  }

  if (next_page == cur_page) {
    /* nothing to do */
    return false;
  }

  girara_debug("bisecting between %d and %d, jumping to %d", zathura->bisect.start, zathura->bisect.end, next_page);
  zathura->bisect.last_jump = next_page;
  zathura->bisect.start = next_start;
  zathura->bisect.end = next_end;

  zathura_jumplist_add(zathura);
  page_set(zathura, next_page);
  zathura_jumplist_add(zathura);

  return false;
}
Beispiel #16
0
void
synctex_highlight_rects(zathura_t* zathura, unsigned int page,
                        girara_list_t** rectangles)
{
  const unsigned int number_of_pages = zathura_document_get_number_of_pages(zathura->document);

  for (unsigned int p = 0; p != number_of_pages; ++p) {
    GObject* widget = G_OBJECT(zathura->pages[p]);

    g_object_set(widget, "draw-links", FALSE, "search-results", rectangles[p],
                 NULL);
    if (p == page) {
      g_object_set(widget, "search-current", 0, NULL);
    }
  }

  document_draw_search_results(zathura, true);

  girara_list_t* rect_list = rectangles[page];
  if (rect_list == NULL || girara_list_size(rect_list) == 0) {
    girara_debug("No rectangles for the given page. Jumping to page %u.", page);
    page_set(zathura, page);
    return;
  }

  bool search_hadjust = true;
  girara_setting_get(zathura->ui.session, "search-hadjust", &search_hadjust);

  /* compute the position of the center of the page */
  double pos_x = 0;
  double pos_y = 0;
  page_number_to_position(zathura->document, page, 0.5, 0.5, &pos_x, &pos_y);

  /* correction to center the current result                          */
  /* NOTE: rectangle is in viewport units, already scaled and rotated */
  unsigned int cell_height = 0;
  unsigned int cell_width = 0;
  zathura_document_get_cell_size(zathura->document, &cell_height, &cell_width);

  unsigned int doc_height = 0;
  unsigned int doc_width = 0;
  zathura_document_get_document_size(zathura->document, &doc_height, &doc_width);

  /* Need to adjust rectangle to page scale and orientation */
  zathura_page_t* doc_page = zathura_document_get_page(zathura->document, page);
  zathura_rectangle_t* rect = girara_list_nth(rect_list, 0);
  if (rect == NULL) {
    girara_debug("List of rectangles is broken. Jumping to page %u.", page);
    page_set(zathura, page);
    return;
  }

  zathura_rectangle_t rectangle = recalc_rectangle(doc_page, *rect);

  /* compute the center of the rectangle, which will be aligned to the center
     of the viewport */
  double center_x = (rectangle.x1 + rectangle.x2) / 2;
  double center_y = (rectangle.y1 + rectangle.y2) / 2;

  pos_y += (center_y - (double)cell_height/2) / (double)doc_height;
  if (search_hadjust == true) {
    pos_x += (center_x - (double)cell_width/2) / (double)doc_width;
  }

  /* move to position */
  girara_debug("Jumping to page %u position (%f, %f).", page, pos_x, pos_y);
  zathura_jumplist_add(zathura);
  position_set(zathura, pos_x, pos_y);
  zathura_jumplist_add(zathura);
}
Beispiel #17
0
void
cb_view_vadjustment_value_changed(GtkAdjustment* GIRARA_UNUSED(adjustment), gpointer data)
{
  zathura_t* zathura = data;
  if (zathura == NULL || zathura->document == NULL || zathura->ui.page_widget == NULL) {
    return;
  }

  GtkAdjustment* view_vadjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view));
  GtkAdjustment* view_hadjustment = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view));

  /* current adjustment values */
  GdkRectangle view_rect = {
    .x      = 0,
    .y      = 0,
    .width  = gtk_adjustment_get_page_size(view_hadjustment),
    .height = gtk_adjustment_get_page_size(view_vadjustment)
  };

  int page_padding = 1;
  girara_setting_get(zathura->ui.session, "page-padding", &page_padding);

  GdkRectangle center = {
    .x      = (view_rect.width  + 1) / 2,
    .y      = (view_rect.height + 1) / 2,
    .width  = (2 * page_padding) + 1,
    .height = (2 * page_padding) + 1
  };

  unsigned int number_of_pages = zathura_document_get_number_of_pages(zathura->document);
  double scale = zathura_document_get_scale(zathura->document);

  bool updated = false;
  /* find page that fits */
  for (unsigned int page_id = 0; page_id < number_of_pages; page_id++) {
    zathura_page_t* page = zathura_document_get_page(zathura->document, page_id);

    GdkRectangle page_rect = {
      .width  = zathura_page_get_width(page)  * scale,
      .height = zathura_page_get_height(page) * scale
    };
    GtkWidget* page_widget = zathura_page_get_widget(zathura, page);
    gtk_widget_translate_coordinates(page_widget,
                                     zathura->ui.session->gtk.view, 0, 0, &page_rect.x, &page_rect.y);

    if (gdk_rectangle_intersect(&view_rect, &page_rect, NULL) == TRUE) {
      zathura_page_set_visibility(page, true);
      if (zathura->global.update_page_number == true && updated == false
          && gdk_rectangle_intersect(&center, &page_rect, NULL) == TRUE) {
        zathura_document_set_current_page_number(zathura->document, page_id);
        updated = true;
      }
    } else {
      zathura_page_set_visibility(page, false);
    }
    zathura_page_widget_update_view_time(ZATHURA_PAGE(page_widget));
  }

  statusbar_page_number_update(zathura);
}

void
cb_pages_per_row_value_changed(girara_session_t* session, const char* UNUSED(name), girara_setting_type_t UNUSED(type), void* value, void* UNUSED(data))
{
  g_return_if_fail(value != NULL);
  g_return_if_fail(session != NULL);
  g_return_if_fail(session->global.data != NULL);
  zathura_t* zathura = session->global.data;

  int pages_per_row = *(int*) value;

  if (pages_per_row < 1) {
    pages_per_row = 1;
  }

  unsigned int first_page_column = 1;
  girara_setting_get(session, "first-page-column", &first_page_column);

  page_widget_set_mode(zathura, pages_per_row, first_page_column);

  if (zathura->document != NULL) {
    unsigned int current_page = zathura_document_get_current_page_number(zathura->document);
    page_set_delayed(zathura, current_page);
  }
}
Beispiel #18
0
bool
sc_search(girara_session_t* session, girara_argument_t* argument,
          girara_event_t* UNUSED(event), unsigned int UNUSED(t))
{
  g_return_val_if_fail(session != NULL, false);
  g_return_val_if_fail(session->global.data != NULL, false);
  zathura_t* zathura = session->global.data;
  g_return_val_if_fail(argument != NULL, false);
  g_return_val_if_fail(zathura->document != NULL, false);

  const int num_pages = zathura_document_get_number_of_pages(zathura->document);
  const int cur_page  = zathura_document_get_current_page_number(zathura->document);

  int diff = argument->n == FORWARD ? 1 : -1;
  if (zathura->global.search_direction == BACKWARD)
    diff = -diff;

  zathura_page_t* target_page = NULL;
  int target_idx = 0;

  for (int page_id = 0; page_id < num_pages; ++page_id) {
    int tmp = cur_page + diff * page_id;
    zathura_page_t* page = zathura_document_get_page(zathura->document, (tmp + num_pages) % num_pages);
    if (page == NULL) {
      continue;
    }

    GtkWidget* page_widget = zathura_page_get_widget(zathura, page);

    int num_search_results = 0, current = -1;
    g_object_get(page_widget, "search-current", &current,
                 "search-length", &num_search_results, NULL);
    if (num_search_results == 0 || current == -1) {
      continue;
    }

    if (diff == 1 && current < num_search_results - 1) {
      /* the next result is on the same page */
      target_page = page;
      target_idx = current + 1;
    } else if (diff == -1 && current > 0) {
      target_page = page;
      target_idx = current - 1;
    } else {
      /* the next result is on a different page */
      zathura_jumplist_save(zathura);

      g_object_set(page_widget, "search-current", -1, NULL);

      for (int npage_id = 1; page_id < num_pages; ++npage_id) {
        int ntmp = cur_page + diff * (page_id + npage_id);
        zathura_page_t* npage = zathura_document_get_page(zathura->document, (ntmp + 2*num_pages) % num_pages);
        zathura_document_set_current_page_number(zathura->document, zathura_page_get_index(npage));
        GtkWidget* npage_page_widget = zathura_page_get_widget(zathura, npage);
        g_object_get(npage_page_widget, "search-length", &num_search_results, NULL);
        if (num_search_results != 0) {
          target_page = npage;
          target_idx = diff == 1 ? 0 : num_search_results - 1;
          break;
        }
      }

      zathura_jumplist_add(zathura);
    }

    break;
  }

  if (target_page != NULL) {
    girara_list_t* results = NULL;
    GtkWidget* page_widget = zathura_page_get_widget(zathura, target_page);
    g_object_set(page_widget, "search-current", target_idx, NULL);
    g_object_get(page_widget, "search-results", &results, NULL);

    zathura_rectangle_t* rect = girara_list_nth(results, target_idx);
    zathura_rectangle_t rectangle = recalc_rectangle(target_page, *rect);
    page_offset_t offset;
    page_calculate_offset(zathura, target_page, &offset);

    GtkAdjustment* view_vadjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view));
    int y = offset.y - gtk_adjustment_get_page_size(view_vadjustment) / 2 + rectangle.y1;
    set_adjustment(view_vadjustment, y);

    bool search_hadjust = true;
    girara_setting_get(session, "search-hadjust", &search_hadjust);
    if (search_hadjust == true) {
      GtkAdjustment* view_hadjustment = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view));
      int x = offset.x - gtk_adjustment_get_page_size(view_hadjustment) / 2 + rectangle.x1;
      set_adjustment(view_hadjustment, x);
    }
  }

  return false;
}
Beispiel #19
0
bool
cmd_search(girara_session_t* session, const char* input, girara_argument_t* argument)
{
  g_return_val_if_fail(session != NULL, false);
  g_return_val_if_fail(input != NULL, false);
  g_return_val_if_fail(argument != NULL, false);
  g_return_val_if_fail(session->global.data != NULL, false);
  zathura_t* zathura = session->global.data;

  if (zathura->document == NULL || strlen(input) == 0) {
    return false;
  }

  zathura_error_t error = ZATHURA_ERROR_OK;

  /* set search direction */
  zathura->global.search_direction = argument->n;

  unsigned int number_of_pages     = zathura_document_get_number_of_pages(zathura->document);
  unsigned int current_page_number = zathura_document_get_current_page_number(zathura->document);

  /* reset search highlighting */
  bool nohlsearch = false;
  girara_setting_get(session, "nohlsearch", &nohlsearch);

  /* search pages */
  for (unsigned int page_id = 0; page_id < number_of_pages; ++page_id) {
    unsigned int index = (page_id + current_page_number) % number_of_pages;
    zathura_page_t* page = zathura_document_get_page(zathura->document, index);
    if (page == NULL) {
      continue;
    }

    GtkWidget* page_widget = zathura_page_get_widget(zathura, page);
    g_object_set(page_widget, "draw-links", FALSE, NULL);

    zathura_renderer_lock(zathura->sync.render_thread);
    girara_list_t* result = zathura_page_search_text(page, input, &error);
    zathura_renderer_unlock(zathura->sync.render_thread);

    if (result == NULL || girara_list_size(result) == 0) {
      girara_list_free(result);
      g_object_set(page_widget, "search-results", NULL, NULL);

      if (error == ZATHURA_ERROR_NOT_IMPLEMENTED) {
        break;
      } else {
        continue;
      }
    }

    g_object_set(page_widget, "search-results", result, NULL);

    if (argument->n == BACKWARD) {
      /* start at bottom hit in page */
      g_object_set(page_widget, "search-current", girara_list_size(result) - 1, NULL);
    } else {
      g_object_set(page_widget, "search-current", 0, NULL);
    }
  }

  girara_argument_t* arg = g_try_malloc0(sizeof(girara_argument_t));
  if (arg == NULL) {
    return false;
  }

  arg->n = FORWARD;
  sc_search(session, arg, NULL, 0);
  g_free(arg);

  return true;
}
Beispiel #20
0
bool
sc_bisect(girara_session_t* session, girara_argument_t* argument,
          girara_event_t* UNUSED(event), unsigned int t)
{
  g_return_val_if_fail(session != NULL, false);
  g_return_val_if_fail(session->global.data != NULL, false);
  zathura_t* zathura = session->global.data;
  g_return_val_if_fail(argument != NULL, false);
  g_return_val_if_fail(zathura->document != NULL, false);

  unsigned int number_of_pages, cur_page, prev_page, prev2_page;
  bool have_prev, have_prev2;

  zathura_jump_t* prev_jump = NULL;
  zathura_jump_t* prev2_jump = NULL;

  number_of_pages= zathura_document_get_number_of_pages(zathura->document);
  cur_page = zathura_document_get_current_page_number(zathura->document);

  prev_page = prev2_page = 0;
  have_prev = have_prev2 = false;

  /* save position at current jump point */
  zathura_jumplist_save(zathura);

  /* process arguments */
  int direction;
  if (t > 0 && t <= number_of_pages) {
    /* jump to page t, and bisect between cur_page and t */
    page_set(zathura, t-1);
    zathura_jumplist_add(zathura);
    if (t-1 > cur_page) {
      direction = BACKWARD;
    } else {
      direction = FORWARD;
    }

  } else if (argument != NULL)  {
    direction = argument->n;

  } else {
    return false;
  }

  cur_page = zathura_document_get_current_page_number(zathura->document);

  if (zathura_jumplist_has_previous(zathura)) {
    /* If there is a previous jump, get its page */
    zathura_jumplist_backward(zathura);
    prev_jump = zathura_jumplist_current(zathura);
    if (prev_jump) {
      prev_page = prev_jump->page;
      have_prev = true;
    }

    if (zathura_jumplist_has_previous(zathura)) {
      /* If there is a second previous jump, get its page. */
      zathura_jumplist_backward(zathura);
      prev2_jump = zathura_jumplist_current(zathura);
      if (prev2_jump) {
        prev2_page = prev2_jump->page;
        have_prev2 = true;
      }
      zathura_jumplist_forward(zathura);
    }
    zathura_jumplist_forward(zathura);
  }

  /* now, we are back at the initial jump. prev_page and prev2_page contain
   the pages for previous and second previous jump if they exist. */

  /* bisect */
  switch(direction) {
    case FORWARD:
      if (have_prev && cur_page <= prev_page) {
        /* add a new jump point */
        if (cur_page < prev_page) {
          page_set(zathura, (cur_page + prev_page)/2);
          zathura_jumplist_add(zathura);
        }

      } else if (have_prev2 && cur_page <= prev2_page) {
        /* save current position at previous jump point */
        if (cur_page < prev2_page) {
          zathura_jumplist_backward(zathura);
          zathura_jumplist_save(zathura);
          zathura_jumplist_forward(zathura);

          page_set(zathura, (cur_page + prev2_page)/2);
          zathura_jumplist_save(zathura);
        }
      } else {
        /* none of prev_page or prev2_page comes after cur_page */
        page_set(zathura, (cur_page + number_of_pages - 1)/2);
        zathura_jumplist_add(zathura);
      }
      break;

    case BACKWARD:
      if (have_prev && prev_page <= cur_page) {
        /* add a new jump point */
        if (prev_page < cur_page) {
          page_set(zathura, (cur_page + prev_page)/2);
          zathura_jumplist_add(zathura);
        }

      } else if (have_prev2 && prev2_page <= cur_page) {
        /* save current position at previous jump point */
        if (prev2_page < cur_page) {
          zathura_jumplist_backward(zathura);
          zathura_jumplist_save(zathura);
          zathura_jumplist_forward(zathura);

          page_set(zathura, (cur_page + prev2_page)/2);
          zathura_jumplist_save(zathura);
        }

      } else {
        /* none of prev_page or prev2_page comes before cur_page */
        page_set(zathura, cur_page/2);
        zathura_jumplist_add(zathura);
      }
      break;
  }

  /* adjust horizontal position */
  GtkAdjustment* hadjustment = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(session->gtk.view));
  cb_view_hadjustment_changed(hadjustment, zathura);

  return false;
}