marks.c 7.85 KB
Newer Older
1
/* SPDX-License-Identifier: Zlib */
Moritz Lipp's avatar
Moritz Lipp committed
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

#include <stdlib.h>
#include <string.h>
#include <girara/session.h>
#include <girara/callbacks.h>
#include <girara/datastructures.h>

#include "callbacks.h"
#include "marks.h"
#include "document.h"
#include "render.h"
#include "utils.h"

static void mark_add(zathura_t* zathura, int key);
static void mark_evaluate(zathura_t* zathura, int key);
static bool cb_marks_view_key_press_event_add(GtkWidget* widget, GdkEventKey*
    event, girara_session_t* session);
static bool cb_marks_view_key_press_event_evaluate(GtkWidget* widget,
    GdkEventKey* event, girara_session_t* session);

struct zathura_mark_s {
  int key; /**> Marks key */
  double position_x; /**> Horizontal adjustment */
  double position_y; /**> Vertical adjustment */
26
  unsigned int page; /**> Page number */
27
  double zoom; /**> Zoom level */
Moritz Lipp's avatar
Moritz Lipp committed
28 29 30 31
};

bool
sc_mark_add(girara_session_t* session, girara_argument_t* UNUSED(argument),
Moritz Lipp's avatar
Moritz Lipp committed
32
            girara_event_t* UNUSED(event), unsigned int UNUSED(t))
Moritz Lipp's avatar
Moritz Lipp committed
33 34 35 36 37 38 39
{
  g_return_val_if_fail(session != NULL,           FALSE);
  g_return_val_if_fail(session->gtk.view != NULL, FALSE);

  /* redirect signal handler */
  g_signal_handler_disconnect(G_OBJECT(session->gtk.view), session->signals.view_key_pressed);
  session->signals.view_key_pressed = g_signal_connect(G_OBJECT(session->gtk.view), "key-press-event",
Moritz Lipp's avatar
Moritz Lipp committed
40
                                      G_CALLBACK(cb_marks_view_key_press_event_add), session);
Moritz Lipp's avatar
Moritz Lipp committed
41 42 43 44 45 46

  return true;
}

bool
sc_mark_evaluate(girara_session_t* session, girara_argument_t* UNUSED(argument),
Moritz Lipp's avatar
Moritz Lipp committed
47
                 girara_event_t* UNUSED(event), unsigned int UNUSED(t))
Moritz Lipp's avatar
Moritz Lipp committed
48 49 50 51 52 53 54
{
  g_return_val_if_fail(session != NULL,           FALSE);
  g_return_val_if_fail(session->gtk.view != NULL, FALSE);

  /* redirect signal handler */
  g_signal_handler_disconnect(G_OBJECT(session->gtk.view), session->signals.view_key_pressed);
  session->signals.view_key_pressed = g_signal_connect(G_OBJECT(session->gtk.view), "key-press-event",
Moritz Lipp's avatar
Moritz Lipp committed
55
                                      G_CALLBACK(cb_marks_view_key_press_event_evaluate), session);
Moritz Lipp's avatar
Moritz Lipp committed
56 57 58 59 60 61

  return true;
}

bool
cb_marks_view_key_press_event_add(GtkWidget* UNUSED(widget), GdkEventKey* event,
Moritz Lipp's avatar
Moritz Lipp committed
62
                                  girara_session_t* session)
Moritz Lipp's avatar
Moritz Lipp committed
63 64 65 66 67 68 69 70 71
{
  g_return_val_if_fail(session != NULL,              FALSE);
  g_return_val_if_fail(session->gtk.view != NULL,    FALSE);
  g_return_val_if_fail(session->global.data != NULL, FALSE);
  zathura_t* zathura = (zathura_t*) session->global.data;

  /* reset signal handler */
  g_signal_handler_disconnect(G_OBJECT(session->gtk.view), session->signals.view_key_pressed);
  session->signals.view_key_pressed = g_signal_connect(G_OBJECT(session->gtk.view), "key-press-event",
Moritz Lipp's avatar
Moritz Lipp committed
72
                                      G_CALLBACK(girara_callback_view_key_press_event), session);
Moritz Lipp's avatar
Moritz Lipp committed
73 74

  /* evaluate key */
Moritz Lipp's avatar
Moritz Lipp committed
75 76 77 78
  if (((event->keyval >= '0' && event->keyval <= '9') ||
       (event->keyval >= 'a' && event->keyval <= 'z') ||
       (event->keyval >= 'A' && event->keyval <= 'Z')
       ) == false) {
Moritz Lipp's avatar
Moritz Lipp committed
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
    return false;
  }

  mark_add(zathura, event->keyval);

  return true;
}

