2 (c) 2009 by Leon Winter
3 (c) 2009 by Hannes Schueller
10 #include <gdk/gdkkeysyms.h>
11 #include <webkit/webkit.h>
12 #include <libsoup/soup.h>
13 #include <JavaScriptCore/JavaScript.h>
14 #include "vimprobable.h"
16 /* inline js fill be filled by js-merge-helper.pl */
19 /* remove numlock symbol from keymask */
20 #define CLEAN(mask) (mask & ~(GDK_MOD2_MASK) & ~(GDK_BUTTON1_MASK) & ~(GDK_BUTTON2_MASK) & ~(GDK_BUTTON3_MASK) & ~(GDK_BUTTON4_MASK) & ~(GDK_BUTTON5_MASK))
23 static void window_destroyed_cb(GtkWidget
*window
, gpointer func_data
);
24 static void webview_title_changed_cb(WebKitWebView
*webview
, WebKitWebFrame
*frame
, char *title
, gpointer user_data
);
25 static void webview_load_committed_cb(WebKitWebView
*webview
, WebKitWebFrame
*frame
, gpointer user_data
);
26 static void webview_title_changed_cb(WebKitWebView
*webview
, WebKitWebFrame
*frame
, char *title
, gpointer user_data
);
27 static void webview_progress_changed_cb(WebKitWebView
*webview
, int progress
, gpointer user_data
);
28 static void webview_load_committed_cb(WebKitWebView
*webview
, WebKitWebFrame
*frame
, gpointer user_data
);
29 static void webview_load_finished_cb(WebKitWebView
*webview
, WebKitWebFrame
*frame
, gpointer user_data
);
30 static gboolean
webview_navigation_cb(WebKitWebView
*webview
, WebKitWebFrame
*frame
, WebKitNetworkRequest
*request
,
31 WebKitWebPolicyDecision
*decision
, gpointer user_data
);
32 static gboolean
webview_open_in_new_window_cb(WebKitWebView
*webview
, WebKitWebFrame
*frame
, gpointer user_data
);
33 static gboolean
webview_new_window_cb(WebKitWebView
*webview
, WebKitWebFrame
*frame
, WebKitNetworkRequest
*request
,
34 WebKitWebNavigationAction
*action
, WebKitWebPolicyDecision
*decision
, gpointer user_data
);
35 static gboolean
webview_mimetype_cb(WebKitWebView
*webview
, WebKitWebFrame
*frame
, WebKitNetworkRequest
*request
,
36 char *mime_type
, WebKitWebPolicyDecision
*decision
, gpointer user_data
);
37 static gboolean
webview_download_cb(WebKitWebView
*webview
, WebKitDownload
*download
, gpointer user_data
);
38 static gboolean
webview_keypress_cb(WebKitWebView
*webview
, GdkEventKey
*event
);
39 static void webview_hoverlink_cb(WebKitWebView
*webview
, char *title
, char *link
, gpointer data
);
40 static gboolean
webview_console_cb(WebKitWebView
*webview
, char *message
, int line
, char *source
, gpointer user_data
);
41 static void webview_scroll_cb(GtkAdjustment
*adjustment
, gpointer user_data
);
42 static void inputbox_activate_cb(GtkEntry
*entry
, gpointer user_data
);
43 static gboolean
inputbox_keypress_cb(GtkEntry
*entry
, GdkEventKey
*event
);
44 static gboolean
inputbox_keyrelease_cb(GtkEntry
*entry
, GdkEventKey
*event
);
45 static gboolean
notify_event_cb(GtkWidget
*widget
, GdkEvent
*event
, gpointer user_data
);
48 static gboolean
complete(const Arg
*arg
);
49 static gboolean
descend(const Arg
*arg
);
50 static gboolean
echo(const Arg
*arg
);
51 static gboolean
input(const Arg
*arg
);
52 static gboolean
navigate(const Arg
*arg
);
53 static gboolean
number(const Arg
*arg
);
54 static gboolean
open(const Arg
*arg
);
55 static gboolean
paste(const Arg
*arg
);
56 static gboolean
quit(const Arg
*arg
);
57 static gboolean
search(const Arg
*arg
);
58 static gboolean
set(const Arg
*arg
);
59 static gboolean
script(const Arg
*arg
);
60 static gboolean
scroll(const Arg
*arg
);
61 static gboolean
yank(const Arg
*arg
);
62 static gboolean
zoom(const Arg
*arg
);
63 static void update_url();
64 static void update_state();
65 static void setup_modkeys();
66 static void setup_gui();
67 static void setup_settings();
68 static void setup_signals();
69 static void ascii_bar(int total
, int state
, char *string
);
70 static gchar
*jsapi_ref_to_string(JSContextRef context
, JSValueRef ref
);
71 static void jsapi_evaluate_script(const gchar
*script
, gchar
**value
, gchar
**message
);
72 static gboolean
toggle_plugins();
73 static gboolean
toggle_images();
74 static gboolean
bookmark();
75 static void history();
78 static GtkWidget
*window
;
80 static GtkAdjustment
*adjust_h
;
81 static GtkAdjustment
*adjust_v
;
82 static GtkWidget
*inputbox
;
83 static GtkWidget
*eventbox
;
84 static GtkWidget
*status_url
;
85 static GtkWidget
*status_state
;
86 static WebKitWebView
*webview
;
87 static SoupSession
*session
;
88 static GtkClipboard
*clipboards
[2];
91 static unsigned int mode
= ModeNormal
;
92 static unsigned int count
= 0;
93 static float zoomstep
;
94 static char scroll_state
[4] = "\0";
96 static char current_modkey
;
97 static char *search_handle
;
98 static gboolean search_direction
;
99 static gboolean echo_active
= FALSE
;
101 char rememberedURI
[128] = "";
103 char inputBuffer
[5] = "";
109 window_destroyed_cb(GtkWidget
*window
, gpointer func_data
) {
114 webview_title_changed_cb(WebKitWebView
*webview
, WebKitWebFrame
*frame
, char *title
, gpointer user_data
) {
115 gtk_window_set_title(GTK_WINDOW(window
), title
);
119 webview_progress_changed_cb(WebKitWebView
*webview
, int progress
, gpointer user_data
) {
120 #ifdef ENABLE_GTK_PROGRESS_BAR
121 gtk_entry_set_progress_fraction(GTK_ENTRY(inputbox
), progress
== 100 ? 0 : (double)progress
/100);
126 #ifdef ENABLE_WGET_PROGRESS_BAR
128 ascii_bar(int total
, int state
, char *string
) {
131 for(i
= 0; i
< state
; i
++)
132 string
[i
] = progressbartickchar
;
133 string
[i
++] = progressbarcurrent
;
134 for(; i
< total
; i
++)
135 string
[i
] = progressbarspacer
;
141 webview_load_committed_cb(WebKitWebView
*webview
, WebKitWebFrame
*frame
, gpointer user_data
) {
142 const char *uri
= webkit_web_view_get_uri(webview
);
148 webview_load_finished_cb(WebKitWebView
*webview
, WebKitWebFrame
*frame
, gpointer user_data
) {
149 Arg a
= { .i
= Silent
, .s
= JS_SETUP
};
151 if (HISTORY_MAX_ENTRIES
> 0)
158 webview_navigation_cb(WebKitWebView
*webview
, WebKitWebFrame
*frame
, WebKitNetworkRequest
*request
,
159 WebKitWebPolicyDecision
*decision
, gpointer user_data
) {
164 webview_open_in_new_window_cb(WebKitWebView
*webview
, WebKitWebFrame
*frame
, gpointer user_data
) {
165 Arg a
= { .i
= TargetNew
, .s
= (char*)webkit_web_view_get_uri(webview
) };
166 if (strlen(rememberedURI
) > 0) {
174 webview_new_window_cb(WebKitWebView
*webview
, WebKitWebFrame
*frame
, WebKitNetworkRequest
*request
,
175 WebKitWebNavigationAction
*action
, WebKitWebPolicyDecision
*decision
, gpointer user_data
) {
176 Arg a
= { .i
= TargetNew
, .s
= (char*)webkit_network_request_get_uri(request
) };
178 webkit_web_policy_decision_ignore(decision
);
183 webview_mimetype_cb(WebKitWebView
*webview
, WebKitWebFrame
*frame
, WebKitNetworkRequest
*request
,
184 char *mime_type
, WebKitWebPolicyDecision
*decision
, gpointer user_data
) {
185 if (webkit_web_view_can_show_mime_type(webview
, mime_type
) == FALSE
) {
186 webkit_web_policy_decision_download(decision
);
187 WebKitDownload
*download
= webkit_download_new(request
);
188 return webview_download_cb(webview
, download
, user_data
);
195 webview_download_cb(WebKitWebView
*webview
, WebKitDownload
*download
, gpointer user_data
) {
196 const gchar
*filename
;
197 gchar
*uri
, *path
, *html
;
198 filename
= webkit_download_get_suggested_filename(download
);
199 if (filename
== NULL
|| strlen(filename
) == 0) {
200 filename
= "vimprobable_download";
202 path
= g_build_filename(g_strdup_printf(DOWNLOADS_PATH
), filename
, NULL
);
203 uri
= g_strconcat("file://", path
, NULL
);
204 webkit_download_set_destination_uri(download
, uri
);
206 html
= g_strdup_printf("Download <b>%s</b>...", filename
);
207 webkit_web_view_load_html_string(webview
, html
, webkit_download_get_uri(download
));
214 webview_keypress_cb(WebKitWebView
*webview
, GdkEventKey
*event
) {
216 Arg a
= { .i
= ModeNormal
, .s
= NULL
};
220 if(CLEAN(event
->state
) == 0) {
221 memset(inputBuffer
, 0, 5);
222 if(current_modkey
== 0 && ((event
->keyval
>= GDK_1
&& event
->keyval
<= GDK_9
)
223 || (event
->keyval
== GDK_0
&& count
))) {
224 count
= (count
? count
* 10 : 0) + (event
->keyval
- GDK_0
);
227 } else if(strchr(modkeys
, event
->keyval
) && current_modkey
!= event
->keyval
) {
228 current_modkey
= event
->keyval
;
234 for(i
= 0; i
< LENGTH(keys
); i
++)
235 if(keys
[i
].mask
== CLEAN(event
->state
)
236 && (keys
[i
].modkey
== current_modkey
237 || (!keys
[i
].modkey
&& !current_modkey
)
238 || keys
[i
].modkey
== GDK_VoidSymbol
) /* wildcard */
239 && keys
[i
].key
== event
->keyval
241 if(keys
[i
].func(&keys
[i
].arg
)) {
242 current_modkey
= count
= 0;
248 if(CLEAN(event
->state
) == 0 && event
->keyval
== GDK_Escape
) {
250 a
.s
= "clearfocus()";
255 case ModePassThrough
:
256 if(CLEAN(event
->state
) == 0 && event
->keyval
== GDK_Escape
) {
267 if(CLEAN(event
->state
) == 0 && event
->keyval
== GDK_Escape
) {
274 } else if (CLEAN(event
->state
) == 0 && ((event
->keyval
>= GDK_1
&& event
->keyval
<= GDK_9
)
275 || (event
->keyval
== GDK_0
&& count
))) {
276 /* allow a zero as non-first number */
277 count
= (count
? count
* 10 : 0) + (event
->keyval
- GDK_0
);
278 if (strlen(inputBuffer
) <= 4) {
279 memset(inputKey
, 0, 2);
280 sprintf(inputKey
, "%d", (event
->keyval
- GDK_0
));
281 strncat(inputBuffer
, inputKey
, 1);
282 a
.s
= g_strconcat("update_hints(", inputBuffer
, ")", NULL
);
295 } else if (CLEAN(event
->state
) == 0 && event
->keyval
== GDK_Return
) {
296 a
.s
= g_strconcat("fire(", inputBuffer
, ")", NULL
);
299 memset(inputBuffer
, 0, 5);
302 } else if (CLEAN(event
->state
) == 0 && event
->keyval
== GDK_BackSpace
) {
303 if (strlen(inputBuffer
) > 0) {
304 strncpy((inputBuffer
+ strlen(inputBuffer
) - 1), "\0", 1);
305 a
.s
= g_strconcat("update_hints(", inputBuffer
, ")", NULL
);
307 count
= ((count
>= 10) ? count
/10 : 0);
318 webview_hoverlink_cb(WebKitWebView
*webview
, char *title
, char *link
, gpointer data
) {
319 const char *uri
= webkit_web_view_get_uri(webview
);
321 memset(rememberedURI
, 0, 128);
323 gtk_label_set_markup(GTK_LABEL(status_url
), g_markup_printf_escaped("<span font=\"%s\">Link: %s</span>", statusfont
, link
));
324 strncpy(rememberedURI
, link
, 128);
330 webview_console_cb(WebKitWebView
*webview
, char *message
, int line
, char *source
, gpointer user_data
) {
333 if(!strcmp(message
, "hintmode_off") || !strcmp(message
, "insertmode_off")) {
336 } else if(!strcmp(message
, "insertmode_on")) {
344 webview_scroll_cb(GtkAdjustment
*adjustment
, gpointer user_data
) {
349 inputbox_activate_cb(GtkEntry
*entry
, gpointer user_data
) {
351 guint16 length
= gtk_entry_get_text_length(entry
);
355 gboolean success
= FALSE
, forward
= FALSE
;
357 a
.i
= HideCompletion
;
361 text
= (char*)gtk_entry_get_text(entry
);
363 for(i
= 0; i
< LENGTH(commands
); i
++) {
364 len
= strlen(commands
[i
].cmd
);
365 if(length
>= len
&& !strncmp(&text
[1], commands
[i
].cmd
, len
) && (text
[len
+ 1] == ' ' || !text
[len
+ 1])) {
366 a
.i
= commands
[i
].arg
.i
;
367 a
.s
= length
> len
+ 2 ? &text
[len
+ 2] : commands
[i
].arg
.s
;
368 if((success
= commands
[i
].func(&a
)))
374 a
.s
= g_strdup_printf("Not a browser command: %s", &text
[1]);
378 } else if((forward
= text
[0] == '/') || text
[0] == '?') {
379 webkit_web_view_unmark_text_matches(webview
);
380 #ifdef ENABLE_MATCH_HIGHLITING
381 webkit_web_view_mark_text_matches(webview
, &text
[1], FALSE
, 0);
382 webkit_web_view_set_highlight_text_matches(webview
, TRUE
);
386 a
.i
= searchoptions
| (forward
? DirectionForward
: DirectionBackwards
);
391 gtk_entry_set_text(entry
, "");
392 gtk_widget_grab_focus(GTK_WIDGET(webview
));
396 inputbox_keypress_cb(GtkEntry
*entry
, GdkEventKey
*event
) {
399 if(event
->keyval
== GDK_Escape
) {
400 a
.i
= HideCompletion
;
404 } else if(event
->keyval
== GDK_Tab
) {
407 } else if(event
->keyval
== GDK_ISO_Left_Tab
) {
415 notify_event_cb(GtkWidget
*widget
, GdkEvent
*event
, gpointer user_data
) {
417 if (mode
== ModeNormal
&& event
->type
== GDK_BUTTON_RELEASE
) {
418 /* handle mouse click events */
419 for (i
= 0; i
< LENGTH(mouse
); i
++) {
420 if (mouse
[i
].mask
== CLEAN(event
->button
.state
)
421 && (mouse
[i
].modkey
== current_modkey
422 || (!mouse
[i
].modkey
&& !current_modkey
)
423 || mouse
[i
].modkey
== GDK_VoidSymbol
) /* wildcard */
424 && mouse
[i
].button
== event
->button
.button
426 if (mouse
[i
].func(&mouse
[i
].arg
)) {
427 current_modkey
= count
= 0;
437 static gboolean
inputbox_keyrelease_cb(GtkEntry
*entry
, GdkEventKey
*event
) {
439 guint16 length
= gtk_entry_get_text_length(entry
);
440 #ifdef ENABLE_INCREMENTAL_SEARCH
441 char *text
= (char*)gtk_entry_get_text(entry
);
442 gboolean forward
= FALSE
;
445 a
.i
= HideCompletion
;
450 #ifdef ENABLE_INCREMENTAL_SEARCH
451 else if(length
> 1 && ((forward
= text
[0] == '/') || text
[0] == '?')) {
452 webkit_web_view_unmark_text_matches(webview
);
453 webkit_web_view_search_text(webview
, &text
[1], searchoptions
& CaseSensitive
, forward
, searchoptions
& Wrapping
);
461 complete(const Arg
*arg
) {
463 const char *filename
;
464 char *str
, *s
, *p
, *markup
, *entry
, *searchfor
, command
[32] = "", suggline
[512] = "", *url
, **suggurls
;
465 size_t listlen
, len
, cmdlen
;
467 gboolean highlight
= FALSE
, finished
= FALSE
;
469 GtkWidget
*row_eventbox
, *el
;
472 static GtkWidget
*table
, **widgets
, *top_border
;
473 static char **suggestions
, *prefix
;
474 static int n
= 0, current
= -1;
476 str
= (char*)gtk_entry_get_text(GTK_ENTRY(inputbox
));
478 if((len
== 0 || str
[0] != ':') && arg
->i
!= HideCompletion
)
481 if(arg
->i
!= HideCompletion
&& widgets
&& current
!= -1 && !strcmp(&str
[1], suggestions
[current
])) {
482 gdk_color_parse(completionbgcolor
[0], &color
);
483 gtk_widget_modify_bg(widgets
[current
], GTK_STATE_NORMAL
, &color
);
484 current
= (n
+ current
+ (arg
->i
== DirectionPrev
? -1 : 1)) % n
;
485 if((arg
->i
== DirectionNext
&& current
== 0)
486 || (arg
->i
== DirectionPrev
&& current
== n
- 1))
492 gtk_widget_destroy(GTK_WIDGET(table
));
493 gtk_widget_destroy(GTK_WIDGET(top_border
));
500 if(arg
->i
== HideCompletion
)
503 } else if(arg
->i
== HideCompletion
)
506 prefix
= strdup(str
);
507 listlen
= LENGTH(commands
);
508 widgets
= malloc(sizeof(GtkWidget
*) * listlen
);
509 suggestions
= malloc(sizeof(char*) * listlen
);
510 top_border
= gtk_event_box_new();
511 gtk_widget_set_size_request(GTK_WIDGET(top_border
), 0, 1);
512 gdk_color_parse(completioncolor
[2], &color
);
513 gtk_widget_modify_bg(top_border
, GTK_STATE_NORMAL
, &color
);
514 table
= gtk_event_box_new();
515 gdk_color_parse(completionbgcolor
[0], &color
);
516 _table
= GTK_BOX(gtk_vbox_new(FALSE
, 0));
518 if (strchr(str
, ' ') == NULL
) {
519 for(i
= 0; i
< listlen
; i
++) {
520 cmdlen
= strlen(commands
[i
].cmd
);
521 if(!highlight
|| (len
- 1 <= cmdlen
&& !strncmp(&str
[1], commands
[i
].cmd
, len
- 1))) {
522 p
= s
= malloc(sizeof(char*) * (highlight
? sizeof(COMPLETION_TAG_OPEN
) + sizeof(COMPLETION_TAG_CLOSE
) - 1 : 1) + cmdlen
);
524 memcpy(p
, COMPLETION_TAG_OPEN
, sizeof(COMPLETION_TAG_OPEN
) - 1);
525 memcpy((p
+= sizeof(COMPLETION_TAG_OPEN
) - 1), &str
[1], len
- 1);
526 memcpy((p
+= len
- 1), COMPLETION_TAG_CLOSE
, sizeof(COMPLETION_TAG_CLOSE
) - 1);
527 p
+= sizeof(COMPLETION_TAG_CLOSE
) - 1;
529 memcpy(p
, &commands
[i
].cmd
[len
- 1], cmdlen
- len
+ 2);
530 row
= GTK_BOX(gtk_hbox_new(FALSE
, 0));
531 row_eventbox
= gtk_event_box_new();
532 gtk_widget_modify_bg(row_eventbox
, GTK_STATE_NORMAL
, &color
);
533 el
= gtk_label_new(NULL
);
534 markup
= g_strconcat("<span font=\"", completionfont
[0], "\" color=\"", completioncolor
[0], "\">", s
, "</span>", NULL
);
536 gtk_label_set_markup(GTK_LABEL(el
), markup
);
538 gtk_misc_set_alignment(GTK_MISC(el
), 0, 0);
539 gtk_box_pack_start(row
, el
, TRUE
, TRUE
, 2);
540 gtk_container_add(GTK_CONTAINER(row_eventbox
), GTK_WIDGET(row
));
541 gtk_box_pack_start(_table
, GTK_WIDGET(row_eventbox
), FALSE
, FALSE
, 0);
542 suggestions
[n
] = commands
[i
].cmd
;
543 widgets
[n
++] = row_eventbox
;
547 /* URL completion using the current command */
548 entry
= (char *)malloc(512 * sizeof(char));
550 memset(entry
, 0, 512);
551 suggurls
= malloc(sizeof(char*) * listlen
);
552 if (suggurls
!= NULL
) {
553 spacepos
= strcspn(str
, " ");
554 searchfor
= (str
+ spacepos
+ 1);
555 strncpy(command
, (str
+ 1), spacepos
- 1);
556 filename
= g_strdup_printf(BOOKMARKS_STORAGE_FILENAME
);
557 f
= fopen(filename
, "r");
559 while (finished
!= TRUE
) {
560 if ((char *)NULL
== fgets(entry
, 512, f
)) {
561 /* check if end of file was reached / error occured */
565 /* end of file reached */
569 if (strstr(entry
, searchfor
) != NULL
) {
570 /* found in bookmarks */
571 memset(suggline
, 0, 512);
572 strncpy(suggline
, command
, 512);
573 strncat(suggline
, " ", 1);
574 url
= strtok(entry
, " ");
575 strncat(suggline
, url
, 512 - strlen(suggline
) - 1);
576 suggurls
[n
] = (char *)malloc(sizeof(char) * 512 + 1);
577 strncpy(suggurls
[n
], suggline
, 512);
578 suggestions
[n
] = suggurls
[n
];
579 row
= GTK_BOX(gtk_hbox_new(FALSE
, 0));
580 row_eventbox
= gtk_event_box_new();
581 gtk_widget_modify_bg(row_eventbox
, GTK_STATE_NORMAL
, &color
);
582 el
= gtk_label_new(NULL
);
583 markup
= g_strconcat("<span font=\"", completionfont
[0], "\" color=\"", completioncolor
[0], "\">", g_markup_escape_text(suggline
, strlen(suggline
)), "</span>", NULL
);
584 gtk_label_set_markup(GTK_LABEL(el
), markup
);
586 gtk_misc_set_alignment(GTK_MISC(el
), 0, 0);
587 gtk_box_pack_start(row
, el
, TRUE
, TRUE
, 2);
588 gtk_container_add(GTK_CONTAINER(row_eventbox
), GTK_WIDGET(row
));
589 gtk_box_pack_start(_table
, GTK_WIDGET(row_eventbox
), FALSE
, FALSE
, 0);
590 widgets
[n
++] = row_eventbox
;
599 filename
= g_strdup_printf(HISTORY_STORAGE_FILENAME
);
600 f
= fopen(filename
, "r");
603 while (finished
!= TRUE
) {
604 if ((char *)NULL
== fgets(entry
, 512, f
)) {
605 /* check if end of file was reached / error occured */
609 /* end of file reached */
613 if (strstr(entry
, searchfor
) != NULL
) {
614 /* found in history */
615 memset(suggline
, 0, 512);
616 strncpy(suggline
, command
, 512);
617 strncat(suggline
, " ", 1);
618 url
= strtok(entry
, " ");
619 strncat(suggline
, url
, 512 - strlen(suggline
) - 1);
620 suggurls
[n
] = (char *)malloc(sizeof(char) * 512 + 1);
621 strncpy(suggurls
[n
], suggline
, 512);
622 suggestions
[n
] = suggurls
[n
];
623 row
= GTK_BOX(gtk_hbox_new(FALSE
, 0));
624 row_eventbox
= gtk_event_box_new();
625 gtk_widget_modify_bg(row_eventbox
, GTK_STATE_NORMAL
, &color
);
626 el
= gtk_label_new(NULL
);
627 markup
= g_strconcat("<span font=\"", completionfont
[0], "\" color=\"", completioncolor
[0], "\">", g_markup_escape_text(suggline
, strlen(suggline
)), "</span>", NULL
);
628 gtk_label_set_markup(GTK_LABEL(el
), markup
);
630 gtk_misc_set_alignment(GTK_MISC(el
), 0, 0);
631 gtk_box_pack_start(row
, el
, TRUE
, TRUE
, 2);
632 gtk_container_add(GTK_CONTAINER(row_eventbox
), GTK_WIDGET(row
));
633 gtk_box_pack_start(_table
, GTK_WIDGET(row_eventbox
), FALSE
, FALSE
, 0);
634 widgets
[n
++] = row_eventbox
;
644 if (suggurls
!= NULL
) {
655 widgets
= realloc(widgets
, sizeof(GtkWidget
*) * n
);
656 suggestions
= realloc(suggestions
, sizeof(char*) * n
);
658 gdk_color_parse(completionbgcolor
[1], &color
);
659 gtk_widget_modify_bg(table
, GTK_STATE_NORMAL
, &color
);
660 el
= gtk_label_new(NULL
);
661 gtk_misc_set_alignment(GTK_MISC(el
), 0, 0);
662 markup
= g_strconcat("<span font=\"", completionfont
[1], "\" color=\"", completioncolor
[1], "\">No Completions</span>", NULL
);
663 gtk_label_set_markup(GTK_LABEL(el
), markup
);
665 gtk_box_pack_start(_table
, GTK_WIDGET(el
), FALSE
, FALSE
, 0);
667 gtk_box_pack_start(box
, GTK_WIDGET(top_border
), FALSE
, FALSE
, 0);
668 gtk_container_add(GTK_CONTAINER(table
), GTK_WIDGET(_table
));
669 gtk_box_pack_start(box
, GTK_WIDGET(table
), FALSE
, FALSE
, 0);
670 gtk_widget_show_all(window
);
673 current
= arg
->i
== DirectionPrev
? n
- 1 : 0;
676 gdk_color_parse(completionbgcolor
[2], &color
);
677 gtk_widget_modify_bg(GTK_WIDGET(widgets
[current
]), GTK_STATE_NORMAL
, &color
);
678 s
= g_strconcat(":", suggestions
[current
], NULL
);
679 gtk_entry_set_text(GTK_ENTRY(inputbox
), s
);
682 gtk_entry_set_text(GTK_ENTRY(inputbox
), prefix
);
683 gtk_editable_set_position(GTK_EDITABLE(inputbox
), -1);
688 descend(const Arg
*arg
) {
689 char *source
= (char*)webkit_web_view_get_uri(webview
), *p
= &source
[0], *new;
691 count
= count
? count
: 1;
695 if(arg
->i
== Rootdir
) {
696 for(i
= 0; i
< 3; i
++) /* get to the third slash */
697 if(!(p
= strchr(++p
, '/')))
698 return TRUE
; /* if we cannot find it quit */
700 len
= strlen(source
);
701 if(!len
) /* if string is empty quit */
703 p
= source
+ len
; /* start at the end */
704 if(*(p
- 1) == '/') /* /\/$/ is not an additional level */
706 for(i
= 0; i
< count
; i
++)
707 while(*(p
--) != '/' || *p
== '/') /* count /\/+/ as one slash */
708 if(p
== source
) /* if we reach the first char pointer quit */
710 ++p
; /* since we do p-- in the while, we are pointing at
711 the char before the slash, so +1 */
713 len
= p
- source
+ 1; /* new length = end - start + 1 */
715 memcpy(new, source
, len
);
717 webkit_web_view_load_uri(webview
, new);
723 echo(const Arg
*arg
) {
724 PangoFontDescription
*font
;
726 int index
= !arg
->s
? 0 : arg
->i
& (~NoAutoHide
);
728 if(index
< Info
|| index
> Error
)
730 font
= pango_font_description_from_string(urlboxfont
[index
]);
731 gtk_widget_modify_font(inputbox
, font
);
732 pango_font_description_free(font
);
733 if(urlboxcolor
[index
])
734 gdk_color_parse(urlboxcolor
[index
], &color
);
735 gtk_widget_modify_text(inputbox
, GTK_STATE_NORMAL
, urlboxcolor
[index
] ? &color
: NULL
);
736 if(urlboxbgcolor
[index
])
737 gdk_color_parse(urlboxbgcolor
[index
], &color
);
738 gtk_widget_modify_base(inputbox
, GTK_STATE_NORMAL
, urlboxbgcolor
[index
] ? &color
: NULL
);
739 gtk_entry_set_text(GTK_ENTRY(inputbox
), !arg
->s
? "" : arg
->s
);
744 input(const Arg
*arg
) {
750 /* to avoid things like :open URL :open URL2 or :open :open URL */
751 gtk_entry_set_text(GTK_ENTRY(inputbox
), "");
752 gtk_editable_insert_text(GTK_EDITABLE(inputbox
), arg
->s
, -1, &pos
);
753 if(arg
->i
& InsertCurrentURL
&& (url
= webkit_web_view_get_uri(webview
)))
754 gtk_editable_insert_text(GTK_EDITABLE(inputbox
), url
, -1, &pos
);
755 gtk_widget_grab_focus(inputbox
);
756 gtk_editable_set_position(GTK_EDITABLE(inputbox
), -1);
761 navigate(const Arg
*arg
) {
762 if(arg
->i
& NavigationForwardBack
)
763 webkit_web_view_go_back_or_forward(webview
, (arg
->i
== NavigationBack
? -1 : 1) * (count
? count
: 1));
764 else if(arg
->i
& NavigationReloadActions
)
765 (arg
->i
== NavigationReload
? webkit_web_view_reload
: webkit_web_view_reload_bypass_cache
)(webview
);
767 webkit_web_view_stop_loading(webview
);
772 number(const Arg
*arg
) {
773 const char *source
= webkit_web_view_get_uri(webview
);
775 int number
, diff
= (count
? count
: 1) * (arg
->i
== Increment
? 1 : -1);
779 uri
= strdup(source
); /* copy string */
781 while(*p
!= '\0') /* goto the end of the string */
784 while(*p
>= '0' && *p
<= '9') /* go back until non number char is reached */
786 if(*(++p
) == '\0') { /* if no numbers were found abort */
790 number
= atoi(p
) + diff
; /* apply diff on number */
792 new = g_strdup_printf("%s%d", uri
, number
); /* create new uri */
793 webkit_web_view_load_uri(webview
, new);
800 open(const Arg
*arg
) {
801 char *argv
[] = { *args
, arg
->s
, NULL
};
802 char *s
= arg
->s
, *p
, *new;
803 Arg a
= { .i
= NavigationReload
};
808 else if(arg
->i
== TargetCurrent
) {
809 len
= strlen(arg
->s
);
810 new = NULL
, p
= strchr(arg
->s
, ' ');
811 if(p
) /* check for search engines */
812 for(i
= 0; i
< LENGTH(searchengines
); i
++)
813 if(!strncmp(arg
->s
, searchengines
[i
].handle
, p
- arg
->s
)) {
814 p
= soup_uri_encode(++p
, "&");
815 new = g_strdup_printf(searchengines
[i
].uri
, p
);
820 if(len
> 3 && strstr(arg
->s
, "://")) { /* valid url? */
821 p
= new = g_malloc(len
+ 1);
822 while(*s
!= '\0') { /* strip whitespaces */
828 } else if (strcspn(arg
->s
, "/") == 0) { /* prepend "file://" */
829 new = g_malloc(sizeof("file://") + len
);
830 strcpy(new, "file://");
831 memcpy(&new[sizeof("file://") - 1], arg
->s
, len
+ 1);
832 } else if(p
|| !strchr(arg
->s
, '.')) { /* whitespaces or no dot? */
833 p
= soup_uri_encode(arg
->s
, "&");
834 new = g_strdup_printf(defsearch
->uri
, p
);
836 } else { /* prepend "http://" */
837 new = g_malloc(sizeof("http://") + len
);
838 strcpy(new, "http://");
839 memcpy(&new[sizeof("http://") - 1], arg
->s
, len
+ 1);
842 webkit_web_view_load_uri(webview
, new);
845 g_spawn_async(NULL
, argv
, NULL
, G_SPAWN_SEARCH_PATH
, NULL
, NULL
, NULL
, NULL
);
850 yank(const Arg
*arg
) {
852 Arg a
= { .i
= Info
};
854 if(arg
->i
& SourceURL
) {
855 url
= webkit_web_view_get_uri(webview
);
858 a
.s
= g_strdup_printf("Yanked %s", url
);
861 if(arg
->i
& ClipboardPrimary
)
862 gtk_clipboard_set_text(clipboards
[0], url
, -1);
863 if(arg
->i
& ClipboardGTK
)
864 gtk_clipboard_set_text(clipboards
[1], url
, -1);
866 webkit_web_view_copy_clipboard(webview
);
871 paste(const Arg
*arg
) {
872 Arg a
= { .i
= arg
->i
& TargetNew
, .s
= NULL
};
874 if(arg
->i
& ClipboardPrimary
)
875 a
.s
= gtk_clipboard_wait_for_text(clipboards
[0]);
876 if(!a
.s
&& arg
->i
& ClipboardGTK
)
877 a
.s
= gtk_clipboard_wait_for_text(clipboards
[1]);
884 quit(const Arg
*arg
) {
890 search(const Arg
*arg
) {
891 count
= count
? count
: 1;
892 gboolean success
, direction
= arg
->i
& DirectionPrev
;
897 search_handle
= strdup(arg
->s
);
901 if(arg
->i
& DirectionAbsolute
)
902 search_direction
= direction
;
904 direction
^= search_direction
;
906 success
= webkit_web_view_search_text(webview
, search_handle
, arg
->i
& CaseSensitive
, direction
, FALSE
);
908 if(arg
->i
& Wrapping
) {
909 success
= webkit_web_view_search_text(webview
, search_handle
, arg
->i
& CaseSensitive
, direction
, TRUE
);
912 a
.s
= g_strdup_printf("search hit %s, continuing at %s",
913 direction
? "BOTTOM" : "TOP",
914 direction
? "TOP" : "BOTTOM");
925 a
.s
= g_strdup_printf("Pattern not found: %s", search_handle
);
933 set(const Arg
*arg
) {
934 Arg a
= { .i
= Info
| NoAutoHide
};
939 search_handle
= NULL
;
940 webkit_web_view_unmark_text_matches(webview
);
942 gtk_entry_set_text(GTK_ENTRY(inputbox
), "");
943 gtk_widget_grab_focus(GTK_WIDGET(webview
));
945 case ModePassThrough
:
946 a
.s
= "-- PASS THROUGH --";
950 a
.s
= "-- PASS TROUGH (next) --";
953 case ModeInsert
: /* should not be called manually but automatically */
954 a
.s
= "-- INSERT --";
959 a
.s
= "show_hints()";
970 jsapi_ref_to_string(JSContextRef context
, JSValueRef ref
) {
971 JSStringRef string_ref
;
975 string_ref
= JSValueToStringCopy(context
, ref
, NULL
);
976 length
= JSStringGetMaximumUTF8CStringSize(string_ref
);
977 string
= g_new(gchar
, length
);
978 JSStringGetUTF8CString(string_ref
, string
, length
);
979 JSStringRelease(string_ref
);
984 jsapi_evaluate_script(const gchar
*script
, gchar
**value
, gchar
**message
) {
985 WebKitWebFrame
*frame
= webkit_web_view_get_main_frame(webview
);
986 JSGlobalContextRef context
= webkit_web_frame_get_global_context(frame
);
988 JSValueRef val
, exception
;
990 str
= JSStringCreateWithUTF8CString(script
);
991 val
= JSEvaluateScript(context
, str
, JSContextGetGlobalObject(context
), NULL
, 0, &exception
);
992 JSStringRelease(str
);
994 *message
= jsapi_ref_to_string(context
, exception
);
996 *value
= jsapi_ref_to_string(context
, val
);
1000 script(const Arg
*arg
) {
1001 gchar
*value
= NULL
, *message
= NULL
;
1006 jsapi_evaluate_script(arg
->s
, &value
, &message
);
1013 if(arg
->i
!= Silent
&& value
) {
1019 if (strlen(value
) == 5 && strncmp(value
, "fired", 5) == 0) {
1028 scroll(const Arg
*arg
) {
1029 GtkAdjustment
*adjust
= (arg
->i
& OrientationHoriz
) ? adjust_h
: adjust_v
;
1031 if(arg
->i
& ScrollMove
)
1032 gtk_adjustment_set_value(adjust
, gtk_adjustment_get_value(adjust
) +
1033 (arg
->i
& (1 << 2) ? 1 : -1) * /* direction */
1034 ((arg
->i
& UnitLine
|| (arg
->i
& UnitBuffer
&& count
)) ? (scrollstep
* (count
? count
: 1)) : (
1035 arg
->i
& UnitBuffer
? gtk_adjustment_get_page_size(adjust
) / 2 :
1036 (count
? count
: 1) * (gtk_adjustment_get_page_size(adjust
) -
1037 (gtk_adjustment_get_page_size(adjust
) > pagingkeep
? pagingkeep
: 0)))));
1039 gtk_adjustment_set_value(adjust
,
1040 ((arg
->i
& (1 << 2)) ? gtk_adjustment_get_upper
: gtk_adjustment_get_lower
)(adjust
));
1046 zoom(const Arg
*arg
) {
1047 webkit_web_view_set_full_content_zoom(webview
, (arg
->i
& ZoomFullContent
) > 0);
1048 webkit_web_view_set_zoom_level(webview
, (arg
->i
& ZoomOut
) ?
1049 webkit_web_view_get_zoom_level(webview
) +
1050 (((float)(count
? count
: 1)) * (arg
->i
& (1 << 1) ? 1.0 : -1.0) * zoomstep
) :
1051 (count
? (float)count
/ 100.0 : 1.0));
1057 static gboolean plugins
;
1058 WebKitWebSettings
*settings
;
1059 settings
= webkit_web_view_get_settings(webview
);
1061 g_object_set((GObject
*)settings
, "enable-plugins", plugins
, NULL
);
1062 g_object_set((GObject
*)settings
, "enable-scripts", plugins
, NULL
);
1063 webkit_web_view_set_settings(webview
, settings
);
1064 webkit_web_view_reload(webview
);
1070 static gboolean images
;
1071 WebKitWebSettings
*settings
;
1072 settings
= webkit_web_view_get_settings(webview
);
1074 g_object_set((GObject
*)settings
, "auto-load-images", images
, NULL
);
1075 webkit_web_view_set_settings(webview
, settings
);
1076 webkit_web_view_reload(webview
);
1083 const char *filename
;
1084 const char *uri
= webkit_web_view_get_uri(webview
);
1085 const char *title
= webkit_web_view_get_title(webview
);
1086 filename
= g_strdup_printf(BOOKMARKS_STORAGE_FILENAME
);
1087 f
= fopen(filename
, "a");
1088 if (f
!= NULL
&& uri
!= NULL
) {
1089 fprintf(f
, "%s", uri
);
1090 if (title
!= NULL
) {
1091 fprintf(f
, "%s", " ");
1092 fprintf(f
, "%s", title
);
1094 fprintf(f
, "%s", "\n");
1104 const char *filename
;
1105 const char *uri
= webkit_web_view_get_uri(webview
);
1106 const char *title
= webkit_web_view_get_title(webview
);
1107 char *entry
, buffer
[512], *new;
1109 gboolean finished
= FALSE
;
1110 if (entry
!= NULL
) {
1112 if (title
!= NULL
) {
1113 entry
= malloc((strlen(uri
) + strlen(title
) + 2) * sizeof(char));
1114 memset(entry
, 0, strlen(uri
) + strlen(title
) + 2);
1116 entry
= malloc((strlen(uri
) + 1) * sizeof(char));
1117 memset(entry
, 0, strlen(uri
) + 1);
1119 strncpy(entry
, uri
, strlen(uri
));
1120 if (title
!= NULL
) {
1121 strncat(entry
, " ", 1);
1122 strncat(entry
, title
, strlen(title
));
1125 filename
= g_strdup_printf(HISTORY_STORAGE_FILENAME
);
1126 f
= fopen(filename
, "r");
1128 new = (char *)malloc(HISTORY_MAX_ENTRIES
* 512 * sizeof(char) + 1);
1130 memset(new, 0, HISTORY_MAX_ENTRIES
* 512 * sizeof(char) + 1);
1131 /* newest entries go on top */
1132 strncpy(new, entry
, strlen(entry
));
1133 strncat(new, "\n", 1);
1134 /* retain at most HISTORY_MAX_ENTIRES - 1 old entries */
1135 while (finished
!= TRUE
) {
1136 if ((char *)NULL
== fgets(buffer
, 512, f
)) {
1137 /* check if end of file was reached / error occured */
1141 /* end of file reached */
1145 /* compare line (-1 because of newline character) */
1146 if (n
!= strlen(buffer
) - 1 || strncmp(entry
, buffer
, n
) != 0) {
1147 /* if the URI is already in history; we put it on top and skip it here */
1148 strncat(new, buffer
, 512);
1151 if (i
>= HISTORY_MAX_ENTRIES
) {
1157 f
= fopen(filename
, "w");
1159 fprintf(f
, "%s", new);
1168 if (entry
!= NULL
) {
1176 update_url(const char *uri
) {
1177 gboolean ssl
= g_str_has_prefix(uri
, "https://");
1179 #ifdef ENABLE_HISTORY_INDICATOR
1180 char before
[] = " [";
1182 gboolean back
= webkit_web_view_can_go_back(webview
);
1183 gboolean fwd
= webkit_web_view_can_go_forward(webview
);
1186 before
[0] = after
[0] = '\0';
1188 gtk_label_set_markup((GtkLabel
*)status_url
, g_markup_printf_escaped(
1189 #ifdef ENABLE_HISTORY_INDICATOR
1190 "<span font=\"%s\">%s%s%s%s%s</span>", statusfont
, uri
,
1191 before
, back
? "+" : "", fwd
? "-" : "", after
1193 "<span font=\"%s\">%s</span>", statusfont
, uri
1196 gdk_color_parse(ssl
? sslbgcolor
: statusbgcolor
, &color
);
1197 gtk_widget_modify_bg(eventbox
, GTK_STATE_NORMAL
, &color
);
1198 gdk_color_parse(ssl
? sslcolor
: statuscolor
, &color
);
1199 gtk_widget_modify_fg(GTK_WIDGET(status_url
), GTK_STATE_NORMAL
, &color
);
1200 gtk_widget_modify_fg(GTK_WIDGET(status_state
), GTK_STATE_NORMAL
, &color
);
1205 int max
= gtk_adjustment_get_upper(adjust_v
) - gtk_adjustment_get_page_size(adjust_v
);
1206 int val
= (int)(gtk_adjustment_get_value(adjust_v
) / max
* 100);
1208 #ifdef ENABLE_WGET_PROGRESS_BAR
1210 char progressbar
[progressbartick
+ 1];
1212 g_object_get((GObject
*)webview
, "progress", &progress
, NULL
);
1216 sprintf(&scroll_state
[0], "All");
1218 sprintf(&scroll_state
[0], "Top");
1220 sprintf(&scroll_state
[0], "Bot");
1222 sprintf(&scroll_state
[0], "%d%%", val
);
1223 #ifdef ENABLE_WGET_PROGRESS_BAR
1224 if(webkit_web_view_get_load_status(webview
) != WEBKIT_LOAD_FINISHED
) {
1225 ascii_bar(progressbartick
, (int)(progress
* progressbartick
/ 100), (char*)progressbar
);
1226 markup
= (char*)g_markup_printf_escaped("<span font=\"%s\">%.0d%c %c%s%c %s</span>",
1227 statusfont
, count
, current_modkey
, progressborderleft
, progressbar
, progressborderright
, scroll_state
);
1230 markup
= (char*)g_markup_printf_escaped("<span font=\"%s\">%.0d%c %s</span>", statusfont
, count
, current_modkey
, scroll_state
);
1231 gtk_label_set_markup(GTK_LABEL(status_state
), markup
);
1237 modkeys
= calloc(LENGTH(keys
) + 1, sizeof(char));
1238 char *ptr
= modkeys
;
1240 for(i
= 0; i
< LENGTH(keys
); i
++)
1241 if(keys
[i
].modkey
&& !strchr(modkeys
, keys
[i
].modkey
))
1242 *(ptr
++) = keys
[i
].modkey
;
1243 modkeys
= realloc(modkeys
, &ptr
[0] - &modkeys
[0] + 1);
1248 GtkScrollbar
*scroll_h
= GTK_SCROLLBAR(gtk_hscrollbar_new(NULL
));
1249 GtkScrollbar
*scroll_v
= GTK_SCROLLBAR(gtk_vscrollbar_new(NULL
));
1250 adjust_h
= gtk_range_get_adjustment(GTK_RANGE(scroll_h
));
1251 adjust_v
= gtk_range_get_adjustment(GTK_RANGE(scroll_v
));
1252 window
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
1253 box
= GTK_BOX(gtk_vbox_new(FALSE
, 0));
1254 inputbox
= gtk_entry_new();
1255 GtkWidget
*viewport
= gtk_scrolled_window_new(adjust_h
, adjust_v
);
1256 webview
= (WebKitWebView
*)webkit_web_view_new();
1257 GtkBox
*statusbar
= GTK_BOX(gtk_hbox_new(FALSE
, 0));
1258 eventbox
= gtk_event_box_new();
1259 status_url
= gtk_label_new(NULL
);
1260 status_state
= gtk_label_new(NULL
);
1262 PangoFontDescription
*font
;
1263 GdkGeometry hints
= { 1, 1 };
1265 clipboards
[0] = gtk_clipboard_get(GDK_SELECTION_PRIMARY
);
1266 clipboards
[1] = gtk_clipboard_get(GDK_NONE
);
1268 gdk_color_parse(statusbgcolor
, &bg
);
1269 gtk_widget_modify_bg(eventbox
, GTK_STATE_NORMAL
, &bg
);
1270 gtk_widget_set_name(window
, "Vimprobable");
1271 gtk_window_set_geometry_hints(GTK_WINDOW(window
), NULL
, &hints
, GDK_HINT_MIN_SIZE
);
1272 #ifdef DISABLE_SCROLLBAR
1273 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(viewport
), GTK_POLICY_NEVER
, GTK_POLICY_NEVER
);
1276 gtk_container_add(GTK_CONTAINER(viewport
), GTK_WIDGET(webview
));
1277 font
= pango_font_description_from_string(urlboxfont
[0]);
1278 gtk_widget_modify_font(GTK_WIDGET(inputbox
), font
);
1279 pango_font_description_free(font
);
1280 gtk_entry_set_inner_border(GTK_ENTRY(inputbox
), NULL
);
1281 gtk_misc_set_alignment(GTK_MISC(status_url
), 0.0, 0.0);
1282 gtk_misc_set_alignment(GTK_MISC(status_state
), 1.0, 0.0);
1283 gtk_box_pack_start(statusbar
, status_url
, TRUE
, TRUE
, 2);
1284 gtk_box_pack_start(statusbar
, status_state
, FALSE
, FALSE
, 2);
1285 gtk_container_add(GTK_CONTAINER(eventbox
), GTK_WIDGET(statusbar
));
1286 gtk_box_pack_start(box
, viewport
, TRUE
, TRUE
, 0);
1287 gtk_box_pack_start(box
, eventbox
, FALSE
, FALSE
, 0);
1288 gtk_entry_set_has_frame(GTK_ENTRY(inputbox
), FALSE
);
1289 gtk_box_pack_end(box
, inputbox
, FALSE
, FALSE
, 0);
1290 gtk_container_add(GTK_CONTAINER(window
), GTK_WIDGET(box
));
1291 gtk_widget_grab_focus(GTK_WIDGET(webview
));
1292 gtk_widget_show_all(window
);
1297 WebKitWebSettings
*settings
= (WebKitWebSettings
*)webkit_web_settings_new();
1299 char *filename
, *new;
1301 #ifdef ENABLE_COOKIE_SUPPORT
1302 SoupCookieJar
*cookiejar
;
1304 session
= webkit_get_default_session();
1305 g_object_set((GObject
*)settings
, "default-font-size", DEFAULT_FONT_SIZE
, NULL
);
1306 g_object_set((GObject
*)settings
, "enable-scripts", enablePlugins
, NULL
);
1307 g_object_set((GObject
*)settings
, "enable-plugins", enablePlugins
, NULL
);
1308 filename
= g_strdup_printf(USER_STYLES_FILENAME
);
1309 filename
= g_strdup_printf("file://%s", filename
);
1310 g_object_set((GObject
*)settings
, "user-stylesheet-uri", filename
, NULL
);
1311 g_object_set((GObject
*)settings
, "user-agent", USER_AGENT
, NULL
);
1312 g_object_get((GObject
*)settings
, "zoom-step", &zoomstep
, NULL
);
1313 webkit_web_view_set_settings(webview
, settings
);
1314 #ifdef ENABLE_COOKIE_SUPPORT
1315 filename
= g_strdup_printf(COOKIES_STORAGE_FILENAME
);
1316 cookiejar
= soup_cookie_jar_text_new(filename
, COOKIES_STORAGE_READONLY
);
1318 soup_session_add_feature(session
, (SoupSessionFeature
*)cookiejar
);
1321 filename
= (char *)g_getenv("http_proxy");
1322 if (filename
!= NULL
&& 0 < (len
= strlen(filename
))) {
1323 if(strstr(filename
, "://") == NULL
) {
1324 /* prepend http:// */
1325 new = g_malloc(sizeof("http://") + len
);
1326 strcpy(new, "http://");
1327 memcpy(&new[sizeof("http://") - 1], filename
, len
+ 1);
1328 proxy_uri
= soup_uri_new(new);
1330 proxy_uri
= soup_uri_new(filename
);
1332 g_object_set(session
, "proxy-uri", proxy_uri
, NULL
);
1339 g_object_connect((GObject
*)window
,
1340 "signal::destroy", (GCallback
)window_destroyed_cb
, NULL
,
1343 g_object_connect((GObject
*)webview
,
1344 "signal::title-changed", (GCallback
)webview_title_changed_cb
, NULL
,
1345 "signal::load-progress-changed", (GCallback
)webview_progress_changed_cb
, NULL
,
1346 "signal::load-committed", (GCallback
)webview_load_committed_cb
, NULL
,
1347 "signal::load-finished", (GCallback
)webview_load_finished_cb
, NULL
,
1348 "signal::navigation-policy-decision-requested", (GCallback
)webview_navigation_cb
, NULL
,
1349 "signal::new-window-policy-decision-requested", (GCallback
)webview_new_window_cb
, NULL
,
1350 "signal::mime-type-policy-decision-requested", (GCallback
)webview_mimetype_cb
, NULL
,
1351 "signal::download-requested", (GCallback
)webview_download_cb
, NULL
,
1352 "signal::key-press-event", (GCallback
)webview_keypress_cb
, NULL
,
1353 "signal::hovering-over-link", (GCallback
)webview_hoverlink_cb
, NULL
,
1354 "signal::console-message", (GCallback
)webview_console_cb
, NULL
,
1355 "signal::create-web-view", (GCallback
)webview_open_in_new_window_cb
, NULL
,
1356 "signal::event", (GCallback
)notify_event_cb
, NULL
,
1358 /* webview adjustment */
1359 g_object_connect((GObject
*)adjust_v
,
1360 "signal::value-changed", (GCallback
)webview_scroll_cb
, NULL
,
1363 g_object_connect((GObject
*)inputbox
,
1364 "signal::activate", (GCallback
)inputbox_activate_cb
, NULL
,
1365 "signal::key-press-event", (GCallback
)inputbox_keypress_cb
, NULL
,
1366 "signal::key-release-event", (GCallback
)inputbox_keyrelease_cb
, NULL
,
1371 main(int argc
, char *argv
[]) {
1375 gtk_init(&argc
, &argv
);
1376 if(!g_thread_supported())
1377 g_thread_init(NULL
);
1380 a
.i
= TargetCurrent
;
1381 a
.s
= argc
> 1 ? argv
[1] : startpage
;
1385 return EXIT_SUCCESS
;