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

3
4
#define _BSD_SOURCE
#define _XOPEN_SOURCE 500
Moritz Lipp's avatar
Moritz Lipp committed
5

6
#include <regex.h>
Moritz Lipp's avatar
Moritz Lipp committed
7
#include <limits.h>
Moritz Lipp's avatar
Moritz Lipp committed
8
9
#include <stdlib.h>
#include <string.h>
Moritz Lipp's avatar
Moritz Lipp committed
10
#include <unistd.h>
Moritz Lipp's avatar
Moritz Lipp committed
11
#include <libgen.h>
12
#include <math.h>
Moritz Lipp's avatar
Moritz Lipp committed
13

Moritz Lipp's avatar
Moritz Lipp committed
14
15
16
#include <poppler/glib/poppler.h>
#include <cairo.h>

17
#include <glib/gstdio.h>
Moritz Lipp's avatar
Moritz Lipp committed
18
19
20
21
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>

/* macros */
Sebastian Ramacher's avatar
Sebastian Ramacher committed
22
#define LENGTH(x) (sizeof(x)/sizeof((x)[0]))
Moritz Lipp's avatar
Moritz Lipp committed
23
#define CLEAN(m) (m & ~(GDK_MOD2_MASK) & ~(GDK_BUTTON1_MASK) & ~(GDK_BUTTON2_MASK) & ~(GDK_BUTTON3_MASK) & ~(GDK_BUTTON4_MASK) & ~(GDK_BUTTON5_MASK) & ~(GDK_LEAVE_NOTIFY_MASK))
24
25
26
27
28
29
#if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC) || defined(__clang__)
/* only gcc, clang and Intel's cc seem support this */
#define NORETURN __attribute__((noreturn))
#else
#define NORETURN
#endif
Moritz Lipp's avatar
Moritz Lipp committed
30

31
32
33
34
35
36
// just remove the #if-#define-#endif block if support for poppler versions
// before 0.15 is dropped
#if !POPPLER_CHECK_VERSION(0,15,0)
#define poppler_page_get_selected_text poppler_page_get_text
#endif

Moritz Lipp's avatar
Moritz Lipp committed
37
/* enums */
Moritz Lipp's avatar
Moritz Lipp committed
38
enum { NEXT, PREVIOUS, LEFT, RIGHT, UP, DOWN, BOTTOM, TOP, HIDE, HIGHLIGHT,
39
40
41
  DELETE_LAST_WORD, DELETE_LAST_CHAR, DEFAULT, ERROR, WARNING, NEXT_GROUP,
  PREVIOUS_GROUP, ZOOM_IN, ZOOM_OUT, ZOOM_ORIGINAL, ZOOM_SPECIFIC, FORWARD,
  BACKWARD, ADJUST_BESTFIT, ADJUST_WIDTH, ADJUST_NONE, CONTINUOUS, DELETE_LAST,
Moritz Lipp's avatar
Moritz Lipp committed
42
  ADD_MARKER, EVAL_MARKER, EXPAND, COLLAPSE, SELECT, GOTO_DEFAULT, GOTO_LABELS,
Moritz Lipp's avatar
Moritz Lipp committed
43
  GOTO_OFFSET, HALF_UP, HALF_DOWN, FULL_UP, FULL_DOWN, NEXT_CHAR, PREVIOUS_CHAR,
Moritz Lipp's avatar
Moritz Lipp committed
44
  DELETE_TO_LINE_START, APPEND_FILEPATH, NO_SEARCH };
Moritz Lipp's avatar
Moritz Lipp committed
45
46
47
48
49

/* define modes */
#define ALL        (1 << 0)
#define FULLSCREEN (1 << 1)
#define INDEX      (1 << 2)
Moritz Lipp's avatar
Moritz Lipp committed
50
#define NORMAL     (1 << 3)
Moritz Lipp's avatar
Moritz Lipp committed
51

52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/* typedefs */
struct CElement
{
  char            *value;
  char            *description;
  struct CElement *next;
};

typedef struct CElement CompletionElement;

struct CGroup
{
  char              *value;
  CompletionElement *elements;
  struct CGroup     *next;
};

typedef struct CGroup CompletionGroup;

typedef struct
{
  CompletionGroup* groups;
} Completion;

typedef struct
{
  char*      command;
  char*      description;
  int        command_id;
  gboolean   is_group;
  GtkWidget* row;
} CompletionRow;

Moritz Lipp's avatar
Moritz Lipp committed
85
86
87
88
89
90
typedef struct
{
  int   n;
  void *data;
} Argument;

Moritz Lipp's avatar
Moritz Lipp committed
91
92
93
94
95
96
typedef struct
{
  char* name;
  int argument;
} ArgumentName;

Moritz Lipp's avatar
Moritz Lipp committed
97
98
99
100
101
typedef struct
{
  int mask;
  int key;
  void (*function)(Argument*);
102
  int mode;
Moritz Lipp's avatar
Moritz Lipp committed
103
104
105
  Argument argument;
} Shortcut;

Moritz Lipp's avatar
Moritz Lipp committed
106
107
108
typedef struct
{
  char* name;
Moritz Lipp's avatar
Moritz Lipp committed
109
110
  int   mode;
  char* display;
Moritz Lipp's avatar
Moritz Lipp committed
111
112
} ModeName;

Moritz Lipp's avatar
Moritz Lipp committed
113
114
115
116
117
118
typedef struct
{
  char* name;
  void (*function)(Argument*);
} ShortcutName;

Moritz Lipp's avatar
Moritz Lipp committed
119
120
typedef struct
{
121
122
123
124
125
126
  int mask;
  int key;
  void (*function)(Argument*);
  Argument argument;
} InputbarShortcut;

Moritz Lipp's avatar
Moritz Lipp committed
127
128
129
130
131
132
133
typedef struct
{
  int direction;
  void (*function)(Argument*);
  Argument argument;
} MouseScrollEvent;

134
135
136
137
typedef struct
{
  char* command;
  char* abbr;
Moritz Lipp's avatar
Moritz Lipp committed
138
  gboolean (*function)(int, char**);
139
140
  Completion* (*completion)(char*);
  char* description;
Moritz Lipp's avatar
Moritz Lipp committed
141
142
} Command;

143
144
145
146
147
148
149
150
151
152
typedef struct
{
  char* regex;
  void (*function)(char*, Argument*);
  Argument argument;
} BufferCommand;

typedef struct
{
  char identifier;
Moritz Lipp's avatar
Moritz Lipp committed
153
  gboolean (*function)(char*, Argument*);
154
155
156
157
  int always;
  Argument argument;
} SpecialCommand;

Moritz Lipp's avatar
Moritz Lipp committed
158
159
160
161
162
163
164
165
struct SCList
{
  Shortcut       element;
  struct SCList *next;
};

