diff options
-rw-r--r-- | doc/dwb.1 | 9 | ||||
-rw-r--r-- | lib/keys.html | 20 | ||||
-rw-r--r-- | lib/settings.html | 48 | ||||
-rw-r--r-- | src/commands.c | 5 | ||||
-rw-r--r-- | src/commands.h | 1 | ||||
-rw-r--r-- | src/config.h | 1 | ||||
-rw-r--r-- | src/dwb.c | 116 | ||||
-rw-r--r-- | src/dwb.h | 3 | ||||
-rw-r--r-- | src/util.c | 31 | ||||
-rw-r--r-- | src/util.h | 3 | ||||
-rw-r--r-- | src/view.c | 1 | ||||
-rw-r--r-- | util/keys.in | 2 | ||||
-rw-r--r-- | util/settings.in | 1 |
13 files changed, 212 insertions, 29 deletions
@@ -362,6 +362,10 @@ Show userscripts (command .BR wi Show the webinspector. Note that 'enable-developer-extras' has to be set. .TP +.BR Control e +Open external editor for current input/textarea (command +.BR open_editor ). +.TP .BR g. Toggle hidden files when browsing local filesystem. .TP @@ -886,6 +890,11 @@ Possible values: true/false, default value: .IR true . .TP +.BR editor +External editor used for inputs/textareas. +default value: +.IR xterm\ -e\ vim\ dwb_uri . +.TP .BR error-color The color for error-messages. Possible values: an rgb color-string, default value: diff --git a/lib/keys.html b/lib/keys.html index 0d4b7180..9e0519ff 100644 --- a/lib/keys.html +++ b/lib/keys.html @@ -875,6 +875,14 @@ <div style='clear:both;'></div> </div> <div class='dwb_line1'> + <div class='dwb_attr'>open_editor</div> + <div style='float:right;'> + <label class='dwb_desc' for='open_editor'>Open an external editor for current input/textarea.</label> + <input id='open_editor' type='text' > + </div> + <div style='clear:both;'></div> + </div> + <div class='dwb_line0'> <div class='dwb_attr'>print</div> <div style='float:right;'> <label class='dwb_desc' for='print'>Print current page</label> @@ -882,7 +890,7 @@ </div> <div style='clear:both;'></div> </div> - <div class='dwb_line0'> + <div class='dwb_line1'> <div class='dwb_attr'>save</div> <div style='float:right;'> <label class='dwb_desc' for='save'>Save all configuration files</label> @@ -890,7 +898,7 @@ </div> <div style='clear:both;'></div> </div> - <div class='dwb_line1'> + <div class='dwb_line0'> <div class='dwb_attr'>save_session</div> <div style='float:right;'> <label class='dwb_desc' for='save_session'>Save current session</label> @@ -898,7 +906,7 @@ </div> <div style='clear:both;'></div> </div> - <div class='dwb_line0'> + <div class='dwb_line1'> <div class='dwb_attr'>save_named_session</div> <div style='float:right;'> <label class='dwb_desc' for='save_named_session'>Save current session with name</label> @@ -906,7 +914,7 @@ </div> <div style='clear:both;'></div> </div> - <div class='dwb_line1'> + <div class='dwb_line0'> <div class='dwb_attr'>toggle_hidden_files</div> <div style='float:right;'> <label class='dwb_desc' for='toggle_hidden_files'>Toggle hidden files in directory listing</label> @@ -914,7 +922,7 @@ </div> <div style='clear:both;'></div> </div> - <div class='dwb_line0'> + <div class='dwb_line1'> <div class='dwb_attr'>save_search_field</div> <div style='float:right;'> <label class='dwb_desc' for='save_search_field'>Add a new searchengine</label> @@ -922,7 +930,7 @@ </div> <div style='clear:both;'></div> </div> - <div class='dwb_line1'> + <div class='dwb_line0'> <div class='dwb_attr'>reload_scripts</div> <div style='float:right;'> <label class='dwb_desc' for='reload_scripts'>Reload all javascript userscripts</label> diff --git a/lib/settings.html b/lib/settings.html index d4d402a2..2682eca5 100644 --- a/lib/settings.html +++ b/lib/settings.html @@ -772,6 +772,14 @@ <div style='clear:both;'></div> </div> <div class='dwb_line0'> + <div class='dwb_attr'>editor</div> + <div style='float:right;'> + <label for='editor' class='dwb_desc'>External editor used for inputs/textareas</label> + <input id='editor' type='text'> + </div> + <div style='clear:both;'></div> + </div> + <div class='dwb_line1'> <div class='dwb_attr'>editable</div> <div style='float:right;'> <label for='editable' class='dwb_desc'>Whether content can be modified</label> @@ -779,7 +787,7 @@ </div> <div style='clear:both;'></div> </div> - <div class='dwb_line1'> + <div class='dwb_line0'> <div class='dwb_attr'>enable-caret-browsing</div> <div style='float:right;'> <label for='enable-caret-browsing' class='dwb_desc'>Whether to enable caret browsing</label> @@ -787,7 +795,7 @@ </div> <div style='clear:both;'></div> </div> - <div class='dwb_line0'> + <div class='dwb_line1'> <div class='dwb_attr'>enable-default-context-menu</div> <div style='float:right;'> <label for='enable-default-context-menu' class='dwb_desc'>Whether to enable the right click context menu</label> @@ -795,7 +803,7 @@ </div> <div style='clear:both;'></div> </div> - <div class='dwb_line1'> + <div class='dwb_line0'> <div class='dwb_attr'>enable-developer-extras</div> <div style='float:right;'> <label for='enable-developer-extras' class='dwb_desc'>Whether developer extensions should be enabled</label> @@ -803,7 +811,7 @@ </div> <div style='clear:both;'></div> </div> - <div class='dwb_line0'> + <div class='dwb_line1'> <div class='dwb_attr'>enable-dom-paste</div> <div style='float:right;'> <label for='enable-dom-paste' class='dwb_desc'>Whether to enable DOM paste</label> @@ -811,7 +819,7 @@ </div> <div style='clear:both;'></div> </div> - <div class='dwb_line1'> + <div class='dwb_line0'> <div class='dwb_attr'>enable-file-access-from-file-uris</div> <div style='float:right;'> <label for='enable-file-access-from-file-uris' class='dwb_desc'>Whether file access from file uris is allowed</label> @@ -819,7 +827,7 @@ </div> <div style='clear:both;'></div> </div> - <div class='dwb_line0'> + <div class='dwb_line1'> <div class='dwb_attr'>enable-html5-database</div> <div style='float:right;'> <label for='enable-html5-database' class='dwb_desc'>Enable HTML5 client side SQL-database support</label> @@ -827,7 +835,7 @@ </div> <div style='clear:both;'></div> </div> - <div class='dwb_line1'> + <div class='dwb_line0'> <div class='dwb_attr'>enable-html5-local-storage</div> <div style='float:right;'> <label for='enable-html5-local-storage' class='dwb_desc'>Enable HTML5 local storage</label> @@ -835,7 +843,7 @@ </div> <div style='clear:both;'></div> </div> - <div class='dwb_line0'> + <div class='dwb_line1'> <div class='dwb_attr'>enable-offline-web-application-cache</div> <div style='float:right;'> <label for='enable-offline-web-application-cache' class='dwb_desc'>Enable HTML5 offline web application cache</label> @@ -843,7 +851,7 @@ </div> <div style='clear:both;'></div> </div> - <div class='dwb_line1'> + <div class='dwb_line0'> <div class='dwb_attr'>enable-page-cache</div> <div style='float:right;'> <label for='enable-page-cache' class='dwb_desc'>Enable page cache</label> @@ -851,7 +859,7 @@ </div> <div style='clear:both;'></div> </div> - <div class='dwb_line0'> + <div class='dwb_line1'> <div class='dwb_attr'>enable-site-specific-quirks</div> <div style='float:right;'> <label for='enable-site-specific-quirks' class='dwb_desc'>Enable site specific compatibility workarounds</label> @@ -859,7 +867,7 @@ </div> <div style='clear:both;'></div> </div> - <div class='dwb_line1'> + <div class='dwb_line0'> <div class='dwb_attr'>enable-spatial-navigation</div> <div style='float:right;'> <label for='enable-spatial-navigation' class='dwb_desc'>Enable spatial navigation</label> @@ -867,7 +875,7 @@ </div> <div style='clear:both;'></div> </div> - <div class='dwb_line0'> + <div class='dwb_line1'> <div class='dwb_attr'>enable-universal-access-from-file-uris</div> <div style='float:right;'> <label for='enable-universal-access-from-file-uris' class='dwb_desc'>Whether to allow files loaded through file:</label> @@ -875,7 +883,7 @@ </div> <div style='clear:both;'></div> </div> - <div class='dwb_line1'> + <div class='dwb_line0'> <div class='dwb_attr'>enable-xss-auditor</div> <div style='float:right;'> <label for='enable-xss-auditor' class='dwb_desc'>Whether to enable the xss auditor</label> @@ -883,7 +891,7 @@ </div> <div style='clear:both;'></div> </div> - <div class='dwb_line0'> + <div class='dwb_line1'> <div class='dwb_attr'>ftp-client</div> <div style='float:right;'> <label for='ftp-client' class='dwb_desc'>Application used for ftp</label> @@ -891,7 +899,7 @@ </div> <div style='clear:both;'></div> </div> - <div class='dwb_line1'> + <div class='dwb_line0'> <div class='dwb_attr'>history-length</div> <div style='float:right;'> <label for='history-length' class='dwb_desc'>Length of the browsing history</label> @@ -899,7 +907,7 @@ </div> <div style='clear:both;'></div> </div> - <div class='dwb_line0'> + <div class='dwb_line1'> <div class='dwb_attr'>mail-client</div> <div style='float:right;'> <label for='mail-client' class='dwb_desc'>Application used for mailto:-urls</label> @@ -907,7 +915,7 @@ </div> <div style='clear:both;'></div> </div> - <div class='dwb_line1'> + <div class='dwb_line0'> <div class='dwb_attr'>print-backgrounds</div> <div style='float:right;'> <label for='print-backgrounds' class='dwb_desc'>Whether background images should be printed</label> @@ -915,7 +923,7 @@ </div> <div style='clear:both;'></div> </div> - <div class='dwb_line0'> + <div class='dwb_line1'> <div class='dwb_attr'>sync-history</div> <div style='float:right;'> <label for='sync-history' class='dwb_desc'>Interval to save history to disk, 0 means save immediately</label> @@ -923,7 +931,7 @@ </div> <div style='clear:both;'></div> </div> - <div class='dwb_line1'> + <div class='dwb_line0'> <div class='dwb_attr'>tab-key-cycles-through-elements</div> <div style='float:right;'> <label for='tab-key-cycles-through-elements' class='dwb_desc'>Tab cycles through elements in insert mode</label> @@ -931,7 +939,7 @@ </div> <div style='clear:both;'></div> </div> - <div class='dwb_line0'> + <div class='dwb_line1'> <div class='dwb_attr'>use-fifo</div> <div style='float:right;'> <label for='use-fifo' class='dwb_desc'>Create a fifo for communication</label> diff --git a/src/commands.c b/src/commands.c index 1691c245..8deac112 100644 --- a/src/commands.c +++ b/src/commands.c @@ -883,4 +883,9 @@ commands_pass_through(KeyMap *km, Arg *arg) { dwb_set_normal_message(dwb.state.fview, false, "-- PASS THROUGH --"); return true; }/*}}}*/ +/* commands_reload_scripts {{{*/ +gboolean +commands_open_editor(KeyMap *km, Arg *arg) { + return dwb_open_in_editor(); +}/*}}}*/ /*}}}*/ diff --git a/src/commands.h b/src/commands.h index 9da706e6..393d3769 100644 --- a/src/commands.h +++ b/src/commands.h @@ -87,4 +87,5 @@ gboolean commands_quit(KeyMap *, Arg *); gboolean commands_reload_scripts(KeyMap *, Arg *); gboolean commands_fullscreen(KeyMap *, Arg *); gboolean commands_pass_through(KeyMap *, Arg *); +gboolean commands_open_editor(KeyMap *, Arg *); #endif diff --git a/src/config.h b/src/config.h index 50646340..4250d51f 100644 --- a/src/config.h +++ b/src/config.h @@ -138,4 +138,5 @@ static KeyValue KEYS[] = { { "quit", { "q", GDK_CONTROL_MASK }, }, { "fullscreen", { "F11", GDK_CONTROL_MASK }, }, { "pass_through", { "i", GDK_CONTROL_MASK }, }, + { "open_editor", { "e", GDK_CONTROL_MASK }, }, }; @@ -86,6 +86,14 @@ static int signals[] = { SIGFPE, SIGILL, SIGINT, SIGQUIT, SIGTERM, SIGALRM, SIGS static int MAX_COMPLETIONS = 11; static char *restore = NULL; +typedef struct _EditorInfo { + char *filename; + char *id; + GList *gl; + WebKitDOMElement *element; + const char *tagname; +} EditorInfo; + /* FUNCTION_MAP{{{*/ static FunctionMap FMAP [] = { @@ -346,6 +354,8 @@ static FunctionMap FMAP [] = { (Func) commands_fullscreen, NULL, ALWAYS_SM, { 0 } }, { { "pass_through", "Pass-through mode" }, 1, (Func) commands_pass_through, NULL, POST_SM, { 0 } }, + { { "open_editor", "Open external editor" }, 1, + (Func) commands_open_editor, NULL, ALWAYS_SM, { 0 } }, };/*}}}*/ /* DWB_SETTINGS {{{*/ @@ -562,7 +572,7 @@ static WebSettings DWB_SETTINGS[] = { SETTING_GLOBAL, BOOLEAN, { .b = true }, (S_Func)dwb_init_vars, }, { { "complete-searchengines", "Whether to complete searchengines with tab", }, SETTING_GLOBAL, BOOLEAN, { .b = false }, (S_Func)dwb_init_vars, }, - { { "complete-commands", "Whether to complete the commmand history", }, + { { "complete-commands", "Whether to complete the command history", }, SETTING_GLOBAL, BOOLEAN, { .b = true }, (S_Func)dwb_init_vars, }, { { "complete-userscripts", "Whether to complete userscripts", }, SETTING_GLOBAL, BOOLEAN, { .b = false }, (S_Func)dwb_init_vars, }, @@ -590,6 +600,8 @@ static WebSettings DWB_SETTINGS[] = { SETTING_GLOBAL, CHAR, { .p = "xterm -e mutt 'dwb_uri'" }, (S_Func)dwb_set_dummy, }, { { "ftp-client", "Program used for ftp", }, SETTING_GLOBAL, CHAR, { .p = "xterm -e ncftp 'dwb_uri'" }, (S_Func)dwb_set_dummy, }, + { { "editor", "External editor", }, + SETTING_GLOBAL, CHAR, { .p = "xterm -e vim dwb_uri" }, (S_Func)dwb_set_dummy, }, { { "adblocker", "Whether to block advertisements via a filterlist", }, SETTING_PER_VIEW, BOOLEAN, { .b = false }, (S_Func)dwb_set_adblock, }, { { "plugin-blocker", "Whether to block flash plugins and replace them with a clickable element", }, @@ -978,6 +990,94 @@ dwb_update_status_text(GList *gl, GtkAdjustment *a) { /*}}}*/ /* FUNCTIONS {{{*/ + +/* dwb_editor_watch (GChildWatchFunc) {{{*/ +static void +dwb_editor_watch(GPid pid, int status, EditorInfo *info) { + char *content = util_get_file_content(info->filename); + WebKitDOMElement *e = NULL; + WebKitWebView *wv; + if (content == NULL) + goto clean; + if (!info->gl || !g_list_find(dwb.state.views, info->gl->data)) { + if (info->id == NULL) + goto clean; + else + wv = CURRENT_WEBVIEW(); + } + else + wv = WEBVIEW(info->gl); + if (info->id != NULL) { + WebKitDOMDocument *doc = webkit_web_view_get_dom_document(wv); + e = webkit_dom_document_get_element_by_id(doc, info->id); + if (e == NULL) + goto clean; + } + else + e = info->element; + + if (WEBKIT_DOM_IS_HTML_INPUT_ELEMENT(e)) + webkit_dom_html_input_element_set_value(WEBKIT_DOM_HTML_INPUT_ELEMENT(e), content); + if (WEBKIT_DOM_IS_HTML_TEXT_AREA_ELEMENT(e)) + webkit_dom_html_text_area_element_set_value(WEBKIT_DOM_HTML_TEXT_AREA_ELEMENT(e), content); + +clean: + unlink(info->filename); + g_free(info->filename); + FREE(info->id); + free(info); +}/*}}}*/ + +/* dwb_open_in_editor(void) ret: gboolean success {{{*/ +gboolean +dwb_open_in_editor(void) { + WebKitDOMDocument *doc = webkit_web_view_get_dom_document(CURRENT_WEBVIEW()); + WebKitDOMElement *active = webkit_dom_html_document_get_active_element(WEBKIT_DOM_HTML_DOCUMENT(doc)); + if (active == NULL) + return false; + + char *tagname = webkit_dom_element_get_tag_name(active); + if (tagname == NULL) + return false; + char *value = NULL; + if (! strcmp(tagname, "INPUT")) + value = webkit_dom_html_input_element_get_value(WEBKIT_DOM_HTML_INPUT_ELEMENT(active)); + else if (!strcmp(tagname, "TEXTAREA")) + value = webkit_dom_html_text_area_element_get_value(WEBKIT_DOM_HTML_TEXT_AREA_ELEMENT(active)); + if (value == NULL) + return false; + + char *path = util_get_temp_filename(); + + char *editor = GET_CHAR("editor"); + char *commandstring = util_string_replace(editor, "dwb_uri", path); + if (commandstring == NULL) + return false; + + g_file_set_contents(path, value, -1, NULL); + char **commands = g_strsplit(commandstring, " ", -1); + GPid pid; + gboolean success = g_spawn_async(NULL, commands, NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &pid, NULL); + if (!success) + return false; + + EditorInfo *info = dwb_malloc(sizeof(EditorInfo)); + char *id = webkit_dom_html_element_get_id(WEBKIT_DOM_HTML_ELEMENT(active)); + if (id != NULL && strlen(id) > 0) { + info->id = g_strdup(id); + } + else { + info->id = NULL; + } + info->tagname = tagname; + info->element = active; + info->filename = path; + info->gl = dwb.state.fview; + g_child_watch_add(pid, (GChildWatchFunc)dwb_editor_watch, info); + + return true; +}/*}}}*/ + /* remove history, bookmark, quickmark {{{*/ static int dwb_remove_navigation_item(GList **content, const char *line, const char *filename) { @@ -2298,6 +2398,7 @@ dwb_normal_mode(gboolean clean) { dwb_clean_vars(); }/*}}}*/ +/* gboolean dwb_highlight_search(void) {{{*/ gboolean dwb_highlight_search() { WebKitWebView *web = CURRENT_WEBVIEW(); @@ -2309,7 +2410,8 @@ dwb_highlight_search() { return true; } return false; -} +}/*}}}*/ + /* dwb_update_search(gboolean ) {{{*/ gboolean dwb_update_search(gboolean forward) { @@ -2971,8 +3073,16 @@ dwb_init_files() { char *profile_path = g_build_filename(path, dwb.misc.profile, NULL); if (!g_file_test(profile_path, G_FILE_TEST_IS_DIR)) { - g_mkdir_with_parents(profile_path, 0755); + g_mkdir_with_parents(profile_path, 0700); + } + char *cache_dir = g_build_filename(g_get_user_cache_dir(), dwb.misc.name, NULL); + if (!g_file_test(cache_dir, G_FILE_TEST_IS_DIR)) { + g_mkdir_with_parents(cache_dir, 0700); + } + else { + util_rmdir(cache_dir, true); } + g_free(cache_dir); dwb.files.bookmarks = g_build_filename(profile_path, "bookmarks", NULL); dwb.files.history = g_build_filename(profile_path, "history", NULL); dwb.files.stylesheet = g_build_filename(profile_path, "stylesheet", NULL); @@ -28,6 +28,7 @@ #include <libgen.h> #include <sys/file.h> #include <sys/stat.h> +#include <sys/time.h> #include <libsoup/soup.h> #include <locale.h> #include <stdarg.h> @@ -730,4 +731,6 @@ void dwb_remove_bookmark(const char *); void dwb_remove_history(const char *); void dwb_remove_quickmark(const char *); +gboolean dwb_open_in_editor(void); + #endif @@ -19,6 +19,18 @@ #include "util.h" /* util_string_replace(const char *haystack, const char *needle, const char *replace) return: char * (alloc){{{*/ + +char * +util_get_temp_filename(void) { + struct timeval t; + gettimeofday(&t, NULL); + const char *path = g_get_user_cache_dir(); + char *filename = g_strdup_printf("edit%lu", t.tv_usec + t.tv_sec*1000000); + char *cache_path = g_build_filename(path, dwb.misc.name, filename, NULL); + g_free(filename); + + return cache_path; +} char * util_string_replace(const char *haystack, const char *needle, const char *replacemant) { char **token; @@ -273,6 +285,25 @@ util_get_directory_content(GString **buffer, const char *dirname) { } }/*}}}*/ +void +util_rmdir(const char *path, gboolean recursive) { + GDir *dir = g_dir_open(path, 0, NULL); + if (dir == NULL) + return; + const char *filename = NULL; + char *fullpath; + while ( (filename = g_dir_read_name(dir)) ) { + fullpath = g_build_filename(path, filename, NULL); + if (!g_file_test(fullpath, G_FILE_TEST_IS_DIR)) { + unlink(fullpath); + } + else if (recursive) { + util_rmdir(fullpath, true); + rmdir(fullpath); + } + g_free(fullpath); + } +} /* util_get_file_content(const char *filename) return: char * (alloc) {{{*/ char * util_get_file_content(const char *filename) { @@ -28,6 +28,9 @@ void util_cut_text(char *, int, int); gboolean util_is_hex(const char *string); int util_test_connect(const char *uri); +char * util_get_temp_filename(void); +void util_rmdir(const char *path, gboolean recursive); + // keys char * dwb_modmask_to_string(guint ); char * util_keyval_to_char(guint ); @@ -1017,6 +1017,7 @@ view_remove(GList *g) { FREE(v); dwb.state.views = g_list_delete_link(dwb.state.views, gl); + gl = NULL; /* Update MAXIMIZED layout */ if (dwb.state.layout & MAXIMIZED) { diff --git a/util/keys.in b/util/keys.in index eb68ce8b..37da84f7 100644 --- a/util/keys.in +++ b/util/keys.in @@ -122,6 +122,7 @@ focus_input Focus the next input new_view New view for next navigation new_window New window for next navigation web_inspector Open the webinspector +open_editor Open an external editor for current input/textarea. print Print current page save Save all configuration files save_session Save current session @@ -129,3 +130,4 @@ save_named_session Save current session with name toggle_hidden_files Toggle hidden files in directory listing save_search_field Add a new searchengine reload_scripts Reload all javascript userscripts + diff --git a/util/settings.in b/util/settings.in index b49b23a0..86e89eaf 100644 --- a/util/settings.in +++ b/util/settings.in @@ -109,6 +109,7 @@ complete-userscripts checkbox Whether to enable tabcompletion for userscripts custom-encoding text The custom encoding of the view download-external-command text External application used for downloads download-use-external-program checkbox Whether to use an external download helper +editor text External editor used for inputs/textareas editable checkbox Whether content can be modified enable-caret-browsing checkbox Whether to enable caret browsing enable-default-context-menu checkbox Whether to enable the right click context menu |