Exemple #1
0
static void
cb_print_draw_page(GtkPrintOperation* print_operation, GtkPrintContext*
                   context, gint page_number, zathura_t* zathura)
{
  if (context == NULL || zathura == NULL || zathura->document == NULL ||
      zathura->ui.session == NULL || zathura->ui.statusbar.file == NULL) {
    gtk_print_operation_cancel(print_operation);
    return;
  }

  /* Update statusbar. */
  char* tmp = g_strdup_printf(_("Printing page %d ..."), page_number);
  girara_statusbar_item_set_text(zathura->ui.session,
                                 zathura->ui.statusbar.file, tmp);
  g_free(tmp);

  /* Get the page and cairo handle.  */
  cairo_t* cairo       = gtk_print_context_get_cairo_context(context);
  zathura_page_t* page = zathura_document_get_page(zathura->document, page_number);
  if (cairo == NULL || page == NULL) {
    gtk_print_operation_cancel(print_operation);
    return;
  }

  girara_debug("printing page %d ...", page_number);
  if (draw_page_cairo(cairo, zathura, page) == true) {
    return;
  }

  girara_debug("printing page %d (fallback) ...", page_number);
  if (draw_page_image(cairo, context, zathura, page) == false) {
    gtk_print_operation_cancel(print_operation);
  }
}
Exemple #2
0
static void
init_database(zathura_t* zathura)
{
  char* database = NULL;
  girara_setting_get(zathura->ui.session, "database", &database);

  if (g_strcmp0(database, "plain") == 0) {
    girara_debug("Using plain database backend.");
    zathura->database = zathura_plaindatabase_new(zathura->config.data_dir);
#ifdef WITH_SQLITE
  } else if (g_strcmp0(database, "sqlite") == 0) {
    girara_debug("Using sqlite database backend.");
    char* tmp =
      g_build_filename(zathura->config.data_dir, "bookmarks.sqlite", NULL);
    zathura->database = zathura_sqldatabase_new(tmp);
    g_free(tmp);
#endif
  } else if (g_strcmp0(database, "null") != 0) {
    girara_error("Database backend '%s' is not supported.", database);
  }

  if (zathura->database == NULL && g_strcmp0(database, "null") != 0) {
    girara_error(
      "Unable to initialize database. Bookmarks won't be available.");
  }
  else {
    g_object_set(G_OBJECT(zathura->ui.session->command_history), "io",
                 zathura->database, NULL);
  }
  g_free(database);
}
Exemple #3
0
static const char*
guess_type_glib(const char* path)
{
  gboolean uncertain = FALSE;
  const char* content_type = g_content_type_guess(path, NULL, 0, &uncertain);
  if (content_type == NULL) {
    girara_debug("g_content_type failed\n");
  } else {
    if (uncertain == FALSE) {
      girara_debug("g_content_type detected filetype: %s", content_type);
      return content_type;
    }
    girara_debug("g_content_type is uncertain, guess: %s", content_type);
  }

  FILE* f = fopen(path, "rb");
  if (f == NULL) {
    return NULL;
  }

  const int fd = fileno(f);
  guchar* content = NULL;
  size_t length = 0u;
  ssize_t bytes_read = -1;
  while (uncertain == TRUE && length < GT_MAX_READ && bytes_read != 0) {
    g_free((void*)content_type);
    content_type = NULL;

    guchar* temp_content = g_try_realloc(content, length + BUFSIZ);
    if (temp_content == NULL) {
      break;
    }
    content = temp_content;

    bytes_read = read(fd, content + length, BUFSIZ);
    if (bytes_read == -1) {
      break;
    }

    length += bytes_read;
    content_type = g_content_type_guess(NULL, content, length, &uncertain);
    girara_debug("new guess: %s uncertain: %d, read: %zu", content_type, uncertain, length);
  }

  fclose(f);
  g_free(content);
  if (uncertain == FALSE) {
    return content_type;
  }

  g_free((void*)content_type);
  return NULL;
}
Exemple #4
0
bool
sc_zoom(girara_session_t* session, girara_argument_t* argument, girara_event_t*
        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);

  zathura_document_set_adjust_mode(zathura->document, ZATHURA_ADJUST_NONE);

  /* retrieve zoom step value */
  int value = 1;
  girara_setting_get(zathura->ui.session, "zoom-step", &value);

  const int nt = (t == 0) ? 1 : t;
  const double zoom_step = 1.0 + value / 100.0 * nt;
  const double old_zoom = zathura_document_get_scale(zathura->document);

  /* specify new zoom value */
  if (argument->n == ZOOM_IN) {
    girara_debug("Increasing zoom by %f.", zoom_step - 1.0);
    zathura_document_set_scale(zathura->document, old_zoom * zoom_step);
  } else if (argument->n == ZOOM_OUT) {
    girara_debug("Decreasing zoom by %f.", zoom_step - 1.0);
    zathura_document_set_scale(zathura->document, old_zoom / zoom_step);
  } else if (argument->n == ZOOM_SPECIFIC) {
    if (t == 0) {
      girara_debug("Setting zoom to 1.");
      zathura_document_set_scale(zathura->document, 1.0);
    } else {
      girara_debug("Setting zoom to %f.", t / 100.0);
      zathura_document_set_scale(zathura->document, t / 100.0);
    }
  } else if (argument->n == ZOOM_SMOOTH) {
    const double dy = (event != NULL) ? event->y : 1.0;
    girara_debug("Increasing zoom by %f.", zoom_step * dy - 1.0);
    zathura_document_set_scale(zathura->document, old_zoom + zoom_step * dy);
  } else {
    girara_debug("Setting zoom to 1.");
    zathura_document_set_scale(zathura->document, 1.0);
  }

  /* zoom limitations */
  const double scale = zathura_document_get_scale(zathura->document);
  zathura_document_set_scale(zathura->document, zathura_correct_scale_value(session, scale));

  const double new_zoom = zathura_document_get_scale(zathura->document);
  if (fabs(new_zoom - old_zoom) <= DBL_EPSILON) {
    girara_debug("New and old zoom level are too close: %f vs. %f, diff = %f", new_zoom, old_zoom, fabs(new_zoom - old_zoom));
    return false;
  }

  girara_debug("Re-rendering with new zoom level %f.", new_zoom);
  render_all(zathura);
  refresh_view(zathura);

  return false;
}
Exemple #5
0
void
cb_widget_screen_changed(GtkWidget* widget, GdkScreen* previous_screen, gpointer data)
{
  girara_debug("called");

  zathura_t* zathura = data;
  if (widget == NULL || zathura == NULL) {
    return;
  }

  /* disconnect previous screen handler if present */
  if (previous_screen != NULL && zathura->signals.monitors_changed_handler > 0) {
    g_signal_handler_disconnect(previous_screen, zathura->signals.monitors_changed_handler);
    zathura->signals.monitors_changed_handler = 0;
  }

  if (gtk_widget_has_screen(widget)) {
    GdkScreen* screen = gtk_widget_get_screen(widget);

    /* connect to new screen */
    zathura->signals.monitors_changed_handler = g_signal_connect(G_OBJECT(screen),
        "monitors-changed", G_CALLBACK(cb_monitors_changed), zathura);
  }

  zathura_update_view_ppi(zathura);
}
Exemple #6
0
} END_TEST