bool cb_marks_view_key_press_event_evaluate(GtkWidget* UNUSED(widget), GdkEventKey*
    event, girara_session_t* session)
{
  g_return_val_if_fail(session != NULL,              FALSE);
  g_return_val_if_fail(session->gtk.view != NULL,    FALSE);
  g_return_val_if_fail(session->global.data != NULL, FALSE);
  zathura_t* zathura = (zathura_t*) session->global.data;

  /* reset signal handler */
  g_signal_handler_disconnect(G_OBJECT(session->gtk.view), session->signals.view_key_pressed);
  session->signals.view_key_pressed = g_signal_connect(G_OBJECT(session->gtk.view), "key-press-event",
Moritz Lipp's avatar
Moritz Lipp committed
98
                                      G_CALLBACK(girara_callback_view_key_press_event), session);
Moritz Lipp's avatar
Moritz Lipp committed
99 100

  /* evaluate key */
Moritz Lipp's avatar
Moritz Lipp committed
101 102 103 104
  if (((event->keyval >= '0' && event->keyval <= '9') ||
       (event->keyval >= 'a' && event->keyval <= 'z') ||
       (event->keyval >= 'A' && event->keyval <= 'Z')
       ) == false) {
Moritz Lipp's avatar
Moritz Lipp committed
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
    return true;
  }

  mark_evaluate(zathura, event->keyval);

  return true;
}

bool
cmd_marks_add(girara_session_t* session, girara_list_t* argument_list)
{
  g_return_val_if_fail(session != NULL, false);
  g_return_val_if_fail(session->global.data != NULL, false);
  zathura_t* zathura = (zathura_t*) session->global.data;

  if (girara_list_size(argument_list) < 1) {
    return false;
  }

  char* key_string = girara_list_nth(argument_list, 0);

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

Sebastian Ramacher's avatar
Sebastian Ramacher committed
130
  if (strlen(key_string) != 1) {
Moritz Lipp's avatar
Moritz Lipp committed
131 132 133 134 135 136
    return false;
  }

  char key = key_string[0];

  if (((key >= 0x41 && key <= 0x5A) || (key >=
Moritz Lipp's avatar
Moritz Lipp committed
137
                                        0x61 && key <= 0x7A)) == false) {
Moritz Lipp's avatar
Moritz Lipp committed
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
    return false;
  }

  mark_add(zathura, key);

  return false;
}

bool
cmd_marks_delete(girara_session_t* session, girara_list_t* argument_list)
{
  g_return_val_if_fail(session != NULL, false);
  g_return_val_if_fail(session->global.data != NULL, false);
  zathura_t* zathura = (zathura_t*) session->global.data;

  if (girara_list_size(argument_list) < 1) {
    return false;
  }

  if (girara_list_size(zathura->global.marks) == 0) {
    return false;
  }

Sebastian Ramacher's avatar
Sebastian Ramacher committed
161 162 163
  GIRARA_LIST_FOREACH_BODY_WITH_ITER(argument_list, char*, iter, key_string,
    if (key_string == NULL) {
      girara_list_iterator_next(iter);
Moritz Lipp's avatar
Moritz Lipp committed
164 165 166
      continue;
    }

Sebastian Ramacher's avatar
Sebastian Ramacher committed
167 168 169 170
    for (unsigned int i = 0; i < strlen(key_string); i++) {
      char key = key_string[i];
      if (((key >= 0x41 && key <= 0x5A) || (key >=
                                            0x61 && key <= 0x7A)) == false) {
Moritz Lipp's avatar
Moritz Lipp committed
171 172 173
        continue;
      }

Sebastian Ramacher's avatar
Sebastian Ramacher committed
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
      /* search for existing mark */
      girara_list_iterator_t* mark_iter = girara_list_iterator(zathura->global.marks);
      do {
        zathura_mark_t* mark = (zathura_mark_t*) girara_list_iterator_data(mark_iter);
        if (mark == NULL) {
          continue;
        }

        if (mark->key == key) {
          girara_list_remove(zathura->global.marks, mark);
          continue;
        }
      } while (girara_list_iterator_next(mark_iter) != NULL);
      girara_list_iterator_free(mark_iter);
    }
  );
Moritz Lipp's avatar
Moritz Lipp committed
190 191 192 193 194 195 196 197 198 199 200

  return true;
}

