From 28b5bb8b78a9e1a0409f3e19825c2a279ee2af8d Mon Sep 17 00:00:00 2001 From: Dave Davenport Date: Wed, 18 Aug 2021 01:16:45 +0200 Subject: [PATCH] [Cleanup] Using clang-tidy --- include/css-colors.h | 17 +- include/dialogs/drun.h | 3 +- include/dialogs/filebrowser.h | 7 +- include/dialogs/help-keys.h | 1 + include/dialogs/script.h | 6 +- include/dialogs/ssh.h | 2 +- include/dialogs/window.h | 3 +- include/display.h | 16 +- include/helper.h | 160 +- include/rofi-types.h | 437 +++--- include/timings.h | 18 +- include/widgets/box.h | 1 + include/widgets/listview.h | 2 + source/css-colors.c | 302 ++-- source/dialogs/combi.c | 510 +++--- source/dialogs/dmenu.c | 1372 +++++++++-------- source/dialogs/drun.c | 2519 +++++++++++++++--------------- source/dialogs/filebrowser.c | 1029 ++++++------- source/dialogs/help-keys.c | 143 +- source/dialogs/run.c | 895 ++++++----- source/dialogs/script.c | 728 +++++---- source/dialogs/ssh.c | 894 ++++++----- source/dialogs/window.c | 1562 ++++++++++--------- source/helper.c | 2232 +++++++++++++-------------- source/history.c | 551 ++++--- source/keyb.c | 2 +- source/mode.c | 214 ++- source/rofi-icon-fetcher.c | 2 +- source/rofi.c | 2 +- source/theme.c | 2640 +++++++++++++++---------------- source/timings.c | 37 +- source/view.c | 2 +- source/widgets/box.c | 605 ++++---- source/widgets/container.c | 153 +- source/widgets/icon.c | 233 ++- source/widgets/listview.c | 1692 ++++++++++---------- source/widgets/scrollbar.c | 216 ++- source/widgets/textbox.c | 1434 +++++++++-------- source/widgets/widget.c | 1154 +++++++------- source/xcb.c | 2743 +++++++++++++++++---------------- source/xrmoptions.c | 1526 ++++++++++-------- 41 files changed, 13115 insertions(+), 12950 deletions(-) diff --git a/include/css-colors.h b/include/css-colors.h index e442c6aa..b357a65c 100644 --- a/include/css-colors.h +++ b/include/css-colors.h @@ -1,6 +1,7 @@ #ifndef ROFI_INCLUDE_CSS_COLORS_H #define ROFI_INCLUDE_CSS_COLORS_H +#include /** * @defgroup CSSCOLORS CssColors * @ingroup HELPERS @@ -13,16 +14,16 @@ /** * Structure of colors. */ -typedef struct CSSColor -{ - /** CSS name of the color. */ - char *name; - /** BGRA 8 bit color components. */ - uint8_t b, g, r, a; -}CSSColor; +typedef struct CSSColor { + /** CSS name of the color. */ + char *name; + /** BGRA 8 bit color components. */ + uint8_t b, g, r, a; +} CSSColor; /** - * Array with all the named colors. Of type #CSSColor, there are #num_CSSColors items in this array. + * Array with all the named colors. Of type #CSSColor, there are #num_CSSColors + * items in this array. */ extern const CSSColor CSSColors[]; /** diff --git a/include/dialogs/drun.h b/include/dialogs/drun.h index be6e0afa..c74a2673 100644 --- a/include/dialogs/drun.h +++ b/include/dialogs/drun.h @@ -28,12 +28,13 @@ #ifndef ROFI_DIALOG_DRUN_H #define ROFI_DIALOG_DRUN_H +#include "mode.h" + /** * @defgroup DRUNMode DRun * @ingroup MODES * @{ */ -#include #ifdef ENABLE_DRUN /** #Mode object representing the desktop menu run dialog. */ extern Mode drun_mode; diff --git a/include/dialogs/filebrowser.h b/include/dialogs/filebrowser.h index aa77cd32..1e9c0fd6 100644 --- a/include/dialogs/filebrowser.h +++ b/include/dialogs/filebrowser.h @@ -27,7 +27,7 @@ #ifndef ROFI_DIALOG_FILE_BROWSER_H #define ROFI_DIALOG_FILE_BROWSER_H - +#include "mode.h" /** * @defgroup FileBrowserMode FileBrowser * @ingroup MODES @@ -42,7 +42,7 @@ extern Mode file_browser_mode; * Create a new filebrowser. * @returns a new filebrowser structure. */ -Mode *create_new_file_browser ( void ); +Mode *create_new_file_browser(void); /** * @param sw Mode object. * @param mretv return value passed in. @@ -52,6 +52,7 @@ Mode *create_new_file_browser ( void ); * * @returns the state the user selected. */ -ModeMode file_browser_mode_completer ( Mode *sw, int mretv, char **input, unsigned int selected_line, char **path ); +ModeMode file_browser_mode_completer(Mode *sw, int mretv, char **input, + unsigned int selected_line, char **path); /**@}*/ #endif // ROFI_DIALOG_FILE_BROWSER_H diff --git a/include/dialogs/help-keys.h b/include/dialogs/help-keys.h index 062a4278..64f0c0b2 100644 --- a/include/dialogs/help-keys.h +++ b/include/dialogs/help-keys.h @@ -28,6 +28,7 @@ #ifndef ROFI_DIALOG_HELPKEYS_H #define ROFI_DIALOG_HELPKEYS_H +#include "mode.h" /** * @defgroup HELPKEYSMode KeysHelp * @ingroup MODES diff --git a/include/dialogs/script.h b/include/dialogs/script.h index c1d1b8d4..090139d6 100644 --- a/include/dialogs/script.h +++ b/include/dialogs/script.h @@ -28,6 +28,8 @@ #ifndef ROFI_DIALOG_SCRIPT_H #define ROFI_DIALOG_SCRIPT_H +#include "mode.h" + /** * @defgroup SCRIPTMode Script * @ingroup MODES @@ -42,7 +44,7 @@ * * @returns NULL when it fails, a newly allocated ScriptOptions when successful. */ -Mode *script_switcher_parse_setup ( const char *str ); +Mode *script_switcher_parse_setup(const char *str); /** * @param token The modi str to check @@ -51,6 +53,6 @@ Mode *script_switcher_parse_setup ( const char *str ); * * @returns true when valid. */ -gboolean script_switcher_is_valid ( const char *token ); +gboolean script_switcher_is_valid(const char *token); /**@}*/ #endif // ROFI_DIALOG_SCRIPT_H diff --git a/include/dialogs/ssh.h b/include/dialogs/ssh.h index 9f72797a..ab95022b 100644 --- a/include/dialogs/ssh.h +++ b/include/dialogs/ssh.h @@ -27,7 +27,7 @@ #ifndef ROFI_DIALOG_SSH_H #define ROFI_DIALOG_SSH_H - +#include "mode.h" /** * @defgroup SSHMode SSH * @ingroup MODES diff --git a/include/dialogs/window.h b/include/dialogs/window.h index 4f0e0526..c25c1368 100644 --- a/include/dialogs/window.h +++ b/include/dialogs/window.h @@ -28,13 +28,14 @@ #ifndef ROFI_DIALOG_WINDOW_H #define ROFI_DIALOG_WINDOW_H +#include "mode.h" + /** * @defgroup WINDOWMode Window * @ingroup MODES * * @{ */ -#include #ifdef WINDOW_MODE extern Mode window_mode; diff --git a/include/display.h b/include/display.h index 1972d48f..12c9eb09 100644 --- a/include/display.h +++ b/include/display.h @@ -28,9 +28,9 @@ #ifndef ROFI_DISPLAY_H #define ROFI_DISPLAY_H -#include #include "helper.h" #include "nkutils-bindings.h" +#include /** * @param main_loop The GMainLoop @@ -40,29 +40,29 @@ * * @returns Whether the setup succeeded or not */ -gboolean display_setup ( GMainLoop *main_loop, NkBindings *bindings ); +gboolean display_setup(GMainLoop *main_loop, NkBindings *bindings); /** * Do some late setup of the display backend * * @returns Whether the setup succeeded or not */ -gboolean display_late_setup ( void ); +gboolean display_late_setup(void); /** * Do some early cleanup, like unmapping the surface */ -void display_early_cleanup ( void ); +void display_early_cleanup(void); /** * Cleanup any remaining display related stuff */ -void display_cleanup ( void ); +void display_cleanup(void); /** * Dumps the display layout for -help output */ -void display_dump_monitor_layout ( void ); +void display_dump_monitor_layout(void); /** * @param context The startup notification context for the application to launch @@ -71,6 +71,8 @@ void display_dump_monitor_layout ( void ); * * Provides the needed child setup function */ -void display_startup_notification ( RofiHelperExecuteContext *context, GSpawnChildSetupFunc *child_setup, gpointer *user_data ); +void display_startup_notification(RofiHelperExecuteContext *context, + GSpawnChildSetupFunc *child_setup, + gpointer *user_data); #endif diff --git a/include/helper.h b/include/helper.h index 6204776a..6de3c74c 100644 --- a/include/helper.h +++ b/include/helper.h @@ -27,8 +27,8 @@ #ifndef ROFI_HELPER_H #define ROFI_HELPER_H -#include #include "rofi-types.h" +#include G_BEGIN_DECLS /** @@ -51,7 +51,7 @@ G_BEGIN_DECLS * * @returns TRUE when successful, FALSE when failed. */ -int helper_parse_setup ( char * string, char ***output, int *length, ... ); +int helper_parse_setup(char *string, char ***output, int *length, ...); /** * @param input The input string. @@ -61,14 +61,14 @@ int helper_parse_setup ( char * string, char ***output, int *length, ... ); * * @returns a newly allocated array of matching objects */ -rofi_int_matcher **helper_tokenize ( const char *input, int case_sensitive ); +rofi_int_matcher **helper_tokenize(const char *input, int case_sensitive); /** * @param tokens Array of regex objects * * Frees the array of matching objects. */ -void helper_tokenize_free ( rofi_int_matcher ** tokens ); +void helper_tokenize_free(rofi_int_matcher **tokens); /** * @param key The key to search for @@ -79,7 +79,7 @@ void helper_tokenize_free ( rofi_int_matcher ** tokens ); * * @returns TRUE if key was found and val was set. */ -int find_arg_char ( const char * const key, char *val ); +int find_arg_char(const char *const key, char *val); /** * @param key The key to search for @@ -89,7 +89,7 @@ int find_arg_char ( const char * const key, char *val ); * * @returns TRUE if key was found and val was set. */ -int find_arg_uint ( const char * const key, unsigned int *val ); +int find_arg_uint(const char *const key, unsigned int *val); /** * @param key The key to search for @@ -99,7 +99,7 @@ int find_arg_uint ( const char * const key, unsigned int *val ); * * @returns TRUE if key was found and val was set. */ -int find_arg_int ( const char * const key, int *val ); +int find_arg_int(const char *const key, int *val); /** * @param key The key to search for @@ -109,7 +109,7 @@ int find_arg_int ( const char * const key, int *val ); * * @returns TRUE if key was found and val was set. */ -int find_arg_str ( const char * const key, char** val ); +int find_arg_str(const char *const key, char **val); /** * @param key The key to search for @@ -118,7 +118,7 @@ int find_arg_str ( const char * const key, char** val ); * * @returns str vector. user should free array. */ -const char ** find_arg_strv ( const char *const key ); +const char **find_arg_strv(const char *const key); /** * @param key The key to search for * @@ -126,7 +126,7 @@ const char ** find_arg_strv ( const char *const key ); * * @returns return position of string or -1 if not found. */ -int find_arg ( const char * const key ); +int find_arg(const char *const key); /** * @param tokens List of (input) tokens to match. @@ -136,36 +136,37 @@ int find_arg ( const char * const key ); * * @returns TRUE when matches, FALSE otherwise */ -int helper_token_match ( rofi_int_matcher * const *tokens, const char *input ); +int helper_token_match(rofi_int_matcher *const *tokens, const char *input); /** * @param cmd The command to execute. * - * Execute cmd using config.run_command and outputs the result (stdout) to the opened file - * descriptor. + * Execute cmd using config.run_command and outputs the result (stdout) to the + * opened file descriptor. * * @returns a valid file descriptor on success, or -1 on failure. */ -int execute_generator ( const char * cmd ) __attribute__( ( nonnull ) ); +int execute_generator(const char *cmd) __attribute__((nonnull)); /** * @param pidfile The pidfile to create. * * returns file descriptor (or -1 when failed) */ -int create_pid_file ( const char *pidfile ); +int create_pid_file(const char *pidfile); /** * Remove pid file */ -void remove_pid_file ( int fd ); +void remove_pid_file(int fd); /** * Do some input validation, especially the first few could break things. * It is good to catch them beforehand. * - * This functions exits the program with 1 when it finds an invalid configuration. + * This functions exits the program with 1 when it finds an invalid + * configuration. */ -int config_sanity_check ( void ); +int config_sanity_check(void); /** * @param arg string to parse. @@ -174,7 +175,7 @@ int config_sanity_check ( void ); * * @returns character. */ -char helper_parse_char ( const char *arg ); +char helper_parse_char(const char *arg); /** * @param argc number of arguments. @@ -182,7 +183,7 @@ char helper_parse_char ( const char *arg ); * * Set the application arguments. */ -void cmd_set_arguments ( int argc, char **argv ); +void cmd_set_arguments(int argc, char **argv); /** * @param input The path to expand @@ -191,7 +192,7 @@ void cmd_set_arguments ( int argc, char **argv ); * * @returns path */ -char *rofi_expand_path ( const char *input ); +char *rofi_expand_path(const char *input); /** * @param needle The string to find match weight off @@ -203,17 +204,19 @@ char *rofi_expand_path ( const char *input ); * * @returns the levenshtein distance between needle and haystack */ -unsigned int levenshtein ( const char *needle, const glong needlelen, const char *haystack, const glong haystacklen ); +unsigned int levenshtein(const char *needle, const glong needlelen, + const char *haystack, const glong haystacklen); /** * @param data the unvalidated character array holding possible UTF-8 data * @param length the length of the data array * - * Convert string to valid utf-8, replacing invalid parts with replacement character. + * Convert string to valid utf-8, replacing invalid parts with replacement + * character. * * @returns the converted UTF-8 string */ -char * rofi_force_utf8 ( const gchar *data, ssize_t length ); +char *rofi_force_utf8(const gchar *data, ssize_t length); /** * @param input the char array holding latin text @@ -223,7 +226,7 @@ char * rofi_force_utf8 ( const gchar *data, ssize_t length ); * * @return the UTF-8 representation of data */ -char * rofi_latin_to_utf8_strdup ( const char *input, gssize length ); +char *rofi_latin_to_utf8_strdup(const char *input, gssize length); /** * @param text the string to escape @@ -232,7 +235,7 @@ char * rofi_latin_to_utf8_strdup ( const char *input, gssize length ); * * @return the escaped string */ -gchar *rofi_escape_markup ( gchar *text ); +gchar *rofi_escape_markup(gchar *text); /** * @param pattern The user input to match against. @@ -240,28 +243,35 @@ gchar *rofi_escape_markup ( gchar *text ); * @param str The input to match against pattern. * @param slen Length of str. * - * rofi_scorer_fuzzy_evaluate implements a global sequence alignment algorithm to find the maximum accumulated score by - * aligning `pattern` to `str`. It applies when `pattern` is a subsequence of `str`. + * rofi_scorer_fuzzy_evaluate implements a global sequence alignment algorithm + * to find the maximum accumulated score by aligning `pattern` to `str`. It + * applies when `pattern` is a subsequence of `str`. * * Scoring criteria - * - Prefer matches at the start of a word, or the start of subwords in CamelCase/camelCase/camel123 words. See WORD_START_SCORE/CAMEL_SCORE. + * - Prefer matches at the start of a word, or the start of subwords in + * CamelCase/camelCase/camel123 words. See WORD_START_SCORE/CAMEL_SCORE. * - Non-word characters matter. See NON_WORD_SCORE. - * - The first characters of words of `pattern` receive bonus because they usually have more significance than the rest. - * See PATTERN_START_MULTIPLIER/PATTERN_NON_START_MULTIPLIER. - * - Superfluous characters in `str` will reduce the score (gap penalty). See GAP_SCORE. - * - Prefer early occurrence of the first character. See LEADING_GAP_SCORE/GAP_SCORE. + * - The first characters of words of `pattern` receive bonus because they + * usually have more significance than the rest. See + * PATTERN_START_MULTIPLIER/PATTERN_NON_START_MULTIPLIER. + * - Superfluous characters in `str` will reduce the score (gap penalty). See + * GAP_SCORE. + * - Prefer early occurrence of the first character. See + * LEADING_GAP_SCORE/GAP_SCORE. * * The recurrence of the dynamic programming: * dp[i][j]: maximum accumulated score by aligning pattern[0..i] to str[0..j] * dp[0][j] = leading_gap_penalty(0, j) + score[j] - * dp[i][j] = max(dp[i-1][j-1] + CONSECUTIVE_SCORE, max(dp[i-1][k] + gap_penalty(k+1, j) + score[j] : k < j)) + * dp[i][j] = max(dp[i-1][j-1] + CONSECUTIVE_SCORE, max(dp[i-1][k] + + * gap_penalty(k+1, j) + score[j] : k < j)) * - * The first dimension can be suppressed since we do not need a matching scheme, which reduces the space complexity from - * O(N*M) to O(M) + * The first dimension can be suppressed since we do not need a matching + * scheme, which reduces the space complexity from O(N*M) to O(M) * * @returns the sorting weight. */ -int rofi_scorer_fuzzy_evaluate ( const char *pattern, glong plen, const char *str, glong slen ); +int rofi_scorer_fuzzy_evaluate(const char *pattern, glong plen, const char *str, + glong slen); /*@}*/ /** @@ -271,31 +281,31 @@ int rofi_scorer_fuzzy_evaluate ( const char *pattern, glong plen, const char *st * * Compares the `G_NORMALIZE_ALL_COMPOSE` forms of the two strings. * - * @returns less than, equal to, or greater than zero if the first `n` characters (not bytes) of `a` - * are found, respectively, to be less than, to match, or be greater than the first `n` - * characters (not bytes) of `b`. + * @returns less than, equal to, or greater than zero if the first `n` + * characters (not bytes) of `a` are found, respectively, to be less than, to + * match, or be greater than the first `n` characters (not bytes) of `b`. */ -int utf8_strncmp ( const char *a, const char* b, size_t n ) __attribute__( ( nonnull ( 1, 2 ) ) ); +int utf8_strncmp(const char *a, const char *b, size_t n) + __attribute__((nonnull(1, 2))); /** * The startup notification context of the application to launch */ -typedef struct -{ - /** The name of the application */ - const gchar *name; - /** The binary name of the application */ - const gchar *binary; - /** The description of the launch */ - const gchar *description; - /** The icon name of the application */ - const gchar *icon; - /** The application id (desktop file with the .desktop suffix) */ - const gchar *app_id; - /** The window manager class of the application */ - const gchar *wmclass; - /** The command we run */ - const gchar *command; +typedef struct { + /** The name of the application */ + const gchar *name; + /** The binary name of the application */ + const gchar *binary; + /** The description of the launch */ + const gchar *description; + /** The icon name of the application */ + const gchar *icon; + /** The application id (desktop file with the .desktop suffix) */ + const gchar *app_id; + /** The window manager class of the application */ + const gchar *wmclass; + /** The command we run */ + const gchar *command; } RofiHelperExecuteContext; /** @@ -309,7 +319,9 @@ typedef struct * * @returns TRUE when successful, FALSE when failed. */ -gboolean helper_execute ( const char *wd, char **args, const char *error_precmd, const char *error_cmd, RofiHelperExecuteContext *context ); +gboolean helper_execute(const char *wd, char **args, const char *error_precmd, + const char *error_cmd, + RofiHelperExecuteContext *context); /** * @param wd The work directory (optional) @@ -322,7 +334,9 @@ gboolean helper_execute ( const char *wd, char **args, const char *error_precmd, * * @returns FALSE On failure, TRUE on success */ -gboolean helper_execute_command ( const char *wd, const char *cmd, gboolean run_in_term, RofiHelperExecuteContext *context ); +gboolean helper_execute_command(const char *wd, const char *cmd, + gboolean run_in_term, + RofiHelperExecuteContext *context); /** * @param file The file path @@ -331,7 +345,8 @@ gboolean helper_execute_command ( const char *wd, const char *cmd, gboolean run_ * * @returns a cairo surface from an svg path */ -cairo_surface_t *cairo_image_surface_create_from_svg ( const gchar* file, int height ); +cairo_surface_t *cairo_image_surface_create_from_svg(const gchar *file, + int height); /** * Ranges. @@ -344,7 +359,7 @@ cairo_surface_t *cairo_image_surface_create_from_svg ( const gchar* file, int he * * ranges */ -void parse_ranges ( char *input, rofi_range_pair **list, unsigned int *length ); +void parse_ranges(char *input, rofi_range_pair **list, unsigned int *length); /** * @param format The format string used. See below for possible syntax. @@ -361,25 +376,28 @@ void parse_ranges ( char *input, rofi_range_pair **list, unsigned int *length ); * * f: Print the entered filter. * * F: Print the entered filter, quoted * - * This functions outputs the formatted string to stdout, appends a newline (\n) character and - * calls flush on the file descriptor. + * This functions outputs the formatted string to stdout, appends a newline (\n) + * character and calls flush on the file descriptor. */ -void rofi_output_formatted_line ( const char *format, const char *string, int selected_line, const char *filter ); +void rofi_output_formatted_line(const char *format, const char *string, + int selected_line, const char *filter); /** * @param string The string with elements to be replaced - * @param ... Set of {key}, value that will be replaced, terminated by a NULL + * @param ... Set of {key}, value that will be replaced, terminated by a + * NULL * - * Items {key} are replaced by the value if '{key}' is passed as key/value pair, otherwise removed from string. - * If the {key} is in between [] all the text between [] are removed if {key} - * is not found. Otherwise key is replaced and [ & ] removed. + * Items {key} are replaced by the value if '{key}' is passed as key/value pair, + * otherwise removed from string. If the {key} is in between [] all the text + * between [] are removed if {key} is not found. Otherwise key is replaced and [ + * & ] removed. * * This allows for optional replacement, f.e. '{ssh-client} [-t {title}] -e * "{cmd}"' the '-t {title}' is only there if {title} is set. * * @returns a new string with the keys replaced. */ -char *helper_string_replace_if_exists ( char * string, ... ); +char *helper_string_replace_if_exists(char *string, ...); /** * @param file File name passed to option. @@ -387,9 +405,7 @@ char *helper_string_replace_if_exists ( char * string, ... ); * * @returns path to theme or copy of filename if not found. */ -char *helper_get_theme_path ( const char *file, const char *ext ); - - +char *helper_get_theme_path(const char *file, const char *ext); G_END_DECLS diff --git a/include/rofi-types.h b/include/rofi-types.h index e3f862e5..49ea42c6 100644 --- a/include/rofi-types.h +++ b/include/rofi-types.h @@ -1,6 +1,5 @@ #ifndef INCLUDE_ROFI_TYPES_H #define INCLUDE_ROFI_TYPES_H - #include #include G_BEGIN_DECLS @@ -8,232 +7,213 @@ G_BEGIN_DECLS /** * Type of property */ -typedef enum -{ - /** Integer */ - P_INTEGER, - /** Double */ - P_DOUBLE, - /** String */ - P_STRING, - /** Character */ - P_CHAR, - /** Boolean */ - P_BOOLEAN, - /** Color */ - P_COLOR, - /** Image */ - P_IMAGE, - /** RofiPadding */ - P_PADDING, - /** Link to global setting */ - P_LINK, - /** Position */ - P_POSITION, - /** Highlight */ - P_HIGHLIGHT, - /** List */ - P_LIST, - /** Orientation */ - P_ORIENTATION, - /** Cursor */ - P_CURSOR, - /** Inherit */ - P_INHERIT, - /** Number of types. */ - P_NUM_TYPES, +typedef enum { + /** Integer */ + P_INTEGER, + /** Double */ + P_DOUBLE, + /** String */ + P_STRING, + /** Character */ + P_CHAR, + /** Boolean */ + P_BOOLEAN, + /** Color */ + P_COLOR, + /** Image */ + P_IMAGE, + /** RofiPadding */ + P_PADDING, + /** Link to global setting */ + P_LINK, + /** Position */ + P_POSITION, + /** Highlight */ + P_HIGHLIGHT, + /** List */ + P_LIST, + /** Orientation */ + P_ORIENTATION, + /** Cursor */ + P_CURSOR, + /** Inherit */ + P_INHERIT, + /** Number of types. */ + P_NUM_TYPES, } PropertyType; /** * This array maps PropertyType to a user-readable name. * It is important this is kept in sync. */ -extern const char * const PropertyTypeName[P_NUM_TYPES]; +extern const char *const PropertyTypeName[P_NUM_TYPES]; /** Style of text highlight */ -typedef enum -{ - /** no highlight */ - ROFI_HL_NONE = 0, - /** bold */ - ROFI_HL_BOLD = 1, - /** underline */ - ROFI_HL_UNDERLINE = 2, - /** strikethrough */ - ROFI_HL_STRIKETHROUGH = 16, - /** small caps */ - ROFI_HL_SMALL_CAPS = 32, - /** italic */ - ROFI_HL_ITALIC = 4, - /** color */ - ROFI_HL_COLOR = 8 +typedef enum { + /** no highlight */ + ROFI_HL_NONE = 0, + /** bold */ + ROFI_HL_BOLD = 1, + /** underline */ + ROFI_HL_UNDERLINE = 2, + /** strikethrough */ + ROFI_HL_STRIKETHROUGH = 16, + /** small caps */ + ROFI_HL_SMALL_CAPS = 32, + /** italic */ + ROFI_HL_ITALIC = 4, + /** color */ + ROFI_HL_COLOR = 8 } RofiHighlightStyle; /** Style of line */ -typedef enum -{ - /** Solid line */ - ROFI_HL_SOLID, - /** Dashed line */ - ROFI_HL_DASH +typedef enum { + /** Solid line */ + ROFI_HL_SOLID, + /** Dashed line */ + ROFI_HL_DASH } RofiLineStyle; /** * Distance unit type. */ -typedef enum -{ - /** PixelWidth in pixels. */ - ROFI_PU_PX, - /** PixelWidth in millimeters. */ - ROFI_PU_MM, - /** PixelWidth in EM. */ - ROFI_PU_EM, - /** PixelWidget in percentage */ - ROFI_PU_PERCENT, - /** PixelWidth in CH. */ - ROFI_PU_CH, +typedef enum { + /** PixelWidth in pixels. */ + ROFI_PU_PX, + /** PixelWidth in millimeters. */ + ROFI_PU_MM, + /** PixelWidth in EM. */ + ROFI_PU_EM, + /** PixelWidget in percentage */ + ROFI_PU_PERCENT, + /** PixelWidth in CH. */ + ROFI_PU_CH, } RofiPixelUnit; /** * Structure representing a distance. */ -typedef enum -{ - ROFI_DISTANCE_MODIFIER_NONE, - ROFI_DISTANCE_MODIFIER_ADD, - ROFI_DISTANCE_MODIFIER_SUBTRACT, - ROFI_DISTANCE_MODIFIER_DIVIDE, - ROFI_DISTANCE_MODIFIER_MULTIPLY, - ROFI_DISTANCE_MODIFIER_MODULO, - ROFI_DISTANCE_MODIFIER_GROUP, - ROFI_DISTANCE_MODIFIER_MIN, - ROFI_DISTANCE_MODIFIER_MAX, +typedef enum { + ROFI_DISTANCE_MODIFIER_NONE, + ROFI_DISTANCE_MODIFIER_ADD, + ROFI_DISTANCE_MODIFIER_SUBTRACT, + ROFI_DISTANCE_MODIFIER_DIVIDE, + ROFI_DISTANCE_MODIFIER_MULTIPLY, + ROFI_DISTANCE_MODIFIER_MODULO, + ROFI_DISTANCE_MODIFIER_GROUP, + ROFI_DISTANCE_MODIFIER_MIN, + ROFI_DISTANCE_MODIFIER_MAX, } RofiDistanceModifier; -typedef struct RofiDistanceUnit -{ - /** Distance */ - double distance; - /** Unit type of the distance */ - RofiPixelUnit type; +typedef struct RofiDistanceUnit { + /** Distance */ + double distance; + /** Unit type of the distance */ + RofiPixelUnit type; - /** Type */ - RofiDistanceModifier modtype; + /** Type */ + RofiDistanceModifier modtype; - /** Modifier */ - struct RofiDistanceUnit *left; + /** Modifier */ + struct RofiDistanceUnit *left; - /** Modifier */ - struct RofiDistanceUnit *right; + /** Modifier */ + struct RofiDistanceUnit *right; } RofiDistanceUnit; -typedef struct -{ - /** Base */ - RofiDistanceUnit base; - /** Style of the line (optional)*/ - RofiLineStyle style; +typedef struct { + /** Base */ + RofiDistanceUnit base; + /** Style of the line (optional)*/ + RofiLineStyle style; } RofiDistance; /** * Type of orientation. */ -typedef enum -{ - ROFI_ORIENTATION_VERTICAL, - ROFI_ORIENTATION_HORIZONTAL +typedef enum { + ROFI_ORIENTATION_VERTICAL, + ROFI_ORIENTATION_HORIZONTAL } RofiOrientation; /** * Cursor type. */ -typedef enum -{ - ROFI_CURSOR_DEFAULT, - ROFI_CURSOR_POINTER, - ROFI_CURSOR_TEXT +typedef enum { + ROFI_CURSOR_DEFAULT, + ROFI_CURSOR_POINTER, + ROFI_CURSOR_TEXT } RofiCursorType; /** * Represent the color in theme. */ -typedef struct -{ - /** red channel */ - double red; - /** green channel */ - double green; - /** blue channel */ - double blue; - /** alpha channel */ - double alpha; +typedef struct { + /** red channel */ + double red; + /** green channel */ + double green; + /** blue channel */ + double blue; + /** alpha channel */ + double alpha; } ThemeColor; /** * Theme Image */ -typedef enum -{ - ROFI_IMAGE_URL, - ROFI_IMAGE_LINEAR_GRADIENT -} RofiImageType; +typedef enum { ROFI_IMAGE_URL, ROFI_IMAGE_LINEAR_GRADIENT } RofiImageType; -typedef enum -{ - ROFI_DIRECTION_LEFT, - ROFI_DIRECTION_RIGHT, - ROFI_DIRECTION_TOP, - ROFI_DIRECTION_BOTTOM, - ROFI_DIRECTION_ANGLE, +typedef enum { + ROFI_DIRECTION_LEFT, + ROFI_DIRECTION_RIGHT, + ROFI_DIRECTION_TOP, + ROFI_DIRECTION_BOTTOM, + ROFI_DIRECTION_ANGLE, } RofiDirection; -typedef enum -{ - ROFI_SCALE_NONE, - ROFI_SCALE_BOTH, - ROFI_SCALE_HEIGHT, - ROFI_SCALE_WIDTH, +typedef enum { + ROFI_SCALE_NONE, + ROFI_SCALE_BOTH, + ROFI_SCALE_HEIGHT, + ROFI_SCALE_WIDTH, } RofiScaleType; -typedef struct -{ - RofiImageType type; - char *url; - RofiScaleType scaling; - int wsize; - int hsize; +typedef struct { + RofiImageType type; + char *url; + RofiScaleType scaling; + int wsize; + int hsize; - RofiDirection dir; - double angle; - /** colors */ - GList *colors; + RofiDirection dir; + double angle; + /** colors */ + GList *colors; - /** cached image */ - uint32_t surface_id; + /** cached image */ + uint32_t surface_id; } RofiImage; /** * RofiPadding */ -typedef struct -{ - RofiDistance top; - RofiDistance right; - RofiDistance bottom; - RofiDistance left; +typedef struct { + RofiDistance top; + RofiDistance right; + RofiDistance bottom; + RofiDistance left; } RofiPadding; /** * Theme highlight. */ -typedef struct -{ - /** style to display */ - RofiHighlightStyle style; - /** Color */ - ThemeColor color; +typedef struct { + /** style to display */ + RofiHighlightStyle style; + /** Color */ + ThemeColor color; } RofiHighlightColorStyle; /** @@ -245,100 +225,93 @@ typedef struct * * @ingroup CONFIGURATION */ -typedef enum -{ - /** Center */ - WL_CENTER = 0, - /** Top middle */ - WL_NORTH = 1, - /** Middle right */ - WL_EAST = 2, - /** Bottom middle */ - WL_SOUTH = 4, - /** Middle left */ - WL_WEST = 8, - /** Left top corner. */ - WL_NORTH_WEST = WL_NORTH | WL_WEST, - /** Top right */ - WL_NORTH_EAST = WL_NORTH | WL_EAST, - /** Bottom right */ - WL_SOUTH_EAST = WL_SOUTH | WL_EAST, - /** Bottom left */ - WL_SOUTH_WEST = WL_SOUTH | WL_WEST, +typedef enum { + /** Center */ + WL_CENTER = 0, + /** Top middle */ + WL_NORTH = 1, + /** Middle right */ + WL_EAST = 2, + /** Bottom middle */ + WL_SOUTH = 4, + /** Middle left */ + WL_WEST = 8, + /** Left top corner. */ + WL_NORTH_WEST = WL_NORTH | WL_WEST, + /** Top right */ + WL_NORTH_EAST = WL_NORTH | WL_EAST, + /** Bottom right */ + WL_SOUTH_EAST = WL_SOUTH | WL_EAST, + /** Bottom left */ + WL_SOUTH_WEST = WL_SOUTH | WL_WEST, } WindowLocation; -typedef union _PropertyValue -{ - /** integer */ - int i; - /** Double */ - double f; - /** String */ - char *s; - /** Character */ - char c; - /** boolean */ - gboolean b; - /** Color */ - ThemeColor color; - /** RofiPadding */ - RofiPadding padding; - /** Reference */ - struct - { - /** Name */ - char *name; - /** Cached looked up ref */ - struct Property *ref; - /** Property default */ - struct Property *def_value; - } link; - /** Highlight Style */ - RofiHighlightColorStyle highlight; - /** Image */ - RofiImage image; - /** List */ - GList *list; +typedef union _PropertyValue { + /** integer */ + int i; + /** Double */ + double f; + /** String */ + char *s; + /** Character */ + char c; + /** boolean */ + gboolean b; + /** Color */ + ThemeColor color; + /** RofiPadding */ + RofiPadding padding; + /** Reference */ + struct { + /** Name */ + char *name; + /** Cached looked up ref */ + struct Property *ref; + /** Property default */ + struct Property *def_value; + } link; + /** Highlight Style */ + RofiHighlightColorStyle highlight; + /** Image */ + RofiImage image; + /** List */ + GList *list; } PropertyValue; /** * Property structure. */ -typedef struct Property -{ - /** Name of property */ - char *name; - /** Type of property. */ - PropertyType type; - /** Value */ - PropertyValue value; +typedef struct Property { + /** Name of property */ + char *name; + /** Type of property. */ + PropertyType type; + /** Value */ + PropertyValue value; } Property; /** * Structure to hold a range. */ -typedef struct rofi_range_pair -{ - int start; - int stop; +typedef struct rofi_range_pair { + int start; + int stop; } rofi_range_pair; /** * Internal structure for matching. */ -typedef struct rofi_int_matcher_t -{ - GRegex *regex; - gboolean invert; +typedef struct rofi_int_matcher_t { + GRegex *regex; + gboolean invert; } rofi_int_matcher; /** * Structure with data to process by each worker thread. * TODO: Make this more generic wrapper. */ -typedef struct _thread_state -{ - void ( *callback )( struct _thread_state *t, gpointer data ); +typedef struct _thread_state { + void (*callback)(struct _thread_state *t, gpointer data); } thread_state; extern GThreadPool *tpool; diff --git a/include/timings.h b/include/timings.h index 81685f55..a3d8b024 100644 --- a/include/timings.h +++ b/include/timings.h @@ -32,13 +32,12 @@ */ #ifndef ROFI_TIMINGS_H #define ROFI_TIMINGS_H -#include /** * Init the timestamping mechanism . * implementation. */ -void rofi_timings_init ( void ); +void rofi_timings_init(void); /** * @param file filename tick originates from * @param str function name. @@ -47,30 +46,31 @@ void rofi_timings_init ( void ); * * Report a tick. */ -void rofi_timings_tick ( const char *file, char const *str, int line, char const *msg ); +void rofi_timings_tick(const char *file, char const *str, int line, + char const *msg); /** * Stop the timestamping mechanism */ -void rofi_timings_quit ( void ); +void rofi_timings_quit(void); /** * Start timestamping mechanism. * Call to this function is time 0. */ -#define TIMINGS_START() rofi_timings_init () +#define TIMINGS_START() rofi_timings_init() /** * Report current time since TIMINGS_START */ -#define TICK() rofi_timings_tick ( __FILE__, __func__, __LINE__, "" ) +#define TICK() rofi_timings_tick(__FILE__, __func__, __LINE__, "") /** * @param a an string * Report current time since TIMINGS_START */ -#define TICK_N( a ) rofi_timings_tick ( __FILE__, __func__, __LINE__, a ) +#define TICK_N(a) rofi_timings_tick(__FILE__, __func__, __LINE__, a) /** * Stop timestamping mechanism. */ -#define TIMINGS_STOP() rofi_timings_quit () +#define TIMINGS_STOP() rofi_timings_quit() #else @@ -91,7 +91,7 @@ void rofi_timings_quit ( void ); * @param a an string * Report current time since TIMINGS_START */ -#define TICK_N( a ) +#define TICK_N(a) #endif // ROFI_TIMINGS_H /**@}*/ diff --git a/include/widgets/box.h b/include/widgets/box.h index 18c68788..fa455f4f 100644 --- a/include/widgets/box.h +++ b/include/widgets/box.h @@ -29,6 +29,7 @@ #define ROFI_HBOX_H #include "widget.h" +#include "rofi-types.h" /** * @defgroup box box diff --git a/include/widgets/listview.h b/include/widgets/listview.h index f9d2510c..5e3410c0 100644 --- a/include/widgets/listview.h +++ b/include/widgets/listview.h @@ -28,6 +28,8 @@ #ifndef ROFI_LISTVIEW_H #define ROFI_LISTVIEW_H +#include "widgets/textbox.h" + /** * @defgroup listview listview * @ingroup widget diff --git a/source/css-colors.c b/source/css-colors.c index cc2a6b35..9d136056 100644 --- a/source/css-colors.c +++ b/source/css-colors.c @@ -1,154 +1,152 @@ -#include #include "css-colors.h" -const CSSColor CSSColors[] = { - { .name = "AliceBlue", .r = 0xF0, .g = 0xF8, .b = 0xFF }, - { .name = "AntiqueWhite", .r = 0xFA, .g = 0xEB, .b = 0xD7 }, - { .name = "Aqua", .r = 0x00, .g = 0xFF, .b = 0xFF }, - { .name = "Aquamarine", .r = 0x7F, .g = 0xFF, .b = 0xD4 }, - { .name = "Azure", .r = 0xF0, .g = 0xFF, .b = 0xFF }, - { .name = "Beige", .r = 0xF5, .g = 0xF5, .b = 0xDC }, - { .name = "Bisque", .r = 0xFF, .g = 0xE4, .b = 0xC4 }, - { .name = "Black", .r = 0x00, .g = 0x00, .b = 0x00 }, - { .name = "BlanchedAlmond", .r = 0xFF, .g = 0xEB, .b = 0xCD }, - { .name = "Blue", .r = 0x00, .g = 0x00, .b = 0xFF }, - { .name = "BlueViolet", .r = 0x8A, .g = 0x2B, .b = 0xE2 }, - { .name = "Brown", .r = 0xA5, .g = 0x2A, .b = 0x2A }, - { .name = "BurlyWood", .r = 0xDE, .g = 0xB8, .b = 0x87 }, - { .name = "CadetBlue", .r = 0x5F, .g = 0x9E, .b = 0xA0 }, - { .name = "Chartreuse", .r = 0x7F, .g = 0xFF, .b = 0x00 }, - { .name = "Chocolate", .r = 0xD2, .g = 0x69, .b = 0x1E }, - { .name = "Coral", .r = 0xFF, .g = 0x7F, .b = 0x50 }, - { .name = "CornflowerBlue", .r = 0x64, .g = 0x95, .b = 0xED }, - { .name = "Cornsilk", .r = 0xFF, .g = 0xF8, .b = 0xDC }, - { .name = "Crimson", .r = 0xDC, .g = 0x14, .b = 0x3C }, - { .name = "Cyan", .r = 0x00, .g = 0xFF, .b = 0xFF }, - { .name = "DarkBlue", .r = 0x00, .g = 0x00, .b = 0x8B }, - { .name = "DarkCyan", .r = 0x00, .g = 0x8B, .b = 0x8B }, - { .name = "DarkGoldenRod", .r = 0xB8, .g = 0x86, .b = 0x0B }, - { .name = "DarkGray", .r = 0xA9, .g = 0xA9, .b = 0xA9 }, - { .name = "DarkGrey", .r = 0xA9, .g = 0xA9, .b = 0xA9 }, - { .name = "DarkGreen", .r = 0x00, .g = 0x64, .b = 0x00 }, - { .name = "DarkKhaki", .r = 0xBD, .g = 0xB7, .b = 0x6B }, - { .name = "DarkMagenta", .r = 0x8B, .g = 0x00, .b = 0x8B }, - { .name = "DarkOliveGreen", .r = 0x55, .g = 0x6B, .b = 0x2F }, - { .name = "DarkOrange", .r = 0xFF, .g = 0x8C, .b = 0x00 }, - { .name = "DarkOrchid", .r = 0x99, .g = 0x32, .b = 0xCC }, - { .name = "DarkRed", .r = 0x8B, .g = 0x00, .b = 0x00 }, - { .name = "DarkSalmon", .r = 0xE9, .g = 0x96, .b = 0x7A }, - { .name = "DarkSeaGreen", .r = 0x8F, .g = 0xBC, .b = 0x8F }, - { .name = "DarkSlateBlue", .r = 0x48, .g = 0x3D, .b = 0x8B }, - { .name = "DarkSlateGray", .r = 0x2F, .g = 0x4F, .b = 0x4F }, - { .name = "DarkSlateGrey", .r = 0x2F, .g = 0x4F, .b = 0x4F }, - { .name = "DarkTurquoise", .r = 0x00, .g = 0xCE, .b = 0xD1 }, - { .name = "DarkViolet", .r = 0x94, .g = 0x00, .b = 0xD3 }, - { .name = "DeepPink", .r = 0xFF, .g = 0x14, .b = 0x93 }, - { .name = "DeepSkyBlue", .r = 0x00, .g = 0xBF, .b = 0xFF }, - { .name = "DimGray", .r = 0x69, .g = 0x69, .b = 0x69 }, - { .name = "DimGrey", .r = 0x69, .g = 0x69, .b = 0x69 }, - { .name = "DodgerBlue", .r = 0x1E, .g = 0x90, .b = 0xFF }, - { .name = "FireBrick", .r = 0xB2, .g = 0x22, .b = 0x22 }, - { .name = "FloralWhite", .r = 0xFF, .g = 0xFA, .b = 0xF0 }, - { .name = "ForestGreen", .r = 0x22, .g = 0x8B, .b = 0x22 }, - { .name = "Fuchsia", .r = 0xFF, .g = 0x00, .b = 0xFF }, - { .name = "Gainsboro", .r = 0xDC, .g = 0xDC, .b = 0xDC }, - { .name = "GhostWhite", .r = 0xF8, .g = 0xF8, .b = 0xFF }, - { .name = "Gold", .r = 0xFF, .g = 0xD7, .b = 0x00 }, - { .name = "GoldenRod", .r = 0xDA, .g = 0xA5, .b = 0x20 }, - { .name = "Gray", .r = 0x80, .g = 0x80, .b = 0x80 }, - { .name = "Grey", .r = 0x80, .g = 0x80, .b = 0x80 }, - { .name = "Green", .r = 0x00, .g = 0x80, .b = 0x00 }, - { .name = "GreenYellow", .r = 0xAD, .g = 0xFF, .b = 0x2F }, - { .name = "HoneyDew", .r = 0xF0, .g = 0xFF, .b = 0xF0 }, - { .name = "HotPink", .r = 0xFF, .g = 0x69, .b = 0xB4 }, - { .name = "IndianRed", .r = 0xCD, .g = 0x5C, .b = 0x5C }, - { .name = "Indigo", .r = 0x4B, .g = 0x00, .b = 0x82 }, - { .name = "Ivory", .r = 0xFF, .g = 0xFF, .b = 0xF0 }, - { .name = "Khaki", .r = 0xF0, .g = 0xE6, .b = 0x8C }, - { .name = "Lavender", .r = 0xE6, .g = 0xE6, .b = 0xFA }, - { .name = "LavenderBlush", .r = 0xFF, .g = 0xF0, .b = 0xF5 }, - { .name = "LawnGreen", .r = 0x7C, .g = 0xFC, .b = 0x00 }, - { .name = "LemonChiffon", .r = 0xFF, .g = 0xFA, .b = 0xCD }, - { .name = "LightBlue", .r = 0xAD, .g = 0xD8, .b = 0xE6 }, - { .name = "LightCoral", .r = 0xF0, .g = 0x80, .b = 0x80 }, - { .name = "LightCyan", .r = 0xE0, .g = 0xFF, .b = 0xFF }, - { .name = "LightGoldenRodYellow", .r = 0xFA, .g = 0xFA, .b = 0xD2 }, - { .name = "LightGray", .r = 0xD3, .g = 0xD3, .b = 0xD3 }, - { .name = "LightGrey", .r = 0xD3, .g = 0xD3, .b = 0xD3 }, - { .name = "LightGreen", .r = 0x90, .g = 0xEE, .b = 0x90 }, - { .name = "LightPink", .r = 0xFF, .g = 0xB6, .b = 0xC1 }, - { .name = "LightSalmon", .r = 0xFF, .g = 0xA0, .b = 0x7A }, - { .name = "LightSeaGreen", .r = 0x20, .g = 0xB2, .b = 0xAA }, - { .name = "LightSkyBlue", .r = 0x87, .g = 0xCE, .b = 0xFA }, - { .name = "LightSlateGray", .r = 0x77, .g = 0x88, .b = 0x99 }, - { .name = "LightSlateGrey", .r = 0x77, .g = 0x88, .b = 0x99 }, - { .name = "LightSteelBlue", .r = 0xB0, .g = 0xC4, .b = 0xDE }, - { .name = "LightYellow", .r = 0xFF, .g = 0xFF, .b = 0xE0 }, - { .name = "Lime", .r = 0x00, .g = 0xFF, .b = 0x00 }, - { .name = "LimeGreen", .r = 0x32, .g = 0xCD, .b = 0x32 }, - { .name = "Linen", .r = 0xFA, .g = 0xF0, .b = 0xE6 }, - { .name = "Magenta", .r = 0xFF, .g = 0x00, .b = 0xFF }, - { .name = "Maroon", .r = 0x80, .g = 0x00, .b = 0x00 }, - { .name = "MediumAquaMarine", .r = 0x66, .g = 0xCD, .b = 0xAA }, - { .name = "MediumBlue", .r = 0x00, .g = 0x00, .b = 0xCD }, - { .name = "MediumOrchid", .r = 0xBA, .g = 0x55, .b = 0xD3 }, - { .name = "MediumPurple", .r = 0x93, .g = 0x70, .b = 0xDB }, - { .name = "MediumSeaGreen", .r = 0x3C, .g = 0xB3, .b = 0x71 }, - { .name = "MediumSlateBlue", .r = 0x7B, .g = 0x68, .b = 0xEE }, - { .name = "MediumSpringGreen", .r = 0x00, .g = 0xFA, .b = 0x9A }, - { .name = "MediumTurquoise", .r = 0x48, .g = 0xD1, .b = 0xCC }, - { .name = "MediumVioletRed", .r = 0xC7, .g = 0x15, .b = 0x85 }, - { .name = "MidnightBlue", .r = 0x19, .g = 0x19, .b = 0x70 }, - { .name = "MintCream", .r = 0xF5, .g = 0xFF, .b = 0xFA }, - { .name = "MistyRose", .r = 0xFF, .g = 0xE4, .b = 0xE1 }, - { .name = "Moccasin", .r = 0xFF, .g = 0xE4, .b = 0xB5 }, - { .name = "NavajoWhite", .r = 0xFF, .g = 0xDE, .b = 0xAD }, - { .name = "Navy", .r = 0x00, .g = 0x00, .b = 0x80 }, - { .name = "OldLace", .r = 0xFD, .g = 0xF5, .b = 0xE6 }, - { .name = "Olive", .r = 0x80, .g = 0x80, .b = 0x00 }, - { .name = "OliveDrab", .r = 0x6B, .g = 0x8E, .b = 0x23 }, - { .name = "Orange", .r = 0xFF, .g = 0xA5, .b = 0x00 }, - { .name = "OrangeRed", .r = 0xFF, .g = 0x45, .b = 0x00 }, - { .name = "Orchid", .r = 0xDA, .g = 0x70, .b = 0xD6 }, - { .name = "PaleGoldenRod", .r = 0xEE, .g = 0xE8, .b = 0xAA }, - { .name = "PaleGreen", .r = 0x98, .g = 0xFB, .b = 0x98 }, - { .name = "PaleTurquoise", .r = 0xAF, .g = 0xEE, .b = 0xEE }, - { .name = "PaleVioletRed", .r = 0xDB, .g = 0x70, .b = 0x93 }, - { .name = "PapayaWhip", .r = 0xFF, .g = 0xEF, .b = 0xD5 }, - { .name = "PeachPuff", .r = 0xFF, .g = 0xDA, .b = 0xB9 }, - { .name = "Peru", .r = 0xCD, .g = 0x85, .b = 0x3F }, - { .name = "Pink", .r = 0xFF, .g = 0xC0, .b = 0xCB }, - { .name = "Plum", .r = 0xDD, .g = 0xA0, .b = 0xDD }, - { .name = "PowderBlue", .r = 0xB0, .g = 0xE0, .b = 0xE6 }, - { .name = "Purple", .r = 0x80, .g = 0x00, .b = 0x80 }, - { .name = "RebeccaPurple", .r = 0x66, .g = 0x33, .b = 0x99 }, - { .name = "Red", .r = 0xFF, .g = 0x00, .b = 0x00 }, - { .name = "RosyBrown", .r = 0xBC, .g = 0x8F, .b = 0x8F }, - { .name = "RoyalBlue", .r = 0x41, .g = 0x69, .b = 0xE1 }, - { .name = "SaddleBrown", .r = 0x8B, .g = 0x45, .b = 0x13 }, - { .name = "Salmon", .r = 0xFA, .g = 0x80, .b = 0x72 }, - { .name = "SandyBrown", .r = 0xF4, .g = 0xA4, .b = 0x60 }, - { .name = "SeaGreen", .r = 0x2E, .g = 0x8B, .b = 0x57 }, - { .name = "SeaShell", .r = 0xFF, .g = 0xF5, .b = 0xEE }, - { .name = "Sienna", .r = 0xA0, .g = 0x52, .b = 0x2D }, - { .name = "Silver", .r = 0xC0, .g = 0xC0, .b = 0xC0 }, - { .name = "SkyBlue", .r = 0x87, .g = 0xCE, .b = 0xEB }, - { .name = "SlateBlue", .r = 0x6A, .g = 0x5A, .b = 0xCD }, - { .name = "SlateGray", .r = 0x70, .g = 0x80, .b = 0x90 }, - { .name = "SlateGrey", .r = 0x70, .g = 0x80, .b = 0x90 }, - { .name = "Snow", .r = 0xFF, .g = 0xFA, .b = 0xFA }, - { .name = "SpringGreen", .r = 0x00, .g = 0xFF, .b = 0x7F }, - { .name = "SteelBlue", .r = 0x46, .g = 0x82, .b = 0xB4 }, - { .name = "Tan", .r = 0xD2, .g = 0xB4, .b = 0x8C }, - { .name = "Teal", .r = 0x00, .g = 0x80, .b = 0x80 }, - { .name = "Thistle", .r = 0xD8, .g = 0xBF, .b = 0xD8 }, - { .name = "Tomato", .r = 0xFF, .g = 0x63, .b = 0x47 }, - { .name = "Turquoise", .r = 0x40, .g = 0xE0, .b = 0xD0 }, - { .name = "Violet", .r = 0xEE, .g = 0x82, .b = 0xEE }, - { .name = "Wheat", .r = 0xF5, .g = 0xDE, .b = 0xB3 }, - { .name = "White", .r = 0xFF, .g = 0xFF, .b = 0xFF }, - { .name = "WhiteSmoke", .r = 0xF5, .g = 0xF5, .b = 0xF5 }, - { .name = "Yellow", .r = 0xFF, .g = 0xFF, .b = 0x00 }, - { .name = "YellowGreen", .r = 0x9A, .g = 0xCD, .b = 0x32 } -}; +const CSSColor CSSColors[] = { + {.name = "AliceBlue", .r = 0xF0, .g = 0xF8, .b = 0xFF}, + {.name = "AntiqueWhite", .r = 0xFA, .g = 0xEB, .b = 0xD7}, + {.name = "Aqua", .r = 0x00, .g = 0xFF, .b = 0xFF}, + {.name = "Aquamarine", .r = 0x7F, .g = 0xFF, .b = 0xD4}, + {.name = "Azure", .r = 0xF0, .g = 0xFF, .b = 0xFF}, + {.name = "Beige", .r = 0xF5, .g = 0xF5, .b = 0xDC}, + {.name = "Bisque", .r = 0xFF, .g = 0xE4, .b = 0xC4}, + {.name = "Black", .r = 0x00, .g = 0x00, .b = 0x00}, + {.name = "BlanchedAlmond", .r = 0xFF, .g = 0xEB, .b = 0xCD}, + {.name = "Blue", .r = 0x00, .g = 0x00, .b = 0xFF}, + {.name = "BlueViolet", .r = 0x8A, .g = 0x2B, .b = 0xE2}, + {.name = "Brown", .r = 0xA5, .g = 0x2A, .b = 0x2A}, + {.name = "BurlyWood", .r = 0xDE, .g = 0xB8, .b = 0x87}, + {.name = "CadetBlue", .r = 0x5F, .g = 0x9E, .b = 0xA0}, + {.name = "Chartreuse", .r = 0x7F, .g = 0xFF, .b = 0x00}, + {.name = "Chocolate", .r = 0xD2, .g = 0x69, .b = 0x1E}, + {.name = "Coral", .r = 0xFF, .g = 0x7F, .b = 0x50}, + {.name = "CornflowerBlue", .r = 0x64, .g = 0x95, .b = 0xED}, + {.name = "Cornsilk", .r = 0xFF, .g = 0xF8, .b = 0xDC}, + {.name = "Crimson", .r = 0xDC, .g = 0x14, .b = 0x3C}, + {.name = "Cyan", .r = 0x00, .g = 0xFF, .b = 0xFF}, + {.name = "DarkBlue", .r = 0x00, .g = 0x00, .b = 0x8B}, + {.name = "DarkCyan", .r = 0x00, .g = 0x8B, .b = 0x8B}, + {.name = "DarkGoldenRod", .r = 0xB8, .g = 0x86, .b = 0x0B}, + {.name = "DarkGray", .r = 0xA9, .g = 0xA9, .b = 0xA9}, + {.name = "DarkGrey", .r = 0xA9, .g = 0xA9, .b = 0xA9}, + {.name = "DarkGreen", .r = 0x00, .g = 0x64, .b = 0x00}, + {.name = "DarkKhaki", .r = 0xBD, .g = 0xB7, .b = 0x6B}, + {.name = "DarkMagenta", .r = 0x8B, .g = 0x00, .b = 0x8B}, + {.name = "DarkOliveGreen", .r = 0x55, .g = 0x6B, .b = 0x2F}, + {.name = "DarkOrange", .r = 0xFF, .g = 0x8C, .b = 0x00}, + {.name = "DarkOrchid", .r = 0x99, .g = 0x32, .b = 0xCC}, + {.name = "DarkRed", .r = 0x8B, .g = 0x00, .b = 0x00}, + {.name = "DarkSalmon", .r = 0xE9, .g = 0x96, .b = 0x7A}, + {.name = "DarkSeaGreen", .r = 0x8F, .g = 0xBC, .b = 0x8F}, + {.name = "DarkSlateBlue", .r = 0x48, .g = 0x3D, .b = 0x8B}, + {.name = "DarkSlateGray", .r = 0x2F, .g = 0x4F, .b = 0x4F}, + {.name = "DarkSlateGrey", .r = 0x2F, .g = 0x4F, .b = 0x4F}, + {.name = "DarkTurquoise", .r = 0x00, .g = 0xCE, .b = 0xD1}, + {.name = "DarkViolet", .r = 0x94, .g = 0x00, .b = 0xD3}, + {.name = "DeepPink", .r = 0xFF, .g = 0x14, .b = 0x93}, + {.name = "DeepSkyBlue", .r = 0x00, .g = 0xBF, .b = 0xFF}, + {.name = "DimGray", .r = 0x69, .g = 0x69, .b = 0x69}, + {.name = "DimGrey", .r = 0x69, .g = 0x69, .b = 0x69}, + {.name = "DodgerBlue", .r = 0x1E, .g = 0x90, .b = 0xFF}, + {.name = "FireBrick", .r = 0xB2, .g = 0x22, .b = 0x22}, + {.name = "FloralWhite", .r = 0xFF, .g = 0xFA, .b = 0xF0}, + {.name = "ForestGreen", .r = 0x22, .g = 0x8B, .b = 0x22}, + {.name = "Fuchsia", .r = 0xFF, .g = 0x00, .b = 0xFF}, + {.name = "Gainsboro", .r = 0xDC, .g = 0xDC, .b = 0xDC}, + {.name = "GhostWhite", .r = 0xF8, .g = 0xF8, .b = 0xFF}, + {.name = "Gold", .r = 0xFF, .g = 0xD7, .b = 0x00}, + {.name = "GoldenRod", .r = 0xDA, .g = 0xA5, .b = 0x20}, + {.name = "Gray", .r = 0x80, .g = 0x80, .b = 0x80}, + {.name = "Grey", .r = 0x80, .g = 0x80, .b = 0x80}, + {.name = "Green", .r = 0x00, .g = 0x80, .b = 0x00}, + {.name = "GreenYellow", .r = 0xAD, .g = 0xFF, .b = 0x2F}, + {.name = "HoneyDew", .r = 0xF0, .g = 0xFF, .b = 0xF0}, + {.name = "HotPink", .r = 0xFF, .g = 0x69, .b = 0xB4}, + {.name = "IndianRed", .r = 0xCD, .g = 0x5C, .b = 0x5C}, + {.name = "Indigo", .r = 0x4B, .g = 0x00, .b = 0x82}, + {.name = "Ivory", .r = 0xFF, .g = 0xFF, .b = 0xF0}, + {.name = "Khaki", .r = 0xF0, .g = 0xE6, .b = 0x8C}, + {.name = "Lavender", .r = 0xE6, .g = 0xE6, .b = 0xFA}, + {.name = "LavenderBlush", .r = 0xFF, .g = 0xF0, .b = 0xF5}, + {.name = "LawnGreen", .r = 0x7C, .g = 0xFC, .b = 0x00}, + {.name = "LemonChiffon", .r = 0xFF, .g = 0xFA, .b = 0xCD}, + {.name = "LightBlue", .r = 0xAD, .g = 0xD8, .b = 0xE6}, + {.name = "LightCoral", .r = 0xF0, .g = 0x80, .b = 0x80}, + {.name = "LightCyan", .r = 0xE0, .g = 0xFF, .b = 0xFF}, + {.name = "LightGoldenRodYellow", .r = 0xFA, .g = 0xFA, .b = 0xD2}, + {.name = "LightGray", .r = 0xD3, .g = 0xD3, .b = 0xD3}, + {.name = "LightGrey", .r = 0xD3, .g = 0xD3, .b = 0xD3}, + {.name = "LightGreen", .r = 0x90, .g = 0xEE, .b = 0x90}, + {.name = "LightPink", .r = 0xFF, .g = 0xB6, .b = 0xC1}, + {.name = "LightSalmon", .r = 0xFF, .g = 0xA0, .b = 0x7A}, + {.name = "LightSeaGreen", .r = 0x20, .g = 0xB2, .b = 0xAA}, + {.name = "LightSkyBlue", .r = 0x87, .g = 0xCE, .b = 0xFA}, + {.name = "LightSlateGray", .r = 0x77, .g = 0x88, .b = 0x99}, + {.name = "LightSlateGrey", .r = 0x77, .g = 0x88, .b = 0x99}, + {.name = "LightSteelBlue", .r = 0xB0, .g = 0xC4, .b = 0xDE}, + {.name = "LightYellow", .r = 0xFF, .g = 0xFF, .b = 0xE0}, + {.name = "Lime", .r = 0x00, .g = 0xFF, .b = 0x00}, + {.name = "LimeGreen", .r = 0x32, .g = 0xCD, .b = 0x32}, + {.name = "Linen", .r = 0xFA, .g = 0xF0, .b = 0xE6}, + {.name = "Magenta", .r = 0xFF, .g = 0x00, .b = 0xFF}, + {.name = "Maroon", .r = 0x80, .g = 0x00, .b = 0x00}, + {.name = "MediumAquaMarine", .r = 0x66, .g = 0xCD, .b = 0xAA}, + {.name = "MediumBlue", .r = 0x00, .g = 0x00, .b = 0xCD}, + {.name = "MediumOrchid", .r = 0xBA, .g = 0x55, .b = 0xD3}, + {.name = "MediumPurple", .r = 0x93, .g = 0x70, .b = 0xDB}, + {.name = "MediumSeaGreen", .r = 0x3C, .g = 0xB3, .b = 0x71}, + {.name = "MediumSlateBlue", .r = 0x7B, .g = 0x68, .b = 0xEE}, + {.name = "MediumSpringGreen", .r = 0x00, .g = 0xFA, .b = 0x9A}, + {.name = "MediumTurquoise", .r = 0x48, .g = 0xD1, .b = 0xCC}, + {.name = "MediumVioletRed", .r = 0xC7, .g = 0x15, .b = 0x85}, + {.name = "MidnightBlue", .r = 0x19, .g = 0x19, .b = 0x70}, + {.name = "MintCream", .r = 0xF5, .g = 0xFF, .b = 0xFA}, + {.name = "MistyRose", .r = 0xFF, .g = 0xE4, .b = 0xE1}, + {.name = "Moccasin", .r = 0xFF, .g = 0xE4, .b = 0xB5}, + {.name = "NavajoWhite", .r = 0xFF, .g = 0xDE, .b = 0xAD}, + {.name = "Navy", .r = 0x00, .g = 0x00, .b = 0x80}, + {.name = "OldLace", .r = 0xFD, .g = 0xF5, .b = 0xE6}, + {.name = "Olive", .r = 0x80, .g = 0x80, .b = 0x00}, + {.name = "OliveDrab", .r = 0x6B, .g = 0x8E, .b = 0x23}, + {.name = "Orange", .r = 0xFF, .g = 0xA5, .b = 0x00}, + {.name = "OrangeRed", .r = 0xFF, .g = 0x45, .b = 0x00}, + {.name = "Orchid", .r = 0xDA, .g = 0x70, .b = 0xD6}, + {.name = "PaleGoldenRod", .r = 0xEE, .g = 0xE8, .b = 0xAA}, + {.name = "PaleGreen", .r = 0x98, .g = 0xFB, .b = 0x98}, + {.name = "PaleTurquoise", .r = 0xAF, .g = 0xEE, .b = 0xEE}, + {.name = "PaleVioletRed", .r = 0xDB, .g = 0x70, .b = 0x93}, + {.name = "PapayaWhip", .r = 0xFF, .g = 0xEF, .b = 0xD5}, + {.name = "PeachPuff", .r = 0xFF, .g = 0xDA, .b = 0xB9}, + {.name = "Peru", .r = 0xCD, .g = 0x85, .b = 0x3F}, + {.name = "Pink", .r = 0xFF, .g = 0xC0, .b = 0xCB}, + {.name = "Plum", .r = 0xDD, .g = 0xA0, .b = 0xDD}, + {.name = "PowderBlue", .r = 0xB0, .g = 0xE0, .b = 0xE6}, + {.name = "Purple", .r = 0x80, .g = 0x00, .b = 0x80}, + {.name = "RebeccaPurple", .r = 0x66, .g = 0x33, .b = 0x99}, + {.name = "Red", .r = 0xFF, .g = 0x00, .b = 0x00}, + {.name = "RosyBrown", .r = 0xBC, .g = 0x8F, .b = 0x8F}, + {.name = "RoyalBlue", .r = 0x41, .g = 0x69, .b = 0xE1}, + {.name = "SaddleBrown", .r = 0x8B, .g = 0x45, .b = 0x13}, + {.name = "Salmon", .r = 0xFA, .g = 0x80, .b = 0x72}, + {.name = "SandyBrown", .r = 0xF4, .g = 0xA4, .b = 0x60}, + {.name = "SeaGreen", .r = 0x2E, .g = 0x8B, .b = 0x57}, + {.name = "SeaShell", .r = 0xFF, .g = 0xF5, .b = 0xEE}, + {.name = "Sienna", .r = 0xA0, .g = 0x52, .b = 0x2D}, + {.name = "Silver", .r = 0xC0, .g = 0xC0, .b = 0xC0}, + {.name = "SkyBlue", .r = 0x87, .g = 0xCE, .b = 0xEB}, + {.name = "SlateBlue", .r = 0x6A, .g = 0x5A, .b = 0xCD}, + {.name = "SlateGray", .r = 0x70, .g = 0x80, .b = 0x90}, + {.name = "SlateGrey", .r = 0x70, .g = 0x80, .b = 0x90}, + {.name = "Snow", .r = 0xFF, .g = 0xFA, .b = 0xFA}, + {.name = "SpringGreen", .r = 0x00, .g = 0xFF, .b = 0x7F}, + {.name = "SteelBlue", .r = 0x46, .g = 0x82, .b = 0xB4}, + {.name = "Tan", .r = 0xD2, .g = 0xB4, .b = 0x8C}, + {.name = "Teal", .r = 0x00, .g = 0x80, .b = 0x80}, + {.name = "Thistle", .r = 0xD8, .g = 0xBF, .b = 0xD8}, + {.name = "Tomato", .r = 0xFF, .g = 0x63, .b = 0x47}, + {.name = "Turquoise", .r = 0x40, .g = 0xE0, .b = 0xD0}, + {.name = "Violet", .r = 0xEE, .g = 0x82, .b = 0xEE}, + {.name = "Wheat", .r = 0xF5, .g = 0xDE, .b = 0xB3}, + {.name = "White", .r = 0xFF, .g = 0xFF, .b = 0xFF}, + {.name = "WhiteSmoke", .r = 0xF5, .g = 0xF5, .b = 0xF5}, + {.name = "Yellow", .r = 0xFF, .g = 0xFF, .b = 0x00}, + {.name = "YellowGreen", .r = 0x9A, .g = 0xCD, .b = 0x32}}; -const unsigned int num_CSSColors = sizeof ( CSSColors ) / sizeof ( *CSSColors ); +const unsigned int num_CSSColors = sizeof(CSSColors) / sizeof(*CSSColors); diff --git a/source/dialogs/combi.c b/source/dialogs/combi.c index 3063d899..ee4c0421 100644 --- a/source/dialogs/combi.c +++ b/source/dialogs/combi.c @@ -26,294 +26,296 @@ */ /** The log domain of this dialog. */ -#define G_LOG_DOMAIN "Dialogs.Combi" +#define G_LOG_DOMAIN "Dialogs.Combi" -#include -#include -#include -#include -#include "settings.h" #include "helper.h" +#include "settings.h" +#include +#include +#include +#include "mode-private.h" #include #include -#include "mode-private.h" #include /** * Combi Mode */ -typedef struct -{ - Mode *mode; - gboolean disable; +typedef struct { + Mode *mode; + gboolean disable; } CombiMode; -typedef struct -{ - // List of (combined) entries. - unsigned int cmd_list_length; - // List to validate where each switcher starts. - unsigned int *starts; - unsigned int *lengths; - // List of switchers to combine. - unsigned int num_switchers; - CombiMode *switchers; +typedef struct { + // List of (combined) entries. + unsigned int cmd_list_length; + // List to validate where each switcher starts. + unsigned int *starts; + unsigned int *lengths; + // List of switchers to combine. + unsigned int num_switchers; + CombiMode *switchers; } CombiModePrivateData; -static void combi_mode_parse_switchers ( Mode *sw ) -{ - CombiModePrivateData *pd = mode_get_private_data ( sw ); - char *savept = NULL; - // Make a copy, as strtok will modify it. - char *switcher_str = g_strdup ( config.combi_modi ); - const char * const sep = ",#"; - // Split token on ','. This modifies switcher_str. - for ( char *token = strtok_r ( switcher_str, sep, &savept ); token != NULL; - token = strtok_r ( NULL, sep, &savept ) ) { - // Resize and add entry. - pd->switchers = (CombiMode *) g_realloc ( pd->switchers, - sizeof ( CombiMode ) * ( pd->num_switchers + 1 ) ); +static void combi_mode_parse_switchers(Mode *sw) { + CombiModePrivateData *pd = mode_get_private_data(sw); + char *savept = NULL; + // Make a copy, as strtok will modify it. + char *switcher_str = g_strdup(config.combi_modi); + const char *const sep = ",#"; + // Split token on ','. This modifies switcher_str. + for (char *token = strtok_r(switcher_str, sep, &savept); token != NULL; + token = strtok_r(NULL, sep, &savept)) { + // Resize and add entry. + pd->switchers = (CombiMode *)g_realloc( + pd->switchers, sizeof(CombiMode) * (pd->num_switchers + 1)); - Mode *mode = rofi_collect_modi_search ( token ); - if ( mode != NULL ) { - pd->switchers[pd->num_switchers].disable = FALSE; - pd->switchers[pd->num_switchers++].mode = mode; - continue; - } - // If not build in, use custom switchers. - mode = script_switcher_parse_setup ( token ); - if ( mode != NULL ) { - pd->switchers[pd->num_switchers].disable = FALSE; - pd->switchers[pd->num_switchers++].mode = mode; - continue; - } - // Report error, don't continue. - g_warning ( "Invalid script switcher: %s", token ); - token = NULL; + Mode *mode = rofi_collect_modi_search(token); + if (mode != NULL) { + pd->switchers[pd->num_switchers].disable = FALSE; + pd->switchers[pd->num_switchers++].mode = mode; + continue; } - // Free string that was modified by strtok_r - g_free ( switcher_str ); + // If not build in, use custom switchers. + mode = script_switcher_parse_setup(token); + if (mode != NULL) { + pd->switchers[pd->num_switchers].disable = FALSE; + pd->switchers[pd->num_switchers++].mode = mode; + continue; + } + // Report error, don't continue. + g_warning("Invalid script switcher: %s", token); + token = NULL; + } + // Free string that was modified by strtok_r + g_free(switcher_str); } -static unsigned int combi_mode_get_num_entries ( const Mode *sw ) -{ - const CombiModePrivateData *pd = (const CombiModePrivateData *) mode_get_private_data ( sw ); - unsigned int length = 0; - for ( unsigned int i = 0; i < pd->num_switchers; i++ ) { - unsigned int entries = mode_get_num_entries ( pd->switchers[i].mode ); - pd->starts[i] = length; - pd->lengths[i] = entries; - length += entries; - } - return length; +static unsigned int combi_mode_get_num_entries(const Mode *sw) { + const CombiModePrivateData *pd = + (const CombiModePrivateData *)mode_get_private_data(sw); + unsigned int length = 0; + for (unsigned int i = 0; i < pd->num_switchers; i++) { + unsigned int entries = mode_get_num_entries(pd->switchers[i].mode); + pd->starts[i] = length; + pd->lengths[i] = entries; + length += entries; + } + return length; } -static int combi_mode_init ( Mode *sw ) -{ - if ( mode_get_private_data ( sw ) == NULL ) { - CombiModePrivateData *pd = g_malloc0 ( sizeof ( *pd ) ); - mode_set_private_data ( sw, (void *) pd ); - combi_mode_parse_switchers ( sw ); - pd->starts = g_malloc0 ( sizeof ( int ) * pd->num_switchers ); - pd->lengths = g_malloc0 ( sizeof ( int ) * pd->num_switchers ); - for ( unsigned int i = 0; i < pd->num_switchers; i++ ) { - if ( !mode_init ( pd->switchers[i].mode ) ) { - return FALSE; - } - } - if ( pd->cmd_list_length == 0 ) { - pd->cmd_list_length = combi_mode_get_num_entries ( sw ); - } +static int combi_mode_init(Mode *sw) { + if (mode_get_private_data(sw) == NULL) { + CombiModePrivateData *pd = g_malloc0(sizeof(*pd)); + mode_set_private_data(sw, (void *)pd); + combi_mode_parse_switchers(sw); + pd->starts = g_malloc0(sizeof(int) * pd->num_switchers); + pd->lengths = g_malloc0(sizeof(int) * pd->num_switchers); + for (unsigned int i = 0; i < pd->num_switchers; i++) { + if (!mode_init(pd->switchers[i].mode)) { + return FALSE; + } } - return TRUE; -} -static void combi_mode_destroy ( Mode *sw ) -{ - CombiModePrivateData *pd = (CombiModePrivateData *) mode_get_private_data ( sw ); - if ( pd != NULL ) { - g_free ( pd->starts ); - g_free ( pd->lengths ); - // Cleanup switchers. - for ( unsigned int i = 0; i < pd->num_switchers; i++ ) { - mode_destroy ( pd->switchers[i].mode ); - } - g_free ( pd->switchers ); - g_free ( pd ); - mode_set_private_data ( sw, NULL ); + if (pd->cmd_list_length == 0) { + pd->cmd_list_length = combi_mode_get_num_entries(sw); } + } + return TRUE; } -static ModeMode combi_mode_result ( Mode *sw, int mretv, char **input, unsigned int selected_line ) -{ - CombiModePrivateData *pd = mode_get_private_data ( sw ); +static void combi_mode_destroy(Mode *sw) { + CombiModePrivateData *pd = (CombiModePrivateData *)mode_get_private_data(sw); + if (pd != NULL) { + g_free(pd->starts); + g_free(pd->lengths); + // Cleanup switchers. + for (unsigned int i = 0; i < pd->num_switchers; i++) { + mode_destroy(pd->switchers[i].mode); + } + g_free(pd->switchers); + g_free(pd); + mode_set_private_data(sw, NULL); + } +} +static ModeMode combi_mode_result(Mode *sw, int mretv, char **input, + unsigned int selected_line) { + CombiModePrivateData *pd = mode_get_private_data(sw); - if ( input[0][0] == '!' ) { - int switcher = -1; - // Implement strchrnul behaviour. - char *eob = g_utf8_strchr ( input[0], -1, ' ' ); - if ( eob == NULL ) { - eob = &( input[0][strlen ( input[0] )] ); - } - ssize_t bang_len = g_utf8_pointer_to_offset ( input[0], eob ) - 1; - if ( bang_len > 0 ) { - for ( unsigned i = 0; i < pd->num_switchers; i++ ) { - const char *mode_name = mode_get_name ( pd->switchers[i].mode ); - size_t mode_name_len = g_utf8_strlen ( mode_name, -1 ); - if ( (size_t) bang_len <= mode_name_len && utf8_strncmp ( &input[0][1], mode_name, bang_len ) == 0 ) { - switcher = i; - break; - } - } - } - if ( switcher >= 0 ) { - if ( eob[0] == ' ' ) { - char *n = eob + 1; - return mode_result ( pd->switchers[switcher].mode, mretv, &n, - selected_line - pd->starts[switcher] ); - } - return MODE_EXIT; - } - } else if ( ( mretv& MENU_COMPLETE) ) { - return RELOAD_DIALOG; + if (input[0][0] == '!') { + int switcher = -1; + // Implement strchrnul behaviour. + char *eob = g_utf8_strchr(input[0], -1, ' '); + if (eob == NULL) { + eob = &(input[0][strlen(input[0])]); } + ssize_t bang_len = g_utf8_pointer_to_offset(input[0], eob) - 1; + if (bang_len > 0) { + for (unsigned i = 0; i < pd->num_switchers; i++) { + const char *mode_name = mode_get_name(pd->switchers[i].mode); + size_t mode_name_len = g_utf8_strlen(mode_name, -1); + if ((size_t)bang_len <= mode_name_len && + utf8_strncmp(&input[0][1], mode_name, bang_len) == 0) { + switcher = i; + break; + } + } + } + if (switcher >= 0) { + if (eob[0] == ' ') { + char *n = eob + 1; + return mode_result(pd->switchers[switcher].mode, mretv, &n, + selected_line - pd->starts[switcher]); + } + return MODE_EXIT; + } + } else if ((mretv & MENU_COMPLETE)) { + return RELOAD_DIALOG; + } - for ( unsigned i = 0; i < pd->num_switchers; i++ ) { - if ( selected_line >= pd->starts[i] && - selected_line < ( pd->starts[i] + pd->lengths[i] ) ) { - return mode_result ( pd->switchers[i].mode, mretv, input, selected_line - pd->starts[i] ); - } + for (unsigned i = 0; i < pd->num_switchers; i++) { + if (selected_line >= pd->starts[i] && + selected_line < (pd->starts[i] + pd->lengths[i])) { + return mode_result(pd->switchers[i].mode, mretv, input, + selected_line - pd->starts[i]); } - if ( ( mretv & MENU_CUSTOM_INPUT ) ) { - return mode_result ( pd->switchers[0].mode, mretv, input, selected_line ); - } - return MODE_EXIT; + } + if ((mretv & MENU_CUSTOM_INPUT)) { + return mode_result(pd->switchers[0].mode, mretv, input, selected_line); + } + return MODE_EXIT; } -static int combi_mode_match ( const Mode *sw, rofi_int_matcher **tokens, unsigned int index ) -{ - CombiModePrivateData *pd = mode_get_private_data ( sw ); - for ( unsigned i = 0; i < pd->num_switchers; i++ ) { - if ( pd->switchers[i].disable ) { - continue; - } - if ( index >= pd->starts[i] && index < ( pd->starts[i] + pd->lengths[i] ) ) { - return mode_token_match ( pd->switchers[i].mode, tokens, index - pd->starts[i] ); - } +static int combi_mode_match(const Mode *sw, rofi_int_matcher **tokens, + unsigned int index) { + CombiModePrivateData *pd = mode_get_private_data(sw); + for (unsigned i = 0; i < pd->num_switchers; i++) { + if (pd->switchers[i].disable) { + continue; } - return 0; + if (index >= pd->starts[i] && index < (pd->starts[i] + pd->lengths[i])) { + return mode_token_match(pd->switchers[i].mode, tokens, + index - pd->starts[i]); + } + } + return 0; } -static char * combi_mgrv ( const Mode *sw, unsigned int selected_line, int *state, GList **attr_list, int get_entry ) -{ - CombiModePrivateData *pd = mode_get_private_data ( sw ); - if ( !get_entry ) { - for ( unsigned i = 0; i < pd->num_switchers; i++ ) { - if ( selected_line >= pd->starts[i] && selected_line < ( pd->starts[i] + pd->lengths[i] ) ) { - mode_get_display_value ( pd->switchers[i].mode, selected_line - pd->starts[i], state, attr_list, FALSE ); - return NULL; - } - } +static char *combi_mgrv(const Mode *sw, unsigned int selected_line, int *state, + GList **attr_list, int get_entry) { + CombiModePrivateData *pd = mode_get_private_data(sw); + if (!get_entry) { + for (unsigned i = 0; i < pd->num_switchers; i++) { + if (selected_line >= pd->starts[i] && + selected_line < (pd->starts[i] + pd->lengths[i])) { + mode_get_display_value(pd->switchers[i].mode, + selected_line - pd->starts[i], state, attr_list, + FALSE); return NULL; - } - for ( unsigned i = 0; i < pd->num_switchers; i++ ) { - if ( selected_line >= pd->starts[i] && selected_line < ( pd->starts[i] + pd->lengths[i] ) ) { - char * retv; - char * str = retv = mode_get_display_value ( pd->switchers[i].mode, selected_line - pd->starts[i], state, attr_list, TRUE ); - const char *dname = mode_get_display_name ( pd->switchers[i].mode ); - if ( !config.combi_hide_mode_prefix ) { - retv = g_strdup_printf ( "%s %s", dname, str ); - g_free ( str ); - - if ( attr_list != NULL ) { - ThemeWidget *wid = rofi_config_find_widget ( sw->name, NULL, TRUE ); - Property *p = rofi_theme_find_property ( wid, P_COLOR, pd->switchers[i].mode->name, TRUE ); - if ( p != NULL ) { - PangoAttribute *pa = pango_attr_foreground_new ( - p->value.color.red * 65535, - p->value.color.green * 65535, - p->value.color.blue * 65535 ); - pa->start_index = PANGO_ATTR_INDEX_FROM_TEXT_BEGINNING; - pa->end_index = strlen ( dname ); - *attr_list = g_list_append ( *attr_list, pa ); - } - } - } - return retv; - } - } - - return NULL; -} -static char * combi_get_completion ( const Mode *sw, unsigned int index ) -{ - CombiModePrivateData *pd = mode_get_private_data ( sw ); - for ( unsigned i = 0; i < pd->num_switchers; i++ ) { - if ( index >= pd->starts[i] && index < ( pd->starts[i] + pd->lengths[i] ) ) { - char *comp = mode_get_completion ( pd->switchers[i].mode, index - pd->starts[i] ); - char *mcomp = g_strdup_printf ( "!%s %s", mode_get_name ( pd->switchers[i].mode ), comp ); - g_free ( comp ); - return mcomp; - } - } - // Should never get here. - g_assert_not_reached (); - return NULL; -} - -static cairo_surface_t * combi_get_icon ( const Mode *sw, unsigned int index, int height ) -{ - CombiModePrivateData *pd = mode_get_private_data ( sw ); - for ( unsigned i = 0; i < pd->num_switchers; i++ ) { - if ( index >= pd->starts[i] && index < ( pd->starts[i] + pd->lengths[i] ) ) { - cairo_surface_t *icon = mode_get_icon ( pd->switchers[i].mode, index - pd->starts[i], height ); - return icon; - } + } } return NULL; + } + for (unsigned i = 0; i < pd->num_switchers; i++) { + if (selected_line >= pd->starts[i] && + selected_line < (pd->starts[i] + pd->lengths[i])) { + char *retv; + char *str = retv = mode_get_display_value(pd->switchers[i].mode, + selected_line - pd->starts[i], + state, attr_list, TRUE); + const char *dname = mode_get_display_name(pd->switchers[i].mode); + if (!config.combi_hide_mode_prefix) { + retv = g_strdup_printf("%s %s", dname, str); + g_free(str); + + if (attr_list != NULL) { + ThemeWidget *wid = rofi_config_find_widget(sw->name, NULL, TRUE); + Property *p = rofi_theme_find_property( + wid, P_COLOR, pd->switchers[i].mode->name, TRUE); + if (p != NULL) { + PangoAttribute *pa = pango_attr_foreground_new( + p->value.color.red * 65535, p->value.color.green * 65535, + p->value.color.blue * 65535); + pa->start_index = PANGO_ATTR_INDEX_FROM_TEXT_BEGINNING; + pa->end_index = strlen(dname); + *attr_list = g_list_append(*attr_list, pa); + } + } + } + return retv; + } + } + + return NULL; +} +static char *combi_get_completion(const Mode *sw, unsigned int index) { + CombiModePrivateData *pd = mode_get_private_data(sw); + for (unsigned i = 0; i < pd->num_switchers; i++) { + if (index >= pd->starts[i] && index < (pd->starts[i] + pd->lengths[i])) { + char *comp = + mode_get_completion(pd->switchers[i].mode, index - pd->starts[i]); + char *mcomp = + g_strdup_printf("!%s %s", mode_get_name(pd->switchers[i].mode), comp); + g_free(comp); + return mcomp; + } + } + // Should never get here. + g_assert_not_reached(); + return NULL; } -static char * combi_preprocess_input ( Mode *sw, const char *input ) -{ - CombiModePrivateData *pd = mode_get_private_data ( sw ); - for ( unsigned i = 0; i < pd->num_switchers; i++ ) { - pd->switchers[i].disable = FALSE; +static cairo_surface_t *combi_get_icon(const Mode *sw, unsigned int index, + int height) { + CombiModePrivateData *pd = mode_get_private_data(sw); + for (unsigned i = 0; i < pd->num_switchers; i++) { + if (index >= pd->starts[i] && index < (pd->starts[i] + pd->lengths[i])) { + cairo_surface_t *icon = + mode_get_icon(pd->switchers[i].mode, index - pd->starts[i], height); + return icon; } - if ( input != NULL && input[0] == '!' ) { - // Implement strchrnul behaviour. - const char *eob = g_utf8_strchr ( input, -1, ' ' ); - if ( eob == NULL ) { - // Set it to end. - eob = &( input[strlen ( input )] ); - } - ssize_t bang_len = g_utf8_pointer_to_offset ( input, eob ) - 1; - if ( bang_len > 0 ) { - for ( unsigned i = 0; i < pd->num_switchers; i++ ) { - const char *mode_name = mode_get_name ( pd->switchers[i].mode ); - size_t mode_name_len = g_utf8_strlen ( mode_name, -1 ); - if ( !( (size_t) bang_len <= mode_name_len && utf8_strncmp ( &input[1], mode_name, bang_len ) == 0 ) ) { - // No match. - pd->switchers[i].disable = TRUE; - } - } - if ( eob[0] == '\0' || eob[1] == '\0' ) { - return NULL; - } - return g_strdup ( eob + 1 ); - } - } - return g_strdup ( input ); + } + return NULL; } -Mode combi_mode = -{ - .name = "combi", - .cfg_name_key = "display-combi", - ._init = combi_mode_init, - ._get_num_entries = combi_mode_get_num_entries, - ._result = combi_mode_result, - ._destroy = combi_mode_destroy, - ._token_match = combi_mode_match, - ._get_completion = combi_get_completion, - ._get_display_value = combi_mgrv, - ._get_icon = combi_get_icon, - ._preprocess_input = combi_preprocess_input, - .private_data = NULL, - .free = NULL -}; +static char *combi_preprocess_input(Mode *sw, const char *input) { + CombiModePrivateData *pd = mode_get_private_data(sw); + for (unsigned i = 0; i < pd->num_switchers; i++) { + pd->switchers[i].disable = FALSE; + } + if (input != NULL && input[0] == '!') { + // Implement strchrnul behaviour. + const char *eob = g_utf8_strchr(input, -1, ' '); + if (eob == NULL) { + // Set it to end. + eob = &(input[strlen(input)]); + } + ssize_t bang_len = g_utf8_pointer_to_offset(input, eob) - 1; + if (bang_len > 0) { + for (unsigned i = 0; i < pd->num_switchers; i++) { + const char *mode_name = mode_get_name(pd->switchers[i].mode); + size_t mode_name_len = g_utf8_strlen(mode_name, -1); + if (!((size_t)bang_len <= mode_name_len && + utf8_strncmp(&input[1], mode_name, bang_len) == 0)) { + // No match. + pd->switchers[i].disable = TRUE; + } + } + if (eob[0] == '\0' || eob[1] == '\0') { + return NULL; + } + return g_strdup(eob + 1); + } + } + return g_strdup(input); +} + +Mode combi_mode = {.name = "combi", + .cfg_name_key = "display-combi", + ._init = combi_mode_init, + ._get_num_entries = combi_mode_get_num_entries, + ._result = combi_mode_result, + ._destroy = combi_mode_destroy, + ._token_match = combi_mode_match, + ._get_completion = combi_get_completion, + ._get_display_value = combi_mgrv, + ._get_icon = combi_get_icon, + ._preprocess_input = combi_preprocess_input, + .private_data = NULL, + .free = NULL}; diff --git a/source/dialogs/dmenu.c b/source/dialogs/dmenu.c index 069ac30a..8d761844 100644 --- a/source/dialogs/dmenu.c +++ b/source/dialogs/dmenu.c @@ -26,765 +26,793 @@ */ /** The log domain of this dialog. */ -#define G_LOG_DOMAIN "Dialogs.DMenu" +#define G_LOG_DOMAIN "Dialogs.DMenu" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "rofi.h" -#include "settings.h" -#include "widgets/textbox.h" #include "dialogs/dmenu.h" #include "helper.h" -#include "xrmoptions.h" -#include "view.h" #include "rofi-icon-fetcher.h" +#include "rofi.h" +#include "settings.h" +#include "view.h" +#include "widgets/textbox.h" +#include "xrmoptions.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "dialogs/dmenuscriptshared.h" -static int dmenu_mode_init ( Mode *sw ); -static int dmenu_token_match ( const Mode *sw, rofi_int_matcher **tokens, unsigned int index ); -static cairo_surface_t *dmenu_get_icon ( const Mode *sw, unsigned int selected_line, int height ); -static char *dmenu_get_message ( const Mode *sw ); +static int dmenu_mode_init(Mode *sw); +static int dmenu_token_match(const Mode *sw, rofi_int_matcher **tokens, + unsigned int index); +static cairo_surface_t *dmenu_get_icon(const Mode *sw, + unsigned int selected_line, int height); +static char *dmenu_get_message(const Mode *sw); -static inline unsigned int bitget ( uint32_t *array, unsigned int index ) -{ - uint32_t bit = index % 32; - uint32_t val = array[index / 32]; - return ( val >> bit ) & 1; +static inline unsigned int bitget(uint32_t *array, unsigned int index) { + uint32_t bit = index % 32; + uint32_t val = array[index / 32]; + return (val >> bit) & 1; } -static inline void bittoggle ( uint32_t *array, unsigned int index ) -{ - uint32_t bit = index % 32; - uint32_t *v = &array[index / 32]; - *v ^= 1 << bit; +static inline void bittoggle(uint32_t *array, unsigned int index) { + uint32_t bit = index % 32; + uint32_t *v = &array[index / 32]; + *v ^= 1 << bit; } -typedef struct -{ - /** Settings */ - // Separator. - char separator; +typedef struct { + /** Settings */ + // Separator. + char separator; - unsigned int selected_line; - char *message; - char *format; - struct rofi_range_pair * urgent_list; - unsigned int num_urgent_list; - struct rofi_range_pair * active_list; - unsigned int num_active_list; - uint32_t *selected_list; - unsigned int num_selected_list; - unsigned int do_markup; - // List with entries. - DmenuScriptEntry *cmd_list; - unsigned int cmd_list_real_length; - unsigned int cmd_list_length; - unsigned int only_selected; - unsigned int selected_count; + unsigned int selected_line; + char *message; + char *format; + struct rofi_range_pair *urgent_list; + unsigned int num_urgent_list; + struct rofi_range_pair *active_list; + unsigned int num_active_list; + uint32_t *selected_list; + unsigned int num_selected_list; + unsigned int do_markup; + // List with entries. + DmenuScriptEntry *cmd_list; + unsigned int cmd_list_real_length; + unsigned int cmd_list_length; + unsigned int only_selected; + unsigned int selected_count; - gchar **columns; - gchar *column_separator; - gboolean multi_select; + gchar **columns; + gchar *column_separator; + gboolean multi_select; - GCancellable *cancel; - gulong cancel_source; - GInputStream *input_stream; - GDataInputStream *data_input_stream; + GCancellable *cancel; + gulong cancel_source; + GInputStream *input_stream; + GDataInputStream *data_input_stream; } DmenuModePrivateData; -static void async_close_callback ( GObject *source_object, GAsyncResult *res, G_GNUC_UNUSED gpointer user_data ) -{ - g_input_stream_close_finish ( G_INPUT_STREAM ( source_object ), res, NULL ); - g_debug ( "Closing data stream." ); +static void async_close_callback(GObject *source_object, GAsyncResult *res, + G_GNUC_UNUSED gpointer user_data) { + g_input_stream_close_finish(G_INPUT_STREAM(source_object), res, NULL); + g_debug("Closing data stream."); } -static void read_add ( DmenuModePrivateData * pd, char *data, gsize len ) -{ - gsize data_len = len; - if ( ( pd->cmd_list_length + 2 ) > pd->cmd_list_real_length ) { - pd->cmd_list_real_length = MAX ( pd->cmd_list_real_length * 2, 512 ); - pd->cmd_list = g_realloc ( pd->cmd_list, ( pd->cmd_list_real_length ) * sizeof ( DmenuScriptEntry ) ); - } - // Init. - pd->cmd_list[pd->cmd_list_length].icon_fetch_uid = 0; - pd->cmd_list[pd->cmd_list_length].icon_name = NULL; - pd->cmd_list[pd->cmd_list_length].meta = NULL; - pd->cmd_list[pd->cmd_list_length].info = NULL; - char *end = data; - while ( end < data + len && *end != '\0' ) { - end++; - } - if ( end != data + len ) { - data_len = end - data; - dmenuscript_parse_entry_extras ( NULL, &( pd->cmd_list[pd->cmd_list_length] ), end + 1, len - data_len ); - } - char *utfstr = rofi_force_utf8 ( data, data_len ); - pd->cmd_list[pd->cmd_list_length].entry = utfstr; - pd->cmd_list[pd->cmd_list_length + 1].entry = NULL; +static void read_add(DmenuModePrivateData *pd, char *data, gsize len) { + gsize data_len = len; + if ((pd->cmd_list_length + 2) > pd->cmd_list_real_length) { + pd->cmd_list_real_length = MAX(pd->cmd_list_real_length * 2, 512); + pd->cmd_list = g_realloc(pd->cmd_list, (pd->cmd_list_real_length) * + sizeof(DmenuScriptEntry)); + } + // Init. + pd->cmd_list[pd->cmd_list_length].icon_fetch_uid = 0; + pd->cmd_list[pd->cmd_list_length].icon_name = NULL; + pd->cmd_list[pd->cmd_list_length].meta = NULL; + pd->cmd_list[pd->cmd_list_length].info = NULL; + char *end = data; + while (end < data + len && *end != '\0') { + end++; + } + if (end != data + len) { + data_len = end - data; + dmenuscript_parse_entry_extras(NULL, &(pd->cmd_list[pd->cmd_list_length]), + end + 1, len - data_len); + } + char *utfstr = rofi_force_utf8(data, data_len); + pd->cmd_list[pd->cmd_list_length].entry = utfstr; + pd->cmd_list[pd->cmd_list_length + 1].entry = NULL; - pd->cmd_list_length++; + pd->cmd_list_length++; } -static void async_read_callback ( GObject *source_object, GAsyncResult *res, gpointer user_data ) -{ - GDataInputStream *stream = (GDataInputStream *) source_object; - DmenuModePrivateData *pd = (DmenuModePrivateData *) user_data; - gsize len; - char *data = g_data_input_stream_read_upto_finish ( stream, res, &len, NULL ); - if ( data != NULL ) { - // Absorb separator, already in buffer so should not block. - g_data_input_stream_read_byte ( stream, NULL, NULL ); - read_add ( pd, data, len ); - g_free ( data ); - rofi_view_reload (); +static void async_read_callback(GObject *source_object, GAsyncResult *res, + gpointer user_data) { + GDataInputStream *stream = (GDataInputStream *)source_object; + DmenuModePrivateData *pd = (DmenuModePrivateData *)user_data; + gsize len; + char *data = g_data_input_stream_read_upto_finish(stream, res, &len, NULL); + if (data != NULL) { + // Absorb separator, already in buffer so should not block. + g_data_input_stream_read_byte(stream, NULL, NULL); + read_add(pd, data, len); + g_free(data); + rofi_view_reload(); - g_data_input_stream_read_upto_async ( pd->data_input_stream, &( pd->separator ), 1, G_PRIORITY_LOW, pd->cancel, - async_read_callback, pd ); - return; - } - else { - GError *error = NULL; - // Absorb separator, already in buffer so should not block. - // If error == NULL end of stream.. - g_data_input_stream_read_byte ( stream, NULL, &error ); - if ( error == NULL ) { - // Add empty line. - read_add ( pd, "", 0 ); - rofi_view_reload (); + g_data_input_stream_read_upto_async(pd->data_input_stream, &(pd->separator), + 1, G_PRIORITY_LOW, pd->cancel, + async_read_callback, pd); + return; + } else { + GError *error = NULL; + // Absorb separator, already in buffer so should not block. + // If error == NULL end of stream.. + g_data_input_stream_read_byte(stream, NULL, &error); + if (error == NULL) { + // Add empty line. + read_add(pd, "", 0); + rofi_view_reload(); - g_data_input_stream_read_upto_async ( pd->data_input_stream, &( pd->separator ), 1, G_PRIORITY_LOW, pd->cancel, - async_read_callback, pd ); - return; - } - else { - g_error_free ( error ); - } - } - if ( !g_cancellable_is_cancelled ( pd->cancel ) ) { - // Hack, don't use get active. - g_debug ( "Clearing overlay" ); - rofi_view_set_overlay ( rofi_view_get_active (), NULL ); - g_input_stream_close_async ( G_INPUT_STREAM ( stream ), G_PRIORITY_LOW, pd->cancel, async_close_callback, pd ); + g_data_input_stream_read_upto_async(pd->data_input_stream, + &(pd->separator), 1, G_PRIORITY_LOW, + pd->cancel, async_read_callback, pd); + return; } + g_error_free(error); + } + if (!g_cancellable_is_cancelled(pd->cancel)) { + // Hack, don't use get active. + g_debug("Clearing overlay"); + rofi_view_set_overlay(rofi_view_get_active(), NULL); + g_input_stream_close_async(G_INPUT_STREAM(stream), G_PRIORITY_LOW, + pd->cancel, async_close_callback, pd); + } } -static void async_read_cancel ( G_GNUC_UNUSED GCancellable *cancel, G_GNUC_UNUSED gpointer data ) -{ - g_debug ( "Cancelled the async read." ); +static void async_read_cancel(G_GNUC_UNUSED GCancellable *cancel, + G_GNUC_UNUSED gpointer data) { + g_debug("Cancelled the async read."); } -static int get_dmenu_async ( DmenuModePrivateData *pd, int sync_pre_read ) -{ - while ( sync_pre_read-- ) { - gsize len = 0; - char *data = g_data_input_stream_read_upto ( pd->data_input_stream, &( pd->separator ), 1, &len, NULL, NULL ); - if ( data == NULL ) { - g_input_stream_close_async ( G_INPUT_STREAM ( pd->input_stream ), G_PRIORITY_LOW, pd->cancel, async_close_callback, pd ); - return FALSE; - } - g_data_input_stream_read_byte ( pd->data_input_stream, NULL, NULL ); - read_add ( pd, data, len ); - g_free ( data ); +static int get_dmenu_async(DmenuModePrivateData *pd, int sync_pre_read) { + while (sync_pre_read--) { + gsize len = 0; + char *data = g_data_input_stream_read_upto( + pd->data_input_stream, &(pd->separator), 1, &len, NULL, NULL); + if (data == NULL) { + g_input_stream_close_async(G_INPUT_STREAM(pd->input_stream), + G_PRIORITY_LOW, pd->cancel, + async_close_callback, pd); + return FALSE; } - g_data_input_stream_read_upto_async ( pd->data_input_stream, &( pd->separator ), 1, G_PRIORITY_LOW, pd->cancel, - async_read_callback, pd ); - return TRUE; + g_data_input_stream_read_byte(pd->data_input_stream, NULL, NULL); + read_add(pd, data, len); + g_free(data); + } + g_data_input_stream_read_upto_async(pd->data_input_stream, &(pd->separator), + 1, G_PRIORITY_LOW, pd->cancel, + async_read_callback, pd); + return TRUE; } -static void get_dmenu_sync ( DmenuModePrivateData *pd ) -{ - while ( TRUE ) { - gsize len = 0; - char *data = g_data_input_stream_read_upto ( pd->data_input_stream, &( pd->separator ), 1, &len, NULL, NULL ); - if ( data == NULL ) { - break; - } - g_data_input_stream_read_byte ( pd->data_input_stream, NULL, NULL ); - read_add ( pd, data, len ); - g_free ( data ); +static void get_dmenu_sync(DmenuModePrivateData *pd) { + while (TRUE) { + gsize len = 0; + char *data = g_data_input_stream_read_upto( + pd->data_input_stream, &(pd->separator), 1, &len, NULL, NULL); + if (data == NULL) { + break; } - g_input_stream_close_async ( G_INPUT_STREAM ( pd->input_stream ), G_PRIORITY_LOW, pd->cancel, async_close_callback, pd ); + g_data_input_stream_read_byte(pd->data_input_stream, NULL, NULL); + read_add(pd, data, len); + g_free(data); + } + g_input_stream_close_async(G_INPUT_STREAM(pd->input_stream), G_PRIORITY_LOW, + pd->cancel, async_close_callback, pd); } -static unsigned int dmenu_mode_get_num_entries ( const Mode *sw ) -{ - const DmenuModePrivateData *rmpd = (const DmenuModePrivateData *) mode_get_private_data ( sw ); - return rmpd->cmd_list_length; +static unsigned int dmenu_mode_get_num_entries(const Mode *sw) { + const DmenuModePrivateData *rmpd = + (const DmenuModePrivateData *)mode_get_private_data(sw); + return rmpd->cmd_list_length; } -static gchar * dmenu_format_output_string ( const DmenuModePrivateData *pd, const char *input ) -{ - if ( pd->columns == NULL ) { - return g_strdup ( input ); +static gchar *dmenu_format_output_string(const DmenuModePrivateData *pd, + const char *input) { + if (pd->columns == NULL) { + return g_strdup(input); + } + char *retv = NULL; + char **splitted = + g_regex_split_simple(pd->column_separator, input, G_REGEX_CASELESS, 00); + uint32_t ns = 0; + for (; splitted && splitted[ns]; ns++) { + ; + } + for (uint32_t i = 0; pd->columns && pd->columns[i]; i++) { + unsigned int index = + (unsigned int)g_ascii_strtoull(pd->columns[i], NULL, 10); + if (index < ns && index > 0) { + if (retv == NULL) { + retv = g_strdup(splitted[index - 1]); + } else { + gchar *t = g_strjoin("\t", retv, splitted[index - 1], NULL); + g_free(retv); + retv = t; + } } - char *retv = NULL; - char ** splitted = g_regex_split_simple ( pd->column_separator, input, G_REGEX_CASELESS, 00 ); - uint32_t ns = 0; - for (; splitted && splitted[ns]; ns++ ) { - ; - } - for ( uint32_t i = 0; pd->columns && pd->columns[i]; i++ ) { - unsigned int index = (unsigned int ) g_ascii_strtoull ( pd->columns[i], NULL, 10 ); - if ( index < ns && index > 0 ) { - if ( retv == NULL ) { - retv = g_strdup ( splitted[index - 1] ); - } - else { - gchar *t = g_strjoin ( "\t", retv, splitted[index - 1], NULL ); - g_free ( retv ); - retv = t; - } - } - } - g_strfreev ( splitted ); - return retv ? retv : g_strdup ( "" ); + } + g_strfreev(splitted); + return retv ? retv : g_strdup(""); } -static inline unsigned int get_index ( unsigned int length, int index ) -{ - if ( index >= 0 ) { - return index; - } - if ( ( (unsigned int) -index ) <= length ) { - return length + index; - } - // Out of range. - return UINT_MAX; +static inline unsigned int get_index(unsigned int length, int index) { + if (index >= 0) { + return index; + } + if (((unsigned int)-index) <= length) { + return length + index; + } + // Out of range. + return UINT_MAX; } -static char *get_display_data ( const Mode *data, unsigned int index, int *state, G_GNUC_UNUSED GList **list, int get_entry ) -{ - Mode *sw = (Mode *) data; - DmenuModePrivateData *pd = (DmenuModePrivateData *) mode_get_private_data ( sw ); - DmenuScriptEntry *retv = (DmenuScriptEntry *) pd->cmd_list; - for ( unsigned int i = 0; i < pd->num_active_list; i++ ) { - unsigned int start = get_index ( pd->cmd_list_length, pd->active_list[i].start ); - unsigned int stop = get_index ( pd->cmd_list_length, pd->active_list[i].stop ); - if ( index >= start && index <= stop ) { - *state |= ACTIVE; - } +static char *get_display_data(const Mode *data, unsigned int index, int *state, + G_GNUC_UNUSED GList **list, int get_entry) { + Mode *sw = (Mode *)data; + DmenuModePrivateData *pd = (DmenuModePrivateData *)mode_get_private_data(sw); + DmenuScriptEntry *retv = (DmenuScriptEntry *)pd->cmd_list; + for (unsigned int i = 0; i < pd->num_active_list; i++) { + unsigned int start = + get_index(pd->cmd_list_length, pd->active_list[i].start); + unsigned int stop = get_index(pd->cmd_list_length, pd->active_list[i].stop); + if (index >= start && index <= stop) { + *state |= ACTIVE; } - for ( unsigned int i = 0; i < pd->num_urgent_list; i++ ) { - unsigned int start = get_index ( pd->cmd_list_length, pd->urgent_list[i].start ); - unsigned int stop = get_index ( pd->cmd_list_length, pd->urgent_list[i].stop ); - if ( index >= start && index <= stop ) { - *state |= URGENT; - } + } + for (unsigned int i = 0; i < pd->num_urgent_list; i++) { + unsigned int start = + get_index(pd->cmd_list_length, pd->urgent_list[i].start); + unsigned int stop = get_index(pd->cmd_list_length, pd->urgent_list[i].stop); + if (index >= start && index <= stop) { + *state |= URGENT; } - if ( pd->selected_list && bitget ( pd->selected_list, index ) == TRUE ) { - *state |= SELECTED; - } - if ( pd->do_markup ) { - *state |= MARKUP; - } - return get_entry ? dmenu_format_output_string ( pd, retv[index].entry ) : NULL; + } + if (pd->selected_list && bitget(pd->selected_list, index) == TRUE) { + *state |= SELECTED; + } + if (pd->do_markup) { + *state |= MARKUP; + } + return get_entry ? dmenu_format_output_string(pd, retv[index].entry) : NULL; } -static void dmenu_mode_free ( Mode *sw ) -{ - if ( mode_get_private_data ( sw ) == NULL ) { - return; +static void dmenu_mode_free(Mode *sw) { + if (mode_get_private_data(sw) == NULL) { + return; + } + DmenuModePrivateData *pd = (DmenuModePrivateData *)mode_get_private_data(sw); + if (pd != NULL) { + if (pd->cancel) { + // If open, cancel reads. + if (pd->input_stream && !g_input_stream_is_closed(pd->input_stream)) { + g_cancellable_cancel(pd->cancel); + } + // This blocks until cancel is done. + g_cancellable_disconnect(pd->cancel, pd->cancel_source); + if (pd->input_stream) { + // Should close the stream if not yet done. + g_object_unref(pd->data_input_stream); + g_object_unref(pd->input_stream); + } + g_object_unref(pd->cancel); } - DmenuModePrivateData *pd = (DmenuModePrivateData *) mode_get_private_data ( sw ); - if ( pd != NULL ) { - if ( pd->cancel ) { - // If open, cancel reads. - if ( pd->input_stream && !g_input_stream_is_closed ( pd->input_stream ) ) { - g_cancellable_cancel ( pd->cancel ); - } - // This blocks until cancel is done. - g_cancellable_disconnect ( pd->cancel, pd->cancel_source ); - if ( pd->input_stream ) { - // Should close the stream if not yet done. - g_object_unref ( pd->data_input_stream ); - g_object_unref ( pd->input_stream ); - } - g_object_unref ( pd->cancel ); - } - for ( size_t i = 0; i < pd->cmd_list_length; i++ ) { - if ( pd->cmd_list[i].entry ) { - g_free ( pd->cmd_list[i].entry ); - g_free ( pd->cmd_list[i].icon_name ); - g_free ( pd->cmd_list[i].meta ); - g_free ( pd->cmd_list[i].info ); - } - } - g_free ( pd->cmd_list ); - g_free ( pd->urgent_list ); - g_free ( pd->active_list ); - g_free ( pd->selected_list ); - - g_free ( pd ); - mode_set_private_data ( sw, NULL ); + for (size_t i = 0; i < pd->cmd_list_length; i++) { + if (pd->cmd_list[i].entry) { + g_free(pd->cmd_list[i].entry); + g_free(pd->cmd_list[i].icon_name); + g_free(pd->cmd_list[i].meta); + g_free(pd->cmd_list[i].info); + } } + g_free(pd->cmd_list); + g_free(pd->urgent_list); + g_free(pd->active_list); + g_free(pd->selected_list); + + g_free(pd); + mode_set_private_data(sw, NULL); + } } #include "mode-private.h" /** dmenu Mode object. */ -Mode dmenu_mode = -{ - .name = "dmenu", - .cfg_name_key = "display-combi", - ._init = dmenu_mode_init, - ._get_num_entries = dmenu_mode_get_num_entries, - ._result = NULL, - ._destroy = dmenu_mode_free, - ._token_match = dmenu_token_match, - ._get_display_value = get_display_data, - ._get_icon = dmenu_get_icon, - ._get_completion = NULL, - ._preprocess_input = NULL, - ._get_message = dmenu_get_message, - .private_data = NULL, - .free = NULL, - .display_name = "dmenu" -}; +Mode dmenu_mode = {.name = "dmenu", + .cfg_name_key = "display-combi", + ._init = dmenu_mode_init, + ._get_num_entries = dmenu_mode_get_num_entries, + ._result = NULL, + ._destroy = dmenu_mode_free, + ._token_match = dmenu_token_match, + ._get_display_value = get_display_data, + ._get_icon = dmenu_get_icon, + ._get_completion = NULL, + ._preprocess_input = NULL, + ._get_message = dmenu_get_message, + .private_data = NULL, + .free = NULL, + .display_name = "dmenu"}; -static int dmenu_mode_init ( Mode *sw ) -{ - if ( mode_get_private_data ( sw ) != NULL ) { - return TRUE; - } - mode_set_private_data ( sw, g_malloc0 ( sizeof ( DmenuModePrivateData ) ) ); - DmenuModePrivateData *pd = (DmenuModePrivateData *) mode_get_private_data ( sw ); - - pd->separator = '\n'; - pd->selected_line = UINT32_MAX; - - find_arg_str ( "-mesg", &( pd->message ) ); - - // Input data separator. - find_arg_char ( "-sep", &( pd->separator ) ); - - find_arg_uint ( "-selected-row", &( pd->selected_line ) ); - // By default we print the unescaped line back. - pd->format = "s"; - - // Allow user to override the output format. - find_arg_str ( "-format", &( pd->format ) ); - // Urgent. - char *str = NULL; - find_arg_str ( "-u", &str ); - if ( str != NULL ) { - parse_ranges ( str, &( pd->urgent_list ), &( pd->num_urgent_list ) ); - } - // Active - str = NULL; - find_arg_str ( "-a", &str ); - if ( str != NULL ) { - parse_ranges ( str, &( pd->active_list ), &( pd->num_active_list ) ); - } - - // DMENU COMPATIBILITY - unsigned int lines = DEFAULT_MENU_LINES; - find_arg_uint ( "-l", &( lines ) ); - if ( lines != DEFAULT_MENU_LINES ) { - Property *p = rofi_theme_property_create ( P_INTEGER ); - p->name = g_strdup("lines"); - p->value.i = lines; - ThemeWidget *widget = rofi_theme_find_or_create_name ( rofi_theme, "listview" ); - GHashTable *table = g_hash_table_new_full ( g_str_hash, g_str_equal, NULL, (GDestroyNotify) rofi_theme_property_free ); - - g_hash_table_replace ( table, p->name, p ); - rofi_theme_widget_add_properties ( widget, table ); - g_hash_table_destroy ( table ); - } - - str = NULL; - find_arg_str ( "-window-title", &str ); - if ( str ) { - dmenu_mode.display_name = str; - } - - /** - * Dmenu compatibility. - * `-b` put on bottom. - */ - if ( find_arg ( "-b" ) >= 0 ) { - config.location = 6; - } - /* -i case insensitive */ - config.case_sensitive = TRUE; - if ( find_arg ( "-i" ) >= 0 ) { - config.case_sensitive = FALSE; - } - int fd = STDIN_FILENO; - str = NULL; - if ( find_arg_str ( "-input", &str ) ) { - char *estr = rofi_expand_path ( str ); - fd = open ( str, O_RDONLY ); - if ( fd < 0 ) { - char *msg = g_markup_printf_escaped ( "Failed to open file: %s:\n\t%s", estr, g_strerror ( errno ) ); - rofi_view_error_dialog ( msg, TRUE ); - g_free ( msg ); - g_free ( estr ); - return TRUE; - } - g_free ( estr ); - } - // If input is stdin, and a tty, do not read as rofi grabs input and therefore blocks. - if ( !( fd == STDIN_FILENO && isatty ( fd ) == 1 ) ) { - pd->cancel = g_cancellable_new (); - pd->cancel_source = g_cancellable_connect ( pd->cancel, G_CALLBACK ( async_read_cancel ), pd, NULL ); - pd->input_stream = g_unix_input_stream_new ( fd, fd != STDIN_FILENO ); - pd->data_input_stream = g_data_input_stream_new ( pd->input_stream ); - } - gchar *columns = NULL; - if ( find_arg_str ( "-display-columns", &columns ) ) { - pd->columns = g_strsplit ( columns, ",", 0 ); - pd->column_separator = "\t"; - find_arg_str ( "-display-column-separator", &pd->column_separator ); - } +static int dmenu_mode_init(Mode *sw) { + if (mode_get_private_data(sw) != NULL) { return TRUE; + } + mode_set_private_data(sw, g_malloc0(sizeof(DmenuModePrivateData))); + DmenuModePrivateData *pd = (DmenuModePrivateData *)mode_get_private_data(sw); + + pd->separator = '\n'; + pd->selected_line = UINT32_MAX; + + find_arg_str("-mesg", &(pd->message)); + + // Input data separator. + find_arg_char("-sep", &(pd->separator)); + + find_arg_uint("-selected-row", &(pd->selected_line)); + // By default we print the unescaped line back. + pd->format = "s"; + + // Allow user to override the output format. + find_arg_str("-format", &(pd->format)); + // Urgent. + char *str = NULL; + find_arg_str("-u", &str); + if (str != NULL) { + parse_ranges(str, &(pd->urgent_list), &(pd->num_urgent_list)); + } + // Active + str = NULL; + find_arg_str("-a", &str); + if (str != NULL) { + parse_ranges(str, &(pd->active_list), &(pd->num_active_list)); + } + + // DMENU COMPATIBILITY + unsigned int lines = DEFAULT_MENU_LINES; + find_arg_uint("-l", &(lines)); + if (lines != DEFAULT_MENU_LINES) { + Property *p = rofi_theme_property_create(P_INTEGER); + p->name = g_strdup("lines"); + p->value.i = lines; + ThemeWidget *widget = + rofi_theme_find_or_create_name(rofi_theme, "listview"); + GHashTable *table = + g_hash_table_new_full(g_str_hash, g_str_equal, NULL, + (GDestroyNotify)rofi_theme_property_free); + + g_hash_table_replace(table, p->name, p); + rofi_theme_widget_add_properties(widget, table); + g_hash_table_destroy(table); + } + + str = NULL; + find_arg_str("-window-title", &str); + if (str) { + dmenu_mode.display_name = str; + } + + /** + * Dmenu compatibility. + * `-b` put on bottom. + */ + if (find_arg("-b") >= 0) { + config.location = 6; + } + /* -i case insensitive */ + config.case_sensitive = TRUE; + if (find_arg("-i") >= 0) { + config.case_sensitive = FALSE; + } + int fd = STDIN_FILENO; + str = NULL; + if (find_arg_str("-input", &str)) { + char *estr = rofi_expand_path(str); + fd = open(str, O_RDONLY); + if (fd < 0) { + char *msg = g_markup_printf_escaped( + "Failed to open file: %s:\n\t%s", estr, + g_strerror(errno)); + rofi_view_error_dialog(msg, TRUE); + g_free(msg); + g_free(estr); + return TRUE; + } + g_free(estr); + } + // If input is stdin, and a tty, do not read as rofi grabs input and therefore + // blocks. + if (!(fd == STDIN_FILENO && isatty(fd) == 1)) { + pd->cancel = g_cancellable_new(); + pd->cancel_source = g_cancellable_connect( + pd->cancel, G_CALLBACK(async_read_cancel), pd, NULL); + pd->input_stream = g_unix_input_stream_new(fd, fd != STDIN_FILENO); + pd->data_input_stream = g_data_input_stream_new(pd->input_stream); + } + gchar *columns = NULL; + if (find_arg_str("-display-columns", &columns)) { + pd->columns = g_strsplit(columns, ",", 0); + pd->column_separator = "\t"; + find_arg_str("-display-column-separator", &pd->column_separator); + } + return TRUE; } -static int dmenu_token_match ( const Mode *sw, rofi_int_matcher **tokens, unsigned int index ) -{ - DmenuModePrivateData *rmpd = (DmenuModePrivateData *) mode_get_private_data ( sw ); - /** Strip out the markup when matching. */ - char *esc = NULL; - if ( rmpd->do_markup ) { - pango_parse_markup ( rmpd->cmd_list[index].entry, -1, 0, NULL, &esc, NULL, NULL ); - } - else { - esc = rmpd->cmd_list[index].entry; - } - if ( esc ) { - // int retv = helper_token_match ( tokens, esc ); - int match = 1; - if ( tokens ) { - for ( int j = 0; match && tokens != NULL && tokens[j] != NULL; j++ ) { - rofi_int_matcher *ftokens[2] = { tokens[j], NULL }; - int test = 0; - test = helper_token_match ( ftokens, esc ); - if ( test == tokens[j]->invert && rmpd->cmd_list[index].meta ) { - test = helper_token_match ( ftokens, rmpd->cmd_list[index].meta ); - } +static int dmenu_token_match(const Mode *sw, rofi_int_matcher **tokens, + unsigned int index) { + DmenuModePrivateData *rmpd = + (DmenuModePrivateData *)mode_get_private_data(sw); + /** Strip out the markup when matching. */ + char *esc = NULL; + if (rmpd->do_markup) { + pango_parse_markup(rmpd->cmd_list[index].entry, -1, 0, NULL, &esc, NULL, + NULL); + } else { + esc = rmpd->cmd_list[index].entry; + } + if (esc) { + // int retv = helper_token_match ( tokens, esc ); + int match = 1; + if (tokens) { + for (int j = 0; match && tokens != NULL && tokens[j] != NULL; j++) { + rofi_int_matcher *ftokens[2] = {tokens[j], NULL}; + int test = 0; + test = helper_token_match(ftokens, esc); + if (test == tokens[j]->invert && rmpd->cmd_list[index].meta) { + test = helper_token_match(ftokens, rmpd->cmd_list[index].meta); + } - if ( test == 0 ) { - match = 0; - } - } + if (test == 0) { + match = 0; } - if ( rmpd->do_markup ) { - g_free ( esc ); - } - return match; + } } - return FALSE; + if (rmpd->do_markup) { + g_free(esc); + } + return match; + } + return FALSE; } -static char *dmenu_get_message ( const Mode *sw ) -{ - DmenuModePrivateData *pd = (DmenuModePrivateData *) mode_get_private_data ( sw ); - if ( pd->message ) { - return g_strdup ( pd->message ); - } +static char *dmenu_get_message(const Mode *sw) { + DmenuModePrivateData *pd = (DmenuModePrivateData *)mode_get_private_data(sw); + if (pd->message) { + return g_strdup(pd->message); + } + return NULL; +} +static cairo_surface_t *dmenu_get_icon(const Mode *sw, + unsigned int selected_line, int height) { + DmenuModePrivateData *pd = (DmenuModePrivateData *)mode_get_private_data(sw); + g_return_val_if_fail(pd->cmd_list != NULL, NULL); + DmenuScriptEntry *dr = &(pd->cmd_list[selected_line]); + if (dr->icon_name == NULL) { return NULL; -} -static cairo_surface_t *dmenu_get_icon ( const Mode *sw, unsigned int selected_line, int height ) -{ - DmenuModePrivateData *pd = (DmenuModePrivateData *) mode_get_private_data ( sw ); - g_return_val_if_fail ( pd->cmd_list != NULL, NULL ); - DmenuScriptEntry *dr = &( pd->cmd_list[selected_line] ); - if ( dr->icon_name == NULL ) { - return NULL; - } - if ( dr->icon_fetch_uid > 0 ) { - return rofi_icon_fetcher_get ( dr->icon_fetch_uid ); - } - dr->icon_fetch_uid = rofi_icon_fetcher_query ( dr->icon_name, height ); - return rofi_icon_fetcher_get ( dr->icon_fetch_uid ); + } + if (dr->icon_fetch_uid > 0) { + return rofi_icon_fetcher_get(dr->icon_fetch_uid); + } + dr->icon_fetch_uid = rofi_icon_fetcher_query(dr->icon_name, height); + return rofi_icon_fetcher_get(dr->icon_fetch_uid); } -static void dmenu_finish ( RofiViewState *state, int retv ) -{ - if ( retv == FALSE ) { - rofi_set_return_code ( EXIT_FAILURE ); - } - else if ( retv >= 10 ) { - rofi_set_return_code ( retv ); - } - else { - rofi_set_return_code ( EXIT_SUCCESS ); - } - rofi_view_set_active ( NULL ); - rofi_view_free ( state ); - mode_destroy ( &dmenu_mode ); +static void dmenu_finish(RofiViewState *state, int retv) { + if (retv == FALSE) { + rofi_set_return_code(EXIT_FAILURE); + } else if (retv >= 10) { + rofi_set_return_code(retv); + } else { + rofi_set_return_code(EXIT_SUCCESS); + } + rofi_view_set_active(NULL); + rofi_view_free(state); + mode_destroy(&dmenu_mode); } -static void dmenu_print_results ( DmenuModePrivateData *pd, const char *input ) -{ - DmenuScriptEntry *cmd_list = pd->cmd_list; - int seen = FALSE; - if ( pd->selected_list != NULL ) { - for ( unsigned int st = 0; st < pd->cmd_list_length; st++ ) { - if ( bitget ( pd->selected_list, st ) ) { - seen = TRUE; - rofi_output_formatted_line ( pd->format, cmd_list[st].entry, st, input ); - } - } +static void dmenu_print_results(DmenuModePrivateData *pd, const char *input) { + DmenuScriptEntry *cmd_list = pd->cmd_list; + int seen = FALSE; + if (pd->selected_list != NULL) { + for (unsigned int st = 0; st < pd->cmd_list_length; st++) { + if (bitget(pd->selected_list, st)) { + seen = TRUE; + rofi_output_formatted_line(pd->format, cmd_list[st].entry, st, input); + } } - if ( !seen ) { - const char *cmd = input; - if ( pd->selected_line != UINT32_MAX ) { - cmd = cmd_list[pd->selected_line].entry; - } - rofi_output_formatted_line ( pd->format, cmd, pd->selected_line, input ); + } + if (!seen) { + const char *cmd = input; + if (pd->selected_line != UINT32_MAX) { + cmd = cmd_list[pd->selected_line].entry; } + rofi_output_formatted_line(pd->format, cmd, pd->selected_line, input); + } } -static void dmenu_finalize ( RofiViewState *state ) -{ - int retv = FALSE; - DmenuModePrivateData *pd = (DmenuModePrivateData *) rofi_view_get_mode ( state )->private_data; - unsigned int cmd_list_length = pd->cmd_list_length; - DmenuScriptEntry *cmd_list = pd->cmd_list; +static void dmenu_finalize(RofiViewState *state) { + int retv = FALSE; + DmenuModePrivateData *pd = + (DmenuModePrivateData *)rofi_view_get_mode(state)->private_data; + unsigned int cmd_list_length = pd->cmd_list_length; + DmenuScriptEntry *cmd_list = pd->cmd_list; - char *input = g_strdup ( rofi_view_get_user_input ( state ) ); - pd->selected_line = rofi_view_get_selected_line ( state );; - MenuReturn mretv = rofi_view_get_return_value ( state ); - unsigned int next_pos = rofi_view_get_next_position ( state ); - int restart = 0; - // Special behavior. - if ( pd->only_selected ) { - /** - * Select item mode. - */ - restart = 1; - // Skip if no valid item is selected. - if ( ( mretv & MENU_CANCEL ) == MENU_CANCEL ) { - // In no custom mode we allow canceling. - restart = ( find_arg ( "-only-match" ) >= 0 ); + char *input = g_strdup(rofi_view_get_user_input(state)); + pd->selected_line = rofi_view_get_selected_line(state); + ; + MenuReturn mretv = rofi_view_get_return_value(state); + unsigned int next_pos = rofi_view_get_next_position(state); + int restart = 0; + // Special behavior. + if (pd->only_selected) { + /** + * Select item mode. + */ + restart = 1; + // Skip if no valid item is selected. + if ((mretv & MENU_CANCEL) == MENU_CANCEL) { + // In no custom mode we allow canceling. + restart = (find_arg("-only-match") >= 0); + } else if (pd->selected_line != UINT32_MAX) { + if ((mretv & MENU_CUSTOM_ACTION) && pd->multi_select) { + restart = TRUE; + if (pd->selected_list == NULL) { + pd->selected_list = + g_malloc0(sizeof(uint32_t) * (pd->cmd_list_length / 32 + 1)); } - else if ( pd->selected_line != UINT32_MAX ) { - if ( ( mretv & MENU_CUSTOM_ACTION ) && pd->multi_select ) { - restart = TRUE; - if ( pd->selected_list == NULL ) { - pd->selected_list = g_malloc0 ( sizeof ( uint32_t ) * ( pd->cmd_list_length / 32 + 1 ) ); - } - pd->selected_count += ( bitget ( pd->selected_list, pd->selected_line ) ? ( -1 ) : ( 1 ) ); - bittoggle ( pd->selected_list, pd->selected_line ); - // Move to next line. - pd->selected_line = MIN ( next_pos, cmd_list_length - 1 ); - if ( pd->selected_count > 0 ) { - char *str = g_strdup_printf ( "%u/%u", pd->selected_count, pd->cmd_list_length ); - rofi_view_set_overlay ( state, str ); - g_free ( str ); - } - else { - rofi_view_set_overlay ( state, NULL ); - } - } - else if ( ( mretv & ( MENU_OK | MENU_CUSTOM_COMMAND ) ) && cmd_list[pd->selected_line].entry != NULL ) { - if ( cmd_list[pd->selected_line].nonselectable == TRUE ) { - g_free ( input ); - return; - } - dmenu_print_results ( pd, input ); - retv = TRUE; - if ( ( mretv & MENU_CUSTOM_COMMAND ) ) { - retv = 10 + ( mretv & MENU_LOWER_MASK ); - } - g_free ( input ); - dmenu_finish ( state, retv ); - return; - } - else { - pd->selected_line = next_pos - 1; - } + pd->selected_count += + (bitget(pd->selected_list, pd->selected_line) ? (-1) : (1)); + bittoggle(pd->selected_list, pd->selected_line); + // Move to next line. + pd->selected_line = MIN(next_pos, cmd_list_length - 1); + if (pd->selected_count > 0) { + char *str = + g_strdup_printf("%u/%u", pd->selected_count, pd->cmd_list_length); + rofi_view_set_overlay(state, str); + g_free(str); + } else { + rofi_view_set_overlay(state, NULL); } - // Restart - rofi_view_restart ( state ); - rofi_view_set_selected_line ( state, pd->selected_line ); - if ( !restart ) { - dmenu_finish ( state, retv ); + } else if ((mretv & (MENU_OK | MENU_CUSTOM_COMMAND)) && + cmd_list[pd->selected_line].entry != NULL) { + if (cmd_list[pd->selected_line].nonselectable == TRUE) { + g_free(input); + return; } + dmenu_print_results(pd, input); + retv = TRUE; + if ((mretv & MENU_CUSTOM_COMMAND)) { + retv = 10 + (mretv & MENU_LOWER_MASK); + } + g_free(input); + dmenu_finish(state, retv); return; + } else { + pd->selected_line = next_pos - 1; + } } - // We normally do not want to restart the loop. + // Restart + rofi_view_restart(state); + rofi_view_set_selected_line(state, pd->selected_line); + if (!restart) { + dmenu_finish(state, retv); + } + return; + } + // We normally do not want to restart the loop. + restart = FALSE; + // Normal mode + if ((mretv & MENU_OK) && pd->selected_line != UINT32_MAX && + cmd_list[pd->selected_line].entry != NULL) { + // Check if entry is non-selectable. + if (cmd_list[pd->selected_line].nonselectable == TRUE) { + g_free(input); + return; + } + if ((mretv & MENU_CUSTOM_ACTION) && pd->multi_select) { + restart = TRUE; + if (pd->selected_list == NULL) { + pd->selected_list = + g_malloc0(sizeof(uint32_t) * (pd->cmd_list_length / 32 + 1)); + } + pd->selected_count += + (bitget(pd->selected_list, pd->selected_line) ? (-1) : (1)); + bittoggle(pd->selected_list, pd->selected_line); + // Move to next line. + pd->selected_line = MIN(next_pos, cmd_list_length - 1); + if (pd->selected_count > 0) { + char *str = + g_strdup_printf("%u/%u", pd->selected_count, pd->cmd_list_length); + rofi_view_set_overlay(state, str); + g_free(str); + } else { + rofi_view_set_overlay(state, NULL); + } + } else { + dmenu_print_results(pd, input); + } + retv = TRUE; + } + // Custom input + else if ((mretv & (MENU_CUSTOM_INPUT))) { + dmenu_print_results(pd, input); + + retv = TRUE; + } + // Quick switch with entry selected. + else if ((mretv & MENU_CUSTOM_COMMAND)) { + dmenu_print_results(pd, input); + restart = FALSE; - // Normal mode - if ( ( mretv & MENU_OK ) && pd->selected_line != UINT32_MAX && cmd_list[pd->selected_line].entry != NULL ) { - // Check if entry is non-selectable. - if ( cmd_list[pd->selected_line].nonselectable == TRUE ) { - g_free ( input ); - return; - } - if ( ( mretv & MENU_CUSTOM_ACTION ) && pd->multi_select ) { - restart = TRUE; - if ( pd->selected_list == NULL ) { - pd->selected_list = g_malloc0 ( sizeof ( uint32_t ) * ( pd->cmd_list_length / 32 + 1 ) ); - } - pd->selected_count += ( bitget ( pd->selected_list, pd->selected_line ) ? ( -1 ) : ( 1 ) ); - bittoggle ( pd->selected_list, pd->selected_line ); - // Move to next line. - pd->selected_line = MIN ( next_pos, cmd_list_length - 1 ); - if ( pd->selected_count > 0 ) { - char *str = g_strdup_printf ( "%u/%u", pd->selected_count, pd->cmd_list_length ); - rofi_view_set_overlay ( state, str ); - g_free ( str ); - } - else { - rofi_view_set_overlay ( state, NULL ); - } - } - else { - dmenu_print_results ( pd, input ); - } - retv = TRUE; - } - // Custom input - else if ( ( mretv & ( MENU_CUSTOM_INPUT ) ) ) { - dmenu_print_results ( pd, input ); - - retv = TRUE; - } - // Quick switch with entry selected. - else if ( ( mretv & MENU_CUSTOM_COMMAND ) ) { - dmenu_print_results ( pd, input ); - - restart = FALSE; - retv = 10 + ( mretv & MENU_LOWER_MASK ); - } - g_free ( input ); - if ( restart ) { - rofi_view_restart ( state ); - rofi_view_set_selected_line ( state, pd->selected_line ); - } - else { - dmenu_finish ( state, retv ); - } + retv = 10 + (mretv & MENU_LOWER_MASK); + } + g_free(input); + if (restart) { + rofi_view_restart(state); + rofi_view_set_selected_line(state, pd->selected_line); + } else { + dmenu_finish(state, retv); + } } -int dmenu_switcher_dialog ( void ) -{ - mode_init ( &dmenu_mode ); - MenuFlags menu_flags = MENU_NORMAL; - DmenuModePrivateData *pd = (DmenuModePrivateData *) dmenu_mode.private_data; - int async = TRUE; +int dmenu_switcher_dialog(void) { + mode_init(&dmenu_mode); + MenuFlags menu_flags = MENU_NORMAL; + DmenuModePrivateData *pd = (DmenuModePrivateData *)dmenu_mode.private_data; + int async = TRUE; - // For now these only work in sync mode. - if ( find_arg ( "-sync" ) >= 0 || find_arg ( "-dump" ) >= 0 || find_arg ( "-select" ) >= 0 - || find_arg ( "-no-custom" ) >= 0 || find_arg ( "-only-match" ) >= 0 || config.auto_select || - find_arg ( "-selected-row" ) >= 0 ) { - async = FALSE; - } + // For now these only work in sync mode. + if (find_arg("-sync") >= 0 || find_arg("-dump") >= 0 || + find_arg("-select") >= 0 || find_arg("-no-custom") >= 0 || + find_arg("-only-match") >= 0 || config.auto_select || + find_arg("-selected-row") >= 0) { + async = FALSE; + } - // Check if the subsystem is setup for reading, otherwise do not read. - if ( pd->cancel != NULL ) { - if ( async ) { - unsigned int pre_read = 25; - find_arg_uint ( "-async-pre-read", &pre_read ); - async = get_dmenu_async ( pd, pre_read ); - } - else { - get_dmenu_sync ( pd ); - } + // Check if the subsystem is setup for reading, otherwise do not read. + if (pd->cancel != NULL) { + if (async) { + unsigned int pre_read = 25; + find_arg_uint("-async-pre-read", &pre_read); + async = get_dmenu_async(pd, pre_read); + } else { + get_dmenu_sync(pd); } - char *input = NULL; - unsigned int cmd_list_length = pd->cmd_list_length; - DmenuScriptEntry *cmd_list = pd->cmd_list; + } + char *input = NULL; + unsigned int cmd_list_length = pd->cmd_list_length; + DmenuScriptEntry *cmd_list = pd->cmd_list; - pd->only_selected = FALSE; - pd->multi_select = FALSE; - if ( find_arg ( "-multi-select" ) >= 0 ) { - menu_flags = MENU_INDICATOR; - pd->multi_select = TRUE; + pd->only_selected = FALSE; + pd->multi_select = FALSE; + if (find_arg("-multi-select") >= 0) { + menu_flags = MENU_INDICATOR; + pd->multi_select = TRUE; + } + if (find_arg("-markup-rows") >= 0) { + pd->do_markup = TRUE; + } + if (find_arg("-only-match") >= 0 || find_arg("-no-custom") >= 0) { + pd->only_selected = TRUE; + if (cmd_list_length == 0) { + return TRUE; } - if ( find_arg ( "-markup-rows" ) >= 0 ) { - pd->do_markup = TRUE; - } - if ( find_arg ( "-only-match" ) >= 0 || find_arg ( "-no-custom" ) >= 0 ) { - pd->only_selected = TRUE; - if ( cmd_list_length == 0 ) { - return TRUE; - } - } - if ( config.auto_select && cmd_list_length == 1 ) { - rofi_output_formatted_line ( pd->format, cmd_list[0].entry, 0, config.filter ); - return TRUE; - } - if ( find_arg ( "-password" ) >= 0 ) { - menu_flags |= MENU_PASSWORD; - } - /* copy filter string */ - input = g_strdup ( config.filter ); + } + if (config.auto_select && cmd_list_length == 1) { + rofi_output_formatted_line(pd->format, cmd_list[0].entry, 0, config.filter); + return TRUE; + } + if (find_arg("-password") >= 0) { + menu_flags |= MENU_PASSWORD; + } + /* copy filter string */ + input = g_strdup(config.filter); - char *select = NULL; - find_arg_str ( "-select", &select ); - if ( select != NULL ) { - rofi_int_matcher **tokens = helper_tokenize ( select, config.case_sensitive ); - unsigned int i = 0; - for ( i = 0; i < cmd_list_length; i++ ) { - if ( helper_token_match ( tokens, cmd_list[i].entry ) ) { - pd->selected_line = i; - break; - } - } - helper_tokenize_free ( tokens ); + char *select = NULL; + find_arg_str("-select", &select); + if (select != NULL) { + rofi_int_matcher **tokens = helper_tokenize(select, config.case_sensitive); + unsigned int i = 0; + for (i = 0; i < cmd_list_length; i++) { + if (helper_token_match(tokens, cmd_list[i].entry)) { + pd->selected_line = i; + break; + } } - if ( find_arg ( "-dump" ) >= 0 ) { - rofi_int_matcher **tokens = helper_tokenize ( config.filter ? config.filter : "", config.case_sensitive ); - unsigned int i = 0; - for ( i = 0; i < cmd_list_length; i++ ) { - if ( tokens == NULL || helper_token_match ( tokens, cmd_list[i].entry ) ) { - rofi_output_formatted_line ( pd->format, cmd_list[i].entry, i, config.filter ); - } - } - helper_tokenize_free ( tokens ); - dmenu_mode_free ( &dmenu_mode ); - g_free ( input ); - return TRUE; + helper_tokenize_free(tokens); + } + if (find_arg("-dump") >= 0) { + rofi_int_matcher **tokens = helper_tokenize( + config.filter ? config.filter : "", config.case_sensitive); + unsigned int i = 0; + for (i = 0; i < cmd_list_length; i++) { + if (tokens == NULL || helper_token_match(tokens, cmd_list[i].entry)) { + rofi_output_formatted_line(pd->format, cmd_list[i].entry, i, + config.filter); + } } - find_arg_str ( "-p", &( dmenu_mode.display_name ) ); - RofiViewState *state = rofi_view_create ( &dmenu_mode, input, menu_flags, dmenu_finalize ); + helper_tokenize_free(tokens); + dmenu_mode_free(&dmenu_mode); + g_free(input); + return TRUE; + } + find_arg_str("-p", &(dmenu_mode.display_name)); + RofiViewState *state = + rofi_view_create(&dmenu_mode, input, menu_flags, dmenu_finalize); - if ( find_arg ( "-keep-right" ) >= 0 ) { - rofi_view_ellipsize_start ( state ); - } - // @TODO we should do this better. - if ( async && ( pd->cancel != NULL ) ) { - rofi_view_set_overlay ( state, "Loading.. " ); - } - rofi_view_set_selected_line ( state, pd->selected_line ); - rofi_view_set_active ( state ); + if (find_arg("-keep-right") >= 0) { + rofi_view_ellipsize_start(state); + } + // @TODO we should do this better. + if (async && (pd->cancel != NULL)) { + rofi_view_set_overlay(state, "Loading.. "); + } + rofi_view_set_selected_line(state, pd->selected_line); + rofi_view_set_active(state); - return FALSE; + return FALSE; } -void print_dmenu_options ( void ) -{ - int is_term = isatty ( fileno ( stdout ) ); - print_help_msg ( "-mesg", "[string]", "Print a small user message under the prompt (uses pango markup)", NULL, is_term ); - print_help_msg ( "-p", "[string]", "Prompt to display left of entry field", NULL, is_term ); - print_help_msg ( "-selected-row", "[integer]", "Select row", NULL, is_term ); - print_help_msg ( "-format", "[string]", "Output format string", "s", is_term ); - print_help_msg ( "-u", "[list]", "List of row indexes to mark urgent", NULL, is_term ); - print_help_msg ( "-a", "[list]", "List of row indexes to mark active", NULL, is_term ); - print_help_msg ( "-l", "[integer] ", "Number of rows to display", NULL, is_term ); - print_help_msg ( "-window-title", "[string] ", "Set the dmenu window title", NULL, is_term ); - print_help_msg ( "-i", "", "Set filter to be case insensitive", NULL, is_term ); - print_help_msg ( "-only-match", "", "Force selection to be given entry, disallow no match", NULL, is_term ); - print_help_msg ( "-no-custom", "", "Don't accept custom entry, allow no match", NULL, is_term ); - print_help_msg ( "-select", "[string]", "Select the first row that matches", NULL, is_term ); - print_help_msg ( "-password", "", "Do not show what the user inputs. Show '*' instead.", NULL, is_term ); - print_help_msg ( "-markup-rows", "", "Allow and render pango markup as input data.", NULL, is_term ); - print_help_msg ( "-sep", "[char]", "Element separator.", "'\\n'", is_term ); - print_help_msg ( "-input", "[filename]", "Read input from file instead from standard input.", NULL, is_term ); - print_help_msg ( "-sync", "", "Force dmenu to first read all input data, then show dialog.", NULL, is_term ); - print_help_msg ( "-async-pre-read", "[number]", "Read several entries blocking before switching to async mode", "25", is_term ); - print_help_msg ( "-w", "windowid", "Position over window with X11 windowid.", NULL, is_term ); - print_help_msg ( "-keep-right", "", "Set ellipsize to end.", NULL, is_term ); +void print_dmenu_options(void) { + int is_term = isatty(fileno(stdout)); + print_help_msg( + "-mesg", "[string]", + "Print a small user message under the prompt (uses pango markup)", NULL, + is_term); + print_help_msg("-p", "[string]", "Prompt to display left of entry field", + NULL, is_term); + print_help_msg("-selected-row", "[integer]", "Select row", NULL, is_term); + print_help_msg("-format", "[string]", "Output format string", "s", is_term); + print_help_msg("-u", "[list]", "List of row indexes to mark urgent", NULL, + is_term); + print_help_msg("-a", "[list]", "List of row indexes to mark active", NULL, + is_term); + print_help_msg("-l", "[integer] ", "Number of rows to display", NULL, + is_term); + print_help_msg("-window-title", "[string] ", "Set the dmenu window title", + NULL, is_term); + print_help_msg("-i", "", "Set filter to be case insensitive", NULL, is_term); + print_help_msg("-only-match", "", + "Force selection to be given entry, disallow no match", NULL, + is_term); + print_help_msg("-no-custom", "", "Don't accept custom entry, allow no match", + NULL, is_term); + print_help_msg("-select", "[string]", "Select the first row that matches", + NULL, is_term); + print_help_msg("-password", "", + "Do not show what the user inputs. Show '*' instead.", NULL, + is_term); + print_help_msg("-markup-rows", "", + "Allow and render pango markup as input data.", NULL, is_term); + print_help_msg("-sep", "[char]", "Element separator.", "'\\n'", is_term); + print_help_msg("-input", "[filename]", + "Read input from file instead from standard input.", NULL, + is_term); + print_help_msg("-sync", "", + "Force dmenu to first read all input data, then show dialog.", + NULL, is_term); + print_help_msg("-async-pre-read", "[number]", + "Read several entries blocking before switching to async mode", + "25", is_term); + print_help_msg("-w", "windowid", "Position over window with X11 windowid.", + NULL, is_term); + print_help_msg("-keep-right", "", "Set ellipsize to end.", NULL, is_term); } diff --git a/source/dialogs/drun.c b/source/dialogs/drun.c index 13060a67..06d3595c 100644 --- a/source/dialogs/drun.c +++ b/source/dialogs/drun.c @@ -26,1407 +26,1434 @@ */ /** The log domain of this dialog. */ -#define G_LOG_DOMAIN "Dialogs.DRun" +#define G_LOG_DOMAIN "Dialogs.DRun" #include #ifdef ENABLE_DRUN -#include -#include #include +#include +#include -#include +#include +#include #include #include -#include -#include -#include -#include #include -#include +#include +#include +#include +#include -#include "rofi.h" -#include "settings.h" -#include "helper.h" -#include "timings.h" -#include "widgets/textbox.h" -#include "history.h" #include "dialogs/drun.h" #include "dialogs/filebrowser.h" +#include "helper.h" +#include "history.h" #include "mode-private.h" +#include "rofi.h" +#include "settings.h" +#include "timings.h" +#include "widgets/textbox.h" #include "xcb.h" #include "rofi-icon-fetcher.h" -#define DRUN_CACHE_FILE "rofi3.druncache" -#define DRUN_DESKTOP_CACHE_FILE "rofi-drun-desktop.cache" +#define DRUN_CACHE_FILE "rofi3.druncache" +#define DRUN_DESKTOP_CACHE_FILE "rofi-drun-desktop.cache" char *DRUN_GROUP_NAME = "Desktop Entry"; typedef struct _DRunModePrivateData DRunModePrivateData; -typedef enum -{ - DRUN_DESKTOP_ENTRY_TYPE_UNDETERMINED = 0, - DRUN_DESKTOP_ENTRY_TYPE_APPLICATION, - DRUN_DESKTOP_ENTRY_TYPE_LINK, - DRUN_DESKTOP_ENTRY_TYPE_SERVICE, - DRUN_DESKTOP_ENTRY_TYPE_DIRECTORY, +typedef enum { + DRUN_DESKTOP_ENTRY_TYPE_UNDETERMINED = 0, + DRUN_DESKTOP_ENTRY_TYPE_APPLICATION, + DRUN_DESKTOP_ENTRY_TYPE_LINK, + DRUN_DESKTOP_ENTRY_TYPE_SERVICE, + DRUN_DESKTOP_ENTRY_TYPE_DIRECTORY, } DRunDesktopEntryType; /** * Store extra information about the entry. * Currently the executable and if it should run in terminal. */ -typedef struct -{ - DRunModePrivateData *pd; - /* category */ - char *action; - /* Root */ - char *root; - /* Path to desktop file */ - char *path; - /* Application id (.desktop filename) */ - char *app_id; - /* Desktop id */ - char *desktop_id; - /* Icon stuff */ - char *icon_name; - /* Icon size is used to indicate what size is requested by the gui. - * secondary it indicates if the request for a lookup has been issued (0 not issued ) - */ - int icon_size; - /* Surface holding the icon. */ - cairo_surface_t *icon; - /* Executable - for Application entries only */ - char *exec; - /* Name of the Entry */ - char *name; - /* Generic Name */ - char *generic_name; - /* Categories */ - char **categories; - /* Keywords */ - char **keywords; - /* Comments */ - char *comment; +typedef struct { + DRunModePrivateData *pd; + /* category */ + char *action; + /* Root */ + char *root; + /* Path to desktop file */ + char *path; + /* Application id (.desktop filename) */ + char *app_id; + /* Desktop id */ + char *desktop_id; + /* Icon stuff */ + char *icon_name; + /* Icon size is used to indicate what size is requested by the gui. + * secondary it indicates if the request for a lookup has been issued (0 not + * issued ) + */ + int icon_size; + /* Surface holding the icon. */ + cairo_surface_t *icon; + /* Executable - for Application entries only */ + char *exec; + /* Name of the Entry */ + char *name; + /* Generic Name */ + char *generic_name; + /* Categories */ + char **categories; + /* Keywords */ + char **keywords; + /* Comments */ + char *comment; - GKeyFile *key_file; + GKeyFile *key_file; - gint sort_index; + gint sort_index; - uint32_t icon_fetch_uid; + uint32_t icon_fetch_uid; - DRunDesktopEntryType type; + DRunDesktopEntryType type; } DRunModeEntry; -typedef struct -{ - const char *entry_field_name; - gboolean enabled_match; - gboolean enabled_display; +typedef struct { + const char *entry_field_name; + gboolean enabled_match; + gboolean enabled_display; } DRunEntryField; -typedef enum -{ - DRUN_MATCH_FIELD_NAME, - DRUN_MATCH_FIELD_GENERIC, - DRUN_MATCH_FIELD_EXEC, - DRUN_MATCH_FIELD_CATEGORIES, - DRUN_MATCH_FIELD_KEYWORDS, - DRUN_MATCH_FIELD_COMMENT, - DRUN_MATCH_NUM_FIELDS, +typedef enum { + DRUN_MATCH_FIELD_NAME, + DRUN_MATCH_FIELD_GENERIC, + DRUN_MATCH_FIELD_EXEC, + DRUN_MATCH_FIELD_CATEGORIES, + DRUN_MATCH_FIELD_KEYWORDS, + DRUN_MATCH_FIELD_COMMENT, + DRUN_MATCH_NUM_FIELDS, } DRunMatchingFields; static DRunEntryField matching_entry_fields[DRUN_MATCH_NUM_FIELDS] = { - { .entry_field_name = "name", .enabled_match = TRUE, .enabled_display = TRUE, }, - { .entry_field_name = "generic", .enabled_match = TRUE, .enabled_display = TRUE, }, - { .entry_field_name = "exec", .enabled_match = TRUE, .enabled_display = TRUE, }, - { .entry_field_name = "categories", .enabled_match = TRUE, .enabled_display = TRUE, }, - { .entry_field_name = "keywords", .enabled_match = TRUE, .enabled_display = TRUE, }, - { .entry_field_name = "comment", .enabled_match = FALSE,.enabled_display = FALSE,} + { + .entry_field_name = "name", + .enabled_match = TRUE, + .enabled_display = TRUE, + }, + { + .entry_field_name = "generic", + .enabled_match = TRUE, + .enabled_display = TRUE, + }, + { + .entry_field_name = "exec", + .enabled_match = TRUE, + .enabled_display = TRUE, + }, + { + .entry_field_name = "categories", + .enabled_match = TRUE, + .enabled_display = TRUE, + }, + { + .entry_field_name = "keywords", + .enabled_match = TRUE, + .enabled_display = TRUE, + }, + { + .entry_field_name = "comment", + .enabled_match = FALSE, + .enabled_display = FALSE, + }}; + +struct _DRunModePrivateData { + DRunModeEntry *entry_list; + unsigned int cmd_list_length; + unsigned int cmd_list_length_actual; + // List of disabled entries. + GHashTable *disabled_entries; + unsigned int disabled_entries_length; + unsigned int expected_line_height; + + char **show_categories; + + // Theme + const gchar *icon_theme; + // DE + gchar **current_desktop_list; + + gboolean file_complete; + Mode *completer; + char *old_completer_input; + uint32_t selected_line; + char *old_input; + + /** fallback icon */ + uint32_t fallback_icon_fetch_uid; + cairo_surface_t *fallback_icon; }; -struct _DRunModePrivateData -{ - DRunModeEntry *entry_list; - unsigned int cmd_list_length; - unsigned int cmd_list_length_actual; - // List of disabled entries. - GHashTable *disabled_entries; - unsigned int disabled_entries_length; - unsigned int expected_line_height; - - char **show_categories; - - // Theme - const gchar *icon_theme; - // DE - gchar **current_desktop_list; - - - gboolean file_complete; - Mode *completer; - char *old_completer_input; - uint32_t selected_line; - char *old_input; - - /** fallback icon */ - uint32_t fallback_icon_fetch_uid; - cairo_surface_t *fallback_icon; +struct RegexEvalArg { + DRunModeEntry *e; + const char *path; + gboolean success; }; -struct RegexEvalArg -{ - DRunModeEntry *e; - const char *path; - gboolean success; -}; +static gboolean drun_helper_eval_cb(const GMatchInfo *info, GString *res, + gpointer data) { + // TODO quoting is not right? Find description not very clear, need to check. + struct RegexEvalArg *e = (struct RegexEvalArg *)data; -static gboolean drun_helper_eval_cb ( const GMatchInfo *info, GString *res, gpointer data ) -{ - // TODO quoting is not right? Find description not very clear, need to check. - struct RegexEvalArg *e = (struct RegexEvalArg *) data; - - gchar *match; - // Get the match - match = g_match_info_fetch ( info, 0 ); - if ( match != NULL ) { - switch ( match[1] ) - { - case 'f': - case 'F': - case 'u': - case 'U': - g_string_append(res, e->path); - break; - // Unsupported - case 'i': - // TODO - if ( e->e && e->e->icon ) { - g_string_append_printf(res, "--icon %s", e->e->icon_name ); - } - break; - // Deprecated - case 'd': - case 'D': - case 'n': - case 'N': - case 'v': - case 'm': - break; - case '%': - g_string_append ( res, "%" ); - break; - case 'k': - if ( e->e->path ) { - char *esc = g_shell_quote ( e->e->path ); - g_string_append ( res, esc ); - g_free ( esc ); - } - break; - case 'c': - if ( e->e->name ) { - char *esc = g_shell_quote ( e->e->name ); - g_string_append ( res, esc ); - g_free ( esc ); - } - break; - // Invalid, this entry should not be processed -> throw error. - default: - e->success = FALSE; - g_free ( match ); - return TRUE; - } - g_free ( match ); + gchar *match; + // Get the match + match = g_match_info_fetch(info, 0); + if (match != NULL) { + switch (match[1]) { + case 'f': + case 'F': + case 'u': + case 'U': + g_string_append(res, e->path); + break; + // Unsupported + case 'i': + // TODO + if (e->e && e->e->icon) { + g_string_append_printf(res, "--icon %s", e->e->icon_name); + } + break; + // Deprecated + case 'd': + case 'D': + case 'n': + case 'N': + case 'v': + case 'm': + break; + case '%': + g_string_append(res, "%"); + break; + case 'k': + if (e->e->path) { + char *esc = g_shell_quote(e->e->path); + g_string_append(res, esc); + g_free(esc); + } + break; + case 'c': + if (e->e->name) { + char *esc = g_shell_quote(e->e->name); + g_string_append(res, esc); + g_free(esc); + } + break; + // Invalid, this entry should not be processed -> throw error. + default: + e->success = FALSE; + g_free(match); + return TRUE; } - // Continue replacement. - return FALSE; + g_free(match); + } + // Continue replacement. + return FALSE; } -static void launch_link_entry ( DRunModeEntry *e ) -{ - if ( e->key_file == NULL ) { - GKeyFile *kf = g_key_file_new (); - GError *error = NULL; - gboolean res = g_key_file_load_from_file ( kf, e->path, 0, &error ); - if ( res ) { - e->key_file = kf; - } - else { - g_warning ( "[%s] [%s] Failed to parse desktop file because: %s.", e->app_id, e->path, error->message ); - g_error_free ( error ); - g_key_file_free ( kf ); - return; - } - } - - gchar *url = g_key_file_get_string ( e->key_file, e->action, "URL", NULL ); - if ( url == NULL || strlen ( url ) == 0 ) { - g_warning ( "[%s] [%s] No URL found.", e->app_id, e->path ); - g_free ( url ); - return; - } - - gsize command_len = strlen ( config.drun_url_launcher ) + strlen ( url ) + 2; // space + terminator = 2 - gchar *command = g_newa ( gchar, command_len ); - g_snprintf ( command, command_len, "%s %s", config.drun_url_launcher, url ); - g_free ( url ); - - g_debug ( "Link launch command: |%s|", command ); - if ( helper_execute_command ( NULL, command, FALSE, NULL ) ) { - char *path = g_build_filename ( cache_dir, DRUN_CACHE_FILE, NULL ); - // Store it based on the unique identifiers (desktop_id). - history_set ( path, e->desktop_id ); - g_free ( path ); - } -} -static void exec_cmd_entry ( DRunModeEntry *e, const char *path ) -{ +static void launch_link_entry(DRunModeEntry *e) { + if (e->key_file == NULL) { + GKeyFile *kf = g_key_file_new(); GError *error = NULL; - GRegex *reg = g_regex_new ( "%[a-zA-Z%]", 0, 0, &error ); - if ( error != NULL ) { - g_warning ( "Internal error, failed to create regex: %s.", error->message ); - g_error_free ( error ); - return; + gboolean res = g_key_file_load_from_file(kf, e->path, 0, &error); + if (res) { + e->key_file = kf; + } else { + g_warning("[%s] [%s] Failed to parse desktop file because: %s.", + e->app_id, e->path, error->message); + g_error_free(error); + g_key_file_free(kf); + return; } - struct RegexEvalArg earg = { .e = e, .path = path, .success = TRUE }; - char *str = g_regex_replace_eval ( reg, e->exec, -1, 0, 0, drun_helper_eval_cb, &earg, &error ); - if ( error != NULL ) { - g_warning ( "Internal error, failed replace field codes: %s.", error->message ); - g_error_free ( error ); - return; - } - g_regex_unref ( reg ); - if ( earg.success == FALSE ) { - g_warning ( "Invalid field code in Exec line: %s.", e->exec );; - return; - } - if ( str == NULL ) { - g_warning ( "Nothing to execute after processing: %s.", e->exec );; - return; - } - g_debug ( "Parsed command: |%s| into |%s|.", e->exec, str ); + } - if ( e->key_file == NULL ) { - GKeyFile *kf = g_key_file_new (); - GError *error = NULL; - gboolean res = g_key_file_load_from_file ( kf, e->path, 0, &error ); - if ( res ) { - e->key_file = kf; - } - else { - g_warning ( "[%s] [%s] Failed to parse desktop file because: %s.", e->app_id, e->path, error->message ); - g_error_free ( error ); - g_key_file_free ( kf ); + gchar *url = g_key_file_get_string(e->key_file, e->action, "URL", NULL); + if (url == NULL || strlen(url) == 0) { + g_warning("[%s] [%s] No URL found.", e->app_id, e->path); + g_free(url); + return; + } - return; - } - } + gsize command_len = strlen(config.drun_url_launcher) + strlen(url) + + 2; // space + terminator = 2 + gchar *command = g_newa(gchar, command_len); + g_snprintf(command, command_len, "%s %s", config.drun_url_launcher, url); + g_free(url); - const gchar *fp = g_strstrip ( str ); - gchar *exec_path = g_key_file_get_string ( e->key_file, e->action, "Path", NULL ); - if ( exec_path != NULL && strlen ( exec_path ) == 0 ) { - // If it is empty, ignore this property. (#529) - g_free ( exec_path ); - exec_path = NULL; - } + g_debug("Link launch command: |%s|", command); + if (helper_execute_command(NULL, command, FALSE, NULL)) { + char *path = g_build_filename(cache_dir, DRUN_CACHE_FILE, NULL); + // Store it based on the unique identifiers (desktop_id). + history_set(path, e->desktop_id); + g_free(path); + } +} +static void exec_cmd_entry(DRunModeEntry *e, const char *path) { + GError *error = NULL; + GRegex *reg = g_regex_new("%[a-zA-Z%]", 0, 0, &error); + if (error != NULL) { + g_warning("Internal error, failed to create regex: %s.", error->message); + g_error_free(error); + return; + } + struct RegexEvalArg earg = {.e = e, .path = path, .success = TRUE}; + char *str = g_regex_replace_eval(reg, e->exec, -1, 0, 0, drun_helper_eval_cb, + &earg, &error); + if (error != NULL) { + g_warning("Internal error, failed replace field codes: %s.", + error->message); + g_error_free(error); + return; + } + g_regex_unref(reg); + if (earg.success == FALSE) { + g_warning("Invalid field code in Exec line: %s.", e->exec); + ; + return; + } + if (str == NULL) { + g_warning("Nothing to execute after processing: %s.", e->exec); + ; + return; + } + g_debug("Parsed command: |%s| into |%s|.", e->exec, str); - RofiHelperExecuteContext context = { - .name = e->name, - .icon = e->icon_name, - .app_id = e->app_id, - }; - gboolean sn = g_key_file_get_boolean ( e->key_file, e->action, "StartupNotify", NULL ); - gchar *wmclass = NULL; - if ( sn && g_key_file_has_key ( e->key_file, e->action, "StartupWMClass", NULL ) ) { - context.wmclass = wmclass = g_key_file_get_string ( e->key_file, e->action, "StartupWMClass", NULL ); - } + if (e->key_file == NULL) { + GKeyFile *kf = g_key_file_new(); + GError *error = NULL; + gboolean res = g_key_file_load_from_file(kf, e->path, 0, &error); + if (res) { + e->key_file = kf; + } else { + g_warning("[%s] [%s] Failed to parse desktop file because: %s.", + e->app_id, e->path, error->message); + g_error_free(error); + g_key_file_free(kf); - // Returns false if not found, if key not found, we don't want run in terminal. - gboolean terminal = g_key_file_get_boolean ( e->key_file, e->action, "Terminal", NULL ); - if ( helper_execute_command ( exec_path, fp, terminal, sn ? &context : NULL ) ) { - char *path = g_build_filename ( cache_dir, DRUN_CACHE_FILE, NULL ); - // Store it based on the unique identifiers (desktop_id). - history_set ( path, e->desktop_id ); - g_free ( path ); + return; } - g_free ( wmclass ); - g_free ( exec_path ); - g_free ( str ); + } + + const gchar *fp = g_strstrip(str); + gchar *exec_path = + g_key_file_get_string(e->key_file, e->action, "Path", NULL); + if (exec_path != NULL && strlen(exec_path) == 0) { + // If it is empty, ignore this property. (#529) + g_free(exec_path); + exec_path = NULL; + } + + RofiHelperExecuteContext context = { + .name = e->name, + .icon = e->icon_name, + .app_id = e->app_id, + }; + gboolean sn = + g_key_file_get_boolean(e->key_file, e->action, "StartupNotify", NULL); + gchar *wmclass = NULL; + if (sn && + g_key_file_has_key(e->key_file, e->action, "StartupWMClass", NULL)) { + context.wmclass = wmclass = + g_key_file_get_string(e->key_file, e->action, "StartupWMClass", NULL); + } + + // Returns false if not found, if key not found, we don't want run in + // terminal. + gboolean terminal = + g_key_file_get_boolean(e->key_file, e->action, "Terminal", NULL); + if (helper_execute_command(exec_path, fp, terminal, sn ? &context : NULL)) { + char *path = g_build_filename(cache_dir, DRUN_CACHE_FILE, NULL); + // Store it based on the unique identifiers (desktop_id). + history_set(path, e->desktop_id); + g_free(path); + } + g_free(wmclass); + g_free(exec_path); + g_free(str); } -static gboolean rofi_strv_contains ( const char * const *categories, const char *const *field ) -{ - for ( int i = 0; categories && categories[i]; i++ ) { - for ( int j = 0; field[j]; j++ ) { - if ( g_str_equal ( categories[i], field[j] ) ) { - return TRUE; - } - } +static gboolean rofi_strv_contains(const char *const *categories, + const char *const *field) { + for (int i = 0; categories && categories[i]; i++) { + for (int j = 0; field[j]; j++) { + if (g_str_equal(categories[i], field[j])) { + return TRUE; + } } - return FALSE; + } + return FALSE; } /** * This function absorbs/freeÅ› path, so this is no longer available afterwards. */ -static void read_desktop_file ( DRunModePrivateData *pd, const char *root, const char *path, const gchar *basename, const char *action ) -{ - DRunDesktopEntryType desktop_entry_type = DRUN_DESKTOP_ENTRY_TYPE_UNDETERMINED; - int parse_action = ( config.drun_show_actions && action != DRUN_GROUP_NAME ); - // Create ID on stack. - // We know strlen (path ) > strlen(root)+1 - const ssize_t id_len = strlen ( path ) - strlen ( root ); - char id[id_len]; - g_strlcpy ( id, &( path[strlen ( root ) + 1] ), id_len ); - for ( int index = 0; index < id_len; index++ ) { - if ( id[index] == '/' ) { - id[index] = '-'; - } +static void read_desktop_file(DRunModePrivateData *pd, const char *root, + const char *path, const gchar *basename, + const char *action) { + DRunDesktopEntryType desktop_entry_type = + DRUN_DESKTOP_ENTRY_TYPE_UNDETERMINED; + int parse_action = (config.drun_show_actions && action != DRUN_GROUP_NAME); + // Create ID on stack. + // We know strlen (path ) > strlen(root)+1 + const ssize_t id_len = strlen(path) - strlen(root); + char id[id_len]; + g_strlcpy(id, &(path[strlen(root) + 1]), id_len); + for (int index = 0; index < id_len; index++) { + if (id[index] == '/') { + id[index] = '-'; } + } - // Check if item is on disabled list. - if ( g_hash_table_contains ( pd->disabled_entries, id ) && !parse_action ) { - g_debug ( "[%s] [%s] Skipping, was previously seen.", id, path ); - return; - } - GKeyFile *kf = g_key_file_new (); - GError *error = NULL; - gboolean res = g_key_file_load_from_file ( kf, path, 0, &error ); - // If error, skip to next entry - if ( !res ) { - g_debug ( "[%s] [%s] Failed to parse desktop file because: %s.", id, path, error->message ); - g_error_free ( error ); - g_key_file_free ( kf ); - return; - } - - if ( g_key_file_has_group ( kf, action ) == FALSE ) { - // No type? ignore. - g_debug ( "[%s] [%s] Invalid desktop file: No %s group", id, path, action ); - g_key_file_free ( kf ); - return; - } - // Skip non Application entries. - gchar *key = g_key_file_get_string ( kf, DRUN_GROUP_NAME, "Type", NULL ); - if ( key == NULL ) { - // No type? ignore. - g_debug ( "[%s] [%s] Invalid desktop file: No type indicated", id, path ); - g_key_file_free ( kf ); - return; - } - if ( !g_strcmp0 ( key, "Application" ) ) { - desktop_entry_type = DRUN_DESKTOP_ENTRY_TYPE_APPLICATION; - } - else if ( !g_strcmp0 ( key, "Link" ) ) { - desktop_entry_type = DRUN_DESKTOP_ENTRY_TYPE_LINK; - } - else if ( !g_strcmp0 ( key, "Service" ) ) { - desktop_entry_type = DRUN_DESKTOP_ENTRY_TYPE_SERVICE; - g_debug ( "Service file detected." ); - } - else { - g_debug ( "[%s] [%s] Skipping desktop file: Not of type Application or Link (%s)", id, path, key ); - g_free ( key ); - g_key_file_free ( kf ); - return; - } - g_free ( key ); - - // Name key is required. - if ( !g_key_file_has_key ( kf, DRUN_GROUP_NAME, "Name", NULL ) ) { - g_debug ( "[%s] [%s] Invalid desktop file: no 'Name' key present.", id, path ); - g_key_file_free ( kf ); - return; - } - - // Skip hidden entries. - if ( g_key_file_get_boolean ( kf, DRUN_GROUP_NAME, "Hidden", NULL ) ) { - g_debug ( "[%s] [%s] Adding desktop file to disabled list: 'Hidden' key is true", id, path ); - g_key_file_free ( kf ); - g_hash_table_add ( pd->disabled_entries, g_strdup ( id ) ); - return; - } - if ( pd->current_desktop_list ) { - gboolean show = TRUE; - // If the DE is set, check the keys. - if ( g_key_file_has_key ( kf, DRUN_GROUP_NAME, "OnlyShowIn", NULL ) ) { - gsize llength = 0; - show = FALSE; - gchar **list = g_key_file_get_string_list ( kf, DRUN_GROUP_NAME, "OnlyShowIn", &llength, NULL ); - if ( list ) { - for ( gsize lcd = 0; !show && pd->current_desktop_list[lcd]; lcd++ ) { - for ( gsize lle = 0; !show && lle < llength; lle++ ) { - show = ( g_strcmp0 ( pd->current_desktop_list[lcd], list[lle] ) == 0 ); - } - } - g_strfreev ( list ); - } - } - if ( show && g_key_file_has_key ( kf, DRUN_GROUP_NAME, "NotShowIn", NULL ) ) { - gsize llength = 0; - gchar **list = g_key_file_get_string_list ( kf, DRUN_GROUP_NAME, "NotShowIn", &llength, NULL ); - if ( list ) { - for ( gsize lcd = 0; show && pd->current_desktop_list[lcd]; lcd++ ) { - for ( gsize lle = 0; show && lle < llength; lle++ ) { - show = !( g_strcmp0 ( pd->current_desktop_list[lcd], list[lle] ) == 0 ); - } - } - g_strfreev ( list ); - } - } - - if ( !show ) { - g_debug ( "[%s] [%s] Adding desktop file to disabled list: 'OnlyShowIn'/'NotShowIn' keys don't match current desktop", id, path ); - g_key_file_free ( kf ); - g_hash_table_add ( pd->disabled_entries, g_strdup ( id ) ); - return; - } - } - // Skip entries that have NoDisplay set. - if ( g_key_file_get_boolean ( kf, DRUN_GROUP_NAME, "NoDisplay", NULL ) ) { - g_debug ( "[%s] [%s] Adding desktop file to disabled list: 'NoDisplay' key is true", id, path ); - g_key_file_free ( kf ); - g_hash_table_add ( pd->disabled_entries, g_strdup ( id ) ); - return; - } - - // We need Exec, don't support DBusActivatable - if ( desktop_entry_type == DRUN_DESKTOP_ENTRY_TYPE_APPLICATION - && !g_key_file_has_key ( kf, DRUN_GROUP_NAME, "Exec", NULL ) ) { - g_debug ( "[%s] [%s] Unsupported desktop file: no 'Exec' key present for type Application.", id, path ); - g_key_file_free ( kf ); - return; - } - if ( desktop_entry_type == DRUN_DESKTOP_ENTRY_TYPE_SERVICE - && !g_key_file_has_key ( kf, DRUN_GROUP_NAME, "Exec", NULL ) ) { - g_debug ( "[%s] [%s] Unsupported desktop file: no 'Exec' key present for type Service.", id, path ); - g_key_file_free ( kf ); - return; - } - if ( desktop_entry_type == DRUN_DESKTOP_ENTRY_TYPE_LINK - && !g_key_file_has_key ( kf, DRUN_GROUP_NAME, "URL", NULL ) ) { - g_debug ( "[%s] [%s] Unsupported desktop file: no 'URL' key present for type Link.", id, path ); - g_key_file_free ( kf ); - return; - } - - if ( g_key_file_has_key ( kf, DRUN_GROUP_NAME, "TryExec", NULL ) ) { - char *te = g_key_file_get_string ( kf, DRUN_GROUP_NAME, "TryExec", NULL ); - if ( !g_path_is_absolute ( te ) ) { - char *fp = g_find_program_in_path ( te ); - if ( fp == NULL ) { - g_free ( te ); - g_key_file_free ( kf ); - return; - } - g_free ( fp ); - } - else { - if ( g_file_test ( te, G_FILE_TEST_IS_EXECUTABLE ) == FALSE ) { - g_free ( te ); - g_key_file_free ( kf ); - return; - } - } - g_free ( te ); - } - - char **categories = NULL; - if ( pd->show_categories ) { - categories = g_key_file_get_locale_string_list ( kf, DRUN_GROUP_NAME, "Categories", NULL, NULL, NULL ); - if ( !rofi_strv_contains ( (const char * const *) categories, (const char * const *) pd->show_categories ) ) { - g_strfreev ( categories ); - g_key_file_free ( kf ); - return; - } - } - - size_t nl = ( ( pd->cmd_list_length ) + 1 ); - if ( nl >= pd->cmd_list_length_actual ) { - pd->cmd_list_length_actual += 256; - pd->entry_list = g_realloc ( pd->entry_list, pd->cmd_list_length_actual * sizeof ( *( pd->entry_list ) ) ); - } - // Make sure order is preserved, this will break when cmd_list_length is bigger then INT_MAX. - // This is not likely to happen. - if ( G_UNLIKELY ( pd->cmd_list_length > INT_MAX ) ) { - // Default to smallest value. - pd->entry_list[pd->cmd_list_length].sort_index = INT_MIN; - } - else { - pd->entry_list[pd->cmd_list_length].sort_index = -nl; - } - pd->entry_list[pd->cmd_list_length].icon_size = 0; - pd->entry_list[pd->cmd_list_length].icon_fetch_uid = 0; - pd->entry_list[pd->cmd_list_length].root = g_strdup ( root ); - pd->entry_list[pd->cmd_list_length].path = g_strdup ( path ); - pd->entry_list[pd->cmd_list_length].desktop_id = g_strdup ( id ); - pd->entry_list[pd->cmd_list_length].app_id = g_strndup ( basename, strlen ( basename ) - strlen ( ".desktop" ) ); - gchar *n = g_key_file_get_locale_string ( kf, DRUN_GROUP_NAME, "Name", NULL, NULL ); - - if ( action != DRUN_GROUP_NAME ) { - gchar *na = g_key_file_get_locale_string ( kf, action, "Name", NULL, NULL ); - gchar *l = g_strdup_printf ( "%s - %s", n, na ); - g_free ( n ); - n = l; - } - pd->entry_list[pd->cmd_list_length].name = n; - pd->entry_list[pd->cmd_list_length].action = DRUN_GROUP_NAME; - gchar *gn = g_key_file_get_locale_string ( kf, DRUN_GROUP_NAME, "GenericName", NULL, NULL ); - pd->entry_list[pd->cmd_list_length].generic_name = gn; - if ( matching_entry_fields[DRUN_MATCH_FIELD_KEYWORDS].enabled_match - || matching_entry_fields[DRUN_MATCH_FIELD_CATEGORIES].enabled_display) { - pd->entry_list[pd->cmd_list_length].keywords = g_key_file_get_locale_string_list ( kf, DRUN_GROUP_NAME, "Keywords", NULL, NULL, NULL ); - } - else { - pd->entry_list[pd->cmd_list_length].keywords = NULL; - } - - if ( matching_entry_fields[DRUN_MATCH_FIELD_CATEGORIES].enabled_match - || matching_entry_fields[DRUN_MATCH_FIELD_CATEGORIES].enabled_display ) { - if ( categories ) { - pd->entry_list[pd->cmd_list_length].categories = categories; - categories = NULL; - } - else { - pd->entry_list[pd->cmd_list_length].categories = g_key_file_get_locale_string_list ( kf, DRUN_GROUP_NAME, "Categories", NULL, NULL, NULL ); - } - } - else { - pd->entry_list[pd->cmd_list_length].categories = NULL; - } - g_strfreev ( categories ); - - pd->entry_list[pd->cmd_list_length].type = desktop_entry_type; - if ( desktop_entry_type == DRUN_DESKTOP_ENTRY_TYPE_APPLICATION || - desktop_entry_type == DRUN_DESKTOP_ENTRY_TYPE_SERVICE ) { - pd->entry_list[pd->cmd_list_length].exec = g_key_file_get_string ( kf, action, "Exec", NULL ); - } - else { - pd->entry_list[pd->cmd_list_length].exec = NULL; - } - - if ( matching_entry_fields[DRUN_MATCH_FIELD_COMMENT].enabled_match - || matching_entry_fields[DRUN_MATCH_FIELD_COMMENT].enabled_display ) { - pd->entry_list[pd->cmd_list_length].comment = g_key_file_get_locale_string ( kf, - DRUN_GROUP_NAME, "Comment", NULL, NULL ); - } - else { - pd->entry_list[pd->cmd_list_length].comment = NULL; - } - pd->entry_list[pd->cmd_list_length].icon_name = g_key_file_get_locale_string ( kf, DRUN_GROUP_NAME, "Icon", NULL, NULL ); - pd->entry_list[pd->cmd_list_length].icon = NULL; - - // Keep keyfile around. - pd->entry_list[pd->cmd_list_length].key_file = kf; - // We don't want to parse items with this id anymore. - g_hash_table_add ( pd->disabled_entries, g_strdup ( id ) ); - g_debug ( "[%s] Using file %s.", id, path ); - ( pd->cmd_list_length )++; - - if ( !parse_action ) { - gsize actions_length = 0; - char **actions = g_key_file_get_string_list ( kf, DRUN_GROUP_NAME, "Actions", &actions_length, NULL ); - for ( gsize iter = 0; iter < actions_length; iter++ ) { - char *new_action = g_strdup_printf ( "Desktop Action %s", actions[iter] ); - read_desktop_file ( pd, root, path, basename, new_action ); - g_free ( new_action ); - } - g_strfreev ( actions ); - } + // Check if item is on disabled list. + if (g_hash_table_contains(pd->disabled_entries, id) && !parse_action) { + g_debug("[%s] [%s] Skipping, was previously seen.", id, path); return; + } + GKeyFile *kf = g_key_file_new(); + GError *error = NULL; + gboolean res = g_key_file_load_from_file(kf, path, 0, &error); + // If error, skip to next entry + if (!res) { + g_debug("[%s] [%s] Failed to parse desktop file because: %s.", id, path, + error->message); + g_error_free(error); + g_key_file_free(kf); + return; + } + + if (g_key_file_has_group(kf, action) == FALSE) { + // No type? ignore. + g_debug("[%s] [%s] Invalid desktop file: No %s group", id, path, action); + g_key_file_free(kf); + return; + } + // Skip non Application entries. + gchar *key = g_key_file_get_string(kf, DRUN_GROUP_NAME, "Type", NULL); + if (key == NULL) { + // No type? ignore. + g_debug("[%s] [%s] Invalid desktop file: No type indicated", id, path); + g_key_file_free(kf); + return; + } + if (!g_strcmp0(key, "Application")) { + desktop_entry_type = DRUN_DESKTOP_ENTRY_TYPE_APPLICATION; + } else if (!g_strcmp0(key, "Link")) { + desktop_entry_type = DRUN_DESKTOP_ENTRY_TYPE_LINK; + } else if (!g_strcmp0(key, "Service")) { + desktop_entry_type = DRUN_DESKTOP_ENTRY_TYPE_SERVICE; + g_debug("Service file detected."); + } else { + g_debug( + "[%s] [%s] Skipping desktop file: Not of type Application or Link (%s)", + id, path, key); + g_free(key); + g_key_file_free(kf); + return; + } + g_free(key); + + // Name key is required. + if (!g_key_file_has_key(kf, DRUN_GROUP_NAME, "Name", NULL)) { + g_debug("[%s] [%s] Invalid desktop file: no 'Name' key present.", id, path); + g_key_file_free(kf); + return; + } + + // Skip hidden entries. + if (g_key_file_get_boolean(kf, DRUN_GROUP_NAME, "Hidden", NULL)) { + g_debug( + "[%s] [%s] Adding desktop file to disabled list: 'Hidden' key is true", + id, path); + g_key_file_free(kf); + g_hash_table_add(pd->disabled_entries, g_strdup(id)); + return; + } + if (pd->current_desktop_list) { + gboolean show = TRUE; + // If the DE is set, check the keys. + if (g_key_file_has_key(kf, DRUN_GROUP_NAME, "OnlyShowIn", NULL)) { + gsize llength = 0; + show = FALSE; + gchar **list = g_key_file_get_string_list(kf, DRUN_GROUP_NAME, + "OnlyShowIn", &llength, NULL); + if (list) { + for (gsize lcd = 0; !show && pd->current_desktop_list[lcd]; lcd++) { + for (gsize lle = 0; !show && lle < llength; lle++) { + show = (g_strcmp0(pd->current_desktop_list[lcd], list[lle]) == 0); + } + } + g_strfreev(list); + } + } + if (show && g_key_file_has_key(kf, DRUN_GROUP_NAME, "NotShowIn", NULL)) { + gsize llength = 0; + gchar **list = g_key_file_get_string_list(kf, DRUN_GROUP_NAME, + "NotShowIn", &llength, NULL); + if (list) { + for (gsize lcd = 0; show && pd->current_desktop_list[lcd]; lcd++) { + for (gsize lle = 0; show && lle < llength; lle++) { + show = !(g_strcmp0(pd->current_desktop_list[lcd], list[lle]) == 0); + } + } + g_strfreev(list); + } + } + + if (!show) { + g_debug("[%s] [%s] Adding desktop file to disabled list: " + "'OnlyShowIn'/'NotShowIn' keys don't match current desktop", + id, path); + g_key_file_free(kf); + g_hash_table_add(pd->disabled_entries, g_strdup(id)); + return; + } + } + // Skip entries that have NoDisplay set. + if (g_key_file_get_boolean(kf, DRUN_GROUP_NAME, "NoDisplay", NULL)) { + g_debug("[%s] [%s] Adding desktop file to disabled list: 'NoDisplay' key " + "is true", + id, path); + g_key_file_free(kf); + g_hash_table_add(pd->disabled_entries, g_strdup(id)); + return; + } + + // We need Exec, don't support DBusActivatable + if (desktop_entry_type == DRUN_DESKTOP_ENTRY_TYPE_APPLICATION && + !g_key_file_has_key(kf, DRUN_GROUP_NAME, "Exec", NULL)) { + g_debug("[%s] [%s] Unsupported desktop file: no 'Exec' key present for " + "type Application.", + id, path); + g_key_file_free(kf); + return; + } + if (desktop_entry_type == DRUN_DESKTOP_ENTRY_TYPE_SERVICE && + !g_key_file_has_key(kf, DRUN_GROUP_NAME, "Exec", NULL)) { + g_debug("[%s] [%s] Unsupported desktop file: no 'Exec' key present for " + "type Service.", + id, path); + g_key_file_free(kf); + return; + } + if (desktop_entry_type == DRUN_DESKTOP_ENTRY_TYPE_LINK && + !g_key_file_has_key(kf, DRUN_GROUP_NAME, "URL", NULL)) { + g_debug("[%s] [%s] Unsupported desktop file: no 'URL' key present for type " + "Link.", + id, path); + g_key_file_free(kf); + return; + } + + if (g_key_file_has_key(kf, DRUN_GROUP_NAME, "TryExec", NULL)) { + char *te = g_key_file_get_string(kf, DRUN_GROUP_NAME, "TryExec", NULL); + if (!g_path_is_absolute(te)) { + char *fp = g_find_program_in_path(te); + if (fp == NULL) { + g_free(te); + g_key_file_free(kf); + return; + } + g_free(fp); + } else { + if (g_file_test(te, G_FILE_TEST_IS_EXECUTABLE) == FALSE) { + g_free(te); + g_key_file_free(kf); + return; + } + } + g_free(te); + } + + char **categories = NULL; + if (pd->show_categories) { + categories = g_key_file_get_locale_string_list( + kf, DRUN_GROUP_NAME, "Categories", NULL, NULL, NULL); + if (!rofi_strv_contains((const char *const *)categories, + (const char *const *)pd->show_categories)) { + g_strfreev(categories); + g_key_file_free(kf); + return; + } + } + + size_t nl = ((pd->cmd_list_length) + 1); + if (nl >= pd->cmd_list_length_actual) { + pd->cmd_list_length_actual += 256; + pd->entry_list = g_realloc(pd->entry_list, pd->cmd_list_length_actual * + sizeof(*(pd->entry_list))); + } + // Make sure order is preserved, this will break when cmd_list_length is + // bigger then INT_MAX. This is not likely to happen. + if (G_UNLIKELY(pd->cmd_list_length > INT_MAX)) { + // Default to smallest value. + pd->entry_list[pd->cmd_list_length].sort_index = INT_MIN; + } else { + pd->entry_list[pd->cmd_list_length].sort_index = -nl; + } + pd->entry_list[pd->cmd_list_length].icon_size = 0; + pd->entry_list[pd->cmd_list_length].icon_fetch_uid = 0; + pd->entry_list[pd->cmd_list_length].root = g_strdup(root); + pd->entry_list[pd->cmd_list_length].path = g_strdup(path); + pd->entry_list[pd->cmd_list_length].desktop_id = g_strdup(id); + pd->entry_list[pd->cmd_list_length].app_id = + g_strndup(basename, strlen(basename) - strlen(".desktop")); + gchar *n = + g_key_file_get_locale_string(kf, DRUN_GROUP_NAME, "Name", NULL, NULL); + + if (action != DRUN_GROUP_NAME) { + gchar *na = g_key_file_get_locale_string(kf, action, "Name", NULL, NULL); + gchar *l = g_strdup_printf("%s - %s", n, na); + g_free(n); + n = l; + } + pd->entry_list[pd->cmd_list_length].name = n; + pd->entry_list[pd->cmd_list_length].action = DRUN_GROUP_NAME; + gchar *gn = g_key_file_get_locale_string(kf, DRUN_GROUP_NAME, "GenericName", + NULL, NULL); + pd->entry_list[pd->cmd_list_length].generic_name = gn; + if (matching_entry_fields[DRUN_MATCH_FIELD_KEYWORDS].enabled_match || + matching_entry_fields[DRUN_MATCH_FIELD_CATEGORIES].enabled_display) { + pd->entry_list[pd->cmd_list_length].keywords = + g_key_file_get_locale_string_list(kf, DRUN_GROUP_NAME, "Keywords", NULL, + NULL, NULL); + } else { + pd->entry_list[pd->cmd_list_length].keywords = NULL; + } + + if (matching_entry_fields[DRUN_MATCH_FIELD_CATEGORIES].enabled_match || + matching_entry_fields[DRUN_MATCH_FIELD_CATEGORIES].enabled_display) { + if (categories) { + pd->entry_list[pd->cmd_list_length].categories = categories; + categories = NULL; + } else { + pd->entry_list[pd->cmd_list_length].categories = + g_key_file_get_locale_string_list(kf, DRUN_GROUP_NAME, "Categories", + NULL, NULL, NULL); + } + } else { + pd->entry_list[pd->cmd_list_length].categories = NULL; + } + g_strfreev(categories); + + pd->entry_list[pd->cmd_list_length].type = desktop_entry_type; + if (desktop_entry_type == DRUN_DESKTOP_ENTRY_TYPE_APPLICATION || + desktop_entry_type == DRUN_DESKTOP_ENTRY_TYPE_SERVICE) { + pd->entry_list[pd->cmd_list_length].exec = + g_key_file_get_string(kf, action, "Exec", NULL); + } else { + pd->entry_list[pd->cmd_list_length].exec = NULL; + } + + if (matching_entry_fields[DRUN_MATCH_FIELD_COMMENT].enabled_match || + matching_entry_fields[DRUN_MATCH_FIELD_COMMENT].enabled_display) { + pd->entry_list[pd->cmd_list_length].comment = g_key_file_get_locale_string( + kf, DRUN_GROUP_NAME, "Comment", NULL, NULL); + } else { + pd->entry_list[pd->cmd_list_length].comment = NULL; + } + pd->entry_list[pd->cmd_list_length].icon_name = + g_key_file_get_locale_string(kf, DRUN_GROUP_NAME, "Icon", NULL, NULL); + pd->entry_list[pd->cmd_list_length].icon = NULL; + + // Keep keyfile around. + pd->entry_list[pd->cmd_list_length].key_file = kf; + // We don't want to parse items with this id anymore. + g_hash_table_add(pd->disabled_entries, g_strdup(id)); + g_debug("[%s] Using file %s.", id, path); + (pd->cmd_list_length)++; + + if (!parse_action) { + gsize actions_length = 0; + char **actions = g_key_file_get_string_list(kf, DRUN_GROUP_NAME, "Actions", + &actions_length, NULL); + for (gsize iter = 0; iter < actions_length; iter++) { + char *new_action = g_strdup_printf("Desktop Action %s", actions[iter]); + read_desktop_file(pd, root, path, basename, new_action); + g_free(new_action); + } + g_strfreev(actions); + } + return; } /** * Internal spider used to get list of executables. */ -static void walk_dir ( DRunModePrivateData *pd, const char *root, const char *dirname ) -{ - DIR *dir; +static void walk_dir(DRunModePrivateData *pd, const char *root, + const char *dirname) { + DIR *dir; - g_debug ( "Checking directory %s for desktop files.", dirname ); - dir = opendir ( dirname ); - if ( dir == NULL ) { - return; + g_debug("Checking directory %s for desktop files.", dirname); + dir = opendir(dirname); + if (dir == NULL) { + return; + } + + struct dirent *file; + gchar *filename = NULL; + struct stat st; + while ((file = readdir(dir)) != NULL) { + if (file->d_name[0] == '.') { + continue; + } + switch (file->d_type) { + case DT_LNK: + case DT_REG: + case DT_DIR: + case DT_UNKNOWN: + filename = g_build_filename(dirname, file->d_name, NULL); + break; + default: + continue; } - struct dirent *file; - gchar *filename = NULL; - struct stat st; - while ( ( file = readdir ( dir ) ) != NULL ) { - if ( file->d_name[0] == '.' ) { - continue; + // On a link, or if FS does not support providing this information + // Fallback to stat method. + if (file->d_type == DT_LNK || file->d_type == DT_UNKNOWN) { + file->d_type = DT_UNKNOWN; + if (stat(filename, &st) == 0) { + if (S_ISDIR(st.st_mode)) { + file->d_type = DT_DIR; + } else if (S_ISREG(st.st_mode)) { + file->d_type = DT_REG; } - switch ( file->d_type ) - { - case DT_LNK: - case DT_REG: - case DT_DIR: - case DT_UNKNOWN: - filename = g_build_filename ( dirname, file->d_name, NULL ); - break; - default: - continue; - } - - // On a link, or if FS does not support providing this information - // Fallback to stat method. - if ( file->d_type == DT_LNK || file->d_type == DT_UNKNOWN ) { - file->d_type = DT_UNKNOWN; - if ( stat ( filename, &st ) == 0 ) { - if ( S_ISDIR ( st.st_mode ) ) { - file->d_type = DT_DIR; - } - else if ( S_ISREG ( st.st_mode ) ) { - file->d_type = DT_REG; - } - } - } - - switch ( file->d_type ) - { - case DT_REG: - // Skip files not ending on .desktop. - if ( g_str_has_suffix ( file->d_name, ".desktop" ) ) { - read_desktop_file ( pd, root, filename, file->d_name, DRUN_GROUP_NAME ); - } - break; - case DT_DIR: - walk_dir ( pd, root, filename ); - break; - default: - break; - } - g_free ( filename ); + } } - closedir ( dir ); + + switch (file->d_type) { + case DT_REG: + // Skip files not ending on .desktop. + if (g_str_has_suffix(file->d_name, ".desktop")) { + read_desktop_file(pd, root, filename, file->d_name, DRUN_GROUP_NAME); + } + break; + case DT_DIR: + walk_dir(pd, root, filename); + break; + default: + break; + } + g_free(filename); + } + closedir(dir); } /** * @param entry The command entry to remove from history * * Remove command from history. */ -static void delete_entry_history ( const DRunModeEntry *entry ) -{ - char *path = g_build_filename ( cache_dir, DRUN_CACHE_FILE, NULL ); - history_remove ( path, entry->desktop_id ); - g_free ( path ); +static void delete_entry_history(const DRunModeEntry *entry) { + char *path = g_build_filename(cache_dir, DRUN_CACHE_FILE, NULL); + history_remove(path, entry->desktop_id); + g_free(path); } -static void get_apps_history ( DRunModePrivateData *pd ) -{ - TICK_N ( "Start drun history" ); - unsigned int length = 0; - gchar *path = g_build_filename ( cache_dir, DRUN_CACHE_FILE, NULL ); - gchar **retv = history_get_list ( path, &length ); - for ( unsigned int index = 0; index < length; index++ ) { - for ( size_t i = 0; i < pd->cmd_list_length; i++ ) { - if ( g_strcmp0 ( pd->entry_list[i].desktop_id, retv[index] ) == 0 ) { - unsigned int sort_index = length - index; - if ( G_LIKELY ( sort_index < INT_MAX ) ) { - pd->entry_list[i].sort_index = sort_index; - } - else { - // This won't sort right anymore, but never gonna hit it anyway. - pd->entry_list[i].sort_index = INT_MAX; - } - } +static void get_apps_history(DRunModePrivateData *pd) { + TICK_N("Start drun history"); + unsigned int length = 0; + gchar *path = g_build_filename(cache_dir, DRUN_CACHE_FILE, NULL); + gchar **retv = history_get_list(path, &length); + for (unsigned int index = 0; index < length; index++) { + for (size_t i = 0; i < pd->cmd_list_length; i++) { + if (g_strcmp0(pd->entry_list[i].desktop_id, retv[index]) == 0) { + unsigned int sort_index = length - index; + if (G_LIKELY(sort_index < INT_MAX)) { + pd->entry_list[i].sort_index = sort_index; + } else { + // This won't sort right anymore, but never gonna hit it anyway. + pd->entry_list[i].sort_index = INT_MAX; } + } } - g_strfreev ( retv ); - g_free ( path ); - TICK_N ( "Stop drun history" ); + } + g_strfreev(retv); + g_free(path); + TICK_N("Stop drun history"); } -static gint drun_int_sort_list ( gconstpointer a, gconstpointer b, G_GNUC_UNUSED gpointer user_data ) -{ - DRunModeEntry *da = (DRunModeEntry *) a; - DRunModeEntry *db = (DRunModeEntry *) b; +static gint drun_int_sort_list(gconstpointer a, gconstpointer b, + G_GNUC_UNUSED gpointer user_data) { + DRunModeEntry *da = (DRunModeEntry *)a; + DRunModeEntry *db = (DRunModeEntry *)b; - if ( da->sort_index < 0 && db->sort_index < 0 ) { - if ( da->name == NULL && db->name == NULL ) { - return 0; - } - else if ( da->name == NULL ) { - return -1; - } - else if ( db->name == NULL ) { - return 1; - } - return g_utf8_collate ( da->name, db->name ); + if (da->sort_index < 0 && db->sort_index < 0) { + if (da->name == NULL && db->name == NULL) { + return 0; } - else { - return db->sort_index - da->sort_index; + if (da->name == NULL) { + return -1; } + if (db->name == NULL) { + return 1; + } + return g_utf8_collate(da->name, db->name); + } + return db->sort_index - da->sort_index; } /******************************************* -* Cache voodoo * -*******************************************/ + * Cache voodoo * + *******************************************/ -#define CACHE_VERSION 2 -static void drun_write_str ( FILE *fd, const char *str ) -{ - size_t l = ( str == NULL ? 0 : strlen ( str ) ); - fwrite ( &l, sizeof ( l ), 1, fd ); - // Only write string if it is not NULL or empty. - if ( l > 0 ) { - // Also writeout terminating '\0' - fwrite ( str, 1, l + 1, fd ); - } +#define CACHE_VERSION 2 +static void drun_write_str(FILE *fd, const char *str) { + size_t l = (str == NULL ? 0 : strlen(str)); + fwrite(&l, sizeof(l), 1, fd); + // Only write string if it is not NULL or empty. + if (l > 0) { + // Also writeout terminating '\0' + fwrite(str, 1, l + 1, fd); + } } -static void drun_write_integer ( FILE *fd, int32_t val ) -{ - fwrite ( &val, sizeof ( val ), 1, fd ); +static void drun_write_integer(FILE *fd, int32_t val) { + fwrite(&val, sizeof(val), 1, fd); } -static void drun_read_integer ( FILE *fd, int32_t *type ) -{ - if ( fread ( type, sizeof ( int32_t ), 1, fd ) != 1 ) { - g_warning ( "Failed to read entry, cache corrupt?" ); - return; - } +static void drun_read_integer(FILE *fd, int32_t *type) { + if (fread(type, sizeof(int32_t), 1, fd) != 1) { + g_warning("Failed to read entry, cache corrupt?"); + return; + } } -static void drun_read_string ( FILE *fd, char **str ) -{ - size_t l = 0; +static void drun_read_string(FILE *fd, char **str) { + size_t l = 0; - if ( fread ( &l, sizeof ( l ), 1, fd ) != 1 ) { - g_warning ( "Failed to read entry, cache corrupt?" ); - return; - } - ( *str ) = NULL; - if ( l > 0 ) { - // Include \0 - l++; - ( *str ) = g_malloc ( l ); - if ( fread ( ( *str ), 1, l, fd ) != l ) { - g_warning ( "Failed to read entry, cache corrupt?" ); - } + if (fread(&l, sizeof(l), 1, fd) != 1) { + g_warning("Failed to read entry, cache corrupt?"); + return; + } + (*str) = NULL; + if (l > 0) { + // Include \0 + l++; + (*str) = g_malloc(l); + if (fread((*str), 1, l, fd) != l) { + g_warning("Failed to read entry, cache corrupt?"); } + } } -static void drun_write_strv ( FILE *fd, char **str ) -{ - guint vl = ( str == NULL ? 0 : g_strv_length ( str ) ); - fwrite ( &vl, sizeof ( vl ), 1, fd ); - for ( guint index = 0; index < vl; index++ ) { - drun_write_str ( fd, str[index] ); - } +static void drun_write_strv(FILE *fd, char **str) { + guint vl = (str == NULL ? 0 : g_strv_length(str)); + fwrite(&vl, sizeof(vl), 1, fd); + for (guint index = 0; index < vl; index++) { + drun_write_str(fd, str[index]); + } } -static void drun_read_stringv ( FILE *fd, char ***str ) -{ - guint vl = 0; - ( *str ) = NULL; - if ( fread ( &vl, sizeof ( vl ), 1, fd ) != 1 ) { - g_warning ( "Failed to read entry, cache corrupt?" ); - return; - } - if ( vl > 0 ) { - // Include terminating NULL entry. - ( *str ) = g_malloc0 ( ( vl + 1 ) * sizeof ( **str ) ); - for ( guint index = 0; index < vl; index++ ) { - drun_read_string ( fd, &( ( *str )[index] ) ); - } +static void drun_read_stringv(FILE *fd, char ***str) { + guint vl = 0; + (*str) = NULL; + if (fread(&vl, sizeof(vl), 1, fd) != 1) { + g_warning("Failed to read entry, cache corrupt?"); + return; + } + if (vl > 0) { + // Include terminating NULL entry. + (*str) = g_malloc0((vl + 1) * sizeof(**str)); + for (guint index = 0; index < vl; index++) { + drun_read_string(fd, &((*str)[index])); } + } } -static void write_cache ( DRunModePrivateData *pd, const char *cache_file ) -{ - if ( cache_file == NULL || config.drun_use_desktop_cache == FALSE ) { - return; - } - TICK_N ( "DRUN Write CACHE: start" ); +static void write_cache(DRunModePrivateData *pd, const char *cache_file) { + if (cache_file == NULL || config.drun_use_desktop_cache == FALSE) { + return; + } + TICK_N("DRUN Write CACHE: start"); - FILE *fd = fopen ( cache_file, "w" ); - if ( fd == NULL ) { - g_warning ( "Failed to write to cache file" ); - return; - } - uint8_t version = CACHE_VERSION; - fwrite ( &version, sizeof ( version ), 1, fd ); + FILE *fd = fopen(cache_file, "w"); + if (fd == NULL) { + g_warning("Failed to write to cache file"); + return; + } + uint8_t version = CACHE_VERSION; + fwrite(&version, sizeof(version), 1, fd); - fwrite ( &( pd->cmd_list_length ), sizeof ( pd->cmd_list_length ), 1, fd ); - for ( unsigned int index = 0; index < pd->cmd_list_length; index++ ) { - DRunModeEntry *entry = &( pd->entry_list[index] ); + fwrite(&(pd->cmd_list_length), sizeof(pd->cmd_list_length), 1, fd); + for (unsigned int index = 0; index < pd->cmd_list_length; index++) { + DRunModeEntry *entry = &(pd->entry_list[index]); - drun_write_str ( fd, entry->action ); - drun_write_str ( fd, entry->root ); - drun_write_str ( fd, entry->path ); - drun_write_str ( fd, entry->app_id ); - drun_write_str ( fd, entry->desktop_id ); - drun_write_str ( fd, entry->icon_name ); - drun_write_str ( fd, entry->exec ); - drun_write_str ( fd, entry->name ); - drun_write_str ( fd, entry->generic_name ); + drun_write_str(fd, entry->action); + drun_write_str(fd, entry->root); + drun_write_str(fd, entry->path); + drun_write_str(fd, entry->app_id); + drun_write_str(fd, entry->desktop_id); + drun_write_str(fd, entry->icon_name); + drun_write_str(fd, entry->exec); + drun_write_str(fd, entry->name); + drun_write_str(fd, entry->generic_name); - drun_write_strv ( fd, entry->categories ); - drun_write_strv ( fd, entry->keywords ); + drun_write_strv(fd, entry->categories); + drun_write_strv(fd, entry->keywords); - drun_write_str ( fd, entry->comment ); - drun_write_integer ( fd, (int32_t) entry->type ); - } + drun_write_str(fd, entry->comment); + drun_write_integer(fd, (int32_t)entry->type); + } - fclose ( fd ); - TICK_N ( "DRUN Write CACHE: end" ); + fclose(fd); + TICK_N("DRUN Write CACHE: end"); } /** * Read cache file. returns FALSE when success. */ -static gboolean drun_read_cache ( DRunModePrivateData *pd, const char *cache_file ) -{ - if ( cache_file == NULL || config.drun_use_desktop_cache == FALSE ) { - return TRUE; - } +static gboolean drun_read_cache(DRunModePrivateData *pd, + const char *cache_file) { + if (cache_file == NULL || config.drun_use_desktop_cache == FALSE) { + return TRUE; + } - if ( config.drun_reload_desktop_cache ) { - return TRUE; - } - TICK_N ( "DRUN Read CACHE: start" ); - FILE *fd = fopen ( cache_file, "r" ); - if ( fd == NULL ) { - TICK_N ( "DRUN Read CACHE: stop" ); - return TRUE; - } + if (config.drun_reload_desktop_cache) { + return TRUE; + } + TICK_N("DRUN Read CACHE: start"); + FILE *fd = fopen(cache_file, "r"); + if (fd == NULL) { + TICK_N("DRUN Read CACHE: stop"); + return TRUE; + } - // Read version. - uint8_t version = 0; + // Read version. + uint8_t version = 0; - if ( fread ( &version, sizeof ( version ), 1, fd ) != 1 ) { - fclose ( fd ); - g_warning ( "Cache corrupt, ignoring." ); - TICK_N ( "DRUN Read CACHE: stop" ); - return TRUE; - } + if (fread(&version, sizeof(version), 1, fd) != 1) { + fclose(fd); + g_warning("Cache corrupt, ignoring."); + TICK_N("DRUN Read CACHE: stop"); + return TRUE; + } - if ( version != CACHE_VERSION ) { - fclose ( fd ); - g_warning ( "Cache file wrong version, ignoring." ); - TICK_N ( "DRUN Read CACHE: stop" ); - return TRUE; - } + if (version != CACHE_VERSION) { + fclose(fd); + g_warning("Cache file wrong version, ignoring."); + TICK_N("DRUN Read CACHE: stop"); + return TRUE; + } - if ( fread ( &( pd->cmd_list_length ), sizeof ( pd->cmd_list_length ), 1, fd ) != 1 ) { - fclose ( fd ); - g_warning ( "Cache corrupt, ignoring." ); - TICK_N ( "DRUN Read CACHE: stop" ); - return TRUE; - } - // set actual length to length; - pd->cmd_list_length_actual = pd->cmd_list_length; + if (fread(&(pd->cmd_list_length), sizeof(pd->cmd_list_length), 1, fd) != 1) { + fclose(fd); + g_warning("Cache corrupt, ignoring."); + TICK_N("DRUN Read CACHE: stop"); + return TRUE; + } + // set actual length to length; + pd->cmd_list_length_actual = pd->cmd_list_length; - pd->entry_list = g_malloc0 ( pd->cmd_list_length_actual * sizeof ( *( pd->entry_list ) ) ); + pd->entry_list = + g_malloc0(pd->cmd_list_length_actual * sizeof(*(pd->entry_list))); - for ( unsigned int index = 0; index < pd->cmd_list_length; index++ ) { - DRunModeEntry *entry = &( pd->entry_list[index] ); + for (unsigned int index = 0; index < pd->cmd_list_length; index++) { + DRunModeEntry *entry = &(pd->entry_list[index]); - drun_read_string ( fd, &( entry->action ) ); - drun_read_string ( fd, &( entry->root ) ); - drun_read_string ( fd, &( entry->path ) ); - drun_read_string ( fd, &( entry->app_id ) ); - drun_read_string ( fd, &( entry->desktop_id ) ); - drun_read_string ( fd, &( entry->icon_name ) ); - drun_read_string ( fd, &( entry->exec ) ); - drun_read_string ( fd, &( entry->name ) ); - drun_read_string ( fd, &( entry->generic_name ) ); + drun_read_string(fd, &(entry->action)); + drun_read_string(fd, &(entry->root)); + drun_read_string(fd, &(entry->path)); + drun_read_string(fd, &(entry->app_id)); + drun_read_string(fd, &(entry->desktop_id)); + drun_read_string(fd, &(entry->icon_name)); + drun_read_string(fd, &(entry->exec)); + drun_read_string(fd, &(entry->name)); + drun_read_string(fd, &(entry->generic_name)); - drun_read_stringv ( fd, &( entry->categories ) ); - drun_read_stringv ( fd, &( entry->keywords ) ); + drun_read_stringv(fd, &(entry->categories)); + drun_read_stringv(fd, &(entry->keywords)); - drun_read_string ( fd, &( entry->comment ) ); - int32_t type = 0; - drun_read_integer ( fd, &( type ) ); - entry->type = type; - } + drun_read_string(fd, &(entry->comment)); + int32_t type = 0; + drun_read_integer(fd, &(type)); + entry->type = type; + } - fclose ( fd ); - TICK_N ( "DRUN Read CACHE: stop" ); - return FALSE; + fclose(fd); + TICK_N("DRUN Read CACHE: stop"); + return FALSE; } -static void get_apps ( DRunModePrivateData *pd ) -{ - char *cache_file = g_build_filename ( cache_dir, DRUN_DESKTOP_CACHE_FILE, NULL ); - TICK_N ( "Get Desktop apps (start)" ); - if ( drun_read_cache ( pd, cache_file ) ) { - ThemeWidget *wid = rofi_config_find_widget ( drun_mode.name, NULL, TRUE ); +static void get_apps(DRunModePrivateData *pd) { + char *cache_file = g_build_filename(cache_dir, DRUN_DESKTOP_CACHE_FILE, NULL); + TICK_N("Get Desktop apps (start)"); + if (drun_read_cache(pd, cache_file)) { + ThemeWidget *wid = rofi_config_find_widget(drun_mode.name, NULL, TRUE); - /** Load user entires */ - Property *p = rofi_theme_find_property ( wid, P_BOOLEAN, "parse-user", TRUE ); - if ( p == NULL || ( p->type == P_BOOLEAN && p->value.b )) { - gchar *dir; - // First read the user directory. - dir = g_build_filename ( g_get_user_data_dir (), "applications", NULL ); - walk_dir ( pd, dir, dir ); - g_free ( dir ); - TICK_N ( "Get Desktop apps (user dir)" ); - } + /** Load user entires */ + Property *p = rofi_theme_find_property(wid, P_BOOLEAN, "parse-user", TRUE); + if (p == NULL || (p->type == P_BOOLEAN && p->value.b)) { + gchar *dir; + // First read the user directory. + dir = g_build_filename(g_get_user_data_dir(), "applications", NULL); + walk_dir(pd, dir, dir); + g_free(dir); + TICK_N("Get Desktop apps (user dir)"); + } - /** Load application entires */ - p = rofi_theme_find_property ( wid, P_BOOLEAN, "parse-system", TRUE ); - if ( p == NULL || ( p->type == P_BOOLEAN && p->value.b )) { - // Then read thee system data dirs. - const gchar * const * sys = g_get_system_data_dirs (); - for ( const gchar * const *iter = sys; *iter != NULL; ++iter ) { - gboolean unique = TRUE; - // Stupid duplicate detection, better then walking dir. - for ( const gchar *const *iterd = sys; iterd != iter; ++iterd ) { - if ( g_strcmp0 ( *iter, *iterd ) == 0 ) { - unique = FALSE; - } - } - // Check, we seem to be getting empty string... - if ( unique && ( **iter ) != '\0' ) { - char *dir = g_build_filename ( *iter, "applications", NULL ); - walk_dir ( pd, dir, dir ); - g_free ( dir ); - } + /** Load application entires */ + p = rofi_theme_find_property(wid, P_BOOLEAN, "parse-system", TRUE); + if (p == NULL || (p->type == P_BOOLEAN && p->value.b)) { + // Then read thee system data dirs. + const gchar *const *sys = g_get_system_data_dirs(); + for (const gchar *const *iter = sys; *iter != NULL; ++iter) { + gboolean unique = TRUE; + // Stupid duplicate detection, better then walking dir. + for (const gchar *const *iterd = sys; iterd != iter; ++iterd) { + if (g_strcmp0(*iter, *iterd) == 0) { + unique = FALSE; } - TICK_N ( "Get Desktop apps (system dirs)" ); } - get_apps_history ( pd ); - - g_qsort_with_data ( pd->entry_list, pd->cmd_list_length, sizeof ( DRunModeEntry ), drun_int_sort_list, NULL ); - - TICK_N ( "Sorting done." ); - - write_cache ( pd, cache_file ); + // Check, we seem to be getting empty string... + if (unique && (**iter) != '\0') { + char *dir = g_build_filename(*iter, "applications", NULL); + walk_dir(pd, dir, dir); + g_free(dir); + } + } + TICK_N("Get Desktop apps (system dirs)"); } - g_free ( cache_file ); + get_apps_history(pd); + + g_qsort_with_data(pd->entry_list, pd->cmd_list_length, + sizeof(DRunModeEntry), drun_int_sort_list, NULL); + + TICK_N("Sorting done."); + + write_cache(pd, cache_file); + } + g_free(cache_file); } -static void drun_mode_parse_entry_fields () -{ - char *savept = NULL; - // Make a copy, as strtok will modify it. - char *switcher_str = g_strdup ( config.drun_match_fields ); - const char * const sep = ",#"; - // Split token on ','. This modifies switcher_str. - for ( unsigned int i = 0; i < DRUN_MATCH_NUM_FIELDS; i++ ) { - matching_entry_fields[i].enabled_match = FALSE; - matching_entry_fields[i].enabled_display = FALSE; +static void drun_mode_parse_entry_fields() { + char *savept = NULL; + // Make a copy, as strtok will modify it. + char *switcher_str = g_strdup(config.drun_match_fields); + const char *const sep = ",#"; + // Split token on ','. This modifies switcher_str. + for (unsigned int i = 0; i < DRUN_MATCH_NUM_FIELDS; i++) { + matching_entry_fields[i].enabled_match = FALSE; + matching_entry_fields[i].enabled_display = FALSE; + } + for (char *token = strtok_r(switcher_str, sep, &savept); token != NULL; + token = strtok_r(NULL, sep, &savept)) { + if (strcmp(token, "all") == 0) { + for (unsigned int i = 0; i < DRUN_MATCH_NUM_FIELDS; i++) { + matching_entry_fields[i].enabled_match = TRUE; + matching_entry_fields[i].enabled_display = TRUE; + } + break; } - for ( char *token = strtok_r ( switcher_str, sep, &savept ); token != NULL; - token = strtok_r ( NULL, sep, &savept ) ) { - if ( strcmp ( token, "all" ) == 0 ) { - for ( unsigned int i = 0; i < DRUN_MATCH_NUM_FIELDS; i++ ) { - matching_entry_fields[i].enabled_match = TRUE; - matching_entry_fields[i].enabled_display = TRUE; - } - break; - } - else { - gboolean matched = FALSE; - for ( unsigned int i = 0; i < DRUN_MATCH_NUM_FIELDS; i++ ) { - const char * entry_name = matching_entry_fields[i].entry_field_name; - if ( g_ascii_strcasecmp ( token, entry_name ) == 0 ) { - matching_entry_fields[i].enabled_match = TRUE; - matching_entry_fields[i].enabled_display = TRUE; - matched = TRUE; - } - } - if ( !matched ) { - g_warning ( "Invalid entry name :%s", token ); - } - } + gboolean matched = FALSE; + for (unsigned int i = 0; i < DRUN_MATCH_NUM_FIELDS; i++) { + const char *entry_name = matching_entry_fields[i].entry_field_name; + if (g_ascii_strcasecmp(token, entry_name) == 0) { + matching_entry_fields[i].enabled_match = TRUE; + matching_entry_fields[i].enabled_display = TRUE; + matched = TRUE; + } } - // Free string that was modified by strtok_r - g_free ( switcher_str ); + if (!matched) { + g_warning("Invalid entry name :%s", token); + } + } + // Free string that was modified by strtok_r + g_free(switcher_str); } static void drun_mode_parse_display_format() { - for ( int i = 0; i < DRUN_MATCH_NUM_FIELDS; i++ ) { - if ( matching_entry_fields[i].enabled_display ) continue; + for (int i = 0; i < DRUN_MATCH_NUM_FIELDS; i++) { + if (matching_entry_fields[i].enabled_display) + continue; - gchar* search_term = g_strdup_printf("{%s}",matching_entry_fields[i].entry_field_name); - if ( strstr( config.drun_display_format, search_term) ) { - matching_entry_fields[i].enabled_match = TRUE; - } - g_free( search_term ); + gchar *search_term = + g_strdup_printf("{%s}", matching_entry_fields[i].entry_field_name); + if (strstr(config.drun_display_format, search_term)) { + matching_entry_fields[i].enabled_match = TRUE; } + g_free(search_term); + } } -static int drun_mode_init ( Mode *sw ) -{ - if ( mode_get_private_data ( sw ) != NULL ) { - return TRUE; - } - DRunModePrivateData *pd = g_malloc0 ( sizeof ( *pd ) ); - pd->disabled_entries = g_hash_table_new_full ( g_str_hash, g_str_equal, g_free, NULL ); - mode_set_private_data ( sw, (void *) pd ); - // current desktop - const char *current_desktop = g_getenv ( "XDG_CURRENT_DESKTOP" ); - pd->current_desktop_list = current_desktop ? g_strsplit ( current_desktop, ":", 0 ) : NULL; - - if ( config.drun_categories && *( config.drun_categories ) ) { - pd->show_categories = g_strsplit ( config.drun_categories, ",", 0 ); - } - - drun_mode_parse_entry_fields (); - drun_mode_parse_display_format(); - get_apps ( pd ); - - pd->completer = create_new_file_browser (); - mode_init ( pd->completer ); +static int drun_mode_init(Mode *sw) { + if (mode_get_private_data(sw) != NULL) { return TRUE; + } + DRunModePrivateData *pd = g_malloc0(sizeof(*pd)); + pd->disabled_entries = + g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); + mode_set_private_data(sw, (void *)pd); + // current desktop + const char *current_desktop = g_getenv("XDG_CURRENT_DESKTOP"); + pd->current_desktop_list = + current_desktop ? g_strsplit(current_desktop, ":", 0) : NULL; + + if (config.drun_categories && *(config.drun_categories)) { + pd->show_categories = g_strsplit(config.drun_categories, ",", 0); + } + + drun_mode_parse_entry_fields(); + drun_mode_parse_display_format(); + get_apps(pd); + + pd->completer = create_new_file_browser(); + mode_init(pd->completer); + return TRUE; } -static void drun_entry_clear ( DRunModeEntry *e ) -{ - g_free ( e->root ); - g_free ( e->path ); - g_free ( e->app_id ); - g_free ( e->desktop_id ); - if ( e->icon != NULL ) { - cairo_surface_destroy ( e->icon ); - } - g_free ( e->icon_name ); - g_free ( e->exec ); - g_free ( e->name ); - g_free ( e->generic_name ); - g_free ( e->comment ); - if ( e->action != DRUN_GROUP_NAME ) { - g_free ( e->action ); - } - g_strfreev ( e->categories ); - g_strfreev ( e->keywords ); - if ( e->key_file ) { - g_key_file_free ( e->key_file ); - } +static void drun_entry_clear(DRunModeEntry *e) { + g_free(e->root); + g_free(e->path); + g_free(e->app_id); + g_free(e->desktop_id); + if (e->icon != NULL) { + cairo_surface_destroy(e->icon); + } + g_free(e->icon_name); + g_free(e->exec); + g_free(e->name); + g_free(e->generic_name); + g_free(e->comment); + if (e->action != DRUN_GROUP_NAME) { + g_free(e->action); + } + g_strfreev(e->categories); + g_strfreev(e->keywords); + if (e->key_file) { + g_key_file_free(e->key_file); + } } -static ModeMode drun_mode_result ( Mode *sw, int mretv, char **input, unsigned int selected_line ) -{ - DRunModePrivateData *rmpd = (DRunModePrivateData *) mode_get_private_data ( sw ); - ModeMode retv = MODE_EXIT; +static ModeMode drun_mode_result(Mode *sw, int mretv, char **input, + unsigned int selected_line) { + DRunModePrivateData *rmpd = (DRunModePrivateData *)mode_get_private_data(sw); + ModeMode retv = MODE_EXIT; - if ( rmpd->file_complete == TRUE ) { + if (rmpd->file_complete == TRUE) { - retv = RELOAD_DIALOG; + retv = RELOAD_DIALOG; - if ( ( mretv& (MENU_COMPLETE)) ) { - g_free ( rmpd->old_completer_input ); - rmpd->old_completer_input = *input; - *input = NULL; - if ( rmpd->selected_line < rmpd->cmd_list_length ) { - (*input) = g_strdup ( rmpd->old_input ); - } - rmpd->file_complete = FALSE; + if ((mretv & (MENU_COMPLETE))) { + g_free(rmpd->old_completer_input); + rmpd->old_completer_input = *input; + *input = NULL; + if (rmpd->selected_line < rmpd->cmd_list_length) { + (*input) = g_strdup(rmpd->old_input); + } + rmpd->file_complete = FALSE; + } else if ((mretv & MENU_CANCEL)) { + retv = MODE_EXIT; + } else { + char *path = NULL; + retv = file_browser_mode_completer(rmpd->completer, mretv, input, + selected_line, &path); + if (retv == MODE_EXIT) { + exec_cmd_entry(&(rmpd->entry_list[rmpd->selected_line]), path); + } + g_free(path); + } + return retv; + } + if ((mretv & MENU_OK)) { + switch (rmpd->entry_list[selected_line].type) { + case DRUN_DESKTOP_ENTRY_TYPE_SERVICE: + case DRUN_DESKTOP_ENTRY_TYPE_APPLICATION: + exec_cmd_entry(&(rmpd->entry_list[selected_line]), NULL); + break; + case DRUN_DESKTOP_ENTRY_TYPE_LINK: + launch_link_entry(&(rmpd->entry_list[selected_line])); + break; + default: + g_assert_not_reached(); + } + } else if ((mretv & MENU_CUSTOM_INPUT) && *input != NULL && + *input[0] != '\0') { + RofiHelperExecuteContext context = {.name = NULL}; + gboolean run_in_term = ((mretv & MENU_CUSTOM_ACTION) == MENU_CUSTOM_ACTION); + // FIXME: We assume startup notification in terminals, not in others + if (!helper_execute_command(NULL, *input, run_in_term, + run_in_term ? &context : NULL)) { + retv = RELOAD_DIALOG; + } + } else if ((mretv & MENU_ENTRY_DELETE) && + selected_line < rmpd->cmd_list_length) { + // Positive sort index means it is in history. + if (rmpd->entry_list[selected_line].sort_index >= 0) { + delete_entry_history(&(rmpd->entry_list[selected_line])); + drun_entry_clear(&(rmpd->entry_list[selected_line])); + memmove(&(rmpd->entry_list[selected_line]), + &rmpd->entry_list[selected_line + 1], + sizeof(DRunModeEntry) * + (rmpd->cmd_list_length - selected_line - 1)); + rmpd->cmd_list_length--; + } + retv = RELOAD_DIALOG; + } else if (mretv & MENU_CUSTOM_COMMAND) { + retv = (mretv & MENU_LOWER_MASK); + } else if ((mretv & MENU_COMPLETE)) { + retv = RELOAD_DIALOG; + if (selected_line < rmpd->cmd_list_length) { + switch (rmpd->entry_list[selected_line].type) { + case DRUN_DESKTOP_ENTRY_TYPE_SERVICE: + case DRUN_DESKTOP_ENTRY_TYPE_APPLICATION: { + GRegex *regex = g_regex_new("%[fFuU]", 0, 0, NULL); + + if (g_regex_match(regex, rmpd->entry_list[selected_line].exec, 0, + NULL)) { + rmpd->selected_line = selected_line; + // TODO add check if it supports passing file. + + g_free(rmpd->old_input); + rmpd->old_input = g_strdup(*input); + + if (*input) + g_free(*input); + *input = g_strdup(rmpd->old_completer_input); + + rmpd->file_complete = TRUE; } - else if ( (mretv&MENU_CANCEL) ) { - retv = MODE_EXIT; - } - else { - char *path = NULL; - retv = file_browser_mode_completer ( rmpd->completer, mretv, input, selected_line, &path ); - if ( retv == MODE_EXIT ) { - exec_cmd_entry ( &( rmpd->entry_list[rmpd->selected_line] ), path ); + g_regex_unref(regex); + } + default: + break; + } + } + } + return retv; +} +static void drun_mode_destroy(Mode *sw) { + DRunModePrivateData *rmpd = (DRunModePrivateData *)mode_get_private_data(sw); + if (rmpd != NULL) { + for (size_t i = 0; i < rmpd->cmd_list_length; i++) { + drun_entry_clear(&(rmpd->entry_list[i])); + } + g_hash_table_destroy(rmpd->disabled_entries); + g_free(rmpd->entry_list); - } - g_free (path); + g_free(rmpd->old_completer_input); + g_free(rmpd->old_input); + mode_destroy(rmpd->completer); + + g_strfreev(rmpd->current_desktop_list); + g_strfreev(rmpd->show_categories); + g_free(rmpd); + mode_set_private_data(sw, NULL); + } +} + +static char *_get_display_value(const Mode *sw, unsigned int selected_line, + int *state, G_GNUC_UNUSED GList **list, + int get_entry) { + DRunModePrivateData *pd = (DRunModePrivateData *)mode_get_private_data(sw); + + if (pd->file_complete) { + return pd->completer->_get_display_value(pd->completer, selected_line, + state, list, get_entry); + } + *state |= MARKUP; + if (!get_entry) { + return NULL; + } + if (pd->entry_list == NULL) { + // Should never get here. + return g_strdup("Failed"); + } + /* Free temp storage. */ + DRunModeEntry *dr = &(pd->entry_list[selected_line]); + gchar *cats = NULL; + if (dr->categories) { + char *tcats = g_strjoinv(",", dr->categories); + if (tcats) { + cats = g_markup_escape_text(tcats, -1); + g_free(tcats); + } + } + gchar *keywords = NULL; + if (dr->keywords) { + char *tkeyw = g_strjoinv(",", dr->keywords); + if (tkeyw) { + keywords = g_markup_escape_text(tkeyw, -1); + g_free(tkeyw); + } + } + // Needed for display. + char *egn = NULL; + char *en = NULL; + char *ec = NULL; + if (dr->generic_name) { + egn = g_markup_escape_text(dr->generic_name, -1); + } + if (dr->name) { + en = g_markup_escape_text(dr->name, -1); + } + if (dr->comment) { + ec = g_markup_escape_text(dr->comment, -1); + } + + char *retv = helper_string_replace_if_exists( + config.drun_display_format, "{generic}", egn, "{name}", en, "{comment}", + ec, "{exec}", dr->exec, "{categories}", cats, "{keywords}", keywords, + NULL); + g_free(egn); + g_free(en); + g_free(ec); + g_free(cats); + return retv; +} + +static cairo_surface_t *fallback_icon(DRunModePrivateData *pd, int height) { + if (config.application_fallback_icon) { + // FALLBACK + if (pd->fallback_icon_fetch_uid > 0) { + return rofi_icon_fetcher_get(pd->fallback_icon_fetch_uid); + } + pd->fallback_icon_fetch_uid = + rofi_icon_fetcher_query(config.application_fallback_icon, height); + } + return NULL; +} +static cairo_surface_t *_get_icon(const Mode *sw, unsigned int selected_line, + int height) { + DRunModePrivateData *pd = (DRunModePrivateData *)mode_get_private_data(sw); + if (pd->file_complete) { + return pd->completer->_get_icon(pd->completer, selected_line, height); + } + g_return_val_if_fail(pd->entry_list != NULL, NULL); + DRunModeEntry *dr = &(pd->entry_list[selected_line]); + if (dr->icon_name != NULL) { + if (dr->icon_fetch_uid > 0) { + cairo_surface_t *icon = rofi_icon_fetcher_get(dr->icon_fetch_uid); + if (icon) { + return icon; + } + return fallback_icon(pd, height); + } + dr->icon_fetch_uid = rofi_icon_fetcher_query(dr->icon_name, height); + cairo_surface_t *icon = rofi_icon_fetcher_get(dr->icon_fetch_uid); + if (icon) { + return icon; + } + } + return fallback_icon(pd, height); +} + +static char *drun_get_completion(const Mode *sw, unsigned int index) { + DRunModePrivateData *pd = (DRunModePrivateData *)mode_get_private_data(sw); + /* Free temp storage. */ + DRunModeEntry *dr = &(pd->entry_list[index]); + if (dr->generic_name == NULL) { + return g_strdup(dr->name); + } + return g_strdup_printf("%s", dr->name); +} + +static int drun_token_match(const Mode *data, rofi_int_matcher **tokens, + unsigned int index) { + DRunModePrivateData *rmpd = + (DRunModePrivateData *)mode_get_private_data(data); + if (rmpd->file_complete) { + return rmpd->completer->_token_match(rmpd->completer, tokens, index); + } + int match = 1; + if (tokens) { + for (int j = 0; match && tokens != NULL && tokens[j] != NULL; j++) { + int test = 0; + rofi_int_matcher *ftokens[2] = {tokens[j], NULL}; + // Match name + if (matching_entry_fields[DRUN_MATCH_FIELD_NAME].enabled_match) { + if (rmpd->entry_list[index].name) { + test = helper_token_match(ftokens, rmpd->entry_list[index].name); } + } + if (matching_entry_fields[DRUN_MATCH_FIELD_GENERIC].enabled_match) { + // Match generic name + if (test == tokens[j]->invert && rmpd->entry_list[index].generic_name) { + test = + helper_token_match(ftokens, rmpd->entry_list[index].generic_name); + } + } + if (matching_entry_fields[DRUN_MATCH_FIELD_EXEC].enabled_match) { + // Match executable name. + if (test == tokens[j]->invert && rmpd->entry_list[index].exec) { + test = helper_token_match(ftokens, rmpd->entry_list[index].exec); + } + } + if (matching_entry_fields[DRUN_MATCH_FIELD_CATEGORIES].enabled_match) { + // Match against category. + if (test == tokens[j]->invert) { + gchar **list = rmpd->entry_list[index].categories; + for (int iter = 0; test == tokens[j]->invert && list && list[iter]; + iter++) { + test = helper_token_match(ftokens, list[iter]); + } + } + } + if (matching_entry_fields[DRUN_MATCH_FIELD_KEYWORDS].enabled_match) { + // Match against category. + if (test == tokens[j]->invert) { + gchar **list = rmpd->entry_list[index].keywords; + for (int iter = 0; test == tokens[j]->invert && list && list[iter]; + iter++) { + test = helper_token_match(ftokens, list[iter]); + } + } + } + if (matching_entry_fields[DRUN_MATCH_FIELD_COMMENT].enabled_match) { + + // Match executable name. + if (test == tokens[j]->invert && rmpd->entry_list[index].comment) { + test = helper_token_match(ftokens, rmpd->entry_list[index].comment); + } + } + if (test == 0) { + match = 0; + } + } + } + + return match; +} + +static unsigned int drun_mode_get_num_entries(const Mode *sw) { + const DRunModePrivateData *pd = + (const DRunModePrivateData *)mode_get_private_data(sw); + if (pd->file_complete) { + return pd->completer->_get_num_entries(pd->completer); + } + return pd->cmd_list_length; +} +static char *drun_get_message(const Mode *sw) { + DRunModePrivateData *pd = sw->private_data; + if (pd->file_complete) { + if (pd->selected_line < pd->cmd_list_length) { + char *msg = mode_get_message(pd->completer); + if (msg) { + char *retv = + g_strdup_printf("File complete for: %s\n%s", + pd->entry_list[pd->selected_line].name, msg); + g_free(msg); return retv; + } + return g_strdup_printf("File complete for: %s", + pd->entry_list[pd->selected_line].name); } - if ( ( mretv & MENU_OK ) ) { - switch ( rmpd->entry_list[selected_line].type ) - { - case DRUN_DESKTOP_ENTRY_TYPE_SERVICE: - case DRUN_DESKTOP_ENTRY_TYPE_APPLICATION: - exec_cmd_entry ( &( rmpd->entry_list[selected_line] ), NULL ); - break; - case DRUN_DESKTOP_ENTRY_TYPE_LINK: - launch_link_entry ( &( rmpd->entry_list[selected_line] ) ); - break; - default: - g_assert_not_reached (); - } - } - else if ( ( mretv & MENU_CUSTOM_INPUT ) && *input != NULL && *input[0] != '\0' ) { - RofiHelperExecuteContext context = { .name = NULL }; - gboolean run_in_term = ( ( mretv & MENU_CUSTOM_ACTION ) == MENU_CUSTOM_ACTION ); - // FIXME: We assume startup notification in terminals, not in others - if ( !helper_execute_command ( NULL, *input, run_in_term, run_in_term ? &context : NULL ) ) { - retv = RELOAD_DIALOG; - } - } - else if ( ( mretv & MENU_ENTRY_DELETE ) && selected_line < rmpd->cmd_list_length ) { - // Positive sort index means it is in history. - if ( rmpd->entry_list[selected_line].sort_index >= 0 ) { - delete_entry_history ( &( rmpd->entry_list[selected_line] ) ); - drun_entry_clear ( &( rmpd->entry_list[selected_line] ) ); - memmove ( &( rmpd->entry_list[selected_line] ), &rmpd->entry_list[selected_line + 1], - sizeof ( DRunModeEntry ) * ( rmpd->cmd_list_length - selected_line - 1 ) ); - rmpd->cmd_list_length--; - } - retv = RELOAD_DIALOG; - } - else if ( mretv & MENU_CUSTOM_COMMAND ) { - retv = ( mretv & MENU_LOWER_MASK ); - } - else if ( ( mretv& MENU_COMPLETE) ) { - retv = RELOAD_DIALOG; - if ( selected_line < rmpd->cmd_list_length ) { - switch ( rmpd->entry_list[selected_line].type ) - { - case DRUN_DESKTOP_ENTRY_TYPE_SERVICE: - case DRUN_DESKTOP_ENTRY_TYPE_APPLICATION: - { - GRegex *regex = g_regex_new ("%[fFuU]", 0, 0, NULL); - - if (g_regex_match (regex, rmpd->entry_list[selected_line].exec, 0, NULL) ) { - rmpd->selected_line = selected_line; - // TODO add check if it supports passing file. - - g_free ( rmpd->old_input ); - rmpd->old_input = g_strdup ( *input ); - - if ( *input ) g_free (*input); - *input = g_strdup ( rmpd->old_completer_input ); - - rmpd->file_complete = TRUE; - } - g_regex_unref ( regex ); - } - default: - break; - } - } - } - return retv; -} -static void drun_mode_destroy ( Mode *sw ) -{ - DRunModePrivateData *rmpd = (DRunModePrivateData *) mode_get_private_data ( sw ); - if ( rmpd != NULL ) { - for ( size_t i = 0; i < rmpd->cmd_list_length; i++ ) { - drun_entry_clear ( &( rmpd->entry_list[i] ) ); - } - g_hash_table_destroy ( rmpd->disabled_entries ); - g_free ( rmpd->entry_list ); - - g_free ( rmpd->old_completer_input ); - g_free ( rmpd->old_input ); - mode_destroy ( rmpd->completer ); - - g_strfreev ( rmpd->current_desktop_list ); - g_strfreev ( rmpd->show_categories ); - g_free ( rmpd ); - mode_set_private_data ( sw, NULL ); - } -} - -static char *_get_display_value ( const Mode *sw, unsigned int selected_line, int *state, G_GNUC_UNUSED GList **list, int get_entry ) -{ - DRunModePrivateData *pd = (DRunModePrivateData *) mode_get_private_data ( sw ); - - if ( pd->file_complete ) { - return pd->completer->_get_display_value (pd->completer, selected_line, state, list, get_entry ); - } - *state |= MARKUP; - if ( !get_entry ) { - return NULL; - } - if ( pd->entry_list == NULL ) { - // Should never get here. - return g_strdup ( "Failed" ); - } - /* Free temp storage. */ - DRunModeEntry *dr = &( pd->entry_list[selected_line] ); - gchar *cats = NULL; - if ( dr->categories ) { - char *tcats = g_strjoinv ( ",", dr->categories ); - if ( tcats ) { - cats = g_markup_escape_text ( tcats, -1 ); - g_free ( tcats ); - } - } - gchar *keywords = NULL; - if ( dr->keywords ) { - char *tkeyw = g_strjoinv ( ",", dr->keywords ); - if ( tkeyw ) { - keywords = g_markup_escape_text ( tkeyw, -1 ); - g_free ( tkeyw ); - } - } - // Needed for display. - char *egn = NULL; - char *en = NULL; - char *ec = NULL; - if ( dr->generic_name ) { - egn = g_markup_escape_text ( dr->generic_name, -1 ); - } - if ( dr->name ) { - en = g_markup_escape_text ( dr->name, -1 ); - } - if ( dr->comment ) { - ec = g_markup_escape_text ( dr->comment, -1 ); - } - - char *retv = helper_string_replace_if_exists ( config.drun_display_format, - "{generic}", egn, - "{name}", en, - "{comment}", ec, - "{exec}", dr->exec, - "{categories}", cats, - "{keywords}", keywords, - NULL ); - g_free ( egn ); - g_free ( en ); - g_free ( ec ); - g_free ( cats ); - return retv; -} - -static cairo_surface_t *fallback_icon ( DRunModePrivateData *pd, int height ) -{ - if ( config.application_fallback_icon ) { - // FALLBACK - if ( pd->fallback_icon_fetch_uid > 0 ) { - return rofi_icon_fetcher_get ( pd->fallback_icon_fetch_uid ); - } - pd->fallback_icon_fetch_uid = rofi_icon_fetcher_query ( config.application_fallback_icon, height ); - } - return NULL; -} -static cairo_surface_t *_get_icon ( const Mode *sw, unsigned int selected_line, int height ) -{ - DRunModePrivateData *pd = (DRunModePrivateData *) mode_get_private_data ( sw ); - if ( pd->file_complete ) { - return pd->completer->_get_icon ( pd->completer, selected_line, height ); - } - g_return_val_if_fail ( pd->entry_list != NULL, NULL ); - DRunModeEntry *dr = &( pd->entry_list[selected_line] ); - if ( dr->icon_name != NULL ) { - if ( dr->icon_fetch_uid > 0 ) { - cairo_surface_t *icon = rofi_icon_fetcher_get ( dr->icon_fetch_uid ); - if ( icon ) { - return icon; - } - return fallback_icon ( pd, height ); - } - dr->icon_fetch_uid = rofi_icon_fetcher_query ( dr->icon_name, height ); - cairo_surface_t *icon = rofi_icon_fetcher_get ( dr->icon_fetch_uid ); - if ( icon ) { - return icon; - } - } - return fallback_icon ( pd, height ); -} - -static char *drun_get_completion ( const Mode *sw, unsigned int index ) -{ - DRunModePrivateData *pd = (DRunModePrivateData *) mode_get_private_data ( sw ); - /* Free temp storage. */ - DRunModeEntry *dr = &( pd->entry_list[index] ); - if ( dr->generic_name == NULL ) { - return g_strdup ( dr->name ); - } - else { - return g_strdup_printf ( "%s", dr->name ); - } -} - -static int drun_token_match ( const Mode *data, rofi_int_matcher **tokens, unsigned int index ) -{ - DRunModePrivateData *rmpd = (DRunModePrivateData *) mode_get_private_data ( data ); - if ( rmpd->file_complete ) { - return rmpd->completer->_token_match (rmpd->completer, tokens, index ); - } - int match = 1; - if ( tokens ) { - for ( int j = 0; match && tokens != NULL && tokens[j] != NULL; j++ ) { - int test = 0; - rofi_int_matcher *ftokens[2] = { tokens[j], NULL }; - // Match name - if ( matching_entry_fields[DRUN_MATCH_FIELD_NAME].enabled_match ) { - if ( rmpd->entry_list[index].name ) { - test = helper_token_match ( ftokens, rmpd->entry_list[index].name ); - } - } - if ( matching_entry_fields[DRUN_MATCH_FIELD_GENERIC].enabled_match ) { - // Match generic name - if ( test == tokens[j]->invert && rmpd->entry_list[index].generic_name ) { - test = helper_token_match ( ftokens, rmpd->entry_list[index].generic_name ); - } - } - if ( matching_entry_fields[DRUN_MATCH_FIELD_EXEC].enabled_match ) { - // Match executable name. - if ( test == tokens[j]->invert && rmpd->entry_list[index].exec ) { - test = helper_token_match ( ftokens, rmpd->entry_list[index].exec ); - } - } - if ( matching_entry_fields[DRUN_MATCH_FIELD_CATEGORIES].enabled_match ) { - // Match against category. - if ( test == tokens[j]->invert ) { - gchar **list = rmpd->entry_list[index].categories; - for ( int iter = 0; test == tokens[j]->invert && list && list[iter]; iter++ ) { - test = helper_token_match ( ftokens, list[iter] ); - } - } - } - if ( matching_entry_fields[DRUN_MATCH_FIELD_KEYWORDS].enabled_match ) { - // Match against category. - if ( test == tokens[j]->invert ) { - gchar **list = rmpd->entry_list[index].keywords; - for ( int iter = 0; test == tokens[j]->invert && list && list[iter]; iter++ ) { - test = helper_token_match ( ftokens, list[iter] ); - } - } - } - if ( matching_entry_fields[DRUN_MATCH_FIELD_COMMENT].enabled_match ) { - - // Match executable name. - if ( test == tokens[j]->invert && rmpd->entry_list[index].comment ) { - test = helper_token_match ( ftokens, rmpd->entry_list[index].comment ); - } - } - if ( test == 0 ) { - match = 0; - } - } - } - - return match; -} - -static unsigned int drun_mode_get_num_entries ( const Mode *sw ) -{ - const DRunModePrivateData *pd = (const DRunModePrivateData *) mode_get_private_data ( sw ); - if ( pd->file_complete ) { - return pd->completer->_get_num_entries( pd->completer ); - } - return pd->cmd_list_length; -} -static char *drun_get_message ( const Mode *sw ) -{ - DRunModePrivateData *pd = sw->private_data; - if ( pd->file_complete ) { - if ( pd->selected_line < pd->cmd_list_length ) { - char *msg = mode_get_message ( pd->completer); - if ( msg ) { - char *retv = g_strdup_printf("File complete for: %s\n%s", pd->entry_list[pd->selected_line].name, msg); - g_free (msg); - return retv; - } - return g_strdup_printf("File complete for: %s", pd->entry_list[pd->selected_line].name); - } - } - return NULL; + } + return NULL; } #include "mode-private.h" -Mode drun_mode = -{ - .name = "drun", - .cfg_name_key = "display-drun", - ._init = drun_mode_init, - ._get_num_entries = drun_mode_get_num_entries, - ._result = drun_mode_result, - ._destroy = drun_mode_destroy, - ._token_match = drun_token_match, - ._get_message = drun_get_message, - ._get_completion = drun_get_completion, - ._get_display_value = _get_display_value, - ._get_icon = _get_icon, - ._preprocess_input = NULL, - .private_data = NULL, - .free = NULL -}; +Mode drun_mode = {.name = "drun", + .cfg_name_key = "display-drun", + ._init = drun_mode_init, + ._get_num_entries = drun_mode_get_num_entries, + ._result = drun_mode_result, + ._destroy = drun_mode_destroy, + ._token_match = drun_token_match, + ._get_message = drun_get_message, + ._get_completion = drun_get_completion, + ._get_display_value = _get_display_value, + ._get_icon = _get_icon, + ._preprocess_input = NULL, + .private_data = NULL, + .free = NULL}; #endif // ENABLE_DRUN diff --git a/source/dialogs/filebrowser.c b/source/dialogs/filebrowser.c index de4eac50..c572e279 100644 --- a/source/dialogs/filebrowser.c +++ b/source/dialogs/filebrowser.c @@ -23,499 +23,476 @@ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include -#include -#include -#include #include -#include #include +#include +#include +#include +#include +#include -#include -#include #include +#include +#include -#include "mode.h" -#include "theme.h" -#include "helper.h" -#include "mode-private.h" #include "dialogs/filebrowser.h" -#include "rofi.h" +#include "helper.h" #include "history.h" +#include "mode-private.h" +#include "mode.h" +#include "rofi.h" +#include "theme.h" #include #include "rofi-icon-fetcher.h" -#define FILEBROWSER_CACHE_FILE "rofi3.filebrowsercache" +#define FILEBROWSER_CACHE_FILE "rofi3.filebrowsercache" /** * The internal data structure holding the private data of the TEST Mode. */ -enum FBFileType -{ - UP, - DIRECTORY, - RFILE, - NUM_FILE_TYPES, +enum FBFileType { + UP, + DIRECTORY, + RFILE, + NUM_FILE_TYPES, }; /** * Possible sorting methods */ -enum FBSortingMethod -{ - FB_SORT_NAME, - FB_SORT_TIME, +enum FBSortingMethod { + FB_SORT_NAME, + FB_SORT_TIME, }; /** * Type of time to sort by */ -enum FBSortingTime -{ - FB_MTIME, - FB_ATIME, - FB_CTIME, +enum FBSortingTime { + FB_MTIME, + FB_ATIME, + FB_CTIME, }; /** Icons to use for the file type */ -const char *icon_name[NUM_FILE_TYPES] = -{ - "go-up", - "folder", - "gtk-file" -}; -typedef struct -{ - char *name; - char *path; - enum FBFileType type; - uint32_t icon_fetch_uid; - gboolean link; - time_t time; +const char *icon_name[NUM_FILE_TYPES] = {"go-up", "folder", "gtk-file"}; +typedef struct { + char *name; + char *path; + enum FBFileType type; + uint32_t icon_fetch_uid; + gboolean link; + time_t time; } FBFile; -typedef struct -{ - GFile *current_dir; - FBFile *array; - unsigned int array_length; +typedef struct { + GFile *current_dir; + FBFile *array; + unsigned int array_length; } FileBrowserModePrivateData; -struct -{ - enum FBSortingMethod sorting_method; - enum FBSortingTime sorting_time; - gboolean directories_first; +struct { + enum FBSortingMethod sorting_method; + enum FBSortingTime sorting_time; + gboolean directories_first; } file_browser_config = { - .sorting_method = FB_SORT_NAME, - .sorting_time = FB_MTIME, + .sorting_method = FB_SORT_NAME, + .sorting_time = FB_MTIME, .directories_first = TRUE, }; -static void free_list ( FileBrowserModePrivateData *pd ) -{ - for ( unsigned int i = 0; i < pd->array_length; i++ ) { - FBFile *fb = &( pd->array[i] ); - g_free ( fb->name ); - g_free ( fb->path ); - } - g_free ( pd->array ); - pd->array = NULL; - pd->array_length = 0; +static void free_list(FileBrowserModePrivateData *pd) { + for (unsigned int i = 0; i < pd->array_length; i++) { + FBFile *fb = &(pd->array[i]); + g_free(fb->name); + g_free(fb->path); + } + g_free(pd->array); + pd->array = NULL; + pd->array_length = 0; } -#include #include +#include -static gint compare_name ( gconstpointer a, gconstpointer b, G_GNUC_UNUSED gpointer data ) -{ - FBFile *fa = (FBFile *) a; - FBFile *fb = (FBFile *) b; +static gint compare_name(gconstpointer a, gconstpointer b, + G_GNUC_UNUSED gpointer data) { + FBFile *fa = (FBFile *)a; + FBFile *fb = (FBFile *)b; - if ( file_browser_config.directories_first && fa->type != fb->type ) { - return fa->type - fb->type; - } + if (file_browser_config.directories_first && fa->type != fb->type) { + return fa->type - fb->type; + } - return g_strcmp0 ( fa->name, fb->name ); + return g_strcmp0(fa->name, fb->name); } -static gint compare_time ( gconstpointer a, gconstpointer b, G_GNUC_UNUSED gpointer data ) -{ - FBFile *fa = (FBFile *) a; - FBFile *fb = (FBFile *) b; +static gint compare_time(gconstpointer a, gconstpointer b, + G_GNUC_UNUSED gpointer data) { + FBFile *fa = (FBFile *)a; + FBFile *fb = (FBFile *)b; - if ( file_browser_config.directories_first && fa->type != fb->type ) { - return fa->type - fb->type; - } + if (file_browser_config.directories_first && fa->type != fb->type) { + return fa->type - fb->type; + } - if ( fa->time < 0 ) { - return -1; - } + if (fa->time < 0) { + return -1; + } - if ( fb->time < 0 ) { - return 1; - } + if (fb->time < 0) { + return 1; + } - return fb->time - fa->time; + return fb->time - fa->time; } -static gint compare ( gconstpointer a, gconstpointer b, gpointer data ) -{ - GCompareDataFunc comparator = NULL; +static gint compare(gconstpointer a, gconstpointer b, gpointer data) { + GCompareDataFunc comparator = NULL; - switch ( file_browser_config.sorting_method ) - { - case FB_SORT_NAME: - comparator = compare_name; + switch (file_browser_config.sorting_method) { + case FB_SORT_NAME: + comparator = compare_name; + break; + case FB_SORT_TIME: + comparator = compare_time; + break; + default: + comparator = compare_name; + break; + } + + return comparator(a, b, data); +} + +static time_t get_time(const struct stat *statbuf) { + switch (file_browser_config.sorting_time) { + case FB_MTIME: + return statbuf->st_mtim.tv_sec; + case FB_ATIME: + return statbuf->st_atim.tv_sec; + case FB_CTIME: + return statbuf->st_ctim.tv_sec; + default: + return 0; + } +} + +static void set_time(FBFile *file) { + gchar *path = g_filename_from_utf8(file->path, -1, NULL, NULL, NULL); + + struct stat statbuf; + + if (stat(path, &statbuf) == 0) { + file->time = get_time(&statbuf); + } else { + g_warning("Failed to stat file: %s, %s", path, strerror(errno)); + } + + g_free(path); +} + +static void get_file_browser(Mode *sw) { + FileBrowserModePrivateData *pd = + (FileBrowserModePrivateData *)mode_get_private_data(sw); + /** + * Get the entries to display. + * this gets called on plugin initialization. + */ + char *cdir = g_file_get_path(pd->current_dir); + DIR *dir = opendir(cdir); + if (dir) { + struct dirent *rd = NULL; + while ((rd = readdir(dir)) != NULL) { + if (g_strcmp0(rd->d_name, "..") == 0) { + pd->array = + g_realloc(pd->array, (pd->array_length + 1) * sizeof(FBFile)); + // Rofi expects utf-8, so lets convert the filename. + pd->array[pd->array_length].name = g_strdup(".."); + pd->array[pd->array_length].path = NULL; + pd->array[pd->array_length].type = UP; + pd->array[pd->array_length].icon_fetch_uid = 0; + pd->array[pd->array_length].link = FALSE; + pd->array[pd->array_length].time = -1; + pd->array_length++; + continue; + } + if (rd->d_name[0] == '.') { + continue; + } + + switch (rd->d_type) { + case DT_BLK: + case DT_CHR: + case DT_FIFO: + case DT_UNKNOWN: + case DT_SOCK: + default: break; - case FB_SORT_TIME: - comparator = compare_time; + case DT_REG: + case DT_DIR: + pd->array = + g_realloc(pd->array, (pd->array_length + 1) * sizeof(FBFile)); + // Rofi expects utf-8, so lets convert the filename. + pd->array[pd->array_length].name = + g_filename_to_utf8(rd->d_name, -1, NULL, NULL, NULL); + pd->array[pd->array_length].path = + g_build_filename(cdir, rd->d_name, NULL); + pd->array[pd->array_length].type = + (rd->d_type == DT_DIR) ? DIRECTORY : RFILE; + pd->array[pd->array_length].icon_fetch_uid = 0; + pd->array[pd->array_length].link = FALSE; + + if (file_browser_config.sorting_method == FB_SORT_TIME) { + set_time(&pd->array[pd->array_length]); + } + + pd->array_length++; break; - default: - comparator = compare_name; - break; - } - - return comparator ( a, b, data ); -} - -static time_t get_time ( const struct stat *statbuf ) -{ - switch ( file_browser_config.sorting_time ) - { - case FB_MTIME: - return statbuf->st_mtim.tv_sec; - case FB_ATIME: - return statbuf->st_atim.tv_sec; - case FB_CTIME: - return statbuf->st_ctim.tv_sec; - default: - return 0; - } -} - -static void set_time ( FBFile *file ) -{ - gchar* path = g_filename_from_utf8 ( file->path, -1, NULL, NULL, NULL ); - - struct stat statbuf; - - if ( stat ( path, &statbuf ) == 0 ) { - file->time = get_time ( &statbuf ); - } - else { - g_warning ( "Failed to stat file: %s, %s", path, strerror ( errno ) ); - } - - g_free ( path ); -} - -static void get_file_browser ( Mode *sw ) -{ - FileBrowserModePrivateData *pd = (FileBrowserModePrivateData *) mode_get_private_data ( sw ); - /** - * Get the entries to display. - * this gets called on plugin initialization. - */ - char *cdir = g_file_get_path ( pd->current_dir ); - DIR *dir = opendir ( cdir ); - if ( dir ) { - struct dirent *rd = NULL; - while ( ( rd = readdir ( dir ) ) != NULL ) { - if ( g_strcmp0 ( rd->d_name, ".." ) == 0 ) { - pd->array = g_realloc ( pd->array, ( pd->array_length + 1 ) * sizeof ( FBFile ) ); - // Rofi expects utf-8, so lets convert the filename. - pd->array[pd->array_length].name = g_strdup ( ".." ); - pd->array[pd->array_length].path = NULL; - pd->array[pd->array_length].type = UP; - pd->array[pd->array_length].icon_fetch_uid = 0; - pd->array[pd->array_length].link = FALSE; - pd->array[pd->array_length].time = -1; - pd->array_length++; - continue; - } - else if ( rd->d_name[0] == '.' ) { - continue; - } - - switch ( rd->d_type ) - { - case DT_BLK: - case DT_CHR: - case DT_FIFO: - case DT_UNKNOWN: - case DT_SOCK: - default: - break; - case DT_REG: - case DT_DIR: - pd->array = g_realloc ( pd->array, ( pd->array_length + 1 ) * sizeof ( FBFile ) ); - // Rofi expects utf-8, so lets convert the filename. - pd->array[pd->array_length].name = g_filename_to_utf8 ( rd->d_name, -1, NULL, NULL, NULL ); - pd->array[pd->array_length].path = g_build_filename ( cdir, rd->d_name, NULL ); - pd->array[pd->array_length].type = ( rd->d_type == DT_DIR ) ? DIRECTORY : RFILE; - pd->array[pd->array_length].icon_fetch_uid = 0; - pd->array[pd->array_length].link = FALSE; - - if ( file_browser_config.sorting_method == FB_SORT_TIME ) { - set_time ( &pd->array[pd->array_length] ); - } - - pd->array_length++; - break; - case DT_LNK: - pd->array = g_realloc ( pd->array, ( pd->array_length + 1 ) * sizeof ( FBFile ) ); - // Rofi expects utf-8, so lets convert the filename. - pd->array[pd->array_length].name = g_filename_to_utf8 ( rd->d_name, -1, NULL, NULL, NULL ); - pd->array[pd->array_length].path = g_build_filename ( cdir, rd->d_name, NULL ); - pd->array[pd->array_length].icon_fetch_uid = 0; - pd->array[pd->array_length].link = TRUE; - // Default to file. + case DT_LNK: + pd->array = + g_realloc(pd->array, (pd->array_length + 1) * sizeof(FBFile)); + // Rofi expects utf-8, so lets convert the filename. + pd->array[pd->array_length].name = + g_filename_to_utf8(rd->d_name, -1, NULL, NULL, NULL); + pd->array[pd->array_length].path = + g_build_filename(cdir, rd->d_name, NULL); + pd->array[pd->array_length].icon_fetch_uid = 0; + pd->array[pd->array_length].link = TRUE; + // Default to file. + pd->array[pd->array_length].type = RFILE; + { + // If we have link, use a stat to fine out what it is, if we fail, we + // mark it as file. + // TODO have a 'broken link' mode? + // Convert full path to right encoding. + char *file = g_filename_from_utf8(pd->array[pd->array_length].path, + -1, NULL, NULL, NULL); + if (file) { + struct stat statbuf; + if (stat(file, &statbuf) == 0) { + if (S_ISDIR(statbuf.st_mode)) { + pd->array[pd->array_length].type = DIRECTORY; + } else if (S_ISREG(statbuf.st_mode)) { pd->array[pd->array_length].type = RFILE; - { - // If we have link, use a stat to fine out what it is, if we fail, we mark it as file. - // TODO have a 'broken link' mode? - // Convert full path to right encoding. - char *file = g_filename_from_utf8 ( pd->array[pd->array_length].path, -1, NULL, NULL, NULL ); - if ( file ) { - struct stat statbuf; - if ( stat ( file, &statbuf ) == 0 ) { - if ( S_ISDIR ( statbuf.st_mode ) ) { - pd->array[pd->array_length].type = DIRECTORY; - } - else if ( S_ISREG ( statbuf.st_mode ) ) { - pd->array[pd->array_length].type = RFILE; - } + } - if ( file_browser_config.sorting_method == FB_SORT_TIME ) { - pd->array[pd->array_length].time = get_time ( &statbuf ); - } - } - else { - g_warning ( "Failed to stat file: %s, %s", file, strerror ( errno ) ); - } - - g_free ( file ); - } - } - pd->array_length++; - break; + if (file_browser_config.sorting_method == FB_SORT_TIME) { + pd->array[pd->array_length].time = get_time(&statbuf); + } + } else { + g_warning("Failed to stat file: %s, %s", file, strerror(errno)); } + + g_free(file); + } } - closedir ( dir ); + pd->array_length++; + break; + } } - g_qsort_with_data ( pd->array, pd->array_length, sizeof ( FBFile ), compare, NULL ); + closedir(dir); + } + g_qsort_with_data(pd->array, pd->array_length, sizeof(FBFile), compare, NULL); } -static void file_browser_mode_init_config ( Mode *sw ) -{ - char *msg = NULL; - gboolean found_error = FALSE; +static void file_browser_mode_init_config(Mode *sw) { + char *msg = NULL; + gboolean found_error = FALSE; - ThemeWidget *wid = rofi_config_find_widget ( sw->name, NULL, TRUE ); + ThemeWidget *wid = rofi_config_find_widget(sw->name, NULL, TRUE); - Property *p = rofi_theme_find_property ( wid, P_STRING, "sorting-method", TRUE ); - if ( p != NULL && p->type == P_STRING ) { - if ( g_strcmp0 ( p->value.s, "name" ) == 0 ) { - file_browser_config.sorting_method = FB_SORT_NAME; - } - else if ( g_strcmp0 ( p->value.s, "mtime" ) == 0 ) { - file_browser_config.sorting_method = FB_SORT_TIME; - file_browser_config.sorting_time = FB_MTIME; - } - else if ( g_strcmp0 ( p->value.s, "atime" ) == 0 ) { - file_browser_config.sorting_method = FB_SORT_TIME; - file_browser_config.sorting_time = FB_ATIME; - } - else if ( g_strcmp0 ( p->value.s, "ctime" ) == 0 ) { - file_browser_config.sorting_method = FB_SORT_TIME; - file_browser_config.sorting_time = FB_CTIME; - } - else { - found_error = TRUE; - - msg = g_strdup_printf ( "\"%s\" is not a valid filebrowser sorting method", p->value.s ); - } - } - - p = rofi_theme_find_property ( wid, P_BOOLEAN, "directories-first", TRUE ); - if ( p != NULL && p->type == P_BOOLEAN ) { - file_browser_config.directories_first = p->value.b; - } - - if ( found_error ) { - rofi_view_error_dialog ( msg, FALSE ); - - g_free ( msg ); - } -} - -static void file_browser_mode_init_current_dir ( Mode *sw ) { - FileBrowserModePrivateData *pd = (FileBrowserModePrivateData *) mode_get_private_data ( sw ); - - ThemeWidget *wid = rofi_config_find_widget ( sw->name, NULL, TRUE ); - - Property *p = rofi_theme_find_property ( wid, P_STRING, "directory", TRUE ); - - gboolean config_has_valid_dir = p != NULL && p->type == P_STRING - && g_file_test ( p->value.s, G_FILE_TEST_IS_DIR ); - - if ( config_has_valid_dir ) { - pd->current_dir = g_file_new_for_path ( p->value.s ); + Property *p = rofi_theme_find_property(wid, P_STRING, "sorting-method", TRUE); + if (p != NULL && p->type == P_STRING) { + if (g_strcmp0(p->value.s, "name") == 0) { + file_browser_config.sorting_method = FB_SORT_NAME; + } else if (g_strcmp0(p->value.s, "mtime") == 0) { + file_browser_config.sorting_method = FB_SORT_TIME; + file_browser_config.sorting_time = FB_MTIME; + } else if (g_strcmp0(p->value.s, "atime") == 0) { + file_browser_config.sorting_method = FB_SORT_TIME; + file_browser_config.sorting_time = FB_ATIME; + } else if (g_strcmp0(p->value.s, "ctime") == 0) { + file_browser_config.sorting_method = FB_SORT_TIME; + file_browser_config.sorting_time = FB_CTIME; } else { - char *current_dir = NULL; - char *cache_file = g_build_filename ( cache_dir, FILEBROWSER_CACHE_FILE, NULL ); + found_error = TRUE; - if ( g_file_get_contents ( cache_file, ¤t_dir, NULL, NULL ) ) { - if ( g_file_test ( current_dir, G_FILE_TEST_IS_DIR ) ) { - pd->current_dir = g_file_new_for_path ( current_dir ); - } - - g_free ( current_dir ); - } - - // Store it based on the unique identifiers (desktop_id). - g_free ( cache_file ); + msg = g_strdup_printf("\"%s\" is not a valid filebrowser sorting method", + p->value.s); } + } + p = rofi_theme_find_property(wid, P_BOOLEAN, "directories-first", TRUE); + if (p != NULL && p->type == P_BOOLEAN) { + file_browser_config.directories_first = p->value.b; + } - if ( pd->current_dir == NULL ) { - pd->current_dir = g_file_new_for_path ( g_get_home_dir () ); - } + if (found_error) { + rofi_view_error_dialog(msg, FALSE); + + g_free(msg); + } } -static int file_browser_mode_init ( Mode *sw ) -{ - /** - * Called on startup when enabled (in modi list) - */ - if ( mode_get_private_data ( sw ) == NULL ) { - FileBrowserModePrivateData *pd = g_malloc0 ( sizeof ( *pd ) ); - mode_set_private_data ( sw, (void *) pd ); +static void file_browser_mode_init_current_dir(Mode *sw) { + FileBrowserModePrivateData *pd = + (FileBrowserModePrivateData *)mode_get_private_data(sw); - file_browser_mode_init_config ( sw ); - file_browser_mode_init_current_dir ( sw ); + ThemeWidget *wid = rofi_config_find_widget(sw->name, NULL, TRUE); - // Load content. - get_file_browser ( sw ); + Property *p = rofi_theme_find_property(wid, P_STRING, "directory", TRUE); + + gboolean config_has_valid_dir = p != NULL && p->type == P_STRING && + g_file_test(p->value.s, G_FILE_TEST_IS_DIR); + + if (config_has_valid_dir) { + pd->current_dir = g_file_new_for_path(p->value.s); + } else { + char *current_dir = NULL; + char *cache_file = + g_build_filename(cache_dir, FILEBROWSER_CACHE_FILE, NULL); + + if (g_file_get_contents(cache_file, ¤t_dir, NULL, NULL)) { + if (g_file_test(current_dir, G_FILE_TEST_IS_DIR)) { + pd->current_dir = g_file_new_for_path(current_dir); + } + + g_free(current_dir); } - return TRUE; -} -static unsigned int file_browser_mode_get_num_entries ( const Mode *sw ) -{ - const FileBrowserModePrivateData *pd = (const FileBrowserModePrivateData *) mode_get_private_data ( sw ); - return pd->array_length; + + // Store it based on the unique identifiers (desktop_id). + g_free(cache_file); + } + + if (pd->current_dir == NULL) { + pd->current_dir = g_file_new_for_path(g_get_home_dir()); + } } -static ModeMode file_browser_mode_result ( Mode *sw, int mretv, char **input, unsigned int selected_line ) -{ - ModeMode retv = MODE_EXIT; - FileBrowserModePrivateData *pd = (FileBrowserModePrivateData *) mode_get_private_data ( sw ); - if ( mretv & MENU_NEXT ) { - retv = NEXT_DIALOG; - } - else if ( mretv & MENU_PREVIOUS ) { - retv = PREVIOUS_DIALOG; - } - else if ( mretv & MENU_QUICK_SWITCH ) { - retv = ( mretv & MENU_LOWER_MASK ); - } - else if ( mretv & MENU_CUSTOM_COMMAND ) { - retv = ( mretv & MENU_LOWER_MASK ); - } - else if ( ( mretv & MENU_OK ) ) { - if ( selected_line < pd->array_length ) { - if ( pd->array[selected_line].type == UP ) { - GFile *new = g_file_get_parent ( pd->current_dir ); - if ( new ) { - g_object_unref ( pd->current_dir ); - pd->current_dir = new; - free_list ( pd ); - get_file_browser ( sw ); - return RESET_DIALOG; - } - } - else if ( pd->array[selected_line].type == DIRECTORY ) { - char *path = g_build_filename ( cache_dir, FILEBROWSER_CACHE_FILE, NULL ); - g_file_set_contents ( path, pd->array[selected_line].path, -1, NULL ); - g_free ( path ); - GFile *new = g_file_new_for_path ( pd->array[selected_line].path ); - g_object_unref ( pd->current_dir ); - pd->current_dir = new; - free_list ( pd ); - get_file_browser ( sw ); - return RESET_DIALOG; - } - else if ( pd->array[selected_line].type == RFILE ) { - char *d = g_filename_from_utf8 ( pd->array[selected_line].path, -1, NULL, NULL, NULL ); - char *d_esc = g_shell_quote ( d ); - char *cmd = g_strdup_printf ( "xdg-open %s", d_esc ); - g_free ( d_esc ); - g_free ( d ); - char *cdir = g_file_get_path ( pd->current_dir ); - helper_execute_command ( cdir, cmd, FALSE, NULL ); - g_free ( cdir ); - g_free ( cmd ); - return MODE_EXIT; - } - } - retv = RELOAD_DIALOG; - } - else if ( ( mretv & MENU_CUSTOM_INPUT ) && *input ) { - char *p = rofi_expand_path ( *input ); - char *dir = g_filename_from_utf8 ( p, -1, NULL, NULL, NULL ); - g_free ( p ); - if ( g_file_test ( dir, G_FILE_TEST_EXISTS ) ) { - if ( g_file_test ( dir, G_FILE_TEST_IS_DIR ) ) { - g_object_unref ( pd->current_dir ); - pd->current_dir = g_file_new_for_path ( dir ); - g_free ( dir ); - free_list ( pd ); - get_file_browser ( sw ); - return RESET_DIALOG; - } - } - g_free ( dir ); - retv = RELOAD_DIALOG; - } - else if ( ( mretv & MENU_ENTRY_DELETE ) == MENU_ENTRY_DELETE ) { - retv = RELOAD_DIALOG; - } - return retv; +static int file_browser_mode_init(Mode *sw) { + /** + * Called on startup when enabled (in modi list) + */ + if (mode_get_private_data(sw) == NULL) { + FileBrowserModePrivateData *pd = g_malloc0(sizeof(*pd)); + mode_set_private_data(sw, (void *)pd); + + file_browser_mode_init_config(sw); + file_browser_mode_init_current_dir(sw); + + // Load content. + get_file_browser(sw); + } + return TRUE; +} +static unsigned int file_browser_mode_get_num_entries(const Mode *sw) { + const FileBrowserModePrivateData *pd = + (const FileBrowserModePrivateData *)mode_get_private_data(sw); + return pd->array_length; } -static void file_browser_mode_destroy ( Mode *sw ) -{ - FileBrowserModePrivateData *pd = (FileBrowserModePrivateData *) mode_get_private_data ( sw ); - if ( pd != NULL ) { - g_object_unref ( pd->current_dir ); - free_list ( pd ); - g_free ( pd ); - mode_set_private_data ( sw, NULL ); +static ModeMode file_browser_mode_result(Mode *sw, int mretv, char **input, + unsigned int selected_line) { + ModeMode retv = MODE_EXIT; + FileBrowserModePrivateData *pd = + (FileBrowserModePrivateData *)mode_get_private_data(sw); + if (mretv & MENU_NEXT) { + retv = NEXT_DIALOG; + } else if (mretv & MENU_PREVIOUS) { + retv = PREVIOUS_DIALOG; + } else if (mretv & MENU_QUICK_SWITCH) { + retv = (mretv & MENU_LOWER_MASK); + } else if (mretv & MENU_CUSTOM_COMMAND) { + retv = (mretv & MENU_LOWER_MASK); + } else if ((mretv & MENU_OK)) { + if (selected_line < pd->array_length) { + if (pd->array[selected_line].type == UP) { + GFile *new = g_file_get_parent(pd->current_dir); + if (new) { + g_object_unref(pd->current_dir); + pd->current_dir = new; + free_list(pd); + get_file_browser(sw); + return RESET_DIALOG; + } + } else if (pd->array[selected_line].type == DIRECTORY) { + char *path = g_build_filename(cache_dir, FILEBROWSER_CACHE_FILE, NULL); + g_file_set_contents(path, pd->array[selected_line].path, -1, NULL); + g_free(path); + GFile *new = g_file_new_for_path(pd->array[selected_line].path); + g_object_unref(pd->current_dir); + pd->current_dir = new; + free_list(pd); + get_file_browser(sw); + return RESET_DIALOG; + } else if (pd->array[selected_line].type == RFILE) { + char *d = g_filename_from_utf8(pd->array[selected_line].path, -1, NULL, + NULL, NULL); + char *d_esc = g_shell_quote(d); + char *cmd = g_strdup_printf("xdg-open %s", d_esc); + g_free(d_esc); + g_free(d); + char *cdir = g_file_get_path(pd->current_dir); + helper_execute_command(cdir, cmd, FALSE, NULL); + g_free(cdir); + g_free(cmd); + return MODE_EXIT; + } } + retv = RELOAD_DIALOG; + } else if ((mretv & MENU_CUSTOM_INPUT) && *input) { + char *p = rofi_expand_path(*input); + char *dir = g_filename_from_utf8(p, -1, NULL, NULL, NULL); + g_free(p); + if (g_file_test(dir, G_FILE_TEST_EXISTS)) { + if (g_file_test(dir, G_FILE_TEST_IS_DIR)) { + g_object_unref(pd->current_dir); + pd->current_dir = g_file_new_for_path(dir); + g_free(dir); + free_list(pd); + get_file_browser(sw); + return RESET_DIALOG; + } + } + g_free(dir); + retv = RELOAD_DIALOG; + } else if ((mretv & MENU_ENTRY_DELETE) == MENU_ENTRY_DELETE) { + retv = RELOAD_DIALOG; + } + return retv; } -static char *_get_display_value ( const Mode *sw, unsigned int selected_line, G_GNUC_UNUSED int *state, G_GNUC_UNUSED GList **attr_list, int get_entry ) -{ - FileBrowserModePrivateData *pd = (FileBrowserModePrivateData *) mode_get_private_data ( sw ); +static void file_browser_mode_destroy(Mode *sw) { + FileBrowserModePrivateData *pd = + (FileBrowserModePrivateData *)mode_get_private_data(sw); + if (pd != NULL) { + g_object_unref(pd->current_dir); + free_list(pd); + g_free(pd); + mode_set_private_data(sw, NULL); + } +} - // Only return the string if requested, otherwise only set state. - if ( !get_entry ) { - return NULL; - } - if ( pd->array[selected_line].type == UP ) { - return g_strdup ( " .." ); - } - else { - if ( pd->array[selected_line].link ) { - return g_strconcat ( "@", pd->array[selected_line].name, NULL ); - } - else { - return g_strdup ( pd->array[selected_line].name ); - } - } - return g_strdup ( "n/a" ); +static char *_get_display_value(const Mode *sw, unsigned int selected_line, + G_GNUC_UNUSED int *state, + G_GNUC_UNUSED GList **attr_list, + int get_entry) { + FileBrowserModePrivateData *pd = + (FileBrowserModePrivateData *)mode_get_private_data(sw); + + // Only return the string if requested, otherwise only set state. + if (!get_entry) { + return NULL; + } + if (pd->array[selected_line].type == UP) { + return g_strdup(" .."); + } + if (pd->array[selected_line].link) { + return g_strconcat("@", pd->array[selected_line].name, NULL); + } + return g_strdup(pd->array[selected_line].name); } /** @@ -527,142 +504,136 @@ static char *_get_display_value ( const Mode *sw, unsigned int selected_line, G_ * * @returns try when a match. */ -static int file_browser_token_match ( const Mode *sw, rofi_int_matcher **tokens, unsigned int index ) -{ - FileBrowserModePrivateData *pd = (FileBrowserModePrivateData *) mode_get_private_data ( sw ); +static int file_browser_token_match(const Mode *sw, rofi_int_matcher **tokens, + unsigned int index) { + FileBrowserModePrivateData *pd = + (FileBrowserModePrivateData *)mode_get_private_data(sw); - // Call default matching function. - return helper_token_match ( tokens, pd->array[index].name ); + // Call default matching function. + return helper_token_match(tokens, pd->array[index].name); } -static cairo_surface_t *_get_icon ( const Mode *sw, unsigned int selected_line, int height ) -{ - FileBrowserModePrivateData *pd = (FileBrowserModePrivateData *) mode_get_private_data ( sw ); - g_return_val_if_fail ( pd->array != NULL, NULL ); - FBFile *dr = &( pd->array[selected_line] ); - if ( dr->icon_fetch_uid > 0 ) { - return rofi_icon_fetcher_get ( dr->icon_fetch_uid ); - } - if ( rofi_icon_fetcher_file_is_image ( dr->path ) ) { - dr->icon_fetch_uid = rofi_icon_fetcher_query ( dr->path, height ); - } - else { - dr->icon_fetch_uid = rofi_icon_fetcher_query ( icon_name[dr->type], height ); - } - return rofi_icon_fetcher_get ( dr->icon_fetch_uid ); +static cairo_surface_t *_get_icon(const Mode *sw, unsigned int selected_line, + int height) { + FileBrowserModePrivateData *pd = + (FileBrowserModePrivateData *)mode_get_private_data(sw); + g_return_val_if_fail(pd->array != NULL, NULL); + FBFile *dr = &(pd->array[selected_line]); + if (dr->icon_fetch_uid > 0) { + return rofi_icon_fetcher_get(dr->icon_fetch_uid); + } + if (rofi_icon_fetcher_file_is_image(dr->path)) { + dr->icon_fetch_uid = rofi_icon_fetcher_query(dr->path, height); + } else { + dr->icon_fetch_uid = rofi_icon_fetcher_query(icon_name[dr->type], height); + } + return rofi_icon_fetcher_get(dr->icon_fetch_uid); } -static char * _get_message ( const Mode *sw ) -{ - FileBrowserModePrivateData *pd = (FileBrowserModePrivateData *) mode_get_private_data ( sw ); - if ( pd->current_dir ) { - char *dirname = g_file_get_parse_name ( pd->current_dir ); - char *str = g_markup_printf_escaped ( "Current directory: %s", dirname ); - g_free ( dirname ); - return str; - } - return "n/a"; +static char *_get_message(const Mode *sw) { + FileBrowserModePrivateData *pd = + (FileBrowserModePrivateData *)mode_get_private_data(sw); + if (pd->current_dir) { + char *dirname = g_file_get_parse_name(pd->current_dir); + char *str = + g_markup_printf_escaped("Current directory: %s", dirname); + g_free(dirname); + return str; + } + return "n/a"; } -static char *_get_completion ( const Mode *sw, unsigned int index ) -{ - FileBrowserModePrivateData *pd = (FileBrowserModePrivateData *) mode_get_private_data ( sw ); +static char *_get_completion(const Mode *sw, unsigned int index) { + FileBrowserModePrivateData *pd = + (FileBrowserModePrivateData *)mode_get_private_data(sw); - char *d = g_strescape ( pd->array[index].path, NULL ); - return d; + char *d = g_strescape(pd->array[index].path, NULL); + return d; } -Mode *create_new_file_browser ( void ) -{ - Mode *sw = g_malloc0 ( sizeof ( Mode ) ); +Mode *create_new_file_browser(void) { + Mode *sw = g_malloc0(sizeof(Mode)); - *sw = file_browser_mode; + *sw = file_browser_mode; - sw->private_data = NULL; - return sw; + sw->private_data = NULL; + return sw; } #if 1 -ModeMode file_browser_mode_completer ( Mode *sw, int mretv, char **input, unsigned int selected_line, char **path ) -{ - ModeMode retv = MODE_EXIT; - FileBrowserModePrivateData *pd = (FileBrowserModePrivateData *) mode_get_private_data ( sw ); - if ( mretv & MENU_NEXT ) { - retv = NEXT_DIALOG; - } - else if ( mretv & MENU_PREVIOUS ) { - retv = PREVIOUS_DIALOG; - } - else if ( mretv & MENU_QUICK_SWITCH ) { - retv = ( mretv & MENU_LOWER_MASK ); - } - else if ( ( mretv & MENU_OK ) ) { - if ( selected_line < pd->array_length ) { - if ( pd->array[selected_line].type == UP ) { - GFile *new = g_file_get_parent ( pd->current_dir ); - if ( new ) { - g_object_unref ( pd->current_dir ); - pd->current_dir = new; - free_list ( pd ); - get_file_browser ( sw ); - return RESET_DIALOG; - } - } - else if ( pd->array[selected_line].type == DIRECTORY ) { - GFile *new = g_file_new_for_path ( pd->array[selected_line].path ); - g_object_unref ( pd->current_dir ); - pd->current_dir = new; - free_list ( pd ); - get_file_browser ( sw ); - return RESET_DIALOG; - } - else if ( pd->array[selected_line].type == RFILE ) { - *path = g_strescape ( pd->array[selected_line].path, NULL ); - return MODE_EXIT; - } +ModeMode file_browser_mode_completer(Mode *sw, int mretv, char **input, + unsigned int selected_line, char **path) { + ModeMode retv = MODE_EXIT; + FileBrowserModePrivateData *pd = + (FileBrowserModePrivateData *)mode_get_private_data(sw); + if (mretv & MENU_NEXT) { + retv = NEXT_DIALOG; + } else if (mretv & MENU_PREVIOUS) { + retv = PREVIOUS_DIALOG; + } else if (mretv & MENU_QUICK_SWITCH) { + retv = (mretv & MENU_LOWER_MASK); + } else if ((mretv & MENU_OK)) { + if (selected_line < pd->array_length) { + if (pd->array[selected_line].type == UP) { + GFile *new = g_file_get_parent(pd->current_dir); + if (new) { + g_object_unref(pd->current_dir); + pd->current_dir = new; + free_list(pd); + get_file_browser(sw); + return RESET_DIALOG; } - retv = RELOAD_DIALOG; + } else if (pd->array[selected_line].type == DIRECTORY) { + GFile *new = g_file_new_for_path(pd->array[selected_line].path); + g_object_unref(pd->current_dir); + pd->current_dir = new; + free_list(pd); + get_file_browser(sw); + return RESET_DIALOG; + } else if (pd->array[selected_line].type == RFILE) { + *path = g_strescape(pd->array[selected_line].path, NULL); + return MODE_EXIT; + } } - else if ( ( mretv & MENU_CUSTOM_INPUT ) && *input ) { - char *p = rofi_expand_path ( *input ); - char *dir = g_filename_from_utf8 ( p, -1, NULL, NULL, NULL ); - g_free ( p ); - if ( g_file_test ( dir, G_FILE_TEST_EXISTS ) ) { - if ( g_file_test ( dir, G_FILE_TEST_IS_DIR ) ) { - g_object_unref ( pd->current_dir ); - pd->current_dir = g_file_new_for_path ( dir ); - g_free ( dir ); - free_list ( pd ); - get_file_browser ( sw ); - return RESET_DIALOG; - } - } - g_free ( dir ); - retv = RELOAD_DIALOG; + retv = RELOAD_DIALOG; + } else if ((mretv & MENU_CUSTOM_INPUT) && *input) { + char *p = rofi_expand_path(*input); + char *dir = g_filename_from_utf8(p, -1, NULL, NULL, NULL); + g_free(p); + if (g_file_test(dir, G_FILE_TEST_EXISTS)) { + if (g_file_test(dir, G_FILE_TEST_IS_DIR)) { + g_object_unref(pd->current_dir); + pd->current_dir = g_file_new_for_path(dir); + g_free(dir); + free_list(pd); + get_file_browser(sw); + return RESET_DIALOG; + } } - else if ( ( mretv & MENU_ENTRY_DELETE ) == MENU_ENTRY_DELETE ) { - retv = RELOAD_DIALOG; - } - return retv; + g_free(dir); + retv = RELOAD_DIALOG; + } else if ((mretv & MENU_ENTRY_DELETE) == MENU_ENTRY_DELETE) { + retv = RELOAD_DIALOG; + } + return retv; } #endif -Mode file_browser_mode = -{ - .display_name = NULL, - .abi_version = ABI_VERSION, - .name = "filebrowser", - .cfg_name_key = "display-filebrowser", - ._init = file_browser_mode_init, - ._get_num_entries = file_browser_mode_get_num_entries, - ._result = file_browser_mode_result, - ._destroy = file_browser_mode_destroy, - ._token_match = file_browser_token_match, +Mode file_browser_mode = { + .display_name = NULL, + .abi_version = ABI_VERSION, + .name = "filebrowser", + .cfg_name_key = "display-filebrowser", + ._init = file_browser_mode_init, + ._get_num_entries = file_browser_mode_get_num_entries, + ._result = file_browser_mode_result, + ._destroy = file_browser_mode_destroy, + ._token_match = file_browser_token_match, ._get_display_value = _get_display_value, - ._get_icon = _get_icon, - ._get_message = _get_message, - ._get_completion = _get_completion, - ._preprocess_input = NULL, - .private_data = NULL, - .free = NULL, + ._get_icon = _get_icon, + ._get_message = _get_message, + ._get_completion = _get_completion, + ._preprocess_input = NULL, + .private_data = NULL, + .free = NULL, }; diff --git a/source/dialogs/help-keys.c b/source/dialogs/help-keys.c index 77176918..b11db615 100644 --- a/source/dialogs/help-keys.c +++ b/source/dialogs/help-keys.c @@ -26,103 +26,96 @@ */ #include -#include #include +#include -#include +#include +#include #include #include -#include -#include -#include #include -#include +#include +#include +#include +#include "dialogs/help-keys.h" +#include "helper.h" #include "rofi.h" #include "settings.h" -#include "helper.h" -#include "xrmoptions.h" -#include "dialogs/help-keys.h" #include "widgets/textbox.h" +#include "xrmoptions.h" -typedef struct -{ - char **messages; - unsigned int messages_length; +typedef struct { + char **messages; + unsigned int messages_length; } KeysHelpModePrivateData; -static void get_apps ( KeysHelpModePrivateData *pd ) -{ - pd->messages = config_parser_return_display_help ( &( pd->messages_length ) ); +static void get_apps(KeysHelpModePrivateData *pd) { + pd->messages = config_parser_return_display_help(&(pd->messages_length)); } -static int help_keys_mode_init ( Mode *sw ) -{ - if ( mode_get_private_data ( sw ) == NULL ) { - KeysHelpModePrivateData *pd = g_malloc0 ( sizeof ( *pd ) ); - mode_set_private_data ( sw, (void *) pd ); - get_apps ( pd ); - } - return TRUE; +static int help_keys_mode_init(Mode *sw) { + if (mode_get_private_data(sw) == NULL) { + KeysHelpModePrivateData *pd = g_malloc0(sizeof(*pd)); + mode_set_private_data(sw, (void *)pd); + get_apps(pd); + } + return TRUE; } -static ModeMode help_keys_mode_result ( G_GNUC_UNUSED Mode *sw, - int mretv, - G_GNUC_UNUSED char **input, - G_GNUC_UNUSED unsigned int selected_line ) -{ - if ( mretv & MENU_CUSTOM_COMMAND ) { - int retv = ( mretv & MENU_LOWER_MASK ); - return retv; - } - return MODE_EXIT; +static ModeMode +help_keys_mode_result(G_GNUC_UNUSED Mode *sw, int mretv, + G_GNUC_UNUSED char **input, + G_GNUC_UNUSED unsigned int selected_line) { + if (mretv & MENU_CUSTOM_COMMAND) { + int retv = (mretv & MENU_LOWER_MASK); + return retv; + } + return MODE_EXIT; } -static void help_keys_mode_destroy ( Mode *sw ) -{ - KeysHelpModePrivateData *rmpd = (KeysHelpModePrivateData *) mode_get_private_data ( sw ); - if ( rmpd != NULL ) { - g_strfreev ( rmpd->messages ); - g_free ( rmpd ); - mode_set_private_data ( sw, NULL ); - } +static void help_keys_mode_destroy(Mode *sw) { + KeysHelpModePrivateData *rmpd = + (KeysHelpModePrivateData *)mode_get_private_data(sw); + if (rmpd != NULL) { + g_strfreev(rmpd->messages); + g_free(rmpd); + mode_set_private_data(sw, NULL); + } } -static char *_get_display_value ( const Mode *sw, unsigned int selected_line, int *state, G_GNUC_UNUSED GList **list, int get_entry ) -{ - KeysHelpModePrivateData *pd = (KeysHelpModePrivateData *) mode_get_private_data ( sw ); - *state |= MARKUP; - if ( !get_entry ) { - return NULL; - } - return g_strdup ( pd->messages[selected_line] ); +static char *_get_display_value(const Mode *sw, unsigned int selected_line, + int *state, G_GNUC_UNUSED GList **list, + int get_entry) { + KeysHelpModePrivateData *pd = + (KeysHelpModePrivateData *)mode_get_private_data(sw); + *state |= MARKUP; + if (!get_entry) { + return NULL; + } + return g_strdup(pd->messages[selected_line]); } -static int help_keys_token_match ( const Mode *data, - rofi_int_matcher **tokens, - unsigned int index - ) -{ - KeysHelpModePrivateData *rmpd = (KeysHelpModePrivateData *) mode_get_private_data ( data ); - return helper_token_match ( tokens, rmpd->messages[index] ); +static int help_keys_token_match(const Mode *data, rofi_int_matcher **tokens, + unsigned int index) { + KeysHelpModePrivateData *rmpd = + (KeysHelpModePrivateData *)mode_get_private_data(data); + return helper_token_match(tokens, rmpd->messages[index]); } -static unsigned int help_keys_mode_get_num_entries ( const Mode *sw ) -{ - const KeysHelpModePrivateData *pd = (const KeysHelpModePrivateData *) mode_get_private_data ( sw ); - return pd->messages_length; +static unsigned int help_keys_mode_get_num_entries(const Mode *sw) { + const KeysHelpModePrivateData *pd = + (const KeysHelpModePrivateData *)mode_get_private_data(sw); + return pd->messages_length; } #include "mode-private.h" -Mode help_keys_mode = -{ - .name = "keys", - .cfg_name_key = "display-keys", - ._init = help_keys_mode_init, - ._get_num_entries = help_keys_mode_get_num_entries, - ._result = help_keys_mode_result, - ._destroy = help_keys_mode_destroy, - ._token_match = help_keys_token_match, - ._get_completion = NULL, - ._get_display_value = _get_display_value, - .private_data = NULL, - .free = NULL -}; +Mode help_keys_mode = {.name = "keys", + .cfg_name_key = "display-keys", + ._init = help_keys_mode_init, + ._get_num_entries = help_keys_mode_get_num_entries, + ._result = help_keys_mode_result, + ._destroy = help_keys_mode_destroy, + ._token_match = help_keys_token_match, + ._get_completion = NULL, + ._get_display_value = _get_display_value, + .private_data = NULL, + .free = NULL}; diff --git a/source/dialogs/run.c b/source/dialogs/run.c index 90b0c5c1..9a289afc 100644 --- a/source/dialogs/run.c +++ b/source/dialogs/run.c @@ -31,65 +31,63 @@ */ /** The log domain of this dialog. */ -#define G_LOG_DOMAIN "Dialogs.Run" +#define G_LOG_DOMAIN "Dialogs.Run" #include -#include #include +#include -#include +#include +#include #include #include -#include -#include -#include #include -#include +#include +#include +#include -#include "rofi.h" -#include "settings.h" +#include "dialogs/filebrowser.h" +#include "dialogs/run.h" #include "helper.h" #include "history.h" -#include "dialogs/run.h" -#include "dialogs/filebrowser.h" +#include "rofi.h" +#include "settings.h" #include "mode-private.h" -#include "timings.h" #include "rofi-icon-fetcher.h" +#include "timings.h" /** * Name of the history file where previously chosen commands are stored. */ -#define RUN_CACHE_FILE "rofi-3.runcache" +#define RUN_CACHE_FILE "rofi-3.runcache" -typedef struct -{ - char *entry; - uint32_t icon_fetch_uid; - /* Surface holding the icon. */ - cairo_surface_t *icon; +typedef struct { + char *entry; + uint32_t icon_fetch_uid; + /* Surface holding the icon. */ + cairo_surface_t *icon; } RunEntry; /** * The internal data structure holding the private data of the Run Mode. */ -typedef struct -{ - /** list of available commands. */ - RunEntry *cmd_list; - /** Length of the #cmd_list. */ - unsigned int cmd_list_length; +typedef struct { + /** list of available commands. */ + RunEntry *cmd_list; + /** Length of the #cmd_list. */ + unsigned int cmd_list_length; - /** Current mode. */ - gboolean file_complete; - uint32_t selected_line; - char *old_input; + /** Current mode. */ + gboolean file_complete; + uint32_t selected_line; + char *old_input; - Mode *completer; - char *old_completer_input; - /** fallback icon */ - uint32_t fallback_icon_fetch_uid; - cairo_surface_t *fallback_icon; + Mode *completer; + char *old_completer_input; + /** fallback icon */ + uint32_t fallback_icon_fetch_uid; + cairo_surface_t *fallback_icon; } RunModePrivateData; /** @@ -98,40 +96,39 @@ typedef struct * * Execute command and add to history. */ -static gboolean exec_cmd ( const char *cmd, int run_in_term ) -{ - GError *error = NULL; - if ( !cmd || !cmd[0] ) { - return FALSE; - } - gsize lf_cmd_size = 0; - gchar *lf_cmd = g_locale_from_utf8 ( cmd, -1, NULL, &lf_cmd_size, &error ); - if ( error != NULL ) { - g_warning ( "Failed to convert command to locale encoding: %s", error->message ); - g_error_free ( error ); - return FALSE; - } +static gboolean exec_cmd(const char *cmd, int run_in_term) { + GError *error = NULL; + if (!cmd || !cmd[0]) { + return FALSE; + } + gsize lf_cmd_size = 0; + gchar *lf_cmd = g_locale_from_utf8(cmd, -1, NULL, &lf_cmd_size, &error); + if (error != NULL) { + g_warning("Failed to convert command to locale encoding: %s", + error->message); + g_error_free(error); + return FALSE; + } - char *path = g_build_filename ( cache_dir, RUN_CACHE_FILE, NULL ); - RofiHelperExecuteContext context = { .name = NULL }; - // FIXME: assume startup notification support for terminals - if ( helper_execute_command ( NULL, lf_cmd, run_in_term, run_in_term ? &context : NULL ) ) { - /** - * This happens in non-critical time (After launching app) - * It is allowed to be a bit slower. - */ + char *path = g_build_filename(cache_dir, RUN_CACHE_FILE, NULL); + RofiHelperExecuteContext context = {.name = NULL}; + // FIXME: assume startup notification support for terminals + if (helper_execute_command(NULL, lf_cmd, run_in_term, + run_in_term ? &context : NULL)) { + /** + * This happens in non-critical time (After launching app) + * It is allowed to be a bit slower. + */ - history_set ( path, cmd ); - g_free ( path ); - g_free ( lf_cmd ); - return TRUE; - } - else { - history_remove ( path, cmd ); - g_free ( path ); - g_free ( lf_cmd ); - return FALSE; - } + history_set(path, cmd); + g_free(path); + g_free(lf_cmd); + return TRUE; + } + history_remove(path, cmd); + g_free(path); + g_free(lf_cmd); + return FALSE; } /** @@ -139,13 +136,12 @@ static gboolean exec_cmd ( const char *cmd, int run_in_term ) * * Remove command from history. */ -static void delete_entry ( const RunEntry *cmd ) -{ - char *path = g_build_filename ( cache_dir, RUN_CACHE_FILE, NULL ); +static void delete_entry(const RunEntry *cmd) { + char *path = g_build_filename(cache_dir, RUN_CACHE_FILE, NULL); - history_remove ( path, cmd->entry ); + history_remove(path, cmd->entry); - g_free ( path ); + g_free(path); } /** @@ -155,438 +151,435 @@ static void delete_entry ( const RunEntry *cmd ) * * Function used for sorting. * - * @returns returns less then, equal to and greater than zero is a is less than, is a match or greater than b. + * @returns returns less then, equal to and greater than zero is a is less than, + * is a match or greater than b. */ -static int sort_func ( const void *a, const void *b, G_GNUC_UNUSED void *data ) -{ - const RunEntry *astr = ( const RunEntry * ) a; - const RunEntry *bstr = ( const RunEntry * ) b; +static int sort_func(const void *a, const void *b, G_GNUC_UNUSED void *data) { + const RunEntry *astr = (const RunEntry *)a; + const RunEntry *bstr = (const RunEntry *)b; - if ( astr->entry == NULL && bstr->entry == NULL ) { - return 0; - } - else if ( astr->entry == NULL ) { - return 1; - } - else if ( bstr->entry == NULL ) { - return -1; - } - return g_strcmp0 ( astr->entry , bstr->entry ); + if (astr->entry == NULL && bstr->entry == NULL) { + return 0; + } + if (astr->entry == NULL) { + return 1; + } + if (bstr->entry == NULL) { + return -1; + } + return g_strcmp0(astr->entry, bstr->entry); } /** * External spider to get list of executables. */ -static RunEntry * get_apps_external ( RunEntry *retv, unsigned int *length, unsigned int num_favorites ) -{ - int fd = execute_generator ( config.run_list_command ); - if ( fd >= 0 ) { - FILE *inp = fdopen ( fd, "r" ); - if ( inp ) { - char *buffer = NULL; - size_t buffer_length = 0; +static RunEntry *get_apps_external(RunEntry *retv, unsigned int *length, + unsigned int num_favorites) { + int fd = execute_generator(config.run_list_command); + if (fd >= 0) { + FILE *inp = fdopen(fd, "r"); + if (inp) { + char *buffer = NULL; + size_t buffer_length = 0; - while ( getline ( &buffer, &buffer_length, inp ) > 0 ) { - int found = 0; - // Filter out line-end. - if ( buffer[strlen ( buffer ) - 1] == '\n' ) { - buffer[strlen ( buffer ) - 1] = '\0'; - } - - // This is a nice little penalty, but doable? time will tell. - // given num_favorites is max 25. - for ( unsigned int j = 0; found == 0 && j < num_favorites; j++ ) { - if ( strcasecmp ( buffer, retv[j].entry ) == 0 ) { - found = 1; - } - } - - if ( found == 1 ) { - continue; - } - - // No duplicate, add it. - retv = g_realloc ( retv, ( ( *length ) + 2 ) * sizeof ( RunEntry ) ); - retv[( *length )].entry = g_strdup ( buffer ); - retv[( *length )].icon = NULL; - retv[( *length )].icon_fetch_uid = 0; - - ( *length )++; - } - if ( buffer != NULL ) { - free ( buffer ); - } - if ( fclose ( inp ) != 0 ) { - g_warning ( "Failed to close stdout off executor script: '%s'", - g_strerror ( errno ) ); - } + while (getline(&buffer, &buffer_length, inp) > 0) { + int found = 0; + // Filter out line-end. + if (buffer[strlen(buffer) - 1] == '\n') { + buffer[strlen(buffer) - 1] = '\0'; } + + // This is a nice little penalty, but doable? time will tell. + // given num_favorites is max 25. + for (unsigned int j = 0; found == 0 && j < num_favorites; j++) { + if (strcasecmp(buffer, retv[j].entry) == 0) { + found = 1; + } + } + + if (found == 1) { + continue; + } + + // No duplicate, add it. + retv = g_realloc(retv, ((*length) + 2) * sizeof(RunEntry)); + retv[(*length)].entry = g_strdup(buffer); + retv[(*length)].icon = NULL; + retv[(*length)].icon_fetch_uid = 0; + + (*length)++; + } + if (buffer != NULL) { + free(buffer); + } + if (fclose(inp) != 0) { + g_warning("Failed to close stdout off executor script: '%s'", + g_strerror(errno)); + } } - retv[( *length ) ].entry = NULL; - retv[( *length ) ].icon = NULL; - retv[( *length ) ].icon_fetch_uid = 0; - return retv; + } + retv[(*length)].entry = NULL; + retv[(*length)].icon = NULL; + retv[(*length)].icon_fetch_uid = 0; + return retv; } /** * Internal spider used to get list of executables. */ -static RunEntry * get_apps ( unsigned int *length ) -{ - GError *error = NULL; - RunEntry *retv = NULL; - unsigned int num_favorites = 0; - char *path; +static RunEntry *get_apps(unsigned int *length) { + GError *error = NULL; + RunEntry *retv = NULL; + unsigned int num_favorites = 0; + char *path; - if ( g_getenv ( "PATH" ) == NULL ) { - return NULL; + if (g_getenv("PATH") == NULL) { + return NULL; + } + TICK_N("start"); + path = g_build_filename(cache_dir, RUN_CACHE_FILE, NULL); + char **hretv = history_get_list(path, length); + retv = (RunEntry *)g_malloc0((*length + 1) * sizeof(RunEntry)); + for (unsigned int i = 0; i < *length; i++) { + retv[i].entry = hretv[i]; + } + g_free(hretv); + g_free(path); + // Keep track of how many where loaded as favorite. + num_favorites = (*length); + + path = g_strdup(g_getenv("PATH")); + + gsize l = 0; + gchar *homedir = g_locale_to_utf8(g_get_home_dir(), -1, NULL, &l, &error); + if (error != NULL) { + g_debug("Failed to convert homedir to UTF-8: %s", error->message); + for (unsigned int i = 0; retv[i].entry != NULL; i++) { + g_free(retv[i].entry); } - TICK_N ( "start" ); - path = g_build_filename ( cache_dir, RUN_CACHE_FILE, NULL ); - char **hretv = history_get_list ( path, length ); - retv = (RunEntry*)g_malloc0((*length+1)*sizeof(RunEntry)); - for ( unsigned int i = 0; i < *length; i++ ) { - retv[i].entry = hretv[i]; - } - g_free(hretv); - g_free ( path ); - // Keep track of how many where loaded as favorite. - num_favorites = ( *length ); + g_free(retv); + g_clear_error(&error); + g_free(homedir); + return NULL; + } - path = g_strdup ( g_getenv ( "PATH" ) ); + const char *const sep = ":"; + char *strtok_savepointer = NULL; + for (const char *dirname = strtok_r(path, sep, &strtok_savepointer); + dirname != NULL; dirname = strtok_r(NULL, sep, &strtok_savepointer)) { + char *fpath = rofi_expand_path(dirname); + DIR *dir = opendir(fpath); + g_debug("Checking path %s for executable.", fpath); + g_free(fpath); - gsize l = 0; - gchar *homedir = g_locale_to_utf8 ( g_get_home_dir (), -1, NULL, &l, &error ); - if ( error != NULL ) { - g_debug ( "Failed to convert homedir to UTF-8: %s", error->message ); - for ( unsigned int i = 0; retv[i].entry != NULL ; i++ ) { - g_free ( retv[i].entry ); + if (dir != NULL) { + struct dirent *dent; + gsize dirn_len = 0; + gchar *dirn = g_locale_to_utf8(dirname, -1, NULL, &dirn_len, &error); + if (error != NULL) { + g_debug("Failed to convert directory name to UTF-8: %s", + error->message); + g_clear_error(&error); + closedir(dir); + continue; + } + gboolean is_homedir = g_str_has_prefix(dirn, homedir); + g_free(dirn); + + while ((dent = readdir(dir)) != NULL) { + if (dent->d_type != DT_REG && dent->d_type != DT_LNK && + dent->d_type != DT_UNKNOWN) { + continue; } - g_free(retv); - g_clear_error ( &error ); - g_free ( homedir ); - return NULL; - } - - const char *const sep = ":"; - char *strtok_savepointer = NULL; - for ( const char *dirname = strtok_r ( path, sep, &strtok_savepointer ); dirname != NULL; dirname = strtok_r ( NULL, sep, &strtok_savepointer ) ) { - char *fpath = rofi_expand_path ( dirname ); - DIR *dir = opendir ( fpath ); - g_debug ( "Checking path %s for executable.", fpath ); - g_free ( fpath ); - - if ( dir != NULL ) { - struct dirent *dent; - gsize dirn_len = 0; - gchar *dirn = g_locale_to_utf8 ( dirname, -1, NULL, &dirn_len, &error ); - if ( error != NULL ) { - g_debug ( "Failed to convert directory name to UTF-8: %s", error->message ); - g_clear_error ( &error ); - closedir ( dir ); - continue; - } - gboolean is_homedir = g_str_has_prefix ( dirn, homedir ); - g_free ( dirn ); - - while ( ( dent = readdir ( dir ) ) != NULL ) { - if ( dent->d_type != DT_REG && dent->d_type != DT_LNK && dent->d_type != DT_UNKNOWN ) { - continue; - } - // Skip dot files. - if ( dent->d_name[0] == '.' ) { - continue; - } - if ( is_homedir ) { - gchar *fpath = g_build_filename ( dirname, dent->d_name, NULL ); - gboolean b = g_file_test ( fpath, G_FILE_TEST_IS_EXECUTABLE ); - g_free ( fpath ); - if ( !b ) { - continue; - } - } - - gsize name_len; - gchar *name = g_filename_to_utf8 ( dent->d_name, -1, NULL, &name_len, &error ); - if ( error != NULL ) { - g_debug ( "Failed to convert filename to UTF-8: %s", error->message ); - g_clear_error ( &error ); - g_free ( name ); - continue; - } - // This is a nice little penalty, but doable? time will tell. - // given num_favorites is max 25. - int found = 0; - for ( unsigned int j = 0; found == 0 && j < num_favorites; j++ ) { - if ( g_strcmp0 ( name, retv[j].entry ) == 0 ) { - found = 1; - } - } - - if ( found == 1 ) { - g_free ( name ); - continue; - } - - retv = g_realloc ( retv, ( ( *length ) + 2 ) * sizeof ( RunEntry ) ); - retv[( *length )].entry = name; - retv[( *length )].icon = NULL; - retv[( *length )].icon_fetch_uid = 0; - retv[( *length ) + 1].entry = NULL; - retv[( *length ) + 1].icon = NULL; - retv[( *length ) + 1].icon_fetch_uid = 0; - ( *length )++; - } - - closedir ( dir ); + // Skip dot files. + if (dent->d_name[0] == '.') { + continue; } - } - g_free ( homedir ); - - // Get external apps. - if ( config.run_list_command != NULL && config.run_list_command[0] != '\0' ) { - retv = get_apps_external ( retv, length, num_favorites ); - } - // No sorting needed. - if ( ( *length ) == 0 ) { - return retv; - } - // TODO: check this is still fast enough. (takes 1ms on laptop.) - if ( ( *length ) > num_favorites ) { - g_qsort_with_data ( &(retv[num_favorites]), ( *length ) - num_favorites, sizeof ( RunEntry ), sort_func, NULL ); - } - g_free ( path ); - - unsigned int removed = 0; - for ( unsigned int index = num_favorites; index < ( ( *length ) - 1 ); index++ ) { - if ( g_strcmp0 ( retv[index].entry , retv[index + 1].entry ) == 0 ) { - g_free ( retv[index].entry ); - retv[index].entry = NULL; - removed++; + if (is_homedir) { + gchar *fpath = g_build_filename(dirname, dent->d_name, NULL); + gboolean b = g_file_test(fpath, G_FILE_TEST_IS_EXECUTABLE); + g_free(fpath); + if (!b) { + continue; + } } - } - if ( ( *length ) > num_favorites ) { - g_qsort_with_data ( &(retv[num_favorites]), ( *length ) - num_favorites, sizeof ( RunEntry ), - sort_func, - NULL ); - } - // Reduce array length; - ( *length ) -= removed; + gsize name_len; + gchar *name = + g_filename_to_utf8(dent->d_name, -1, NULL, &name_len, &error); + if (error != NULL) { + g_debug("Failed to convert filename to UTF-8: %s", error->message); + g_clear_error(&error); + g_free(name); + continue; + } + // This is a nice little penalty, but doable? time will tell. + // given num_favorites is max 25. + int found = 0; + for (unsigned int j = 0; found == 0 && j < num_favorites; j++) { + if (g_strcmp0(name, retv[j].entry) == 0) { + found = 1; + } + } - TICK_N ( "stop" ); + if (found == 1) { + g_free(name); + continue; + } + + retv = g_realloc(retv, ((*length) + 2) * sizeof(RunEntry)); + retv[(*length)].entry = name; + retv[(*length)].icon = NULL; + retv[(*length)].icon_fetch_uid = 0; + retv[(*length) + 1].entry = NULL; + retv[(*length) + 1].icon = NULL; + retv[(*length) + 1].icon_fetch_uid = 0; + (*length)++; + } + + closedir(dir); + } + } + g_free(homedir); + + // Get external apps. + if (config.run_list_command != NULL && config.run_list_command[0] != '\0') { + retv = get_apps_external(retv, length, num_favorites); + } + // No sorting needed. + if ((*length) == 0) { return retv; + } + // TODO: check this is still fast enough. (takes 1ms on laptop.) + if ((*length) > num_favorites) { + g_qsort_with_data(&(retv[num_favorites]), (*length) - num_favorites, + sizeof(RunEntry), sort_func, NULL); + } + g_free(path); + + unsigned int removed = 0; + for (unsigned int index = num_favorites; index < ((*length) - 1); index++) { + if (g_strcmp0(retv[index].entry, retv[index + 1].entry) == 0) { + g_free(retv[index].entry); + retv[index].entry = NULL; + removed++; + } + } + + if ((*length) > num_favorites) { + g_qsort_with_data(&(retv[num_favorites]), (*length) - num_favorites, + sizeof(RunEntry), sort_func, NULL); + } + // Reduce array length; + (*length) -= removed; + + TICK_N("stop"); + return retv; } -static int run_mode_init ( Mode *sw ) -{ - if ( sw->private_data == NULL ) { - RunModePrivateData *pd = g_malloc0 ( sizeof ( *pd ) ); - sw->private_data = (void *) pd; - pd->cmd_list = get_apps ( &( pd->cmd_list_length ) ); - pd->completer = create_new_file_browser (); - mode_init ( pd->completer ); - } +static int run_mode_init(Mode *sw) { + if (sw->private_data == NULL) { + RunModePrivateData *pd = g_malloc0(sizeof(*pd)); + sw->private_data = (void *)pd; + pd->cmd_list = get_apps(&(pd->cmd_list_length)); + pd->completer = create_new_file_browser(); + mode_init(pd->completer); + } - return TRUE; + return TRUE; } -static void run_mode_destroy ( Mode *sw ) -{ - RunModePrivateData *rmpd = (RunModePrivateData *) sw->private_data; - if ( rmpd != NULL ) { - for ( unsigned int i = 0; i < rmpd->cmd_list_length; i++ ) { - g_free ( rmpd->cmd_list[i].entry ); - if ( rmpd->cmd_list[i].icon != NULL ) { - cairo_surface_destroy ( rmpd->cmd_list[i].icon ); - } - } - g_free ( rmpd->cmd_list ); - g_free ( rmpd->old_input ); - g_free ( rmpd->old_completer_input ); - mode_destroy ( rmpd->completer ); - g_free ( rmpd ); - sw->private_data = NULL; +static void run_mode_destroy(Mode *sw) { + RunModePrivateData *rmpd = (RunModePrivateData *)sw->private_data; + if (rmpd != NULL) { + for (unsigned int i = 0; i < rmpd->cmd_list_length; i++) { + g_free(rmpd->cmd_list[i].entry); + if (rmpd->cmd_list[i].icon != NULL) { + cairo_surface_destroy(rmpd->cmd_list[i].icon); + } } + g_free(rmpd->cmd_list); + g_free(rmpd->old_input); + g_free(rmpd->old_completer_input); + mode_destroy(rmpd->completer); + g_free(rmpd); + sw->private_data = NULL; + } } -static unsigned int run_mode_get_num_entries ( const Mode *sw ) -{ - const RunModePrivateData *rmpd = (const RunModePrivateData *) sw->private_data; - if ( rmpd->file_complete ) { - return rmpd->completer->_get_num_entries( rmpd->completer ); - } - return rmpd->cmd_list_length; +static unsigned int run_mode_get_num_entries(const Mode *sw) { + const RunModePrivateData *rmpd = (const RunModePrivateData *)sw->private_data; + if (rmpd->file_complete) { + return rmpd->completer->_get_num_entries(rmpd->completer); + } + return rmpd->cmd_list_length; } -static ModeMode run_mode_result ( Mode *sw, int mretv, char **input, unsigned int selected_line ) -{ - RunModePrivateData *rmpd = (RunModePrivateData *) sw->private_data; - ModeMode retv = MODE_EXIT; +static ModeMode run_mode_result(Mode *sw, int mretv, char **input, + unsigned int selected_line) { + RunModePrivateData *rmpd = (RunModePrivateData *)sw->private_data; + ModeMode retv = MODE_EXIT; - gboolean run_in_term = ( ( mretv & MENU_CUSTOM_ACTION ) == MENU_CUSTOM_ACTION ); - if ( rmpd->file_complete == TRUE ) { + gboolean run_in_term = ((mretv & MENU_CUSTOM_ACTION) == MENU_CUSTOM_ACTION); + if (rmpd->file_complete == TRUE) { - retv = RELOAD_DIALOG; + retv = RELOAD_DIALOG; - if ( ( mretv& (MENU_COMPLETE)) ) { - g_free ( rmpd->old_completer_input ); - rmpd->old_completer_input = *input; - *input = NULL; - if ( rmpd->selected_line < rmpd->cmd_list_length ) { - (*input) = g_strdup ( rmpd->old_input ); - } - rmpd->file_complete = FALSE; - } - else if ( (mretv&MENU_CANCEL) ) { - retv = MODE_EXIT; - } - else { - char *path = NULL; - retv = file_browser_mode_completer ( rmpd->completer, mretv, input, selected_line, &path ); - if ( retv == MODE_EXIT ) { - if ( path == NULL ) { - exec_cmd ( rmpd->cmd_list[rmpd->selected_line].entry, run_in_term ); - } - else { - char *arg= g_strdup_printf ( "%s '%s'", rmpd->cmd_list[rmpd->selected_line].entry, path); - exec_cmd ( arg, run_in_term ); - g_free(arg); - } - - } - g_free (path); - } - return retv; - } - - if ( ( mretv & MENU_OK ) && rmpd->cmd_list[selected_line].entry != NULL ) { - if ( !exec_cmd ( rmpd->cmd_list[selected_line].entry, run_in_term ) ) { - retv = RELOAD_DIALOG; - } - } - else if ( ( mretv & MENU_CUSTOM_INPUT ) && *input != NULL && *input[0] != '\0' ) { - if ( !exec_cmd ( *input, run_in_term ) ) { - retv = RELOAD_DIALOG; - } - } - else if ( ( mretv & MENU_ENTRY_DELETE ) && rmpd->cmd_list[selected_line].entry ) { - delete_entry ( &(rmpd->cmd_list[selected_line]) ); - - // Clear the list. - retv = RELOAD_DIALOG; - run_mode_destroy ( sw ); - run_mode_init ( sw ); - } - else if ( mretv & MENU_CUSTOM_COMMAND ) { - retv = ( mretv & MENU_LOWER_MASK ); - } - else if ( ( mretv& MENU_COMPLETE) ) { - retv = RELOAD_DIALOG; - if ( selected_line < rmpd->cmd_list_length ) { - rmpd->selected_line = selected_line; - - g_free ( rmpd->old_input ); - rmpd->old_input = g_strdup ( *input ); - - if ( *input ) g_free (*input); - *input = g_strdup ( rmpd->old_completer_input ); - - rmpd->file_complete = TRUE; + if ((mretv & (MENU_COMPLETE))) { + g_free(rmpd->old_completer_input); + rmpd->old_completer_input = *input; + *input = NULL; + if (rmpd->selected_line < rmpd->cmd_list_length) { + (*input) = g_strdup(rmpd->old_input); + } + rmpd->file_complete = FALSE; + } else if ((mretv & MENU_CANCEL)) { + retv = MODE_EXIT; + } else { + char *path = NULL; + retv = file_browser_mode_completer(rmpd->completer, mretv, input, + selected_line, &path); + if (retv == MODE_EXIT) { + if (path == NULL) { + exec_cmd(rmpd->cmd_list[rmpd->selected_line].entry, run_in_term); + } else { + char *arg = g_strdup_printf( + "%s '%s'", rmpd->cmd_list[rmpd->selected_line].entry, path); + exec_cmd(arg, run_in_term); + g_free(arg); } + } + g_free(path); } return retv; + } + + if ((mretv & MENU_OK) && rmpd->cmd_list[selected_line].entry != NULL) { + if (!exec_cmd(rmpd->cmd_list[selected_line].entry, run_in_term)) { + retv = RELOAD_DIALOG; + } + } else if ((mretv & MENU_CUSTOM_INPUT) && *input != NULL && + *input[0] != '\0') { + if (!exec_cmd(*input, run_in_term)) { + retv = RELOAD_DIALOG; + } + } else if ((mretv & MENU_ENTRY_DELETE) && + rmpd->cmd_list[selected_line].entry) { + delete_entry(&(rmpd->cmd_list[selected_line])); + + // Clear the list. + retv = RELOAD_DIALOG; + run_mode_destroy(sw); + run_mode_init(sw); + } else if (mretv & MENU_CUSTOM_COMMAND) { + retv = (mretv & MENU_LOWER_MASK); + } else if ((mretv & MENU_COMPLETE)) { + retv = RELOAD_DIALOG; + if (selected_line < rmpd->cmd_list_length) { + rmpd->selected_line = selected_line; + + g_free(rmpd->old_input); + rmpd->old_input = g_strdup(*input); + + if (*input) + g_free(*input); + *input = g_strdup(rmpd->old_completer_input); + + rmpd->file_complete = TRUE; + } + } + return retv; } -static char *_get_display_value ( const Mode *sw, unsigned int selected_line, G_GNUC_UNUSED int *state, G_GNUC_UNUSED GList **list, int get_entry ) -{ - const RunModePrivateData *rmpd = (const RunModePrivateData *) sw->private_data; - if ( rmpd->file_complete ) { - return rmpd->completer->_get_display_value (rmpd->completer, selected_line, state, list, get_entry ); - } - return get_entry ? g_strdup ( rmpd->cmd_list[selected_line].entry ) : NULL; +static char *_get_display_value(const Mode *sw, unsigned int selected_line, + G_GNUC_UNUSED int *state, + G_GNUC_UNUSED GList **list, int get_entry) { + const RunModePrivateData *rmpd = (const RunModePrivateData *)sw->private_data; + if (rmpd->file_complete) { + return rmpd->completer->_get_display_value(rmpd->completer, selected_line, + state, list, get_entry); + } + return get_entry ? g_strdup(rmpd->cmd_list[selected_line].entry) : NULL; } -static int run_token_match ( const Mode *sw, rofi_int_matcher **tokens, unsigned int index ) -{ - const RunModePrivateData *rmpd = (const RunModePrivateData *) sw->private_data; - if ( rmpd->file_complete ) { - return rmpd->completer->_token_match (rmpd->completer, tokens, index ); - } - return helper_token_match ( tokens, rmpd->cmd_list[index].entry ); +static int run_token_match(const Mode *sw, rofi_int_matcher **tokens, + unsigned int index) { + const RunModePrivateData *rmpd = (const RunModePrivateData *)sw->private_data; + if (rmpd->file_complete) { + return rmpd->completer->_token_match(rmpd->completer, tokens, index); + } + return helper_token_match(tokens, rmpd->cmd_list[index].entry); } -static char *run_get_message ( const Mode *sw ) -{ - RunModePrivateData *pd = sw->private_data; - if ( pd->file_complete ) { - if ( pd->selected_line < pd->cmd_list_length ) { - char *msg = mode_get_message ( pd->completer); - if ( msg ) { - char *retv = g_strdup_printf("File complete for: %s\n%s", pd->cmd_list[pd->selected_line].entry, msg); - g_free (msg); - return retv; - } - return g_strdup_printf("File complete for: %s", pd->cmd_list[pd->selected_line].entry); - } +static char *run_get_message(const Mode *sw) { + RunModePrivateData *pd = sw->private_data; + if (pd->file_complete) { + if (pd->selected_line < pd->cmd_list_length) { + char *msg = mode_get_message(pd->completer); + if (msg) { + char *retv = + g_strdup_printf("File complete for: %s\n%s", + pd->cmd_list[pd->selected_line].entry, msg); + g_free(msg); + return retv; + } + return g_strdup_printf("File complete for: %s", + pd->cmd_list[pd->selected_line].entry); } - return NULL; + } + return NULL; } -static cairo_surface_t *fallback_icon ( RunModePrivateData *pd, int height ) -{ - if ( config.application_fallback_icon ) { - // FALLBACK - if ( pd->fallback_icon_fetch_uid > 0 ) { - return rofi_icon_fetcher_get ( pd->fallback_icon_fetch_uid ); - } - pd->fallback_icon_fetch_uid = rofi_icon_fetcher_query ( config.application_fallback_icon, height ); +static cairo_surface_t *fallback_icon(RunModePrivateData *pd, int height) { + if (config.application_fallback_icon) { + // FALLBACK + if (pd->fallback_icon_fetch_uid > 0) { + return rofi_icon_fetcher_get(pd->fallback_icon_fetch_uid); } - return NULL; + pd->fallback_icon_fetch_uid = + rofi_icon_fetcher_query(config.application_fallback_icon, height); + } + return NULL; +} +static cairo_surface_t *_get_icon(const Mode *sw, unsigned int selected_line, + int height) { + RunModePrivateData *pd = (RunModePrivateData *)mode_get_private_data(sw); + if (pd->file_complete) { + return pd->completer->_get_icon(pd->completer, selected_line, height); + } + g_return_val_if_fail(pd->cmd_list != NULL, NULL); + RunEntry *dr = &(pd->cmd_list[selected_line]); -} -static cairo_surface_t *_get_icon ( const Mode *sw, unsigned int selected_line, int height ) -{ - RunModePrivateData *pd = (RunModePrivateData *) mode_get_private_data ( sw ); - if ( pd->file_complete ) { - return pd->completer->_get_icon ( pd->completer, selected_line, height ); + if (dr->icon_fetch_uid > 0) { + cairo_surface_t *icon = rofi_icon_fetcher_get(dr->icon_fetch_uid); + if (icon) { + return icon; } - g_return_val_if_fail ( pd->cmd_list != NULL, NULL ); - RunEntry *dr = &( pd->cmd_list[selected_line] ); - - if ( dr->icon_fetch_uid > 0 ) { - cairo_surface_t *icon = rofi_icon_fetcher_get ( dr->icon_fetch_uid ); - if ( icon ) { - return icon; - } - return fallback_icon ( pd, height ); + return fallback_icon(pd, height); + } + /** lookup icon */ + char **str = g_strsplit(dr->entry, " ", 2); + if (str) { + dr->icon_fetch_uid = rofi_icon_fetcher_query(str[0], height); + g_strfreev(str); + cairo_surface_t *icon = rofi_icon_fetcher_get(dr->icon_fetch_uid); + if (icon) { + return icon; } - /** lookup icon */ - char ** str = g_strsplit(dr->entry, " ", 2); - if ( str ) { - dr->icon_fetch_uid = rofi_icon_fetcher_query ( str[0], height ); - g_strfreev ( str ); - cairo_surface_t *icon = rofi_icon_fetcher_get ( dr->icon_fetch_uid ); - if ( icon ) { - return icon; - } - } - return fallback_icon ( pd, height ); + } + return fallback_icon(pd, height); } #include "mode-private.h" -Mode run_mode = -{ - .name = "run", - .cfg_name_key = "display-run", - ._init = run_mode_init, - ._get_num_entries = run_mode_get_num_entries, - ._result = run_mode_result, - ._destroy = run_mode_destroy, - ._token_match = run_token_match, - ._get_message = run_get_message, - ._get_display_value = _get_display_value, - ._get_icon = _get_icon, - ._get_completion = NULL, - ._preprocess_input = NULL, - .private_data = NULL, - .free = NULL -}; +Mode run_mode = {.name = "run", + .cfg_name_key = "display-run", + ._init = run_mode_init, + ._get_num_entries = run_mode_get_num_entries, + ._result = run_mode_result, + ._destroy = run_mode_destroy, + ._token_match = run_token_match, + ._get_message = run_get_message, + ._get_display_value = _get_display_value, + ._get_icon = _get_icon, + ._get_completion = NULL, + ._preprocess_input = NULL, + .private_data = NULL, + .free = NULL}; /** @}*/ diff --git a/source/dialogs/script.c b/source/dialogs/script.c index 99b7ac6c..a23e528d 100644 --- a/source/dialogs/script.c +++ b/source/dialogs/script.c @@ -26,20 +26,19 @@ */ /** The log domain of this dialog. */ -#define G_LOG_DOMAIN "Dialogs.Script" +#define G_LOG_DOMAIN "Dialogs.Script" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "rofi.h" #include "dialogs/script.h" #include "helper.h" +#include "rofi.h" +#include +#include +#include +#include +#include +#include +#include +#include #include "widgets/textbox.h" @@ -49,424 +48,415 @@ #include "dialogs/dmenuscriptshared.h" -typedef struct -{ - /** ID of the current script. */ - unsigned int id; - /** List of visible items. */ - DmenuScriptEntry *cmd_list; - /** length list of visible items. */ - unsigned int cmd_list_length; +typedef struct { + /** ID of the current script. */ + unsigned int id; + /** List of visible items. */ + DmenuScriptEntry *cmd_list; + /** length list of visible items. */ + unsigned int cmd_list_length; - /** Urgent list */ - struct rofi_range_pair * urgent_list; - unsigned int num_urgent_list; - /** Active list */ - struct rofi_range_pair * active_list; - unsigned int num_active_list; - /** Configuration settings. */ - char *message; - char *prompt; - gboolean do_markup; - char delim; - /** no custom */ - gboolean no_custom; + /** Urgent list */ + struct rofi_range_pair *urgent_list; + unsigned int num_urgent_list; + /** Active list */ + struct rofi_range_pair *active_list; + unsigned int num_active_list; + /** Configuration settings. */ + char *message; + char *prompt; + gboolean do_markup; + char delim; + /** no custom */ + gboolean no_custom; - gboolean use_hot_keys; + gboolean use_hot_keys; } ScriptModePrivateData; /** * Shared function between DMENU and Script mode. */ -void dmenuscript_parse_entry_extras ( G_GNUC_UNUSED Mode *sw, DmenuScriptEntry *entry, char *buffer, G_GNUC_UNUSED size_t length ) -{ - gchar **extras = g_strsplit ( buffer, "\x1f", -1 ); - gchar **extra; - for ( extra = extras; *extra != NULL && *( extra + 1 ) != NULL; extra += 2 ) { - gchar *key = *extra; - gchar *value = *( extra + 1 ); - if ( strcasecmp ( key, "icon" ) == 0 ) { - entry->icon_name = value; - } - else if ( strcasecmp ( key, "meta" ) == 0 ) { - entry->meta = value; - } - else if ( strcasecmp ( key, "info" ) == 0 ) { - entry->info = value; - } - else if ( strcasecmp ( key, "nonselectable" ) == 0 ) { - entry->nonselectable = strcasecmp ( value, "true" ) == 0; - g_free ( value ); - } - else { - g_free ( value ); - } - g_free ( key ); +void dmenuscript_parse_entry_extras(G_GNUC_UNUSED Mode *sw, + DmenuScriptEntry *entry, char *buffer, + G_GNUC_UNUSED size_t length) { + gchar **extras = g_strsplit(buffer, "\x1f", -1); + gchar **extra; + for (extra = extras; *extra != NULL && *(extra + 1) != NULL; extra += 2) { + gchar *key = *extra; + gchar *value = *(extra + 1); + if (strcasecmp(key, "icon") == 0) { + entry->icon_name = value; + } else if (strcasecmp(key, "meta") == 0) { + entry->meta = value; + } else if (strcasecmp(key, "info") == 0) { + entry->info = value; + } else if (strcasecmp(key, "nonselectable") == 0) { + entry->nonselectable = strcasecmp(value, "true") == 0; + g_free(value); + } else { + g_free(value); } - g_free ( extras ); + g_free(key); + } + g_free(extras); } /** * End of shared functions. */ -static void parse_header_entry ( Mode *sw, char *line, ssize_t length ) -{ - ScriptModePrivateData *pd = (ScriptModePrivateData *) sw->private_data; - ssize_t length_key = 0;//strlen ( line ); - while ( length_key < length && line[length_key] != '\x1f' ) { - length_key++; - } +static void parse_header_entry(Mode *sw, char *line, ssize_t length) { + ScriptModePrivateData *pd = (ScriptModePrivateData *)sw->private_data; + ssize_t length_key = 0; // strlen ( line ); + while (length_key < length && line[length_key] != '\x1f') { + length_key++; + } - if ( ( length_key + 1 ) < length ) { - line[length_key] = '\0'; - char *value = line + length_key + 1; - if ( strcasecmp ( line, "message" ) == 0 ) { - g_free ( pd->message ); - pd->message = strlen ( value ) ? g_strdup ( value ) : NULL; - } - else if ( strcasecmp ( line, "prompt" ) == 0 ) { - g_free ( pd->prompt ); - pd->prompt = g_strdup ( value ); - sw->display_name = pd->prompt; - } - else if ( strcasecmp ( line, "markup-rows" ) == 0 ) { - pd->do_markup = ( strcasecmp ( value, "true" ) == 0 ); - } - else if ( strcasecmp ( line, "urgent" ) == 0 ) { - parse_ranges ( value, &( pd->urgent_list ), &( pd->num_urgent_list ) ); - } - else if ( strcasecmp ( line, "active" ) == 0 ) { - parse_ranges ( value, &( pd->active_list ), &( pd->num_active_list ) ); - } - else if ( strcasecmp ( line, "delim" ) == 0 ) { - pd->delim = helper_parse_char ( value ); - } - else if ( strcasecmp ( line, "no-custom" ) == 0 ) { - pd->no_custom = ( strcasecmp ( value, "true" ) == 0 ); - } - else if ( strcasecmp ( line, "use-hot-keys" ) == 0 ) { - pd->use_hot_keys = ( strcasecmp ( value, "true" ) == 0 ); - } + if ((length_key + 1) < length) { + line[length_key] = '\0'; + char *value = line + length_key + 1; + if (strcasecmp(line, "message") == 0) { + g_free(pd->message); + pd->message = strlen(value) ? g_strdup(value) : NULL; + } else if (strcasecmp(line, "prompt") == 0) { + g_free(pd->prompt); + pd->prompt = g_strdup(value); + sw->display_name = pd->prompt; + } else if (strcasecmp(line, "markup-rows") == 0) { + pd->do_markup = (strcasecmp(value, "true") == 0); + } else if (strcasecmp(line, "urgent") == 0) { + parse_ranges(value, &(pd->urgent_list), &(pd->num_urgent_list)); + } else if (strcasecmp(line, "active") == 0) { + parse_ranges(value, &(pd->active_list), &(pd->num_active_list)); + } else if (strcasecmp(line, "delim") == 0) { + pd->delim = helper_parse_char(value); + } else if (strcasecmp(line, "no-custom") == 0) { + pd->no_custom = (strcasecmp(value, "true") == 0); + } else if (strcasecmp(line, "use-hot-keys") == 0) { + pd->use_hot_keys = (strcasecmp(value, "true") == 0); } + } } -static DmenuScriptEntry *execute_executor ( Mode *sw, char *arg, unsigned int *length, int value, DmenuScriptEntry *entry ) -{ - ScriptModePrivateData *pd = (ScriptModePrivateData *) sw->private_data; - int fd = -1; - GError *error = NULL; - DmenuScriptEntry *retv = NULL; - char **argv = NULL; - int argc = 0; - *length = 0; +static DmenuScriptEntry *execute_executor(Mode *sw, char *arg, + unsigned int *length, int value, + DmenuScriptEntry *entry) { + ScriptModePrivateData *pd = (ScriptModePrivateData *)sw->private_data; + int fd = -1; + GError *error = NULL; + DmenuScriptEntry *retv = NULL; + char **argv = NULL; + int argc = 0; + *length = 0; - // Environment - char ** env = g_get_environ (); + // Environment + char **env = g_get_environ(); - char *str_value = g_strdup_printf ( "%d", value ); - env = g_environ_setenv ( env, "ROFI_RETV", str_value, TRUE ); - g_free ( str_value ); + char *str_value = g_strdup_printf("%d", value); + env = g_environ_setenv(env, "ROFI_RETV", str_value, TRUE); + g_free(str_value); - str_value = g_strdup_printf ( "%d", (int) getpid () ); - env = g_environ_setenv ( env, "ROFI_OUTSIDE", str_value, TRUE ); - g_free ( str_value ); + str_value = g_strdup_printf("%d", (int)getpid()); + env = g_environ_setenv(env, "ROFI_OUTSIDE", str_value, TRUE); + g_free(str_value); - if ( entry && entry->info ) { - env = g_environ_setenv ( env, "ROFI_INFO", entry->info, TRUE ); - } + if (entry && entry->info) { + env = g_environ_setenv(env, "ROFI_INFO", entry->info, TRUE); + } - if ( g_shell_parse_argv ( sw->ed, &argc, &argv, &error ) ) { - argv = g_realloc ( argv, ( argc + 2 ) * sizeof ( char* ) ); - argv[argc] = g_strdup ( arg ); - argv[argc + 1] = NULL; - g_spawn_async_with_pipes ( NULL, argv, env, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL, &fd, NULL, &error ); - } - g_strfreev ( env ); - if ( error != NULL ) { - char *msg = g_strdup_printf ( "Failed to execute: '%s'\nError: '%s'", (char *) sw->ed, error->message ); - rofi_view_error_dialog ( msg, FALSE ); - g_free ( msg ); - // print error. - g_error_free ( error ); - fd = -1; - } - if ( fd >= 0 ) { - FILE *inp = fdopen ( fd, "r" ); - if ( inp ) { - char *buffer = NULL; - size_t buffer_length = 0; - ssize_t read_length = 0; - size_t actual_size = 0; - while ( ( read_length = getdelim ( &buffer, &buffer_length, pd->delim, inp ) ) > 0 ) { - // Filter out line-end. - if ( buffer[read_length - 1] == pd->delim ) { - buffer[read_length - 1] = '\0'; - } - if ( buffer[0] == '\0' ) { - parse_header_entry ( sw, &buffer[1], read_length - 1 ); - } - else { - if ( actual_size < ( ( *length ) + 2 ) ) { - actual_size += 256; - retv = g_realloc ( retv, ( actual_size ) * sizeof ( DmenuScriptEntry ) ); - } - size_t buf_length = strlen ( buffer ) + 1; - retv[( *length )].entry = g_memdup ( buffer, buf_length ); - retv[( *length )].icon_name = NULL; - retv[( *length )].meta = NULL; - retv[( *length )].info = NULL; - retv[( *length )].icon_fetch_uid = 0; - retv[( *length )].nonselectable = FALSE; - if ( buf_length > 0 && ( read_length > (ssize_t) buf_length ) ) { - dmenuscript_parse_entry_extras ( sw, &( retv[( *length )] ), buffer + buf_length, read_length - buf_length ); - } - retv[( *length ) + 1].entry = NULL; - ( *length )++; - } - } - if ( buffer ) { - free ( buffer ); - } - if ( fclose ( inp ) != 0 ) { - g_warning ( "Failed to close stdout off executor script: '%s'", - g_strerror ( errno ) ); - } + if (g_shell_parse_argv(sw->ed, &argc, &argv, &error)) { + argv = g_realloc(argv, (argc + 2) * sizeof(char *)); + argv[argc] = g_strdup(arg); + argv[argc + 1] = NULL; + g_spawn_async_with_pipes(NULL, argv, env, G_SPAWN_SEARCH_PATH, NULL, NULL, + NULL, NULL, &fd, NULL, &error); + } + g_strfreev(env); + if (error != NULL) { + char *msg = g_strdup_printf("Failed to execute: '%s'\nError: '%s'", + (char *)sw->ed, error->message); + rofi_view_error_dialog(msg, FALSE); + g_free(msg); + // print error. + g_error_free(error); + fd = -1; + } + if (fd >= 0) { + FILE *inp = fdopen(fd, "r"); + if (inp) { + char *buffer = NULL; + size_t buffer_length = 0; + ssize_t read_length = 0; + size_t actual_size = 0; + while ((read_length = getdelim(&buffer, &buffer_length, pd->delim, inp)) > + 0) { + // Filter out line-end. + if (buffer[read_length - 1] == pd->delim) { + buffer[read_length - 1] = '\0'; } + if (buffer[0] == '\0') { + parse_header_entry(sw, &buffer[1], read_length - 1); + } else { + if (actual_size < ((*length) + 2)) { + actual_size += 256; + retv = g_realloc(retv, (actual_size) * sizeof(DmenuScriptEntry)); + } + size_t buf_length = strlen(buffer) + 1; + retv[(*length)].entry = g_memdup(buffer, buf_length); + retv[(*length)].icon_name = NULL; + retv[(*length)].meta = NULL; + retv[(*length)].info = NULL; + retv[(*length)].icon_fetch_uid = 0; + retv[(*length)].nonselectable = FALSE; + if (buf_length > 0 && (read_length > (ssize_t)buf_length)) { + dmenuscript_parse_entry_extras(sw, &(retv[(*length)]), + buffer + buf_length, + read_length - buf_length); + } + retv[(*length) + 1].entry = NULL; + (*length)++; + } + } + if (buffer) { + free(buffer); + } + if (fclose(inp) != 0) { + g_warning("Failed to close stdout off executor script: '%s'", + g_strerror(errno)); + } } - g_strfreev ( argv ); - return retv; + } + g_strfreev(argv); + return retv; } -static void script_switcher_free ( Mode *sw ) -{ - if ( sw == NULL ) { - return; - } - g_free ( sw->name ); - g_free ( sw->ed ); - g_free ( sw ); +static void script_switcher_free(Mode *sw) { + if (sw == NULL) { + return; + } + g_free(sw->name); + g_free(sw->ed); + g_free(sw); } -static int script_mode_init ( Mode *sw ) -{ - if ( sw->private_data == NULL ) { - ScriptModePrivateData *pd = g_malloc0 ( sizeof ( *pd ) ); - pd->delim = '\n'; - sw->private_data = (void *) pd; - pd->cmd_list = execute_executor ( sw, NULL, &( pd->cmd_list_length ), 0, NULL ); - } - return TRUE; +static int script_mode_init(Mode *sw) { + if (sw->private_data == NULL) { + ScriptModePrivateData *pd = g_malloc0(sizeof(*pd)); + pd->delim = '\n'; + sw->private_data = (void *)pd; + pd->cmd_list = execute_executor(sw, NULL, &(pd->cmd_list_length), 0, NULL); + } + return TRUE; } -static unsigned int script_mode_get_num_entries ( const Mode *sw ) -{ - const ScriptModePrivateData *rmpd = (const ScriptModePrivateData *) sw->private_data; - return rmpd->cmd_list_length; +static unsigned int script_mode_get_num_entries(const Mode *sw) { + const ScriptModePrivateData *rmpd = + (const ScriptModePrivateData *)sw->private_data; + return rmpd->cmd_list_length; } -static void script_mode_reset_highlight ( Mode *sw ) -{ - ScriptModePrivateData *rmpd = (ScriptModePrivateData *) sw->private_data; +static void script_mode_reset_highlight(Mode *sw) { + ScriptModePrivateData *rmpd = (ScriptModePrivateData *)sw->private_data; - rmpd->num_urgent_list = 0; - g_free ( rmpd->urgent_list ); - rmpd->urgent_list = NULL; - rmpd->num_active_list = 0; - g_free ( rmpd->active_list ); - rmpd->active_list = NULL; + rmpd->num_urgent_list = 0; + g_free(rmpd->urgent_list); + rmpd->urgent_list = NULL; + rmpd->num_active_list = 0; + g_free(rmpd->active_list); + rmpd->active_list = NULL; } -static ModeMode script_mode_result ( Mode *sw, int mretv, char **input, unsigned int selected_line ) -{ - ScriptModePrivateData *rmpd = (ScriptModePrivateData *) sw->private_data; - ModeMode retv = MODE_EXIT; - DmenuScriptEntry *new_list = NULL; - unsigned int new_length = 0; +static ModeMode script_mode_result(Mode *sw, int mretv, char **input, + unsigned int selected_line) { + ScriptModePrivateData *rmpd = (ScriptModePrivateData *)sw->private_data; + ModeMode retv = MODE_EXIT; + DmenuScriptEntry *new_list = NULL; + unsigned int new_length = 0; - if ( ( mretv & MENU_CUSTOM_COMMAND ) ) { - if ( rmpd->use_hot_keys ) { - script_mode_reset_highlight ( sw ); - if ( selected_line != UINT32_MAX ) { - new_list = execute_executor ( sw, rmpd->cmd_list[selected_line].entry, &new_length, 10 + ( mretv & MENU_LOWER_MASK ), &( rmpd->cmd_list[selected_line] ) ); - } - else { - if ( rmpd->no_custom == FALSE ) { - new_list = execute_executor ( sw, *input, &new_length, 10 + ( mretv & MENU_LOWER_MASK ), NULL ); - } - else { - return RELOAD_DIALOG; - } - } - } - else { - retv = ( mretv & MENU_LOWER_MASK ); - return retv; + if ((mretv & MENU_CUSTOM_COMMAND)) { + if (rmpd->use_hot_keys) { + script_mode_reset_highlight(sw); + if (selected_line != UINT32_MAX) { + new_list = execute_executor(sw, rmpd->cmd_list[selected_line].entry, + &new_length, 10 + (mretv & MENU_LOWER_MASK), + &(rmpd->cmd_list[selected_line])); + } else { + if (rmpd->no_custom == FALSE) { + new_list = execute_executor(sw, *input, &new_length, + 10 + (mretv & MENU_LOWER_MASK), NULL); + } else { + return RELOAD_DIALOG; } + } + } else { + retv = (mretv & MENU_LOWER_MASK); + return retv; } - else if ( ( mretv & MENU_OK ) && rmpd->cmd_list[selected_line].entry != NULL ) { - if ( rmpd->cmd_list[selected_line].nonselectable ) { - return RELOAD_DIALOG; - } - script_mode_reset_highlight ( sw ); - new_list = execute_executor ( sw, rmpd->cmd_list[selected_line].entry, &new_length, 1, &( rmpd->cmd_list[selected_line] ) ); + } else if ((mretv & MENU_OK) && rmpd->cmd_list[selected_line].entry != NULL) { + if (rmpd->cmd_list[selected_line].nonselectable) { + return RELOAD_DIALOG; } - else if ( ( mretv & MENU_CUSTOM_INPUT ) && *input != NULL && *input[0] != '\0' ) { - if ( rmpd->no_custom == FALSE ) { - script_mode_reset_highlight ( sw ); - new_list = execute_executor ( sw, *input, &new_length, 2, NULL ); - } - else { - return RELOAD_DIALOG; - } + script_mode_reset_highlight(sw); + new_list = + execute_executor(sw, rmpd->cmd_list[selected_line].entry, &new_length, + 1, &(rmpd->cmd_list[selected_line])); + } else if ((mretv & MENU_CUSTOM_INPUT) && *input != NULL && + *input[0] != '\0') { + if (rmpd->no_custom == FALSE) { + script_mode_reset_highlight(sw); + new_list = execute_executor(sw, *input, &new_length, 2, NULL); + } else { + return RELOAD_DIALOG; } + } - // If a new list was generated, use that an loop around. - if ( new_list != NULL ) { - for ( unsigned int i = 0; i < rmpd->cmd_list_length; i++ ) { - g_free ( rmpd->cmd_list[i].entry ); - g_free ( rmpd->cmd_list[i].icon_name ); - g_free ( rmpd->cmd_list[i].meta ); - } - g_free ( rmpd->cmd_list ); - - rmpd->cmd_list = new_list; - rmpd->cmd_list_length = new_length; - retv = RESET_DIALOG; + // If a new list was generated, use that an loop around. + if (new_list != NULL) { + for (unsigned int i = 0; i < rmpd->cmd_list_length; i++) { + g_free(rmpd->cmd_list[i].entry); + g_free(rmpd->cmd_list[i].icon_name); + g_free(rmpd->cmd_list[i].meta); } - return retv; + g_free(rmpd->cmd_list); + + rmpd->cmd_list = new_list; + rmpd->cmd_list_length = new_length; + retv = RESET_DIALOG; + } + return retv; } -static void script_mode_destroy ( Mode *sw ) -{ - ScriptModePrivateData *rmpd = (ScriptModePrivateData *) sw->private_data; - if ( rmpd != NULL ) { - for ( unsigned int i = 0; i < rmpd->cmd_list_length; i++ ) { - g_free ( rmpd->cmd_list[i].entry ); - g_free ( rmpd->cmd_list[i].icon_name ); - g_free ( rmpd->cmd_list[i].meta ); - } - g_free ( rmpd->cmd_list ); - g_free ( rmpd->message ); - g_free ( rmpd->prompt ); - g_free ( rmpd->urgent_list ); - g_free ( rmpd->active_list ); - g_free ( rmpd ); - sw->private_data = NULL; +static void script_mode_destroy(Mode *sw) { + ScriptModePrivateData *rmpd = (ScriptModePrivateData *)sw->private_data; + if (rmpd != NULL) { + for (unsigned int i = 0; i < rmpd->cmd_list_length; i++) { + g_free(rmpd->cmd_list[i].entry); + g_free(rmpd->cmd_list[i].icon_name); + g_free(rmpd->cmd_list[i].meta); } + g_free(rmpd->cmd_list); + g_free(rmpd->message); + g_free(rmpd->prompt); + g_free(rmpd->urgent_list); + g_free(rmpd->active_list); + g_free(rmpd); + sw->private_data = NULL; + } } -static inline unsigned int get_index ( unsigned int length, int index ) -{ - if ( index >= 0 ) { - return index; - } - if ( ( (unsigned int) -index ) <= length ) { - return length + index; - } - // Out of range. - return UINT_MAX; +static inline unsigned int get_index(unsigned int length, int index) { + if (index >= 0) { + return index; + } + if (((unsigned int)-index) <= length) { + return length + index; + } + // Out of range. + return UINT_MAX; } -static char *_get_display_value ( const Mode *sw, unsigned int selected_line, G_GNUC_UNUSED int *state, G_GNUC_UNUSED GList **list, int get_entry ) -{ - ScriptModePrivateData *pd = sw->private_data; - for ( unsigned int i = 0; i < pd->num_active_list; i++ ) { - unsigned int start = get_index ( pd->cmd_list_length, pd->active_list[i].start ); - unsigned int stop = get_index ( pd->cmd_list_length, pd->active_list[i].stop ); - if ( selected_line >= start && selected_line <= stop ) { - *state |= ACTIVE; - } +static char *_get_display_value(const Mode *sw, unsigned int selected_line, + G_GNUC_UNUSED int *state, + G_GNUC_UNUSED GList **list, int get_entry) { + ScriptModePrivateData *pd = sw->private_data; + for (unsigned int i = 0; i < pd->num_active_list; i++) { + unsigned int start = + get_index(pd->cmd_list_length, pd->active_list[i].start); + unsigned int stop = get_index(pd->cmd_list_length, pd->active_list[i].stop); + if (selected_line >= start && selected_line <= stop) { + *state |= ACTIVE; } - for ( unsigned int i = 0; i < pd->num_urgent_list; i++ ) { - unsigned int start = get_index ( pd->cmd_list_length, pd->urgent_list[i].start ); - unsigned int stop = get_index ( pd->cmd_list_length, pd->urgent_list[i].stop ); - if ( selected_line >= start && selected_line <= stop ) { - *state |= URGENT; - } + } + for (unsigned int i = 0; i < pd->num_urgent_list; i++) { + unsigned int start = + get_index(pd->cmd_list_length, pd->urgent_list[i].start); + unsigned int stop = get_index(pd->cmd_list_length, pd->urgent_list[i].stop); + if (selected_line >= start && selected_line <= stop) { + *state |= URGENT; } - if ( pd->do_markup ) { - *state |= MARKUP; - } - return get_entry ? g_strdup ( pd->cmd_list[selected_line].entry ) : NULL; + } + if (pd->do_markup) { + *state |= MARKUP; + } + return get_entry ? g_strdup(pd->cmd_list[selected_line].entry) : NULL; } -static int script_token_match ( const Mode *sw, rofi_int_matcher **tokens, unsigned int index ) -{ - ScriptModePrivateData *rmpd = sw->private_data; - int match = 1; - if ( tokens ) { - for ( int j = 0; match && tokens != NULL && tokens[j] != NULL; j++ ) { - rofi_int_matcher *ftokens[2] = { tokens[j], NULL }; - int test = 0; - test = helper_token_match ( ftokens, rmpd->cmd_list[index].entry ); - if ( test == tokens[j]->invert && rmpd->cmd_list[index].meta ) { - test = helper_token_match ( ftokens, rmpd->cmd_list[index].meta ); - } +static int script_token_match(const Mode *sw, rofi_int_matcher **tokens, + unsigned int index) { + ScriptModePrivateData *rmpd = sw->private_data; + int match = 1; + if (tokens) { + for (int j = 0; match && tokens != NULL && tokens[j] != NULL; j++) { + rofi_int_matcher *ftokens[2] = {tokens[j], NULL}; + int test = 0; + test = helper_token_match(ftokens, rmpd->cmd_list[index].entry); + if (test == tokens[j]->invert && rmpd->cmd_list[index].meta) { + test = helper_token_match(ftokens, rmpd->cmd_list[index].meta); + } - if ( test == 0 ) { - match = 0; - } - } + if (test == 0) { + match = 0; + } } - return match; + } + return match; } -static char *script_get_message ( const Mode *sw ) -{ - ScriptModePrivateData *pd = sw->private_data; - return g_strdup ( pd->message ); +static char *script_get_message(const Mode *sw) { + ScriptModePrivateData *pd = sw->private_data; + return g_strdup(pd->message); } -static cairo_surface_t *script_get_icon ( const Mode *sw, unsigned int selected_line, int height ) -{ - ScriptModePrivateData *pd = (ScriptModePrivateData *) mode_get_private_data ( sw ); - g_return_val_if_fail ( pd->cmd_list != NULL, NULL ); - DmenuScriptEntry *dr = &( pd->cmd_list[selected_line] ); - if ( dr->icon_name == NULL ) { - return NULL; - } - if ( dr->icon_fetch_uid > 0 ) { - return rofi_icon_fetcher_get ( dr->icon_fetch_uid ); - } - dr->icon_fetch_uid = rofi_icon_fetcher_query ( dr->icon_name, height ); - return rofi_icon_fetcher_get ( dr->icon_fetch_uid ); +static cairo_surface_t * +script_get_icon(const Mode *sw, unsigned int selected_line, int height) { + ScriptModePrivateData *pd = + (ScriptModePrivateData *)mode_get_private_data(sw); + g_return_val_if_fail(pd->cmd_list != NULL, NULL); + DmenuScriptEntry *dr = &(pd->cmd_list[selected_line]); + if (dr->icon_name == NULL) { + return NULL; + } + if (dr->icon_fetch_uid > 0) { + return rofi_icon_fetcher_get(dr->icon_fetch_uid); + } + dr->icon_fetch_uid = rofi_icon_fetcher_query(dr->icon_name, height); + return rofi_icon_fetcher_get(dr->icon_fetch_uid); } #include "mode-private.h" -Mode *script_switcher_parse_setup ( const char *str ) -{ - Mode *sw = g_malloc0 ( sizeof ( *sw ) ); - char *endp = NULL; - char *parse = g_strdup ( str ); - unsigned int index = 0; - const char *const sep = ":"; - for ( char *token = strtok_r ( parse, sep, &endp ); token != NULL; token = strtok_r ( NULL, sep, &endp ) ) { - if ( index == 0 ) { - sw->name = g_strdup ( token ); - } - else if ( index == 1 ) { - sw->ed = (void *) rofi_expand_path ( token ); - } - index++; +Mode *script_switcher_parse_setup(const char *str) { + Mode *sw = g_malloc0(sizeof(*sw)); + char *endp = NULL; + char *parse = g_strdup(str); + unsigned int index = 0; + const char *const sep = ":"; + for (char *token = strtok_r(parse, sep, &endp); token != NULL; + token = strtok_r(NULL, sep, &endp)) { + if (index == 0) { + sw->name = g_strdup(token); + } else if (index == 1) { + sw->ed = (void *)rofi_expand_path(token); } - g_free ( parse ); - if ( index == 2 ) { - sw->free = script_switcher_free; - sw->_init = script_mode_init; - sw->_get_num_entries = script_mode_get_num_entries; - sw->_result = script_mode_result; - sw->_destroy = script_mode_destroy; - sw->_token_match = script_token_match; - sw->_get_message = script_get_message; - sw->_get_icon = script_get_icon; - sw->_get_completion = NULL, - sw->_preprocess_input = NULL, - sw->_get_display_value = _get_display_value; + index++; + } + g_free(parse); + if (index == 2) { + sw->free = script_switcher_free; + sw->_init = script_mode_init; + sw->_get_num_entries = script_mode_get_num_entries; + sw->_result = script_mode_result; + sw->_destroy = script_mode_destroy; + sw->_token_match = script_token_match; + sw->_get_message = script_get_message; + sw->_get_icon = script_get_icon; + sw->_get_completion = NULL, sw->_preprocess_input = NULL, + sw->_get_display_value = _get_display_value; - return sw; - } - fprintf ( stderr, "The script command '%s' has %u options, but needs 2: :