typedef struct SCList ShortcutList;

Moritz Lipp's avatar
Moritz Lipp committed
166
167
168
169
170
171
typedef struct
{
  char* identifier;
  int   key;
} GDKKey;

Moritz Lipp's avatar
Moritz Lipp committed
172
173
typedef struct
{
Moritz Lipp's avatar
Moritz Lipp committed
174
175
176
  PopplerPage *page;
  int          id;
  char        *label;
Moritz Lipp's avatar
Moritz Lipp committed
177
178
} Page;

Moritz Lipp's avatar
Moritz Lipp committed
179
180
181
182
183
184
typedef struct
{
  char* name;
  void* variable;
  char  type;
  gboolean render;
185
  gboolean reinit;
Moritz Lipp's avatar
Moritz Lipp committed
186
187
188
  char* description;
} Setting;

Moritz Lipp's avatar
Moritz Lipp committed
189
190
191
192
193
194
typedef struct
{
  int id;
  int page;
} Marker;

Moritz Lipp's avatar
Moritz Lipp committed
195
196
197
198
199
200
typedef struct
{
  char* id;
  int page;
} Bookmark;

Moritz Lipp's avatar
Moritz Lipp committed
201
202
203
204
205
/* zathura */
struct
{
  struct
  {
Moritz Lipp's avatar
Moritz Lipp committed
206
    GtkWidget         *window;
Moritz Lipp's avatar
Moritz Lipp committed
207
    GtkBox            *box;
Moritz Lipp's avatar
Moritz Lipp committed
208
    GtkBox            *continuous;
Moritz Lipp's avatar
Moritz Lipp committed
209
    GtkScrolledWindow *view;
210
    GtkViewport       *viewport;
Moritz Lipp's avatar
Moritz Lipp committed
211
212
213
    GtkWidget         *statusbar;
    GtkBox            *statusbar_entries;
    GtkEntry          *inputbar;
Moritz Lipp's avatar
Moritz Lipp committed
214
    GtkWidget         *index;
Moritz Lipp's avatar
Moritz Lipp committed
215
    GtkWidget         *information;
Moritz Lipp's avatar
Moritz Lipp committed
216
    GtkWidget         *drawing_area;
217
    GtkWidget         *document;
Moritz Lipp's avatar
Moritz Lipp committed
218
    GdkNativeWindow    embed;
Moritz Lipp's avatar
Moritz Lipp committed
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
  } UI;

  struct
  {
    GdkColor default_fg;
    GdkColor default_bg;
    GdkColor inputbar_fg;
    GdkColor inputbar_bg;
    GdkColor statusbar_fg;
    GdkColor statusbar_bg;
    GdkColor completion_fg;
    GdkColor completion_bg;
    GdkColor completion_g_bg;
    GdkColor completion_g_fg;
    GdkColor completion_hl_fg;
    GdkColor completion_hl_bg;
    GdkColor notification_e_fg;
    GdkColor notification_e_bg;
    GdkColor notification_w_fg;
    GdkColor notification_w_bg;
239
240
    GdkColor recolor_darkcolor;
    GdkColor recolor_lightcolor;
241
    GdkColor search_highlight;
Moritz Lipp's avatar
Moritz Lipp committed
242
    GdkColor select_text;
Moritz Lipp's avatar
Moritz Lipp committed
243
244
245
246
247
248
249
250
    PangoFontDescription *font;
  } Style;

  struct
  {
    GtkLabel *status_text;
    GtkLabel *status_buffer;
    GtkLabel *status_state;
neldoreth's avatar
neldoreth committed
251
252
253
254
255
256
257
    GString  *buffer;
    GList    *history;
    int       mode;
    int       viewing_mode;
    gboolean  recolor;
    gboolean  enable_labelmode;
    int       goto_mode;
258
    int       adjust_mode;
neldoreth's avatar
neldoreth committed
259
    gboolean  show_index;
Moritz Lipp's avatar
Moritz Lipp committed
260
261
    gboolean  show_statusbar;
    gboolean  show_inputbar;
Moritz Lipp's avatar
Moritz Lipp committed
262
263
  } Global;

Moritz Lipp's avatar
Moritz Lipp committed
264
265
266
267
268
  struct
  {
    ShortcutList  *sclist;
  } Bindings;

Moritz Lipp's avatar
Moritz Lipp committed
269
270
271
272
273
274
  struct
  {
    gdouble x;
    gdouble y;
  } SelectPoint;

Moritz Lipp's avatar
Moritz Lipp committed
275
276
277
278
  struct
  {
    char* filename;
    char* pages;
Moritz Lipp's avatar
Moritz Lipp committed
279
    int scroll_percentage;
Moritz Lipp's avatar
Moritz Lipp committed
280
281
  } State;

Moritz Lipp's avatar
Moritz Lipp committed
282
283
284
285
286
287
288
  struct
  {
    Marker* markers;
    int number_of_markers;
    int last;
  } Marker;

Moritz Lipp's avatar
Moritz Lipp committed
289
290
  struct
  {
291
    GFileMonitor* monitor;
Moritz Lipp's avatar
Moritz Lipp committed
292
    GFile*        file;
293
  } FileMonitor;
Moritz Lipp's avatar
Moritz Lipp committed
294

Moritz Lipp's avatar
Moritz Lipp committed
295
296
  struct
  {
297
298
    GKeyFile *data;
    char     *file;
Moritz Lipp's avatar
Moritz Lipp committed
299
300
    Bookmark *bookmarks;
    int       number_of_bookmarks;
Moritz Lipp's avatar
Moritz Lipp committed
301
302
  } Bookmarks;

Moritz Lipp's avatar
Moritz Lipp committed
303
304
305
306
  struct
  {
    PopplerDocument *document;
    char            *file;
307
    char            *password;
Moritz Lipp's avatar
Moritz Lipp committed
308
    Page           **pages;
Moritz Lipp's avatar
Moritz Lipp committed
309
    int              page_number;
Moritz Lipp's avatar
Moritz Lipp committed
310
    int              page_offset;
Moritz Lipp's avatar
Moritz Lipp committed
311
    int              number_of_pages;
Moritz Lipp's avatar
Moritz Lipp committed
312
    int              scale;
313
    int              rotate;
Moritz Lipp's avatar
Moritz Lipp committed
314
    cairo_surface_t *surface;
Moritz Lipp's avatar
Moritz Lipp committed
315
316
  } PDF;

317
318
319
  struct
  {
    GStaticMutex pdflib_lock;
int3's avatar
int3 committed
320
    GStaticMutex pdf_obj_lock;
321
    GStaticMutex search_lock;
Moritz Lipp's avatar
Moritz Lipp committed
322
    GStaticMutex select_lock;
323
324
  } Lock;

Moritz Lipp's avatar
Moritz Lipp committed
325
326
327
328
  struct
  {
    GList* results;
    int page;
Moritz Lipp's avatar
Moritz Lipp committed
329
    gboolean draw;
Moritz Lipp's avatar
Moritz Lipp committed
330
    gchar* query;
Moritz Lipp's avatar
Moritz Lipp committed
331
332
  } Search;

333
334
335
336
337
338
339
  struct
  {
    GThread* search_thread;
    gboolean search_thread_running;
    GThread* inotify_thread;
  } Thread;

Moritz Lipp's avatar
Moritz Lipp committed
340
341
342
343
344
345
  struct
  {
    guint inputbar_activate;
    guint inputbar_key_press_event;
  } Handler;

346
347
348
349
350
351
  struct
  {
    gchar* config_dir;
    gchar* data_dir;
  } Config;

352
353
354
355
  struct
  {
    gchar* file;
  } StdinSupport;
Moritz Lipp's avatar
Moritz Lipp committed
356
357
} Zathura;

