Merge branch 'first-page' into 'develop'

Add shortcut to cycle opening column in dual page mode

Closes #191, #234, and #257

See merge request pwmt/zathura!97
This commit is contained in:
Sebastian Ramacher 2024-04-30 21:12:24 +02:00
commit caf087ca20
7 changed files with 184 additions and 12 deletions

View File

@ -127,6 +127,8 @@ General
Show index and switch to **Index mode**
d
Toggle dual page view
D
Cycle opening column in dual page view
F5
Switch to presentation mode
F11

View File

@ -225,6 +225,10 @@ They can also be combined with modifiers:
Change current mode. Pass the desired mode as argument.
* ``cycle_first_page``
In multiple page layout, cycle the column in which the first page is displayed.
* ``display_link``:
Display link target.

View File

@ -443,6 +443,7 @@ void config_load_default(zathura_t* zathura) {
girara_shortcut_add(gsession, GDK_CONTROL_MASK, GDK_KEY_n, NULL, girara_sc_toggle_statusbar, (mode), 0, NULL); \
girara_shortcut_add(gsession, GDK_CONTROL_MASK, GDK_KEY_m, NULL, girara_sc_toggle_inputbar, (mode), 0, NULL); \
girara_shortcut_add(gsession, 0, GDK_KEY_d, NULL, sc_toggle_page_mode, (mode), 0, NULL); \
girara_shortcut_add(gsession, 0, GDK_KEY_D, NULL, sc_cycle_first_column, (mode), 0, NULL); \
\
girara_shortcut_add(gsession, 0, GDK_KEY_q, NULL, sc_quit, (mode), 0, NULL); \
\
@ -596,6 +597,7 @@ void config_load_default(zathura_t* zathura) {
girara_shortcut_mapping_add(gsession, "adjust_window", sc_adjust_window);
girara_shortcut_mapping_add(gsession, "bisect", sc_bisect);
girara_shortcut_mapping_add(gsession, "change_mode", sc_change_mode);
girara_shortcut_mapping_add(gsession, "cycle_first_column", sc_cycle_first_column);
girara_shortcut_mapping_add(gsession, "display_link", sc_display_link);
girara_shortcut_mapping_add(gsession, "copy_link", sc_copy_link);
girara_shortcut_mapping_add(gsession, "copy_filepath", sc_copy_filepath);

View File

@ -150,6 +150,34 @@ sc_change_mode(girara_session_t* session, girara_argument_t* argument,
return false;
}
bool
sc_cycle_first_column(girara_session_t* session, girara_argument_t* UNUSED(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;
if (zathura->document == NULL) {
girara_notify(session, GIRARA_WARNING, _("No document opened."));
return false;
}
int pages_per_row = 1;
girara_setting_get(session, "pages-per-row", &pages_per_row);
char* first_page_column_list = NULL;
girara_setting_get(session, "first-page-column", &first_page_column_list);
if (t == 0) t = 1;
char* new_column_list = increment_first_page_column(first_page_column_list, pages_per_row, t);
g_free(first_page_column_list);
girara_setting_set(session, "first-page-column", new_column_list);
g_free(new_column_list);
return true;
}
bool
sc_display_link(girara_session_t* session, girara_argument_t* UNUSED(argument),
girara_event_t* UNUSED(event), unsigned int UNUSED(t))

View File

@ -38,6 +38,17 @@ bool sc_adjust_window(girara_session_t* session, girara_argument_t* argument, gi
*/
bool sc_change_mode(girara_session_t* session, girara_argument_t* argument, girara_event_t* event, unsigned int t);
/**
* Cycle the column the first page is displayed in
*
* @param session The used girara session
* @param argument The used argument
* @param event Girara event
* @param t Number of executions
* @return true if no error occurred otherwise false
*/
bool sc_cycle_first_column(girara_session_t* session, girara_argument_t* argument, girara_event_t* event, unsigned int t);
/**
* Display a link
*

View File

@ -244,6 +244,52 @@ get_selection(zathura_t* zathura)
return selection;
}
char*
write_first_page_column_list(unsigned int* first_page_columns, unsigned int size)
{
if (first_page_columns == NULL)
return NULL;
char** tokens = g_malloc_n(size+1, sizeof(char*));
tokens[size] = NULL;
for (unsigned int i=0; i<size; i++) {
tokens[i] = g_strdup_printf("%d", first_page_columns[i]);
}
char* first_page_column_list = g_strjoinv(":", tokens);
g_strfreev(tokens);
return first_page_column_list;
}
unsigned int*
parse_first_page_column_list(const char* first_page_column_list, unsigned int* size)
{
if (first_page_column_list == NULL || size == NULL)
return NULL;
char** tokens = g_strsplit(first_page_column_list, ":", 0);
unsigned int length = g_strv_length(tokens);
unsigned int* settings = g_malloc_n(length, sizeof(unsigned int));
for (unsigned int i=0; i<length; i++) {
unsigned long column = 1;
if (g_ascii_string_to_unsigned(tokens[i], 10, 1, i+1, &column, NULL)) {
settings[i] = (unsigned int)column;
} else {
settings[i] = 1;
}
}
g_strfreev(tokens);
*size = length;
return settings;
}
unsigned int
find_first_page_column(const char* first_page_column_list,
const unsigned int pages_per_row)
@ -251,27 +297,70 @@ find_first_page_column(const char* first_page_column_list,
/* sanity checks */
unsigned int first_page_column = 1;
g_return_val_if_fail(first_page_column_list != NULL, first_page_column);
g_return_val_if_fail(*first_page_column_list != '\0', first_page_column);
g_return_val_if_fail(pages_per_row > 0, first_page_column);
/* split settings list */
char** settings = g_strsplit(first_page_column_list, ":", pages_per_row + 1);
const size_t settings_size = g_strv_length(settings);
unsigned int size = 0;
unsigned int* settings = parse_first_page_column_list(first_page_column_list, &size);
/* read setting value corresponding to the specified pages per row */
unsigned int index = pages_per_row - 1;
if (index < settings_size && *settings[index] != '\0') {
first_page_column = atoi(settings[index]);
} else if (*settings[settings_size - 1] != '\0') {
first_page_column = atoi(settings[settings_size - 1]);
if (pages_per_row <= size) {
first_page_column = settings[pages_per_row - 1];
} else if (size > 0) {
first_page_column = settings[size - 1];
}
/* free buffers */
g_strfreev(settings);
g_free(settings);
return first_page_column;
}
char*
increment_first_page_column(const char* first_page_column_list,
const unsigned int pages_per_row, int incr)
{
/* sanity checks */
if (first_page_column_list == NULL)
first_page_column_list = "";
/* This function is a no-op for 1 column layout */
if (pages_per_row <= 1)
return g_strdup(first_page_column_list);
unsigned int size = 0;
unsigned int* settings = parse_first_page_column_list(first_page_column_list, &size);
/* Lookup current setting. Signed value to avoid negative overflow when modifying it later. */
int column = 1;
if (pages_per_row <= size) {
column = settings[pages_per_row - 1];
} else if (size > 0) {
column = settings[size - 1];
}
/* increment and normalise to [1,pages_per_row]. */
column += incr;
column %= pages_per_row; /* range [-pages_per_row+1, pages_per_row-1] */
if (column <= 0)
column += pages_per_row; /* range [1, pages_per_row] */
/* Write back, creating the new cell if necessary. */
if (pages_per_row <= size) {
settings[pages_per_row - 1] = column;
} else {
/* extend settings array */
settings = g_realloc_n(settings, pages_per_row, sizeof(*settings));
for (unsigned int i=size; i<pages_per_row-1; i++) {
/* The value of the last set cell is normally used for all largers pages_per_row,
* so duplicate it to the newly created cells. */
settings[i] = settings[size - 1];
}
settings[pages_per_row-1] = column;
size = pages_per_row;
}
char* new_column_list = write_first_page_column_list(settings, size);
g_free(settings);
return new_column_list;
}
bool
parse_color(GdkRGBA* color, const char* str)
{

View File

@ -107,6 +107,30 @@ GdkAtom* get_selection(zathura_t* zathura);
double zathura_correct_zoom_value(girara_session_t* session, const double
zoom);
/**
* Write a list of 'pages per row to first column' values as a colon separated string.
*
* For valid settings list, this is the inverse of parse_first_page_column_list.
*
* @param[in] first_page_columns The settings vector
* @param[in] size The size of the settings vector
*
* @return The new settings string
*/
char* write_first_page_column(unsigned int* first_page_columns, unsigned int size);
/**
* Parse a 'pages per row to first column' settings list.
*
* For valid settings list, this is the inverse of write_first_page_column_list.
*
* @param[in] first_page_column_list The settings list
* @param[in] size A cell to return the size of the result, mandatory
*
* @return The values from the settings list as a new vector
*/
unsigned int* parse_first_page_column(const char* first_page_column_list, unsigned int* size);
/**
* Extracts the column the first page should be rendered in from the specified
* list of settings corresponding to the specified pages per row
@ -119,6 +143,18 @@ double zathura_correct_zoom_value(girara_session_t* session, const double
unsigned int find_first_page_column(const char* first_page_column_list,
const unsigned int pages_per_row);
/**
* Cycle the column the first page should be rendered in.
*
* @param[in] first_page_column_list The settings list
* @param[in] pages_per_row The current pages per row
* @param[in] incr The value added to the current first page column setting
*
* @return The new modified settings list
*/
char* increment_first_page_column(const char* first_page_column_list,
const unsigned int pages_per_row, int incr);
/**
* Parse color string and print warning if color cannot be parsed.
*