1 /* SPDX-License-Identifier: Zlib */
2
3 #include <stdlib.h>
4 #include <string.h>
5 #include <girara/session.h>
6 #include <girara/callbacks.h>
7 #include <girara/datastructures.h>
8
9 #include "callbacks.h"
10 #include "marks.h"
11 #include "document.h"
12 #include "render.h"
13 #include "utils.h"
14
15 static void mark_add(zathura_t* zathura, int key);
16 static void mark_evaluate(zathura_t* zathura, int key);
17 static bool cb_marks_view_key_press_event_add(GtkWidget* widget, GdkEventKey*
18 event, girara_session_t* session);
19 static bool cb_marks_view_key_press_event_evaluate(GtkWidget* widget,
20 GdkEventKey* event, girara_session_t* session);
21
22 struct zathura_mark_s {
23 int key; /**> Marks key */
24 double position_x; /**> Horizontal adjustment */
25 double position_y; /**> Vertical adjustment */
26 unsigned int page; /**> Page number */
27 double zoom; /**> Zoom level */
28 };
29
30 bool
sc_mark_add(girara_session_t * session,girara_argument_t * UNUSED (argument),girara_event_t * UNUSED (event),unsigned int UNUSED (t))31 sc_mark_add(girara_session_t* session, girara_argument_t* UNUSED(argument),
32 girara_event_t* UNUSED(event), unsigned int UNUSED(t))
33 {
34 g_return_val_if_fail(session != NULL, FALSE);
35 g_return_val_if_fail(session->gtk.view != NULL, FALSE);
36
37 /* redirect signal handler */
38 g_signal_handler_disconnect(G_OBJECT(session->gtk.view), session->signals.view_key_pressed);
39 session->signals.view_key_pressed = g_signal_connect(G_OBJECT(session->gtk.view), "key-press-event",
40 G_CALLBACK(cb_marks_view_key_press_event_add), session);
41
42 return true;
43 }
44
45 bool
sc_mark_evaluate(girara_session_t * session,girara_argument_t * UNUSED (argument),girara_event_t * UNUSED (event),unsigned int UNUSED (t))46 sc_mark_evaluate(girara_session_t* session, girara_argument_t* UNUSED(argument),
47 girara_event_t* UNUSED(event), unsigned int UNUSED(t))
48 {
49 g_return_val_if_fail(session != NULL, FALSE);
50 g_return_val_if_fail(session->gtk.view != NULL, FALSE);
51
52 /* redirect signal handler */
53 g_signal_handler_disconnect(G_OBJECT(session->gtk.view), session->signals.view_key_pressed);
54 session->signals.view_key_pressed = g_signal_connect(G_OBJECT(session->gtk.view), "key-press-event",
55 G_CALLBACK(cb_marks_view_key_press_event_evaluate), session);
56
57 return true;
58 }
59
60 bool
cb_marks_view_key_press_event_add(GtkWidget * UNUSED (widget),GdkEventKey * event,girara_session_t * session)61 cb_marks_view_key_press_event_add(GtkWidget* UNUSED(widget), GdkEventKey* event,
62 girara_session_t* session)
63 {
64 g_return_val_if_fail(session != NULL, FALSE);
65 g_return_val_if_fail(session->gtk.view != NULL, FALSE);
66 g_return_val_if_fail(session->global.data != NULL, FALSE);
67 zathura_t* zathura = (zathura_t*) session->global.data;
68
69 /* reset signal handler */
70 g_signal_handler_disconnect(G_OBJECT(session->gtk.view), session->signals.view_key_pressed);
71 session->signals.view_key_pressed = g_signal_connect(G_OBJECT(session->gtk.view), "key-press-event",
72 G_CALLBACK(girara_callback_view_key_press_event), session);
73
74 /* evaluate key */
75 if (((event->keyval >= '0' && event->keyval <= '9') ||
76 (event->keyval >= 'a' && event->keyval <= 'z') ||
77 (event->keyval >= 'A' && event->keyval <= 'Z')
78 ) == false) {
79 return false;
80 }
81
82 mark_add(zathura, event->keyval);
83
84 return true;
85 }
86
cb_marks_view_key_press_event_evaluate(GtkWidget * UNUSED (widget),GdkEventKey * event,girara_session_t * session)87 bool cb_marks_view_key_press_event_evaluate(GtkWidget* UNUSED(widget), GdkEventKey*
88 event, girara_session_t* session)
89 {
90 g_return_val_if_fail(session != NULL, FALSE);
91 g_return_val_if_fail(session->gtk.view != NULL, FALSE);
92 g_return_val_if_fail(session->global.data != NULL, FALSE);
93 zathura_t* zathura = (zathura_t*) session->global.data;
94
95 /* reset signal handler */
96 g_signal_handler_disconnect(G_OBJECT(session->gtk.view), session->signals.view_key_pressed);
97 session->signals.view_key_pressed = g_signal_connect(G_OBJECT(session->gtk.view), "key-press-event",
98 G_CALLBACK(girara_callback_view_key_press_event), session);
99
100 /* evaluate key */
101 if (((event->keyval >= '0' && event->keyval <= '9') ||
102 (event->keyval >= 'a' && event->keyval <= 'z') ||
103 (event->keyval >= 'A' && event->keyval <= 'Z')
104 ) == false) {
105 return true;
106 }
107
108 mark_evaluate(zathura, event->keyval);
109
110 return true;
111 }
112
113 bool
cmd_marks_add(girara_session_t * session,girara_list_t * argument_list)114 cmd_marks_add(girara_session_t* session, girara_list_t* argument_list)
115 {
116 g_return_val_if_fail(session != NULL, false);
117 g_return_val_if_fail(session->global.data != NULL, false);
118 zathura_t* zathura = (zathura_t*) session->global.data;
119
120 if (girara_list_size(argument_list) < 1) {
121 return false;
122 }
123
124 char* key_string = girara_list_nth(argument_list, 0);
125
126 if (key_string == NULL) {
127 return false;
128 }
129
130 if (strlen(key_string) != 1) {
131 return false;
132 }
133
134 char key = key_string[0];
135
136 if (((key >= 0x41 && key <= 0x5A) || (key >=
137 0x61 && key <= 0x7A)) == false) {
138 return false;
139 }
140
141 mark_add(zathura, key);
142
143 return false;
144 }
145
146 bool
cmd_marks_delete(girara_session_t * session,girara_list_t * argument_list)147 cmd_marks_delete(girara_session_t* session, girara_list_t* argument_list)
148 {
149 g_return_val_if_fail(session != NULL, false);
150 g_return_val_if_fail(session->global.data != NULL, false);
151 zathura_t* zathura = (zathura_t*) session->global.data;
152
153 if (girara_list_size(argument_list) < 1) {
154 return false;
155 }
156
157 if (girara_list_size(zathura->global.marks) == 0) {
158 return false;
159 }
160
161 GIRARA_LIST_FOREACH_BODY_WITH_ITER(argument_list, char*, iter, key_string,
162 if (key_string == NULL) {
163 girara_list_iterator_next(iter);
164 continue;
165 }
166
167 for (unsigned int i = 0; i < strlen(key_string); i++) {
168 char key = key_string[i];
169 if (((key >= 0x41 && key <= 0x5A) || (key >=
170 0x61 && key <= 0x7A)) == false) {
171 continue;
172 }
173
174 /* search for existing mark */
175 girara_list_iterator_t* mark_iter = girara_list_iterator(zathura->global.marks);
176 do {
177 zathura_mark_t* mark = (zathura_mark_t*) girara_list_iterator_data(mark_iter);
178 if (mark == NULL) {
179 continue;
180 }
181
182 if (mark->key == key) {
183 girara_list_remove(zathura->global.marks, mark);
184 continue;
185 }
186 } while (girara_list_iterator_next(mark_iter) != NULL);
187 girara_list_iterator_free(mark_iter);
188 }
189 );
190
191 return true;
192 }
193
194 void
mark_add(zathura_t * zathura,int key)195 mark_add(zathura_t* zathura, int key)
196 {
197 if (zathura == NULL || zathura->document == NULL || zathura->global.marks == NULL) {
198 return;
199 }
200
201 unsigned int page_id = zathura_document_get_current_page_number(zathura->document);
202 double position_x = zathura_document_get_position_x(zathura->document);
203 double position_y = zathura_document_get_position_y(zathura->document);
204
205 double zoom = zathura_document_get_zoom(zathura->document);
206
207 /* search for existing mark */
208 GIRARA_LIST_FOREACH_BODY_WITH_ITER(zathura->global.marks, zathura_mark_t*, iter, mark,
209 if (mark->key == key) {
210 mark->page = page_id;
211 mark->position_x = position_x;
212 mark->position_y = position_y;
213 mark->zoom = zoom;
214 girara_list_iterator_free(iter);
215 return;
216 }
217 );
218
219 /* add new mark */
220 zathura_mark_t* mark = g_try_malloc0(sizeof(zathura_mark_t));
221 if (mark == NULL) {
222 return;
223 }
224
225 mark->key = key;
226 mark->page = page_id;
227 mark->position_x = position_x;
228 mark->position_y = position_y;
229 mark->zoom = zoom;
230
231 girara_list_append(zathura->global.marks, mark);
232 }
233
234 void
mark_evaluate(zathura_t * zathura,int key)235 mark_evaluate(zathura_t* zathura, int key)
236 {
237 if (zathura == NULL || zathura->global.marks == NULL) {
238 return;
239 }
240
241 /* search for existing mark */
242 GIRARA_LIST_FOREACH_BODY(zathura->global.marks, zathura_mark_t*, mark,
243 if (mark != NULL && mark->key == key) {
244 zathura_document_set_zoom(zathura->document,
245 zathura_correct_zoom_value(zathura->ui.session, mark->zoom));
246 render_all(zathura);
247
248 zathura_jumplist_add(zathura);
249 page_set(zathura, mark->page);
250 position_set(zathura, mark->position_x, mark->position_y);
251 zathura_jumplist_add(zathura);
252
253 break;
254 }
255 );
256 }
257
258 void
mark_free(void * data)259 mark_free(void* data)
260 {
261 if (data == NULL) {
262 return;
263 }
264
265 zathura_mark_t* mark = (zathura_mark_t*) data;
266
267 g_free(mark);
268 }
269