358

Moritz Lipp's avatar
Moritz Lipp committed
359
/* function declarations */
Sebastian Ramacher's avatar
Sebastian Ramacher committed
360
361
362
363
364
365
void init_look(void);
void init_directories(void);
void init_bookmarks(void);
void init_keylist(void);
void init_settings(void);
void init_zathura(void);
Moritz Lipp's avatar
Moritz Lipp committed
366
void add_marker(int);
Moritz Lipp's avatar
Moritz Lipp committed
367
void build_index(GtkTreeModel*, GtkTreeIter*, PopplerIndexIter*);
368
void change_mode(int);
369
void calculate_offset(GtkWidget*, double*, double*);
Moritz Lipp's avatar
Moritz Lipp committed
370
void close_file(gboolean);
Sebastian Ramacher's avatar
Sebastian Ramacher committed
371
void enter_password(void);
372
void highlight_result(int, PopplerRectangle*);
Moritz Lipp's avatar
Moritz Lipp committed
373
void draw(int);
Moritz Lipp's avatar
Moritz Lipp committed
374
void eval_marker(int);
375
void notify(int, const char*);
376
gboolean open_file(char*, char*);
377
gboolean open_stdin(gchar*);
378
void open_uri(char*);
379
void out_of_memory(void) NORETURN;
Sebastian Ramacher's avatar
Sebastian Ramacher committed
380
void update_status(void);
381
void read_bookmarks_file(void);
Moritz Lipp's avatar
Moritz Lipp committed
382
void read_configuration_file(const char*);
Sebastian Ramacher's avatar
Sebastian Ramacher committed
383
void read_configuration(void);
Moritz Lipp's avatar
Moritz Lipp committed
384
385
void recalc_rectangle(int, PopplerRectangle*);
void set_completion_row_color(GtkBox*, int, int);
Moritz Lipp's avatar
Moritz Lipp committed
386
void set_page(int);
Moritz Lipp's avatar
Moritz Lipp committed
387
void switch_view(GtkWidget*);
Moritz Lipp's avatar
Moritz Lipp committed
388
GtkEventBox* create_completion_row(GtkBox*, char*, char*, gboolean);
389
390
gchar* fix_path(const gchar*);
gchar* path_from_env(const gchar*);
Sebastian Ramacher's avatar
Sebastian Ramacher committed
391
gchar* get_home_dir(void);
392

Sebastian Ramacher's avatar
Sebastian Ramacher committed
393
Completion* completion_init(void);
394
395
396
397
398
CompletionGroup* completion_group_create(char*);
void completion_add_group(Completion*, CompletionGroup*);
void completion_free(Completion*);
void completion_group_add_element(CompletionGroup*, char*, char*);

Moritz Lipp's avatar
Moritz Lipp committed
399
/* thread declaration */
Moritz Lipp's avatar
Moritz Lipp committed
400
void* search(void*);
Moritz Lipp's avatar
Moritz Lipp committed
401

Moritz Lipp's avatar
Moritz Lipp committed
402
/* shortcut declarations */
403
void sc_abort(Argument*);
Moritz Lipp's avatar
Moritz Lipp committed
404
void sc_adjust_window(Argument*);
405
void sc_change_buffer(Argument*);
406
void sc_change_mode(Argument*);
Moritz Lipp's avatar
Moritz Lipp committed
407
void sc_focus_inputbar(Argument*);
Moritz Lipp's avatar
Moritz Lipp committed
408
void sc_follow(Argument*);
Moritz Lipp's avatar
Moritz Lipp committed
409
void sc_navigate(Argument*);
410
void sc_recolor(Argument*);
Moritz Lipp's avatar
Moritz Lipp committed
411
void sc_reload(Argument*);
Moritz Lipp's avatar
Moritz Lipp committed
412
413
414
void sc_rotate(Argument*);
void sc_scroll(Argument*);
void sc_search(Argument*);
Moritz Lipp's avatar
Moritz Lipp committed
415
void sc_switch_goto_mode(Argument*);
416
void sc_navigate_index(Argument*);
Moritz Lipp's avatar
Moritz Lipp committed
417
void sc_toggle_index(Argument*);
Moritz Lipp's avatar
Moritz Lipp committed
418
void sc_toggle_inputbar(Argument*);
Moritz Lipp's avatar
Moritz Lipp committed
419
void sc_toggle_fullscreen(Argument*);
Moritz Lipp's avatar
Moritz Lipp committed
420
void sc_toggle_statusbar(Argument*);
Moritz Lipp's avatar
Moritz Lipp committed
421
void sc_quit(Argument*);
422
void sc_zoom(Argument*);
Moritz Lipp's avatar
Moritz Lipp committed
423

424
425
426
427
428
429
/* inputbar shortcut declarations */
void isc_abort(Argument*);
void isc_command_history(Argument*);
void isc_completion(Argument*);
void isc_string_manipulation(Argument*);