static void
critical_print(const gchar* GIRARA_UNUSED(log_domain), GLogLevelFlags GIRARA_UNUSED(log_level),
               const gchar* message, gpointer GIRARA_UNUSED(user_data))
{
  girara_debug("expected glib critical: %s", message);
}
Exemple #7
0
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;
}
Exemple #8
0
static const char*
guess_type_magic(const char* path) {
  const char* mime_type = NULL;

  /* creat magic cookie */
  const int flags =
    MAGIC_MIME_TYPE |
    MAGIC_SYMLINK |
    MAGIC_NO_CHECK_APPTYPE |
    MAGIC_NO_CHECK_CDF |
    MAGIC_NO_CHECK_ELF |
    MAGIC_NO_CHECK_ENCODING;
  magic_t magic = magic_open(flags);
  if (magic == NULL) {
    girara_debug("failed creating the magic cookie");
    goto cleanup;
  }

  /* ... and load mime database */
  if (magic_load(magic, NULL) < 0) {
    girara_debug("failed loading the magic database: %s", magic_error(magic));
    goto cleanup;
  }

  /* get the mime type */
  mime_type = magic_file(magic, path);
  if (mime_type == NULL) {
    girara_debug("failed guessing filetype: %s", magic_error(magic));
    goto cleanup;
  }
  /* dup so we own the memory */
  mime_type = g_strdup(mime_type);

  girara_debug("magic detected filetype: %s", mime_type);

cleanup:
  if (magic != NULL) {
    magic_close(magic);
  }

  return mime_type;
}
Exemple #9
0
static char*
guess_type_magic(zathura_content_type_context_t* context, const char* path)
{
  if (context == NULL || context->magic == NULL) {
    return NULL;
  }

  const char* mime_type = NULL;

  /* get the mime type */
  mime_type = magic_file(context->magic, path);
  if (mime_type == NULL) {
    girara_debug("failed guessing filetype: %s", magic_error(context->magic));
    return NULL;
  }
  girara_debug("magic detected filetype: %s", mime_type);

  /* dup so we own the memory */
  return g_strdup(mime_type);;
}
Exemple #10
0
void
cb_monitors_changed(GdkScreen* screen, gpointer data)
{
  girara_debug("signal received");

  zathura_t* zathura = data;
  if (screen == NULL || zathura == NULL) {
    return;
  }

  zathura_update_view_ppi(zathura);
}
Exemple #11
0
static void
render_job(void* data, void* user_data)
{
  zathura_page_t* page = data;
  zathura_t* zathura = user_data;
  if (page == NULL || zathura == NULL) {
    return;
  }

  girara_debug("rendering page %d ...", zathura_page_get_index(page));
  if (render(zathura, page) != true) {
    girara_error("Rendering failed (page %d)\n", zathura_page_get_index(page));
  }
}
Exemple #12
0
void
cb_scale_factor(GObject* object, GParamSpec* UNUSED(pspec), gpointer data)
{
  zathura_t* zathura = data;
  if (zathura == NULL || zathura->document == NULL) {
    return;
  }

  int new_factor = gtk_widget_get_scale_factor(GTK_WIDGET(object));
  if (new_factor == 0) {
    girara_debug("Ignoring new device scale factor = 0");
    return;
  }

  zathura_device_factors_t current = zathura_document_get_device_factors(zathura->document);
  if (fabs(new_factor - current.x) >= DBL_EPSILON ||
      fabs(new_factor - current.y) >= DBL_EPSILON) {
    zathura_document_set_device_factors(zathura->document, new_factor, new_factor);
    girara_debug("New device scale factor: %d", new_factor);
    zathura_update_view_ppi(zathura);
    render_all(zathura);
  }
}
Exemple #13
0
void
cb_window_update_icon(ZathuraRenderRequest* GIRARA_UNUSED(request), cairo_surface_t* surface, void* data)
{
  zathura_t* zathura = data;

  girara_debug("updating window icon");
  GdkPixbuf* pixbuf = gdk_pixbuf_get_from_surface(surface, 0, 0, cairo_image_surface_get_width(surface), cairo_image_surface_get_height(surface));
  if (pixbuf == NULL) {
    girara_error("Unable to convert cairo surface to Gdk Pixbuf.");
  }

  gtk_window_set_icon(GTK_WINDOW(zathura->ui.session->gtk.window), pixbuf);
  g_object_unref(pixbuf);
}
Exemple #14
0
zathura_content_type_context_t*
zathura_content_type_new(void)
{
  zathura_content_type_context_t* context =
    g_try_malloc0(sizeof(zathura_content_type_context_t));
  if (context == NULL) {
    return NULL;
  }

#ifdef WITH_MAGIC
  /* creat magic cookie */
  const int flags =
    MAGIC_MIME_TYPE |
    MAGIC_SYMLINK |
    MAGIC_NO_CHECK_APPTYPE |
    MAGIC_NO_CHECK_CDF |
    MAGIC_NO_CHECK_ELF |
    MAGIC_NO_CHECK_ENCODING;
  magic_t magic = magic_open(flags);
  if (magic == NULL) {
    girara_debug("failed creating the magic cookie");
    return context;
  }

  /* ... and load mime database */
  if (magic_load(magic, NULL) < 0) {
    girara_debug("failed loading the magic database: %s", magic_error(magic));
    magic_close(magic);
    return context;
  }

  context->magic = magic;
#endif

  return context;
}
Exemple #15
0
bool
sc_adjust_window(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);

  if (argument->n < ZATHURA_ADJUST_NONE || argument->n >= ZATHURA_ADJUST_MODE_NUMBER) {
    girara_error("Invalid adjust mode: %d", argument->n);
    girara_notify(session, GIRARA_ERROR, _("Invalid adjust mode: %d"), argument->n);
  } else {
    girara_debug("Setting adjust mode to: %d", argument->n);

    zathura_document_set_adjust_mode(zathura->document, argument->n);
    adjust_view(zathura);
  }

  return false;
}
Exemple #16
0
void
cb_page_widget_scaled_button_release(ZathuraPage* page_widget, GdkEventButton* event,
    void* data)
{
  zathura_t* zathura = data;

  zathura_page_t* page = zathura_page_widget_get_page(page_widget);

  /* set page number (but don't scroll there. it was clicked on, so it's visible) */
  if (event->button == GDK_BUTTON_PRIMARY) {
    zathura_document_set_current_page_number(zathura->document, zathura_page_get_index(page));
    refresh_view(zathura);
  }

  if (event->button != GDK_BUTTON_PRIMARY || !(event->state & GDK_CONTROL_MASK)) {
    return;
  }

  bool synctex = false;
  girara_setting_get(zathura->ui.session, "synctex", &synctex);
  if (synctex == false) {
    return;
  }

  if (zathura->dbus != NULL) {
    zathura_dbus_edit(zathura->dbus, zathura_page_get_index(page), event->x, event->y);
  }

  char* editor = NULL;
  girara_setting_get(zathura->ui.session, "synctex-editor-command", &editor);
  if (editor == NULL || *editor == '\0') {
    girara_debug("No SyncTeX editor specified.");
    g_free(editor);
    return;
  }

  synctex_edit(editor, page, event->x, event->y);
  g_free(editor);
}
Exemple #17
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;
}
Exemple #18
0
static void
cb_print_draw_page(GtkPrintOperation* print_operation, GtkPrintContext*
                   context, gint page_number, zathura_t* zathura)
{
  if (context == NULL || zathura == NULL || zathura->document == NULL ||
      zathura->ui.session == NULL || zathura->ui.statusbar.file == NULL) {
    gtk_print_operation_cancel(print_operation);
    return;
  }

  /* Update statusbar. */
  char* tmp = g_strdup_printf("Printing %d...", page_number);
  girara_statusbar_item_set_text(zathura->ui.session,
                                 zathura->ui.statusbar.file, tmp);
  g_free(tmp);

  /* Get the page and cairo handle.  */
  cairo_t* cairo       = gtk_print_context_get_cairo_context(context);
  zathura_page_t* page = zathura_document_get_page(zathura->document, page_number);
  if (cairo == NULL || page == NULL) {
    gtk_print_operation_cancel(print_operation);
    return;
  }

  /* Try to render the page without a temporary surface. This only works with
   * plugins that support rendering to any surface.  */
  girara_debug("printing page %d ...", page_number);
  zathura_renderer_lock(zathura->sync.render_thread);
  int err = zathura_page_render(page, cairo, true);
  zathura_renderer_unlock(zathura->sync.render_thread);
  if (err == ZATHURA_ERROR_OK) {
    return;
  }

  /* Try to render the page on a temporary image surface. */
  const gdouble width = gtk_print_context_get_width(context);
  const gdouble height = gtk_print_context_get_height(context);

  /* Render to a surface that is 5 times larger to workaround quality issues. */
  const double page_height = zathura_page_get_height(page) * 5;
  const double page_width  = zathura_page_get_width(page) * 5;
  cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, page_width, page_height);
  if (surface == NULL) {
    gtk_print_operation_cancel(print_operation);
    return;
  }

  cairo_t* temp_cairo = cairo_create(surface);
  if (cairo == NULL) {
    gtk_print_operation_cancel(print_operation);
    cairo_surface_destroy(surface);
    return;
  }

  /* Draw a white background. */
  cairo_save(temp_cairo);
  cairo_set_source_rgb(temp_cairo, 1, 1, 1);
  cairo_rectangle(temp_cairo, 0, 0, page_width, page_height);
  cairo_fill(temp_cairo);
  cairo_restore(temp_cairo);

  /* Render the page to the temporary surface */
  girara_debug("printing page %d (fallback) ...", page_number);
  zathura_renderer_lock(zathura->sync.render_thread);
  err = zathura_page_render(page, temp_cairo, true);
  zathura_renderer_unlock(zathura->sync.render_thread);
  if (err != ZATHURA_ERROR_OK) {
    cairo_destroy(temp_cairo);
    cairo_surface_destroy(surface);
    gtk_print_operation_cancel(print_operation);
    return;
  }

  /* Rescale the page and keep the aspect ratio */
  const gdouble scale = MIN(width / page_width, height / page_height);
  cairo_scale(cairo, scale, scale);

  /* Blit temporary surface to original cairo object. */
  cairo_set_source_surface(cairo, surface, 0.0, 0.0);
  cairo_paint(cairo);
  cairo_destroy(temp_cairo);
  cairo_surface_destroy(surface);
}
Exemple #19
0
bool
zathura_init(zathura_t* zathura)
{
  if (zathura == NULL) {
    return false;
  }

  /* create zathura (config/data) directory */
  if (g_mkdir_with_parents(zathura->config.config_dir, 0771) == -1) {
    girara_error("Could not create '%s': %s", zathura->config.config_dir, strerror(errno));
  }

  if (g_mkdir_with_parents(zathura->config.data_dir, 0771) == -1) {
    girara_error("Could not create '%s': %s", zathura->config.data_dir, strerror(errno));
  }

  /* load plugins */
  zathura_plugin_manager_load(zathura->plugins.manager);

  /* configuration */
  config_load_default(zathura);

  /* load global configuration files */
  char* config_path = girara_get_xdg_path(XDG_CONFIG_DIRS);
  girara_list_t* config_dirs = girara_split_path_array(config_path);
  ssize_t size = girara_list_size(config_dirs) - 1;
  for (; size >= 0; --size) {
    const char* dir = girara_list_nth(config_dirs, size);
    char* file = g_build_filename(dir, ZATHURA_RC, NULL);
    config_load_file(zathura, file);
    g_free(file);
  }
  girara_list_free(config_dirs);
  g_free(config_path);

  config_load_file(zathura, GLOBAL_RC);

  /* load local configuration files */
  char* configuration_file = g_build_filename(zathura->config.config_dir, ZATHURA_RC, NULL);
  config_load_file(zathura, configuration_file);
  g_free(configuration_file);

  /* UI */
  if (girara_session_init(zathura->ui.session, "zathura") == false) {
    goto error_free;
  }

  /* girara events */
  zathura->ui.session->events.buffer_changed  = cb_buffer_changed;
  zathura->ui.session->events.unknown_command = cb_unknown_command;

  /* zathura signals */
  zathura->signals.refresh_view = g_signal_new("refresh-view",
                                               GTK_TYPE_WIDGET,
                                               G_SIGNAL_RUN_LAST,
                                               0,
                                               NULL,
                                               NULL,
                                               g_cclosure_marshal_generic,
                                               G_TYPE_NONE,
                                               1,
                                               G_TYPE_POINTER);

  g_signal_connect(G_OBJECT(zathura->ui.session->gtk.view), "refresh-view",
                   G_CALLBACK(cb_refresh_view), zathura);

  /* page view */
#if (GTK_MAJOR_VERSION == 3)
  zathura->ui.page_widget = gtk_grid_new();
  gtk_grid_set_row_homogeneous(GTK_GRID(zathura->ui.page_widget), TRUE);
  gtk_grid_set_column_homogeneous(GTK_GRID(zathura->ui.page_widget), TRUE);
#else
  zathura->ui.page_widget = gtk_table_new(0, 0, TRUE);
#endif
  if (zathura->ui.page_widget == NULL) {
    goto error_free;
  }

  g_signal_connect(G_OBJECT(zathura->ui.session->gtk.window), "size-allocate", G_CALLBACK(cb_view_resized), zathura);

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

  /* Connect hadjustment signals */
  g_signal_connect(G_OBJECT(hadjustment), "value-changed",
      G_CALLBACK(cb_view_hadjustment_value_changed), zathura);
  g_signal_connect(G_OBJECT(hadjustment), "changed",
      G_CALLBACK(cb_view_hadjustment_changed), zathura);

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

  /* Connect vadjustment signals */
  g_signal_connect(G_OBJECT(vadjustment), "value-changed",
      G_CALLBACK(cb_view_vadjustment_value_changed), zathura);
  g_signal_connect(G_OBJECT(vadjustment), "changed",
      G_CALLBACK(cb_view_vadjustment_changed), zathura);

  /* page view alignment */
  zathura->ui.page_widget_alignment = gtk_alignment_new(0.5, 0.5, 0, 0);
  if (zathura->ui.page_widget_alignment == NULL) {
    goto error_free;
  }
  gtk_container_add(GTK_CONTAINER(zathura->ui.page_widget_alignment), zathura->ui.page_widget);

#if (GTK_MAJOR_VERSION == 3)
  gtk_widget_set_hexpand_set(zathura->ui.page_widget_alignment, TRUE);
  gtk_widget_set_hexpand(zathura->ui.page_widget_alignment, FALSE);
  gtk_widget_set_vexpand_set(zathura->ui.page_widget_alignment, TRUE);
  gtk_widget_set_vexpand(zathura->ui.page_widget_alignment, FALSE);
#endif


  gtk_widget_show(zathura->ui.page_widget);

  /* statusbar */
  zathura->ui.statusbar.file = girara_statusbar_item_add(zathura->ui.session, TRUE, TRUE, TRUE, NULL);
  if (zathura->ui.statusbar.file == NULL) {
    goto error_free;
  }

  zathura->ui.statusbar.buffer = girara_statusbar_item_add(zathura->ui.session, FALSE, FALSE, FALSE, NULL);
  if (zathura->ui.statusbar.buffer == NULL) {
    goto error_free;
  }

  zathura->ui.statusbar.page_number = girara_statusbar_item_add(zathura->ui.session, FALSE, FALSE, FALSE, NULL);
  if (zathura->ui.statusbar.page_number == NULL) {
    goto error_free;
  }

  girara_statusbar_item_set_text(zathura->ui.session, zathura->ui.statusbar.file, _("[No name]"));

  /* signals */
  g_signal_connect(G_OBJECT(zathura->ui.session->gtk.window), "destroy", G_CALLBACK(cb_destroy), zathura);

  /* database */
  char* database = NULL;
  girara_setting_get(zathura->ui.session, "database", &database);

  if (g_strcmp0(database, "plain") == 0) {
    girara_debug("Using plain database backend.");
    zathura->database = zathura_plaindatabase_new(zathura->config.data_dir);
#ifdef WITH_SQLITE
  } else if (g_strcmp0(database, "sqlite") == 0) {
    girara_debug("Using sqlite database backend.");
    char* tmp = g_build_filename(zathura->config.data_dir, "bookmarks.sqlite", NULL);
    zathura->database = zathura_sqldatabase_new(tmp);
    g_free(tmp);
#endif
  } else {
    girara_error("Database backend '%s' is not supported.", database);
  }
  g_free(database);

  if (zathura->database == NULL) {
    girara_error("Unable to initialize database. Bookmarks won't be available.");
  } else {
    g_object_set(zathura->ui.session->command_history, "io", zathura->database, NULL);
  }

  /* bookmarks */
  zathura->bookmarks.bookmarks = girara_sorted_list_new2((girara_compare_function_t) zathura_bookmarks_compare,
                                 (girara_free_function_t) zathura_bookmark_free);

  /* jumplist */

  int jumplist_size = 20;
  girara_setting_get(zathura->ui.session, "jumplist-size", &jumplist_size);

  zathura->jumplist.max_size = jumplist_size < 0 ? 0 : jumplist_size;
  zathura->jumplist.list = NULL;
  zathura->jumplist.size = 0;
  zathura->jumplist.cur = NULL;

  return true;

error_free:

  if (zathura->ui.page_widget != NULL) {
    g_object_unref(zathura->ui.page_widget);
  }

  if (zathura->ui.page_widget_alignment != NULL) {
    g_object_unref(zathura->ui.page_widget_alignment);
  }

  return false;
}
Exemple #20
0
void
zathura_plugin_manager_load(zathura_plugin_manager_t* plugin_manager)
{
  if (plugin_manager == NULL || plugin_manager->path == NULL) {
    return;
  }

  GIRARA_LIST_FOREACH(plugin_manager->path, char*, iter, plugindir)
  /* read all files in the plugin directory */
  GDir* dir = g_dir_open(plugindir, 0, NULL);
  if (dir == NULL) {
    girara_error("could not open plugin directory: %s", plugindir);
    girara_list_iterator_next(iter);
    continue;
  }

  char* name = NULL;
  while ((name = (char*) g_dir_read_name(dir)) != NULL) {
    char* path = g_build_filename(plugindir, name, NULL);
    if (g_file_test(path, G_FILE_TEST_IS_REGULAR) == 0) {
      girara_debug("%s is not a regular file. Skipping.", path);
      g_free(path);
      continue;
    }

    if (check_suffix(path) == false) {
      girara_debug("%s is not a plugin file. Skipping.", path);
      g_free(path);
      continue;
    }

    zathura_plugin_t* plugin = NULL;

    /* load plugin */
    GModule* handle = g_module_open(path, G_MODULE_BIND_LOCAL);
    if (handle == NULL) {
      girara_error("could not load plugin %s (%s)", path, g_module_error());
      g_free(path);
      continue;
    }

    /* resolve symbols and check API and ABI version*/
    zathura_plugin_api_version_t api_version = NULL;
    if (g_module_symbol(handle, PLUGIN_API_VERSION_FUNCTION, (gpointer*) &api_version) == FALSE ||
        api_version == NULL) {
      girara_error("could not find '%s' function in plugin %s", PLUGIN_API_VERSION_FUNCTION, path);
      g_free(path);
      g_module_close(handle);
      continue;
    }

    if (api_version() != ZATHURA_API_VERSION) {
      girara_error("plugin %s has been built againt zathura with a different API version (plugin: %d, zathura: %d)",
                   path, api_version(), ZATHURA_API_VERSION);
      g_free(path);
      g_module_close(handle);
      continue;
    }

    zathura_plugin_abi_version_t abi_version = NULL;
    if (g_module_symbol(handle, PLUGIN_ABI_VERSION_FUNCTION, (gpointer*) &abi_version) == FALSE ||
        abi_version == NULL) {
      girara_error("could not find '%s' function in plugin %s", PLUGIN_ABI_VERSION_FUNCTION, path);
      g_free(path);
      g_module_close(handle);
      continue;
    }

    if (abi_version() != ZATHURA_ABI_VERSION) {
      girara_error("plugin %s has been built againt zathura with a different ABI version (plugin: %d, zathura: %d)",
                   path, abi_version(), ZATHURA_ABI_VERSION);
      g_free(path);
      g_module_close(handle);
      continue;
    }

    zathura_plugin_register_service_t register_service = NULL;
    if (g_module_symbol(handle, PLUGIN_REGISTER_FUNCTION, (gpointer*) &register_service) == FALSE ||
        register_service == NULL) {
      girara_error("could not find '%s' function in plugin %s", PLUGIN_REGISTER_FUNCTION, path);
      g_free(path);
      g_module_close(handle);
      continue;
    }

    plugin = g_try_malloc0(sizeof(zathura_plugin_t));
    if (plugin == NULL) {
      girara_error("Failed to allocate memory for plugin.");
      g_free(path);
      g_module_close(handle);
      continue;
    }

    plugin->content_types = girara_list_new2(g_free);
    plugin->handle = handle;

    register_service(plugin);

    /* register functions */
    if (plugin->register_function == NULL) {
      girara_error("plugin has no document functions register function");
      g_free(path);
      g_free(plugin);
      g_module_close(handle);
      continue;
    }

    plugin->register_function(&(plugin->functions));
    plugin->path = path;

    bool ret = register_plugin(plugin_manager, plugin);
    if (ret == false) {
      girara_error("could not register plugin %s", path);
      zathura_plugin_free(plugin);
    } else {
      girara_debug("successfully loaded plugin %s", path);

      zathura_plugin_version_function_t plugin_major = NULL, plugin_minor = NULL, plugin_rev = NULL;
      g_module_symbol(handle, PLUGIN_VERSION_MAJOR_FUNCTION,    (gpointer*) &plugin_major);
      g_module_symbol(handle, PLUGIN_VERSION_MINOR_FUNCTION,    (gpointer*) &plugin_minor);
      g_module_symbol(handle, PLUGIN_VERSION_REVISION_FUNCTION, (gpointer*) &plugin_rev);
      if (plugin_major != NULL && plugin_minor != NULL && plugin_rev != NULL) {
        plugin->version.major = plugin_major();
        plugin->version.minor = plugin_minor();
        plugin->version.rev   = plugin_rev();
        girara_debug("plugin '%s': version %u.%u.%u", path,
                     plugin->version.major, plugin->version.minor,
                     plugin->version.rev);
      }
    }
  }
  g_dir_close(dir);
  GIRARA_LIST_FOREACH_END(zathura->plugins.path, char*, iter, plugindir);
}
Exemple #21
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);
}
Exemple #22
0
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);
}
Exemple #23
0
static const gchar*
guess_type(const char* path)
{
  gboolean uncertain;
  const gchar* content_type = g_content_type_guess(path, NULL, 0, &uncertain);
  if (content_type == NULL) {
    return NULL;
  }

  if (uncertain == FALSE) {
    return content_type;
  }

  girara_debug("g_content_type is uncertain, guess: %s\n", content_type);

  FILE* f = fopen(path, "rb");
  if (f == NULL) {
    return NULL;
  }

  const int fd = fileno(f);
  guchar* content = NULL;
  size_t length = 0u;
  ssize_t bytes_read = -1;
  while (uncertain == TRUE && length < GT_MAX_READ && bytes_read != 0) {
    g_free((void*)content_type);
    content_type = NULL;

    content = g_realloc(content, length + BUFSIZ);
    bytes_read = read(fd, content + length, BUFSIZ);
    if (bytes_read == -1) {
      break;
    }

    length += bytes_read;
    content_type = g_content_type_guess(NULL, content, length, &uncertain);
    girara_debug("new guess: %s uncertain: %d, read: %zu\n", content_type, uncertain, length);
  }

  fclose(f);
  g_free(content);
  if (uncertain == FALSE) {
    return content_type;
  }

  g_free((void*)content_type);
  content_type = NULL;

  girara_debug("falling back to file");

  GString* command = g_string_new("file -b --mime-type ");
  char* tmp        = g_shell_quote(path);

  g_string_append(command, tmp);
  g_free(tmp);

  GError* error = NULL;
  char* out = NULL;
  int ret = 0;
  g_spawn_command_line_sync(command->str, &out, NULL, &ret, &error);
  g_string_free(command, TRUE);
  if (error != NULL) {
    girara_warning("failed to execute command: %s", error->message);
    g_error_free(error);
    g_free(out);
    return NULL;
  }
  if (WEXITSTATUS(ret) != 0) {
    girara_warning("file failed with error code: %d", WEXITSTATUS(ret));
    g_free(out);
    return NULL;
  }

  g_strdelimit(out, "\n\r", '\0');
  return out;
}
Exemple #24
0
static const gchar*
guess_type(const char* path)
{
  const gchar* content_type = NULL;
#ifdef WITH_MAGIC
  const char* mime_type = NULL;

  /* creat magic cookie */
  const int flags =
    MAGIC_MIME_TYPE |
    MAGIC_SYMLINK |
    MAGIC_NO_CHECK_APPTYPE |
    MAGIC_NO_CHECK_CDF |
    MAGIC_NO_CHECK_ELF |
    MAGIC_NO_CHECK_ENCODING;
  magic_t magic = magic_open(flags);
  if (magic == NULL) {
    girara_debug("failed creating the magic cookie");
    goto cleanup;
  }

  /* ... and load mime database */
  if (magic_load(magic, NULL) < 0) {
    girara_debug("failed loading the magic database: %s", magic_error(magic));
    goto cleanup;
  }

  /* get the mime type */
  mime_type = magic_file(magic, path);
  if (mime_type == NULL) {
    girara_debug("failed guessing filetype: %s", magic_error(magic));
    goto cleanup;
  }

  girara_debug("magic detected filetype: %s", mime_type);
  content_type = g_strdup(mime_type);

cleanup:
  if (magic != NULL) {
    magic_close(magic);
  }

  if (content_type != NULL) {
    return content_type;
  }
  /* else fallback to g_content_type_guess method */
#endif /*WITH_MAGIC*/
  gboolean uncertain = FALSE;
  content_type = g_content_type_guess(path, NULL, 0, &uncertain);
  if (content_type == NULL) {
    girara_debug("g_content_type failed\n");
  } else {
    if (uncertain == FALSE) {
      girara_debug("g_content_type detected filetype: %s", content_type);
      return content_type;
    }
    girara_debug("g_content_type is uncertain, guess: %s", content_type);
  }

  FILE* f = fopen(path, "rb");
  if (f == NULL) {
    return NULL;
  }

  const int fd = fileno(f);
  guchar* content = NULL;
  size_t length = 0u;
  ssize_t bytes_read = -1;
  while (uncertain == TRUE && length < GT_MAX_READ && bytes_read != 0) {
    g_free((void*)content_type);
    content_type = NULL;

    content = g_realloc(content, length + BUFSIZ);
    bytes_read = read(fd, content + length, BUFSIZ);
    if (bytes_read == -1) {
      break;
    }

    length += bytes_read;
    content_type = g_content_type_guess(NULL, content, length, &uncertain);
    girara_debug("new guess: %s uncertain: %d, read: %zu", content_type, uncertain, length);
  }

  fclose(f);
  g_free(content);
  if (uncertain == FALSE) {
    return content_type;
  }

  g_free((void*)content_type);
  content_type = NULL;

  girara_debug("falling back to file");

  GString* command = g_string_new("file -b --mime-type ");
  char* tmp        = g_shell_quote(path);

  g_string_append(command, tmp);
  g_free(tmp);

  GError* error = NULL;
  char* out = NULL;
  int ret = 0;
  g_spawn_command_line_sync(command->str, &out, NULL, &ret, &error);
  g_string_free(command, TRUE);
  if (error != NULL) {
    girara_warning("failed to execute command: %s", error->message);
    g_error_free(error);
    g_free(out);
    return NULL;
  }
  if (WEXITSTATUS(ret) != 0) {
    girara_warning("file failed with error code: %d", WEXITSTATUS(ret));
    g_free(out);
    return NULL;
  }

  g_strdelimit(out, "\n\r", '\0');
  return out;
}
Exemple #25
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;
}
Exemple #26
0
bool
zathura_init(zathura_t* zathura)
{
  if (zathura == NULL) {
    return false;
  }

  /* create zathura (config/data) directory */
  if (g_mkdir_with_parents(zathura->config.config_dir, 0771) == -1) {
    girara_error("Could not create '%s': %s", zathura->config.config_dir, strerror(errno));
  }

  if (g_mkdir_with_parents(zathura->config.data_dir, 0771) == -1) {
    girara_error("Could not create '%s': %s", zathura->config.data_dir, strerror(errno));
  }

  /* load plugins */
  zathura_plugin_manager_load(zathura->plugins.manager);

  /* configuration */
  config_load_default(zathura);

  /* load global configuration files */
  char* config_path = girara_get_xdg_path(XDG_CONFIG_DIRS);
  girara_list_t* config_dirs = girara_split_path_array(config_path);
  ssize_t size = girara_list_size(config_dirs) - 1;
  for (; size >= 0; --size) {
    const char* dir = girara_list_nth(config_dirs, size);
    char* file = g_build_filename(dir, ZATHURA_RC, NULL);
    config_load_file(zathura, file);
    g_free(file);
  }
  girara_list_free(config_dirs);
  g_free(config_path);

  config_load_file(zathura, GLOBAL_RC);

  /* load local configuration files */
  char* configuration_file = g_build_filename(zathura->config.config_dir, ZATHURA_RC, NULL);
  config_load_file(zathura, configuration_file);
  g_free(configuration_file);

  /* UI */
  if (girara_session_init(zathura->ui.session, "zathura") == false) {
    goto error_free;
  }

  /* girara events */
  zathura->ui.session->events.buffer_changed  = cb_buffer_changed;
  zathura->ui.session->events.unknown_command = cb_unknown_command;

  /* page view */
#if (GTK_MAJOR_VERSION == 3)
  zathura->ui.page_widget = gtk_grid_new();
  gtk_grid_set_row_homogeneous(GTK_GRID(zathura->ui.page_widget), TRUE);
  gtk_grid_set_column_homogeneous(GTK_GRID(zathura->ui.page_widget), TRUE);
#else
  zathura->ui.page_widget = gtk_table_new(0, 0, TRUE);
#endif
  if (zathura->ui.page_widget == NULL) {
    goto error_free;
  }

  g_signal_connect(G_OBJECT(zathura->ui.session->gtk.window), "size-allocate", G_CALLBACK(cb_view_resized), zathura);

  /* Setup hadjustment tracker */
  GtkAdjustment* hadjustment = gtk_scrolled_window_get_hadjustment(
      GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view));
  zathura->ui.hadjustment = zathura_adjustment_clone(hadjustment);
  g_object_ref_sink(zathura->ui.hadjustment);

  /* Connect hadjustment signals */
  g_signal_connect(G_OBJECT(hadjustment), "value-changed",
      G_CALLBACK(cb_view_vadjustment_value_changed), zathura);
  g_signal_connect(G_OBJECT(hadjustment), "value-changed",
      G_CALLBACK(cb_adjustment_track_value), zathura->ui.hadjustment);
  g_signal_connect(G_OBJECT(hadjustment), "changed",
      G_CALLBACK(cb_view_hadjustment_changed), zathura);
  g_signal_connect(G_OBJECT(hadjustment), "changed",
      G_CALLBACK(cb_adjustment_track_bounds), zathura->ui.hadjustment);

  /* Setup vadjustment tracker */
  GtkAdjustment* vadjustment = gtk_scrolled_window_get_vadjustment(
      GTK_SCROLLED_WINDOW(zathura->ui.session->gtk.view));
  zathura->ui.vadjustment = zathura_adjustment_clone(vadjustment);
  g_object_ref_sink(zathura->ui.vadjustment);

  /* Connect vadjustment signals */
  g_signal_connect(G_OBJECT(vadjustment), "value-changed",
      G_CALLBACK(cb_view_vadjustment_value_changed), zathura);
  g_signal_connect(G_OBJECT(vadjustment), "value-changed",
      G_CALLBACK(cb_adjustment_track_value), zathura->ui.vadjustment);
  g_signal_connect(G_OBJECT(vadjustment), "changed",
      G_CALLBACK(cb_view_vadjustment_changed), zathura);
  g_signal_connect(G_OBJECT(vadjustment), "changed",
      G_CALLBACK(cb_adjustment_track_bounds), zathura->ui.vadjustment);

  /* page view alignment */
  zathura->ui.page_widget_alignment = gtk_alignment_new(0.5, 0.5, 0, 0);
  if (zathura->ui.page_widget_alignment == NULL) {
    goto error_free;
  }
  gtk_container_add(GTK_CONTAINER(zathura->ui.page_widget_alignment), zathura->ui.page_widget);

