"Fossies" - the Fresh Open Source Software Archive

Member "xombrero-1.6.4/externaleditor.c" (17 Feb 2015, 8596 Bytes) of package /linux/www/old/xombrero-1.6.4.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "externaleditor.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright (c) 2012 Elias Norberg <xyzzy@kudzu.se>
    3  * Copyright (c) 2012 Josh Rickmar <jrick@devio.us>
    4  *
    5  * Permission to use, copy, modify, and distribute this software for any
    6  * purpose with or without fee is hereby granted, provided that the above
    7  * copyright notice and this permission notice appear in all copies.
    8  *
    9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   16  */
   17 
   18 #include <xombrero.h>
   19 
   20 #if WEBKIT_CHECK_VERSION(1, 5, 0)
   21     /* we got the DOM API we need */
   22 
   23 struct edit_src_cb_args {
   24         WebKitWebFrame      *frame;
   25         WebKitWebDataSource *data_src;
   26 };
   27 
   28 struct external_editor_args {
   29         GPid        child_pid;
   30         char        *path;
   31         time_t      mtime;
   32         struct tab  *tab;
   33         int     (*callback)(const char *,gpointer);
   34         gpointer    cb_data;
   35 };
   36 
   37 int
   38 update_contents(struct external_editor_args *args)
   39 {
   40     struct stat     st;
   41     int         fd = -1;
   42     int         rv, nb;
   43     GString         *contents = NULL;
   44     char            buf[XT_EE_BUFSZ];
   45 
   46     rv = stat(args->path, &st);
   47     if (rv == -1 && errno == ENOENT)
   48         return (1);
   49     else if (rv == 0 && st.st_mtime > args->mtime) {
   50         DPRINTF("File %s has been modified\n", args->path);
   51         args->mtime = st.st_mtime;
   52 
   53         contents = g_string_sized_new(XT_EE_BUFSZ);
   54         fd = open(args->path, O_RDONLY);
   55         if (fd == -1) {
   56             DPRINTF("open_external_editor_cb, open error, %s\n",
   57                 strerror(errno));
   58             goto done;
   59         }
   60 
   61         for (;;) {
   62             nb = read(fd, buf, XT_EE_BUFSZ);
   63             if (nb < 0) {
   64                 g_string_free(contents, TRUE);
   65                 show_oops(args->tab, strerror(errno));
   66                 goto done;
   67             }
   68 
   69             buf[nb] = '\0';
   70             contents = g_string_append(contents, buf);
   71 
   72             if (nb < XT_EE_BUFSZ)
   73                 break;
   74         }
   75         close(fd);
   76 
   77         DPRINTF("external_editor_cb: contents updated\n");
   78         if (args->callback)
   79             args->callback(contents->str, args->cb_data);
   80 
   81         g_string_free(contents, TRUE);
   82 
   83         return (0);
   84     }
   85 
   86 done:
   87     if (fd != -1)
   88         close(fd);
   89     return (0);
   90 }
   91 
   92 void
   93 external_editor_closed(GPid pid, gint status, gpointer data)
   94 {
   95     struct external_editor_args *args;
   96     struct tab          *t;
   97     int             found_tab = 0;
   98 
   99     args = (struct external_editor_args *)data;
  100 
  101     TAILQ_FOREACH(t, &tabs, entry)
  102         if (t == args->tab) {
  103             found_tab = 1;
  104             break;
  105         }
  106 
  107     /* Tab was deleted */
  108     if (!found_tab)
  109         goto done;
  110 
  111     /*
  112      * unfortunately we can't check the exit status in glib < 2.34,
  113      * otherwise a check and warning would be nice here
  114      */
  115     update_contents(args);
  116 
  117 done:
  118     unlink(args->path);
  119     g_spawn_close_pid(pid); 
  120 }
  121 
  122 int
  123 open_external_editor_cb(gpointer data)
  124 {
  125     struct external_editor_args *args;
  126     struct tab          *t;
  127     int             found_tab = 0;
  128 
  129     args = (struct external_editor_args*)data;
  130 
  131     /* Check if tab is still open */
  132     TAILQ_FOREACH(t, &tabs, entry)
  133         if (t == args->tab) {
  134             found_tab = 1;
  135             break;
  136         }
  137 
  138     /* Tab was deleted */
  139     if (!found_tab)
  140         goto done;
  141 
  142     if (update_contents(args))
  143         goto done;
  144 
  145     return (1);
  146 done:
  147     /* cleanup and remove from event loop */
  148     g_free(args->path);
  149     g_free(args->cb_data);
  150     g_free(args);
  151 
  152     return (0);
  153 }
  154 
  155 int
  156 open_external_editor(struct tab *t, const char *contents,
  157     int (*callback)(const char *, gpointer), gpointer cb_data)
  158 {
  159     struct stat         st;
  160     struct external_editor_args *a;
  161     GPid                pid;
  162     char                *cmdstr;
  163     char                filename[PATH_MAX];
  164     char                **sv;
  165     int             fd;
  166     int             nb, rv;
  167     int             cnt;
  168 
  169     if (external_editor == NULL)
  170         return (0);
  171 
  172     snprintf(filename, sizeof filename, "%s" PS "xombreroXXXXXX", temp_dir);
  173 
  174     /* Create a temporary file */
  175     fd = g_mkstemp(filename);
  176     if (fd == -1) {
  177         show_oops(t, "Cannot create temporary file");
  178         return (1);
  179     }
  180 
  181     nb = 0;
  182     while (contents && nb < strlen(contents)) {
  183         if (strlen(contents) - nb > XT_EE_BUFSZ)
  184             cnt = XT_EE_BUFSZ;
  185         else
  186             cnt = strlen(contents) - nb;
  187 
  188         rv = write(fd, contents+nb, cnt);
  189         if (rv < 0) {
  190             close(fd);
  191             show_oops(t,strerror(errno));
  192             return (1);
  193         }
  194 
  195         nb += rv;
  196     }
  197 
  198     rv = fstat(fd, &st);
  199     if (rv == -1) {
  200         close(fd);
  201         show_oops(t,"Cannot stat file: %s\n", strerror(errno));
  202         return (1);
  203     }
  204     close(fd);
  205 
  206     DPRINTF("edit_src: external_editor: %s\n", external_editor);
  207 
  208     sv = g_strsplit(external_editor, "<file>", -1);
  209     cmdstr = g_strjoinv(filename, sv);
  210     g_strfreev(sv);
  211     sv = g_strsplit_set(cmdstr, " \t", -1);
  212     if (!g_spawn_async(NULL, sv, NULL,
  213         (G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD), NULL, NULL, &pid,
  214         NULL)) {
  215         show_oops(t, "%s: could not spawn process");
  216         g_strfreev(sv);
  217         g_free(cmdstr);
  218         return (1);
  219     }
  220 
  221     g_strfreev(sv);
  222     g_free(cmdstr);
  223 
  224     a = g_malloc(sizeof(struct external_editor_args));
  225     a->child_pid = pid;
  226     a->path = g_strdup(filename);
  227     a->tab = t;
  228     a->mtime = st.st_mtime;
  229     a->callback = callback;
  230     a->cb_data = cb_data;
  231 
  232     /* Check every 100 ms if file has changed */
  233     g_timeout_add(100, (GSourceFunc)open_external_editor_cb,
  234         (gpointer)a);
  235 
  236     /* Stop loop  child has terminated */
  237     g_child_watch_add(pid, external_editor_closed, (gpointer)a);
  238 
  239     return (0);
  240 }
  241 
  242 int
  243 edit_src_cb(const char *contents, gpointer data)
  244 {
  245     struct edit_src_cb_args *args;
  246 
  247     args = (struct edit_src_cb_args *)data;
  248 
  249     webkit_web_frame_load_string(args->frame, contents, NULL,
  250         webkit_web_data_source_get_encoding(args->data_src),
  251         webkit_web_frame_get_uri(args->frame));
  252     return (0);
  253 }
  254 
  255 int
  256 edit_src(struct tab *t, struct karg *args)
  257 {
  258     WebKitWebFrame      *frame;
  259     WebKitWebDataSource *ds;
  260     GString         *contents;
  261     struct edit_src_cb_args *ext_args;
  262 
  263     if (external_editor == NULL){
  264         show_oops(t,"Setting external_editor not set");
  265         return (1);
  266     }
  267 
  268     frame = webkit_web_view_get_focused_frame(t->wv);
  269     ds = webkit_web_frame_get_data_source(frame);
  270     if (webkit_web_data_source_is_loading(ds)) {
  271         show_oops(t,"Webpage is still loading.");
  272         return (1);
  273     }
  274 
  275     contents = webkit_web_data_source_get_data(ds);
  276     if (!contents)
  277         show_oops(t,"No contents - opening empty file");
  278 
  279     ext_args = g_malloc(sizeof(struct edit_src_cb_args));
  280     ext_args->frame = frame;
  281     ext_args->data_src = ds;
  282 
  283     /* Check every 100 ms if file has changed */
  284     open_external_editor(t, contents ? contents->str : "", &edit_src_cb,
  285         ext_args);
  286     return (0);
  287 }
  288 
  289 struct edit_element_cb_args {
  290     WebKitDOMElement    *active;
  291     struct tab      *tab;
  292 };
  293 
  294 int
  295 edit_element_cb(const char *contents, gpointer data)
  296 {
  297     struct              edit_element_cb_args *args;
  298     WebKitDOMHTMLTextAreaElement    *ta;
  299     WebKitDOMHTMLInputElement   *el;
  300 
  301     args = (struct edit_element_cb_args*)data;
  302 
  303     if (!args || !args->active)
  304         return (0);
  305 
  306     el = (WebKitDOMHTMLInputElement*)args->active;
  307     ta = (WebKitDOMHTMLTextAreaElement*)args->active;
  308 
  309     if (WEBKIT_DOM_IS_HTML_INPUT_ELEMENT(el))
  310         webkit_dom_html_input_element_set_value(el, contents);
  311     else if (WEBKIT_DOM_IS_HTML_TEXT_AREA_ELEMENT(ta))
  312         webkit_dom_html_text_area_element_set_value(ta, contents);
  313 
  314     return (0);
  315 }
  316 
  317 int
  318 edit_element(struct tab *t, struct karg *a)
  319 {
  320     WebKitDOMHTMLDocument       *doc;
  321     WebKitDOMElement        *active_element;
  322     WebKitDOMHTMLTextAreaElement    *ta;
  323     WebKitDOMHTMLInputElement   *el;
  324     char                *contents;
  325     struct edit_element_cb_args *args;
  326 
  327     if (external_editor == NULL){
  328         show_oops(t,"Setting external_editor not set");
  329         return (0);
  330     }
  331 
  332     doc = (WebKitDOMHTMLDocument*)webkit_web_view_get_dom_document(t->wv);
  333     active_element = webkit_dom_html_document_get_active_element(doc);
  334     el = (WebKitDOMHTMLInputElement*)active_element;
  335     ta = (WebKitDOMHTMLTextAreaElement*)active_element;
  336 
  337     if (doc == NULL || active_element == NULL ||
  338         (WEBKIT_DOM_IS_HTML_INPUT_ELEMENT(el) == 0 &&
  339         WEBKIT_DOM_IS_HTML_TEXT_AREA_ELEMENT(ta) == 0)) {
  340         show_oops(t, "No active text element!");
  341         return (1);
  342     }
  343 
  344     contents = "";
  345     if (WEBKIT_DOM_IS_HTML_INPUT_ELEMENT(el))
  346         contents = webkit_dom_html_input_element_get_value(el);
  347     else if (WEBKIT_DOM_IS_HTML_TEXT_AREA_ELEMENT(ta))
  348         contents = webkit_dom_html_text_area_element_get_value(ta);
  349 
  350     if ((args = g_malloc(sizeof(struct edit_element_cb_args))) == NULL)
  351         return (1);
  352 
  353     args->tab = t;
  354     args->active = active_element;
  355 
  356     open_external_editor(t, contents, &edit_element_cb,  args);
  357 
  358     return (0);
  359 }
  360 
  361 #else /* Just to make things compile. */
  362 
  363 int
  364 edit_element(struct tab *t, struct karg *a)
  365 {
  366     show_oops(t, "external editor feature requires webkit >= 1.5.0");
  367     return (1);
  368 }
  369 
  370 int
  371 edit_src(struct tab *t, struct karg *args)
  372 {
  373     show_oops(t, "external editor feature requires webkit >= 1.5.0");
  374     return (1);
  375 }
  376 
  377 #endif