Moritz Lipp's avatar
Moritz Lipp committed
430
/* command declarations */
Moritz Lipp's avatar
Moritz Lipp committed
431
432
gboolean cmd_bookmark(int, char**);
gboolean cmd_open_bookmark(int, char**);
Moritz Lipp's avatar
Moritz Lipp committed
433
gboolean cmd_close(int, char**);
Moritz Lipp's avatar
Moritz Lipp committed
434
gboolean cmd_correct_offset(int, char**);
Moritz Lipp's avatar
Moritz Lipp committed
435
gboolean cmd_delete_bookmark(int, char**);
436
gboolean cmd_export(int, char**);
Moritz Lipp's avatar
Moritz Lipp committed
437
gboolean cmd_info(int, char**);
Moritz Lipp's avatar
Moritz Lipp committed
438
gboolean cmd_map(int, char**);
Moritz Lipp's avatar
Moritz Lipp committed
439
440
441
gboolean cmd_open(int, char**);
gboolean cmd_print(int, char**);
gboolean cmd_rotate(int, char**);
Moritz Lipp's avatar
Moritz Lipp committed
442
gboolean cmd_set(int, char**);
Moritz Lipp's avatar
Moritz Lipp committed
443
444
gboolean cmd_quit(int, char**);
gboolean cmd_save(int, char**);
445
gboolean cmd_savef(int, char**);
Moritz Lipp's avatar
Moritz Lipp committed
446

447
/* completion commands */
Moritz Lipp's avatar
Moritz Lipp committed
448
Completion* cc_bookmark(char*);
449
Completion* cc_export(char*);
450
Completion* cc_open(char*);
Moritz Lipp's avatar
Moritz Lipp committed
451
Completion* cc_print(char*);
Moritz Lipp's avatar
Moritz Lipp committed
452
Completion* cc_set(char*);
453
454

/* buffer command declarations */
Moritz Lipp's avatar
Moritz Lipp committed
455
void bcmd_evalmarker(char*, Argument*);
456
void bcmd_goto(char*, Argument*);
Moritz Lipp's avatar
Moritz Lipp committed
457
void bcmd_scroll(char*, Argument*);
Moritz Lipp's avatar
Moritz Lipp committed
458
void bcmd_setmarker(char*, Argument*);
Moritz Lipp's avatar
Moritz Lipp committed
459
void bcmd_zoom(char*, Argument*);
Moritz Lipp's avatar
Moritz Lipp committed
460

461
/* special command delcarations */
Moritz Lipp's avatar
Moritz Lipp committed
462
gboolean scmd_search(gchar*, Argument*);
463
464
465

/* callback declarations */
gboolean cb_destroy(GtkWidget*, gpointer);
Moritz Lipp's avatar
Moritz Lipp committed
466
gboolean cb_draw(GtkWidget*, GdkEventExpose*, gpointer);
467
gboolean cb_index_row_activated(GtkTreeView*, GtkTreePath*, GtkTreeViewColumn*, gpointer);
468
469
gboolean cb_inputbar_kb_pressed(GtkWidget*, GdkEventKey*, gpointer);
gboolean cb_inputbar_activate(GtkEntry*, gpointer);
Moritz Lipp's avatar
Moritz Lipp committed
470
gboolean cb_inputbar_form_activate(GtkEntry*, gpointer);
Moritz Lipp's avatar
Moritz Lipp committed
471
gboolean cb_inputbar_password_activate(GtkEntry*, gpointer);
472
473
gboolean cb_view_kb_pressed(GtkWidget*, GdkEventKey*, gpointer);
gboolean cb_view_resized(GtkWidget*, GtkAllocation*, gpointer);
474
gboolean cb_view_button_pressed(GtkWidget*, GdkEventButton*, gpointer);
475
476
gboolean cb_view_button_release(GtkWidget*, GdkEventButton*, gpointer);
gboolean cb_view_motion_notify(GtkWidget*, GdkEventMotion*, gpointer);
477
gboolean cb_view_scrolled(GtkWidget*, GdkEventScroll*, gpointer);
478
gboolean cb_watch_file(GFileMonitor*, GFile*, GFile*, GFileMonitorEvent, gpointer);
Moritz Lipp's avatar
Moritz Lipp committed
479
480
481
482

/* configuration */
#include "config.h"

483
/* function implementation */
484
void
Sebastian Ramacher's avatar
Sebastian Ramacher committed
485
init_look(void)
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
{
  /* parse  */
  gdk_color_parse(default_fgcolor,        &(Zathura.Style.default_fg));
  gdk_color_parse(default_bgcolor,        &(Zathura.Style.default_bg));
  gdk_color_parse(inputbar_fgcolor,       &(Zathura.Style.inputbar_fg));
  gdk_color_parse(inputbar_bgcolor,       &(Zathura.Style.inputbar_bg));
  gdk_color_parse(statusbar_fgcolor,      &(Zathura.Style.statusbar_fg));
  gdk_color_parse(statusbar_bgcolor,      &(Zathura.Style.statusbar_bg));
  gdk_color_parse(completion_fgcolor,     &(Zathura.Style.completion_fg));
  gdk_color_parse(completion_bgcolor,     &(Zathura.Style.completion_bg));
  gdk_color_parse(completion_g_fgcolor,   &(Zathura.Style.completion_g_fg));
  gdk_color_parse(completion_g_fgcolor,   &(Zathura.Style.completion_g_fg));
  gdk_color_parse(completion_hl_fgcolor,  &(Zathura.Style.completion_hl_fg));
  gdk_color_parse(completion_hl_bgcolor,  &(Zathura.Style.completion_hl_bg));
  gdk_color_parse(notification_e_fgcolor, &(Zathura.Style.notification_e_fg));
  gdk_color_parse(notification_e_bgcolor, &(Zathura.Style.notification_e_bg));
  gdk_color_parse(notification_w_fgcolor, &(Zathura.Style.notification_w_fg));
  gdk_color_parse(notification_w_bgcolor, &(Zathura.Style.notification_w_bg));
  gdk_color_parse(recolor_darkcolor,      &(Zathura.Style.recolor_darkcolor));
  gdk_color_parse(recolor_lightcolor,     &(Zathura.Style.recolor_lightcolor));
  gdk_color_parse(search_highlight,       &(Zathura.Style.search_highlight));
  gdk_color_parse(select_text,            &(Zathura.Style.select_text));
Moritz Lipp's avatar
Moritz Lipp committed
508

509
  pango_font_description_free(Zathura.Style.font);
510
511
  Zathura.Style.font = pango_font_description_from_string(font);

Moritz Lipp's avatar
Moritz Lipp committed
512
513
514
515
  /* window and viewport */
  gtk_widget_modify_bg(GTK_WIDGET(Zathura.UI.window),   GTK_STATE_NORMAL, &(Zathura.Style.default_bg));
  gtk_widget_modify_bg(GTK_WIDGET(Zathura.UI.viewport), GTK_STATE_NORMAL, &(Zathura.Style.default_bg));

516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
  /* drawing area */
  gtk_widget_modify_bg(GTK_WIDGET(Zathura.UI.drawing_area), GTK_STATE_NORMAL, &(Zathura.Style.default_bg));

  /* statusbar */
  gtk_widget_modify_bg(GTK_WIDGET(Zathura.UI.statusbar), GTK_STATE_NORMAL, &(Zathura.Style.statusbar_bg));

  gtk_widget_modify_fg(GTK_WIDGET(Zathura.Global.status_text),  GTK_STATE_NORMAL, &(Zathura.Style.statusbar_fg));
  gtk_widget_modify_fg(GTK_WIDGET(Zathura.Global.status_state), GTK_STATE_NORMAL, &(Zathura.Style.statusbar_fg));
  gtk_widget_modify_fg(GTK_WIDGET(Zathura.Global.status_buffer), GTK_STATE_NORMAL, &(Zathura.Style.statusbar_fg));

  gtk_widget_modify_font(GTK_WIDGET(Zathura.Global.status_text),  Zathura.Style.font);
  gtk_widget_modify_font(GTK_WIDGET(Zathura.Global.status_state), Zathura.Style.font);
  gtk_widget_modify_font(GTK_WIDGET(Zathura.Global.status_buffer), Zathura.Style.font);

  /* inputbar */
  gtk_widget_modify_base(GTK_WIDGET(Zathura.UI.inputbar), GTK_STATE_NORMAL, &(Zathura.Style.inputbar_bg));
  gtk_widget_modify_text(GTK_WIDGET(Zathura.UI.inputbar), GTK_STATE_NORMAL, &(Zathura.Style.inputbar_fg));
  gtk_widget_modify_font(GTK_WIDGET(Zathura.UI.inputbar),                     Zathura.Style.font);

Moritz Lipp's avatar
Moritz Lipp committed
535
536
  g_object_set(G_OBJECT(Zathura.UI.inputbar), "has-frame", FALSE, NULL);

537
538
539
540
541
  /* scrollbars */
  if(show_scrollbars)
    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(Zathura.UI.view), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
  else
    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(Zathura.UI.view), GTK_POLICY_NEVER, GTK_POLICY_NEVER);