#if (GTK_MAJOR_VERSION == 3)
  gtk_widget_set_hexpand_set(zathura->ui.page_widget_alignment, TRUE);
  gtk_widget_set_hexpand(zathura->ui.page_widget_alignment, FALSE);
  gtk_widget_set_vexpand_set(zathura->ui.page_widget_alignment, TRUE);
  gtk_widget_set_vexpand(zathura->ui.page_widget_alignment, FALSE);
#endif


  gtk_widget_show(zathura->ui.page_widget);

  /* statusbar */
  zathura->ui.statusbar.file = girara_statusbar_item_add(zathura->ui.session, TRUE, TRUE, TRUE, NULL);
  if (zathura->ui.statusbar.file == NULL) {
    goto error_free;
  }

  zathura->ui.statusbar.buffer = girara_statusbar_item_add(zathura->ui.session, FALSE, FALSE, FALSE, NULL);
  if (zathura->ui.statusbar.buffer == NULL) {
    goto error_free;
  }

  zathura->ui.statusbar.page_number = girara_statusbar_item_add(zathura->ui.session, FALSE, FALSE, FALSE, NULL);
  if (zathura->ui.statusbar.page_number == NULL) {
    goto error_free;
  }

  girara_statusbar_item_set_text(zathura->ui.session, zathura->ui.statusbar.file, _("[No name]"));

  /* signals */
  g_signal_connect(G_OBJECT(zathura->ui.session->gtk.window), "destroy", G_CALLBACK(cb_destroy), zathura);

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