void
mark_add(zathura_t* zathura, int key)
{
  if (zathura == NULL || zathura->document == NULL || zathura->global.marks == NULL) {
    return;
  }

201 202 203
  unsigned int page_id = zathura_document_get_current_page_number(zathura->document);
  double position_x    = zathura_document_get_position_x(zathura->document);
  double position_y    = zathura_document_get_position_y(zathura->document);
Moritz Lipp's avatar
Moritz Lipp committed
204

205
  double zoom          = zathura_document_get_zoom(zathura->document);
Moritz Lipp's avatar
Moritz Lipp committed
206 207

  /* search for existing mark */
Sebastian Ramacher's avatar
Sebastian Ramacher committed
208 209 210 211 212
  GIRARA_LIST_FOREACH_BODY_WITH_ITER(zathura->global.marks, zathura_mark_t*, iter, mark,
    if (mark->key == key) {
      mark->page       = page_id;
      mark->position_x = position_x;
      mark->position_y = position_y;
213
      mark->zoom       = zoom;
Sebastian Ramacher's avatar
Sebastian Ramacher committed
214 215 216 217
      girara_list_iterator_free(iter);
      return;
    }
  );
Moritz Lipp's avatar
Moritz Lipp committed
218 219

  /* add new mark */
220 221
  zathura_mark_t* mark = g_try_malloc0(sizeof(zathura_mark_t));
  if (mark == NULL) {
Sebastian Ramacher's avatar
Sebastian Ramacher committed
222
    return;
223
  }
Moritz Lipp's avatar
Moritz Lipp committed
224 225

  mark->key        = key;
226
  mark->page       = page_id;
Moritz Lipp's avatar
Moritz Lipp committed
227 228
  mark->position_x = position_x;
  mark->position_y = position_y;
229
  mark->zoom       = zoom;
Moritz Lipp's avatar
Moritz Lipp committed
230 231 232 233 234 235 236 237 238 239 240 241

  girara_list_append(zathura->global.marks, mark);
}

void
mark_evaluate(zathura_t* zathura, int key)
{
  if (zathura == NULL || zathura->global.marks == NULL) {
    return;
  }

  /* search for existing mark */
Sebastian Ramacher's avatar
Sebastian Ramacher committed
242 243
  GIRARA_LIST_FOREACH_BODY(zathura->global.marks, zathura_mark_t*, mark,
    if (mark != NULL && mark->key == key) {
244 245
      zathura_document_set_zoom(zathura->document,
          zathura_correct_zoom_value(zathura->ui.session, mark->zoom));
Sebastian Ramacher's avatar
Sebastian Ramacher committed
246 247 248 249 250 251 252 253 254 255
      render_all(zathura);

      zathura_jumplist_add(zathura);
      page_set(zathura, mark->page);
      position_set(zathura, mark->position_x, mark->position_y);
      zathura_jumplist_add(zathura);

      break;
    }
  );
Moritz Lipp's avatar
Moritz Lipp committed
256 257 258 259 260 261 262 263 264 265 266 267 268
}

void
mark_free(void* data)
{
  if (data == NULL) {
    return;
  }

  zathura_mark_t* mark = (zathura_mark_t*) data;

  g_free(mark);
}