Moritz Lipp's avatar
Moritz Lipp committed
542
543
544
545
546
547
548
549
550
551
552
553

  /* inputbar */
  if(Zathura.Global.show_inputbar)
    gtk_widget_show(GTK_WIDGET(Zathura.UI.inputbar));
  else
    gtk_widget_hide(GTK_WIDGET(Zathura.UI.inputbar));

  /* statusbar */
  if(Zathura.Global.show_statusbar)
    gtk_widget_show(GTK_WIDGET(Zathura.UI.statusbar));
  else
    gtk_widget_hide(GTK_WIDGET(Zathura.UI.statusbar));
554
555
}

556
557
gchar*
fix_path(const gchar* path)
Moritz Lipp's avatar
Moritz Lipp committed
558
559
560
561
562
{
  if (!path)
    return NULL;

  if (path[0] == '~')
563
564
565
566
567
568
  {
    gchar* home_path = get_home_dir();
    gchar* res = g_build_filename(home_path, path + 1, NULL);
    g_free(home_path);
    return res;
  }
Moritz Lipp's avatar
Moritz Lipp committed
569
570
571
572
  else
    return g_strdup(path);
}

573
574
575
576
577
578
579
580
581
582
583
gchar* path_from_env(const gchar* var)
{
  gchar* env = fix_path(g_getenv(var));
  if (!env)
    return NULL;

  gchar* res = g_build_filename(env, "zathura", NULL);
  g_free(env);
  return res;
}

Sebastian Ramacher's avatar
Sebastian Ramacher committed
584
gchar* get_home_dir(void)
585
586
587
588
589
{
  const gchar* homedir = g_getenv("HOME");
  return g_strdup(homedir ? homedir : g_get_home_dir());
}

Moritz Lipp's avatar
Moritz Lipp committed
590
void
Sebastian Ramacher's avatar
Sebastian Ramacher committed
591
init_directories(void)
Moritz Lipp's avatar
Moritz Lipp committed
592
{
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
  /* setup directories */
  if (!Zathura.Config.config_dir)
  {
#ifndef ZATHURA_NO_XDG
    gchar* env = path_from_env("XDG_CONFIG_HOME");
    if (env)
      Zathura.Config.config_dir = env;
    else
#endif
      Zathura.Config.config_dir = fix_path(CONFIG_DIR);
  }
  if (!Zathura.Config.data_dir)
  {
#ifndef ZATHURA_NO_XDG
    gchar* env = path_from_env("XDG_DATA_HOME");
    if (env)
      Zathura.Config.data_dir = env;
    else
#endif
      Zathura.Config.data_dir = fix_path(DATA_DIR);
  }
Moritz Lipp's avatar
Moritz Lipp committed
614

615
616
617
618
619
620
  /* create zathura (config/data) directory */
  g_mkdir_with_parents(Zathura.Config.config_dir, 0771);
  g_mkdir_with_parents(Zathura.Config.data_dir,   0771);
}

void
Sebastian Ramacher's avatar
Sebastian Ramacher committed
621
init_bookmarks(void)
622
{
623
624
625
626
  /* init variables */
  Zathura.Bookmarks.number_of_bookmarks = 0;
  Zathura.Bookmarks.bookmarks = NULL;

627
628
  Zathura.Bookmarks.file = g_build_filename(Zathura.Config.data_dir, BOOKMARK_FILE, NULL);
  read_bookmarks_file();
Moritz Lipp's avatar
Moritz Lipp committed
629
630
}

Moritz Lipp's avatar
Moritz Lipp committed
631
void
Sebastian Ramacher's avatar
Sebastian Ramacher committed
632
init_keylist(void)
Moritz Lipp's avatar
Moritz Lipp committed
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
{
  ShortcutList* e = NULL;
  ShortcutList* p = NULL;

  int i;
  for(i = 0; i < LENGTH(shortcuts); i++)
  {
    e = malloc(sizeof(ShortcutList));
    if(!e)
      out_of_memory();

    e->element = shortcuts[i];
    e->next    = NULL;

    if(!Zathura.Bindings.sclist)
      Zathura.Bindings.sclist = e;
    if(p)
      p->next = e;

    p = e;
  }
}

656
void
Sebastian Ramacher's avatar
Sebastian Ramacher committed
657
init_settings(void)
658
{
Moritz Lipp's avatar
Moritz Lipp committed
659
  Zathura.State.filename     = g_strdup((char*) default_text);
660
  Zathura.Global.adjust_mode = adjust_open;
661

Moritz Lipp's avatar
Moritz Lipp committed
662
  gtk_window_set_default_size(GTK_WINDOW(Zathura.UI.window), default_width, default_height);
663
664
}