#if (GTK_MAJOR_VERSION == 3)
  gtk_grid_set_row_spacing(GTK_GRID(zathura->ui.page_widget), page_padding);
  gtk_grid_set_column_spacing(GTK_GRID(zathura->ui.page_widget), page_padding);
#else
  gtk_table_set_row_spacings(GTK_TABLE(zathura->ui.page_widget), page_padding);
  gtk_table_set_col_spacings(GTK_TABLE(zathura->ui.page_widget), page_padding);
#endif

  /* database */
  char* database = NULL;
  girara_setting_get(zathura->ui.session, "database", &database);

  if (g_strcmp0(database, "plain") == 0) {
    girara_debug("Using plain database backend.");
    zathura->database = zathura_plaindatabase_new(zathura->config.data_dir);
#ifdef WITH_SQLITE
  } else if (g_strcmp0(database, "sqlite") == 0) {
    girara_debug("Using sqlite database backend.");
    char* tmp = g_build_filename(zathura->config.data_dir, "bookmarks.sqlite", NULL);
    zathura->database = zathura_sqldatabase_new(tmp);
    g_free(tmp);
#endif
  } else {
    girara_error("Database backend '%s' is not supported.", database);
  }
  g_free(database);

  if (zathura->database == NULL) {
    girara_error("Unable to initialize database. Bookmarks won't be available.");
  } else {
    g_object_set(zathura->ui.session->command_history, "io", zathura->database, NULL);
  }

  /* bookmarks */
  zathura->bookmarks.bookmarks = girara_sorted_list_new2((girara_compare_function_t) zathura_bookmarks_compare,
                                 (girara_free_function_t) zathura_bookmark_free);

  /* jumplist */

  zathura->jumplist.max_size = 20;
  girara_setting_get(zathura->ui.session, "jumplist-size", &(zathura->jumplist.max_size));

  zathura->jumplist.list = girara_list_new2(g_free);
  zathura->jumplist.size = 0;
  zathura->jumplist.cur = NULL;
  zathura_jumplist_append_jump(zathura);
  zathura->jumplist.cur = girara_list_iterator(zathura->jumplist.list);

  /* page cache */

  int cache_size = 0;
  girara_setting_get(zathura->ui.session, "page-cache-size", &cache_size);
  if (cache_size <= 0) {
    girara_warning("page-cache-size is not positive, using %d instead", ZATHURA_PAGE_CACHE_DEFAULT_SIZE);
    zathura->page_cache.size = ZATHURA_PAGE_CACHE_DEFAULT_SIZE;
  } else {
    zathura->page_cache.size = cache_size;
  }

  zathura->page_cache.cache = g_malloc(zathura->page_cache.size * sizeof(int));
  zathura_page_cache_invalidate_all(zathura);

  return true;