Moritz Lipp's avatar
Moritz Lipp committed
665
void
Sebastian Ramacher's avatar
Sebastian Ramacher committed
666
init_zathura(void)
667
{
668
669
670
  /* init mutexes */
  g_static_mutex_init(&(Zathura.Lock.pdflib_lock));
  g_static_mutex_init(&(Zathura.Lock.search_lock));
int3's avatar
int3 committed
671
  g_static_mutex_init(&(Zathura.Lock.pdf_obj_lock));
Moritz Lipp's avatar
Moritz Lipp committed
672
  g_static_mutex_init(&(Zathura.Lock.select_lock));
Moritz Lipp's avatar
Moritz Lipp committed
673

674
  /* other */
Moritz Lipp's avatar
Moritz Lipp committed
675
676
677
678
679
680
681
  Zathura.Global.mode           = NORMAL;
  Zathura.Global.viewing_mode   = NORMAL;
  Zathura.Global.recolor        = 0;
  Zathura.Global.goto_mode      = GOTO_MODE;
  Zathura.Global.show_index     = FALSE;
  Zathura.Global.show_inputbar  = TRUE;
  Zathura.Global.show_statusbar = TRUE;
682

683
  Zathura.State.pages             = g_strdup("");
Moritz Lipp's avatar
Moritz Lipp committed
684
  Zathura.State.scroll_percentage = 0;
Moritz Lipp's avatar
Moritz Lipp committed
685

Moritz Lipp's avatar
Moritz Lipp committed
686
687
688
689
  Zathura.Marker.markers           = NULL;
  Zathura.Marker.number_of_markers =  0;
  Zathura.Marker.last              = -1;

Moritz Lipp's avatar
Moritz Lipp committed
690
691
  Zathura.Search.results = NULL;
  Zathura.Search.page    = 0;
Moritz Lipp's avatar
Moritz Lipp committed
692
  Zathura.Search.draw    = FALSE;
Moritz Lipp's avatar
Moritz Lipp committed
693
  Zathura.Search.query   = NULL;
Moritz Lipp's avatar
Moritz Lipp committed
694

695
  Zathura.FileMonitor.monitor = NULL;
Moritz Lipp's avatar
Moritz Lipp committed
696
  Zathura.FileMonitor.file    = NULL;
Moritz Lipp's avatar
Moritz Lipp committed
697

698
699
  Zathura.StdinSupport.file   = NULL;

Moritz Lipp's avatar
Moritz Lipp committed
700
701
702
703
704
705
  /* window */
  if(Zathura.UI.embed)
    Zathura.UI.window = gtk_plug_new(Zathura.UI.embed);
  else
    Zathura.UI.window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

706
707
  /* UI */
  Zathura.UI.box               = GTK_BOX(gtk_vbox_new(FALSE, 0));
Moritz Lipp's avatar
Moritz Lipp committed
708
  Zathura.UI.continuous        = GTK_BOX(gtk_vbox_new(FALSE, 0));
709
  Zathura.UI.view              = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new(NULL, NULL));
710
  Zathura.UI.viewport          = GTK_VIEWPORT(gtk_viewport_new(NULL, NULL));
Moritz Lipp's avatar
Moritz Lipp committed
711
  Zathura.UI.drawing_area      = gtk_drawing_area_new();
712
713
714
  Zathura.UI.statusbar         = gtk_event_box_new();
  Zathura.UI.statusbar_entries = GTK_BOX(gtk_hbox_new(FALSE, 0));
  Zathura.UI.inputbar          = GTK_ENTRY(gtk_entry_new());
715
  Zathura.UI.document            = gtk_event_box_new();
Moritz Lipp's avatar
Moritz Lipp committed
716
717

  /* window */
Moritz Lipp's avatar
Moritz Lipp committed
718
  gtk_window_set_title(GTK_WINDOW(Zathura.UI.window), "zathura");
719
  GdkGeometry hints = { 1, 1 };
Moritz Lipp's avatar
Moritz Lipp committed
720
  gtk_window_set_geometry_hints(GTK_WINDOW(Zathura.UI.window), NULL, &hints, GDK_HINT_MIN_SIZE);
721
  g_signal_connect(G_OBJECT(Zathura.UI.window), "destroy", G_CALLBACK(cb_destroy), NULL);
722

723
724
725
  /* box */
  gtk_box_set_spacing(Zathura.UI.box, 0);
  gtk_container_add(GTK_CONTAINER(Zathura.UI.window), GTK_WIDGET(Zathura.UI.box));
Moritz Lipp's avatar
Moritz Lipp committed
726

Moritz Lipp's avatar
Moritz Lipp committed
727
728
729
  /* continuous */
  gtk_box_set_spacing(Zathura.UI.continuous, 5);

730
731
732
733
734
735
736
737
  /* events */
  gtk_container_add(GTK_CONTAINER(Zathura.UI.document), GTK_WIDGET(Zathura.UI.drawing_area));
  gtk_widget_add_events(GTK_WIDGET(Zathura.UI.document), GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK |
      GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);

  g_signal_connect(G_OBJECT(Zathura.UI.document), "button-press-event",   G_CALLBACK(cb_view_button_pressed), NULL);
  g_signal_connect(G_OBJECT(Zathura.UI.document), "button-release-event", G_CALLBACK(cb_view_button_release), NULL);
  g_signal_connect(G_OBJECT(Zathura.UI.document), "motion-notify-event",  G_CALLBACK(cb_view_motion_notify),  NULL);
Moritz Lipp's avatar
Moritz Lipp committed
738
  gtk_widget_show(Zathura.UI.document);
739

740
  /* view */
741
742
743
  g_signal_connect(G_OBJECT(Zathura.UI.view), "key-press-event",      G_CALLBACK(cb_view_kb_pressed),     NULL);
  g_signal_connect(G_OBJECT(Zathura.UI.view), "size-allocate",        G_CALLBACK(cb_view_resized),        NULL);
  g_signal_connect(G_OBJECT(Zathura.UI.view), "scroll-event",         G_CALLBACK(cb_view_scrolled),       NULL);
744
  gtk_container_add(GTK_CONTAINER(Zathura.UI.view), GTK_WIDGET(Zathura.UI.viewport));
Moritz Lipp's avatar
Moritz Lipp committed
745
  gtk_viewport_set_shadow_type(Zathura.UI.viewport, GTK_SHADOW_NONE);
Moritz Lipp's avatar
Moritz Lipp committed
746

Moritz Lipp's avatar
Moritz Lipp committed
747
748
749
750
  /* drawing area */
  gtk_widget_show(Zathura.UI.drawing_area);
  g_signal_connect(G_OBJECT(Zathura.UI.drawing_area), "expose-event", G_CALLBACK(cb_draw), NULL);

751
752
753
754
  /* statusbar */
  Zathura.Global.status_text   = GTK_LABEL(gtk_label_new(NULL));
  Zathura.Global.status_state  = GTK_LABEL(gtk_label_new(NULL));
  Zathura.Global.status_buffer = GTK_LABEL(gtk_label_new(NULL));
Moritz Lipp's avatar
Moritz Lipp committed
755

756
757
758
  gtk_misc_set_alignment(GTK_MISC(Zathura.Global.status_text),  0.0, 0.0);
  gtk_misc_set_alignment(GTK_MISC(Zathura.Global.status_state), 1.0, 0.0);
  gtk_misc_set_alignment(GTK_MISC(Zathura.Global.status_buffer), 1.0, 0.0);
759

760
761
762
  gtk_misc_set_padding(GTK_MISC(Zathura.Global.status_text),  2.0, 4.0);
  gtk_misc_set_padding(GTK_MISC(Zathura.Global.status_state), 2.0, 4.0);
  gtk_misc_set_padding(GTK_MISC(Zathura.Global.status_buffer), 2.0, 4.0);
763

764
765
766
  gtk_label_set_use_markup(Zathura.Global.status_text,  TRUE);
  gtk_label_set_use_markup(Zathura.Global.status_state, TRUE);
  gtk_label_set_use_markup(Zathura.Global.status_buffer, TRUE);
767

768
769
770
  gtk_box_pack_start(Zathura.UI.statusbar_entries, GTK_WIDGET(Zathura.Global.status_text),  TRUE,  TRUE,  2);
  gtk_box_pack_start(Zathura.UI.statusbar_entries, GTK_WIDGET(Zathura.Global.status_buffer), FALSE, FALSE, 2);
  gtk_box_pack_start(Zathura.UI.statusbar_entries, GTK_WIDGET(Zathura.Global.status_state), FALSE, FALSE, 2);
771

772
  gtk_container_add(GTK_CONTAINER(Zathura.UI.statusbar), GTK_WIDGET(Zathura.UI.statusbar_entries));
773

774
775
776
777
  /* inputbar */
  gtk_entry_set_inner_border(Zathura.UI.inputbar, NULL);
  gtk_entry_set_has_frame(   Zathura.UI.inputbar, FALSE);
  gtk_editable_set_editable( GTK_EDITABLE(Zathura.UI.inputbar), TRUE);
Moritz Lipp's avatar
Moritz Lipp committed
778

Moritz Lipp's avatar
Moritz Lipp committed
779
780
781
782
  Zathura.Handler.inputbar_key_press_event =
    g_signal_connect(G_OBJECT(Zathura.UI.inputbar), "key-press-event",   G_CALLBACK(cb_inputbar_kb_pressed), NULL);
  Zathura.Handler.inputbar_activate =
    g_signal_connect(G_OBJECT(Zathura.UI.inputbar), "activate",          G_CALLBACK(cb_inputbar_activate),   NULL);
783

784
785
786
787
  /* packing */
  gtk_box_pack_start(Zathura.UI.box, GTK_WIDGET(Zathura.UI.view),      TRUE,  TRUE,  0);
  gtk_box_pack_start(Zathura.UI.box, GTK_WIDGET(Zathura.UI.statusbar), FALSE, FALSE, 0);
  gtk_box_pack_end(  Zathura.UI.box, GTK_WIDGET(Zathura.UI.inputbar),  FALSE, FALSE, 0);
788
789
}

Moritz Lipp's avatar
Moritz Lipp committed
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
void
add_marker(int id)
{
  if( (id < 0x30) || (id > 0x7A))
    return;

  /* current information */
  int page_number = Zathura.PDF.page_number;

  /* search if entry already exists */
  int i;
  for(i = 0; i < Zathura.Marker.number_of_markers; i++)
  {
    if(Zathura.Marker.markers[i].id == id)
    {
      Zathura.Marker.markers[i].page = page_number;
      Zathura.Marker.last            = page_number;
      return;
    }
  }

  /* add new marker */
  int marker_index = Zathura.Marker.number_of_markers++;
  Zathura.Marker.markers = realloc(Zathura.Marker.markers, sizeof(Marker) *
      (Zathura.Marker.number_of_markers));

  Zathura.Marker.markers[marker_index].id   = id;
  Zathura.Marker.markers[marker_index].page = page_number;
  Zathura.Marker.last                       = page_number;
}

Moritz Lipp's avatar
Moritz Lipp committed
821
822
823
824
825
826
827
828
829
830
831
832
833
834
void
build_index(GtkTreeModel* model, GtkTreeIter* parent, PopplerIndexIter* index_iter)
{
  do
  {
    GtkTreeIter       tree_iter;
    PopplerIndexIter *child;
    PopplerAction    *action;
    gchar            *markup;

    action = poppler_index_iter_get_action(index_iter);
    if(!action)
      continue;

835
    markup = g_markup_escape_text (action->any.title, -1);
Moritz Lipp's avatar
Moritz Lipp committed
836
837

    gtk_tree_store_append(GTK_TREE_STORE(model), &tree_iter, parent);
838
    gtk_tree_store_set(GTK_TREE_STORE(model), &tree_iter, 0, markup, 1, action, -1);
Moritz Lipp's avatar
Moritz Lipp committed
839
840
841
842
843
844
845
    g_object_weak_ref(G_OBJECT(model), (GWeakNotify) poppler_action_free, action);
    g_free(markup);

    child = poppler_index_iter_get_child(index_iter);
    if(child)
      build_index(model, &tree_iter, child);
    poppler_index_iter_free(child);
846
  } while(poppler_index_iter_next(index_iter));
Moritz Lipp's avatar
Moritz Lipp committed
847
848
849
850
}

void
draw(int page_id)
Moritz Lipp's avatar
Moritz Lipp committed
851
{
Moritz Lipp's avatar
Moritz Lipp committed
852
  if(!Zathura.PDF.document || page_id < 0 || page_id >= Zathura.PDF.number_of_pages)
Moritz Lipp's avatar
Moritz Lipp committed
853
854
855
856
    return;

  double page_width, page_height;
  double width, height;
Moritz Lipp's avatar
Moritz Lipp committed
857

Moritz Lipp's avatar
Moritz Lipp committed
858
  double scale = ((double) Zathura.PDF.scale / 100.0);
Moritz Lipp's avatar
Moritz Lipp committed
859

Moritz Lipp's avatar
Moritz Lipp committed
860
861
  int rotate = Zathura.PDF.rotate;

Moritz Lipp's avatar
Moritz Lipp committed
862
863
  Page *current_page = Zathura.PDF.pages[page_id];

Moritz Lipp's avatar
Moritz Lipp committed
864
865
866
  if(Zathura.PDF.surface)
    cairo_surface_destroy(Zathura.PDF.surface);
  Zathura.PDF.surface = NULL;
Moritz Lipp's avatar
Moritz Lipp committed
867

868
  g_static_mutex_lock(&(Zathura.Lock.pdflib_lock));
Moritz Lipp's avatar
Moritz Lipp committed
869
  poppler_page_get_size(current_page->page, &page_width, &page_height);
870
  g_static_mutex_unlock(&(Zathura.Lock.pdflib_lock));
Moritz Lipp's avatar
Moritz Lipp committed
871

Moritz Lipp's avatar
Moritz Lipp committed
872
  if(rotate == 0 || rotate == 180)
Moritz Lipp's avatar
Moritz Lipp committed
873
  {
Moritz Lipp's avatar
Moritz Lipp committed
874
875
    width  = page_width  * scale;
    height = page_height * scale;
Moritz Lipp's avatar
Moritz Lipp committed
876
877
878
  }
  else
  {
Moritz Lipp's avatar
Moritz Lipp committed
879
880
    width  = page_height * scale;
    height = page_width  * scale;
Moritz Lipp's avatar
Moritz Lipp committed
881
882
883
  }

  cairo_t *cairo;
Moritz Lipp's avatar
Moritz Lipp committed
884
885
  Zathura.PDF.surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, width, height);
  cairo = cairo_create(Zathura.PDF.surface);