error_free:

  if (zathura->ui.page_widget != NULL) {
    g_object_unref(zathura->ui.page_widget);
  }

  if (zathura->ui.page_widget_alignment != NULL) {
    g_object_unref(zathura->ui.page_widget_alignment);
  }

  return false;
}
Exemple #27
0
bool
zathura_init(zathura_t* zathura)
{
  if (zathura == NULL) {
    return false;
  }

  /* create zathura (config/data) directory */
  if (g_mkdir_with_parents(zathura->config.config_dir, 0771) == -1) {
    girara_error("Could not create '%s': %s", zathura->config.config_dir, strerror(errno));
  }

  if (g_mkdir_with_parents(zathura->config.data_dir, 0771) == -1) {
    girara_error("Could not create '%s': %s", zathura->config.data_dir, strerror(errno));
  }

  /* load plugins */
  zathura_plugin_manager_load(zathura->plugins.manager);

  /* configuration */
  config_load_default(zathura);
  config_load_files(zathura);

  /* UI */
  if (girara_session_init(zathura->ui.session, "zathura") == false) {
    goto error_free;
  }

  /* girara events */
  zathura->ui.session->events.buffer_changed  = cb_buffer_changed;
  zathura->ui.session->events.unknown_command = cb_unknown_command;

  /* zathura signals */
  zathura->signals.refresh_view = g_signal_new("refresh-view",
                                               GTK_TYPE_WIDGET,
                                               G_SIGNAL_RUN_LAST,
                                               0,
                                               NULL,
                                               NULL,
                                               g_cclosure_marshal_generic,
                                               G_TYPE_NONE,
                                               1,
                                               G_TYPE_POINTER);

  g_signal_connect(G_OBJECT(zathura->ui.session->gtk.view), "refresh-view",
                   G_CALLBACK(cb_refresh_view), zathura);

  /* page view */
  zathura->ui.page_widget = gtk_grid_new();
  gtk_grid_set_row_homogeneous(GTK_GRID(zathura->ui.page_widget), TRUE);
  gtk_grid_set_column_homogeneous(GTK_GRID(zathura->ui.page_widget), TRUE);
  if (zathura->ui.page_widget == NULL) {
    goto error_free;
  }

  g_signal_connect(G_OBJECT(zathura->ui.session->gtk.window), "size-allocate", G_CALLBACK(cb_view_resized), zathura);

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

  /* Connect hadjustment signals */
  g_signal_connect(G_OBJECT(hadjustment), "value-changed",
      G_CALLBACK(cb_view_hadjustment_value_changed), zathura);
  g_signal_connect(G_OBJECT(hadjustment), "changed",
      G_CALLBACK(cb_view_hadjustment_changed), zathura);

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

  /* Connect vadjustment signals */
  g_signal_connect(G_OBJECT(vadjustment), "value-changed",
      G_CALLBACK(cb_view_vadjustment_value_changed), zathura);
  g_signal_connect(G_OBJECT(vadjustment), "changed",
      G_CALLBACK(cb_view_vadjustment_changed), zathura);

  /* page view alignment */
  gtk_widget_set_halign(zathura->ui.page_widget, GTK_ALIGN_CENTER);
  gtk_widget_set_valign(zathura->ui.page_widget, GTK_ALIGN_CENTER);

  gtk_widget_set_hexpand_set(zathura->ui.page_widget, TRUE);
  gtk_widget_set_hexpand(zathura->ui.page_widget, FALSE);
  gtk_widget_set_vexpand_set(zathura->ui.page_widget, TRUE);
  gtk_widget_set_vexpand(zathura->ui.page_widget, FALSE);

  gtk_widget_show(zathura->ui.page_widget);

  /* statusbar */
  zathura->ui.statusbar.file = girara_statusbar_item_add(zathura->ui.session, TRUE, TRUE, TRUE, NULL);
  if (zathura->ui.statusbar.file == NULL) {
    goto error_free;
  }

  zathura->ui.statusbar.buffer = girara_statusbar_item_add(zathura->ui.session, FALSE, FALSE, FALSE, NULL);
  if (zathura->ui.statusbar.buffer == NULL) {
    goto error_free;
  }

  zathura->ui.statusbar.page_number = girara_statusbar_item_add(zathura->ui.session, FALSE, FALSE, FALSE, NULL);
  if (zathura->ui.statusbar.page_number == NULL) {
    goto error_free;
  }

  girara_statusbar_item_set_text(zathura->ui.session, zathura->ui.statusbar.file, _("[No name]"));

  /* signals */
  g_signal_connect(G_OBJECT(zathura->ui.session->gtk.window), "destroy", G_CALLBACK(cb_destroy), zathura);

  /* database */
  char* database = NULL;
  girara_setting_get(zathura->ui.session, "database", &database);

  if (g_strcmp0(database, "plain") == 0) {
    girara_debug("Using plain database backend.");
    zathura->database = zathura_plaindatabase_new(zathura->config.data_dir);
#ifdef WITH_SQLITE
  } else if (g_strcmp0(database, "sqlite") == 0) {
    girara_debug("Using sqlite database backend.");
    char* tmp = g_build_filename(zathura->config.data_dir, "bookmarks.sqlite", NULL);
    zathura->database = zathura_sqldatabase_new(tmp);
    g_free(tmp);
#endif
  } else if (g_strcmp0(database, "null") != 0) {
    girara_error("Database backend '%s' is not supported.", database);
  }

  if (zathura->database == NULL && g_strcmp0(database, "null") != 0) {
    girara_error("Unable to initialize database. Bookmarks won't be available.");
  } else {
    g_object_set(G_OBJECT(zathura->ui.session->command_history), "io", zathura->database, NULL);
  }
  g_free(database);

  /* bookmarks */
  zathura->bookmarks.bookmarks = girara_sorted_list_new2((girara_compare_function_t) zathura_bookmarks_compare,
                                 (girara_free_function_t) zathura_bookmark_free);

  /* jumplist */
  int jumplist_size = 20;
  girara_setting_get(zathura->ui.session, "jumplist-size", &jumplist_size);

  zathura->jumplist.max_size = jumplist_size < 0 ? 0 : jumplist_size;
  zathura->jumplist.list = NULL;
  zathura->jumplist.size = 0;
  zathura->jumplist.cur = NULL;

  /* CSS for index mode */
  GiraraTemplate* csstemplate = girara_session_get_template(zathura->ui.session);

  static const char* index_settings[] = {
    "index-fg",
    "index-bg",
    "index-active-fg",
    "index-active-bg"
  };

  for (size_t s = 0; s < LENGTH(index_settings); ++s) {
    girara_template_add_variable(csstemplate, index_settings[s]);

    char* tmp_value = NULL;
    GdkRGBA rgba = { 0, 0, 0, 0 };
    girara_setting_get(zathura->ui.session, index_settings[s], &tmp_value);
    if (tmp_value != NULL) {
      gdk_rgba_parse(&rgba, tmp_value);
      g_free(tmp_value);
    }

    char* color = gdk_rgba_to_string(&rgba);
    girara_template_set_variable_value(csstemplate,
        index_settings[s], color);
    g_free(color);
  }

  char* css = g_strdup_printf("%s\n%s", girara_template_get_base(csstemplate), CSS_TEMPLATE_INDEX);
  girara_template_set_base(csstemplate, css);
  g_free(css);

  /* Start D-Bus service */
  bool dbus = true;
  girara_setting_get(zathura->ui.session, "dbus-service", &dbus);
  if (dbus == true) {
    zathura->dbus = zathura_dbus_new(zathura);
  }

  return true;

error_free:

  if (zathura->ui.page_widget != NULL) {
    g_object_unref(zathura->ui.page_widget);
  }

  return false;
}