Moritz Lipp's avatar
Moritz Lipp committed
886

Moritz Lipp's avatar
Moritz Lipp committed
887
  cairo_save(cairo);
Moritz Lipp's avatar
Moritz Lipp committed
888
889
890
  cairo_set_source_rgb(cairo, 1, 1, 1);
  cairo_rectangle(cairo, 0, 0, width, height);
  cairo_fill(cairo);
Moritz Lipp's avatar
Moritz Lipp committed
891
892
  cairo_restore(cairo);
  cairo_save(cairo);
Moritz Lipp's avatar
Moritz Lipp committed
893

Moritz Lipp's avatar
Moritz Lipp committed
894
  switch(rotate)
Moritz Lipp's avatar
Moritz Lipp committed
895
896
897
898
899
900
901
902
903
904
905
906
907
908
  {
    case 90:
      cairo_translate(cairo, width, 0);
      break;
    case 180:
      cairo_translate(cairo, width, height);
      break;
    case 270:
      cairo_translate(cairo, 0, height);
      break;
    default:
      cairo_translate(cairo, 0, 0);
  }

Moritz Lipp's avatar
Moritz Lipp committed
909
910
  if(scale != 1.0)
    cairo_scale(cairo, scale, scale);
Moritz Lipp's avatar
Moritz Lipp committed
911

Moritz Lipp's avatar
Moritz Lipp committed
912
913
  if(rotate != 0)
    cairo_rotate(cairo, rotate * G_PI / 180.0);
Moritz Lipp's avatar
Moritz Lipp committed
914

915
  g_static_mutex_lock(&(Zathura.Lock.pdflib_lock));
Moritz Lipp's avatar
Moritz Lipp committed
916
  poppler_page_render(current_page->page, cairo);
917
  g_static_mutex_unlock(&(Zathura.Lock.pdflib_lock));
Moritz Lipp's avatar
Moritz Lipp committed
918

Moritz Lipp's avatar
Moritz Lipp committed
919
920
921
  cairo_restore(cairo);
  cairo_destroy(cairo);

922
  if(Zathura.Global.recolor)
Moritz Lipp's avatar
Moritz Lipp committed
923
  {
Moritz Lipp's avatar
Moritz Lipp committed
924
    unsigned char* image = cairo_image_surface_get_data(Zathura.PDF.surface);
925
    int x, y;
Moritz Lipp's avatar
Moritz Lipp committed
926

927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
    int width     = cairo_image_surface_get_width(Zathura.PDF.surface);
    int height    = cairo_image_surface_get_height(Zathura.PDF.surface);
    int rowstride = cairo_image_surface_get_stride(Zathura.PDF.surface);

    /* recolor code based on qimageblitz library flatten() function
    (http://sourceforge.net/projects/qimageblitz/) */

    int r1 = Zathura.Style.recolor_darkcolor.red    / 257;
    int g1 = Zathura.Style.recolor_darkcolor.green  / 257;
    int b1 = Zathura.Style.recolor_darkcolor.blue   / 257;
    int r2 = Zathura.Style.recolor_lightcolor.red   / 257;
    int g2 = Zathura.Style.recolor_lightcolor.green / 257;
    int b2 = Zathura.Style.recolor_lightcolor.blue  / 257;

    int min = 0x00;
    int max = 0xFF;
    int mean;

    float sr = ((float) r2 - r1) / (max - min);
    float sg = ((float) g2 - g1) / (max - min);
    float sb = ((float) b2 - b1) / (max - min);

Moritz Lipp's avatar
Moritz Lipp committed
949
    for (y = 0; y < height; y++)
950
951
952
    {
      unsigned char* data = image + y * rowstride;

Moritz Lipp's avatar
Moritz Lipp committed
953
      for (x = 0; x < width; x++)
954
955
956
957
958
959
960
961
      {
        mean = (data[0] + data[1] + data[2]) / 3;
        data[2] = sr * (mean - min) + r1 + 0.5;
        data[1] = sg * (mean - min) + g1 + 0.5;
        data[0] = sb * (mean - min) + b1 + 0.5;
        data += 4;
      }
    }
Moritz Lipp's avatar
Moritz Lipp committed
962
  }
Moritz Lipp's avatar
Moritz Lipp committed
963

Moritz Lipp's avatar
Moritz Lipp committed
964
965
  gtk_widget_set_size_request(Zathura.UI.drawing_area, width, height);
  gtk_widget_queue_draw(Zathura.UI.drawing_area);
Moritz Lipp's avatar
Moritz Lipp committed
966
967
}

968
969
void
change_mode(int mode)
970
{
Moritz Lipp's avatar
Moritz Lipp committed
971
972
973
974
975
976
977
  char* mode_text = 0;
  for(unsigned int i = 0; i != LENGTH(mode_names); ++i)
    if(mode_names[i].mode == mode)
    {
      mode_text = mode_names[i].display;
      break;
    }
978

Moritz Lipp's avatar
Moritz Lipp committed
979
  if(!mode_text)
980
  {
Moritz Lipp's avatar
Moritz Lipp committed
981
982
983
984
985
986
987
988
989
990
991
992
993
    switch(mode)
    {
      case ADD_MARKER:
        mode_text = "";
        break;
      case EVAL_MARKER:
        mode_text = "";
        break;
      default:
        mode_text = "";
        mode      = NORMAL;
        break;
    }
994
995
  }

996
997
  Zathura.Global.mode = mode;
  notify(DEFAULT, mode_text);
998
999
}

1000
void
For faster browsing, not all history is shown. View entire blame