3 (c) 2009 by Leon Winter
4 (c) 2009, 2010 by Hannes Schueller
5 (c) 2009, 2010 by Matto Fransen
11 #include "vimprobable.h"
12 #include "utilities.h"
13 #include "callbacks.h"
14 #include "javascript.h"
16 /* remove numlock symbol from keymask */
17 #define CLEAN(mask) (mask & ~(GDK_MOD2_MASK) & ~(GDK_BUTTON1_MASK) & ~(GDK_BUTTON2_MASK) & ~(GDK_BUTTON3_MASK) & ~(GDK_BUTTON4_MASK) & ~(GDK_BUTTON5_MASK))
20 static void inputbox_activate_cb(GtkEntry
*entry
, gpointer user_data
);
21 static gboolean
inputbox_keypress_cb(GtkEntry
*entry
, GdkEventKey
*event
);
22 static gboolean
inputbox_keyrelease_cb(GtkEntry
*entry
, GdkEventKey
*event
);
23 static gboolean
inputbox_changed_cb(GtkEditable
*entry
, gpointer user_data
);
24 static WebKitWebView
* inspector_inspect_web_view_cb(gpointer inspector
, WebKitWebView
* web_view
);
25 static gboolean
notify_event_cb(GtkWidget
*widget
, GdkEvent
*event
, gpointer user_data
);
26 static gboolean
webview_console_cb(WebKitWebView
*webview
, char *message
, int line
, char *source
, gpointer user_data
);
27 static gboolean
webview_download_cb(WebKitWebView
*webview
, WebKitDownload
*download
, gpointer user_data
);
28 static void webview_hoverlink_cb(WebKitWebView
*webview
, char *title
, char *link
, gpointer data
);
29 static gboolean
webview_keypress_cb(WebKitWebView
*webview
, GdkEventKey
*event
);
30 static void webview_load_committed_cb(WebKitWebView
*webview
, WebKitWebFrame
*frame
, gpointer user_data
);
31 static void webview_load_finished_cb(WebKitWebView
*webview
, WebKitWebFrame
*frame
, gpointer user_data
);
32 static gboolean
webview_mimetype_cb(WebKitWebView
*webview
, WebKitWebFrame
*frame
, WebKitNetworkRequest
*request
,
33 char *mime_type
, WebKitWebPolicyDecision
*decision
, gpointer user_data
);
34 static gboolean
webview_new_window_cb(WebKitWebView
*webview
, WebKitWebFrame
*frame
, WebKitNetworkRequest
*request
,
35 WebKitWebNavigationAction
*action
, WebKitWebPolicyDecision
*decision
, gpointer user_data
);
36 static gboolean
webview_open_in_new_window_cb(WebKitWebView
*webview
, WebKitWebFrame
*frame
, gpointer user_data
);
37 static void webview_progress_changed_cb(WebKitWebView
*webview
, int progress
, gpointer user_data
);
38 static void webview_title_changed_cb(WebKitWebView
*webview
, WebKitWebFrame
*frame
, char *title
, gpointer user_data
);
39 static void window_destroyed_cb(GtkWidget
*window
, gpointer func_data
);
42 static gboolean
bookmark(const Arg
*arg
);
43 static gboolean
browser_settings(const Arg
*arg
);
44 static gboolean
commandhistoryfetch(const Arg
*arg
);
45 static gboolean
complete(const Arg
*arg
);
46 static gboolean
descend(const Arg
*arg
);
47 gboolean
echo(const Arg
*arg
);
48 static gboolean
focus_input(const Arg
*arg
);
49 static gboolean
input(const Arg
*arg
);
50 static gboolean
navigate(const Arg
*arg
);
51 static gboolean
number(const Arg
*arg
);
52 static gboolean
open_arg(const Arg
*arg
);
53 static gboolean
paste(const Arg
*arg
);
54 static gboolean
quickmark(const Arg
*arg
);
55 static gboolean
quit(const Arg
*arg
);
56 static gboolean
revive(const Arg
*arg
);
57 static gboolean
print_frame(const Arg
*arg
);
58 static gboolean
search(const Arg
*arg
);
59 static gboolean
set(const Arg
*arg
);
60 static gboolean
script(const Arg
*arg
);
61 static gboolean
scroll(const Arg
*arg
);
62 static gboolean
search_tag(const Arg
*arg
);
63 static gboolean
yank(const Arg
*arg
);
64 static gboolean
view_source(const Arg
* arg
);
65 static gboolean
zoom(const Arg
*arg
);
66 static gboolean
fake_key_event(const Arg
*arg
);
68 static void update_url(const char *uri
);
69 static void setup_modkeys(void);
70 static void setup_gui(void);
71 static void setup_settings(void);
72 static void setup_signals(void);
73 static void ascii_bar(int total
, int state
, char *string
);
74 static gchar
*jsapi_ref_to_string(JSContextRef context
, JSValueRef ref
);
75 static void jsapi_evaluate_script(const gchar
*script
, gchar
**value
, gchar
**message
);
76 static void download_progress(WebKitDownload
*d
, GParamSpec
*pspec
);
77 static void set_widget_font_and_color(GtkWidget
*widget
, const char *font_str
,
78 const char *bg_color_str
, const char *fg_color_str
);
80 static gboolean
history(void);
81 static gboolean
process_set_line(char *line
);
82 void save_command_history(char *line
);
83 void toggle_proxy(gboolean onoff
);
84 void toggle_scrollbars(gboolean onoff
);
86 gboolean
process_keypress(GdkEventKey
*event
);
87 void fill_suggline(char * suggline
, const char * command
, const char *fill_with
);
88 GtkWidget
* fill_eventbox(const char * completion_line
);
94 static GtkWindow
*window
;
95 static GtkWidget
*viewport
;
97 static GtkScrollbar
*scroll_h
;
98 static GtkScrollbar
*scroll_v
;
99 static GtkAdjustment
*adjust_h
;
100 static GtkAdjustment
*adjust_v
;
101 static GtkWidget
*inputbox
;
102 static GtkWidget
*eventbox
;
103 static GtkWidget
*status_url
;
104 static GtkWidget
*status_state
;
105 static WebKitWebView
*webview
;
106 static SoupSession
*session
;
107 static GtkClipboard
*clipboards
[2];
110 static unsigned int mode
= ModeNormal
;
111 static unsigned int count
= 0;
112 static float zoomstep
;
113 static char *modkeys
;
114 static char current_modkey
;
115 static char *search_handle
;
116 static gboolean search_direction
;
117 static gboolean echo_active
= TRUE
;
118 WebKitWebInspector
*inspector
;
120 static GdkNativeWindow embed
= 0;
121 static char *configfile
= NULL
;
122 static char *winid
= NULL
;
124 static char rememberedURI
[128] = "";
125 static char inputKey
[5];
126 static char inputBuffer
[65] = "";
127 static char chars
[65] = "0000000000000000000000000000000000000000000000000000000000000000\n";
128 static char followTarget
[8] = "";
129 char *error_msg
= NULL
;
131 GList
*activeDownloads
;
136 char commandhistory
[COMMANDHISTSIZE
][255];
139 int commandpointer
= 0;
140 KeyList
*keylistroot
= NULL
;
142 /* Cookie-related information.
144 * Note that this cannot be surrounded by #ifdef blocks for
145 * ENABLE_COOKIE_SUPPORT
147 static time_t cookie_timeout
= 4800;
148 static char *cookie_store
;
149 static void handle_cookie_request(SoupMessage
*soup_msg
, gpointer unused
);
150 static const char *get_cookies(SoupURI
*soup_uri
);
151 static void set_single_cookie(SoupCookie
*cookie
);
152 static void new_generic_request(SoupSession
*soup_ses
, SoupMessage
*soup_msg
, gpointer unused
);
156 window_destroyed_cb(GtkWidget
*window
, gpointer func_data
) {
161 webview_title_changed_cb(WebKitWebView
*webview
, WebKitWebFrame
*frame
, char *title
, gpointer user_data
) {
162 gtk_window_set_title(window
, title
);
166 webview_progress_changed_cb(WebKitWebView
*webview
, int progress
, gpointer user_data
) {
167 #ifdef ENABLE_GTK_PROGRESS_BAR
168 gtk_entry_set_progress_fraction(GTK_ENTRY(inputbox
), progress
== 100 ? 0 : (double)progress
/100);
173 #ifdef ENABLE_WGET_PROGRESS_BAR
175 ascii_bar(int total
, int state
, char *string
) {
178 for (i
= 0; i
< state
; i
++)
179 string
[i
] = progressbartickchar
;
180 string
[i
++] = progressbarcurrent
;
181 for (; i
< total
; i
++)
182 string
[i
] = progressbarspacer
;
188 webview_load_committed_cb(WebKitWebView
*webview
, WebKitWebFrame
*frame
, gpointer user_data
) {
189 Arg a
= { .i
= Silent
, .s
= JS_SETUP_HINTS
};
190 const char *uri
= webkit_web_view_get_uri(webview
);
197 webview_load_finished_cb(WebKitWebView
*webview
, WebKitWebFrame
*frame
, gpointer user_data
) {
198 Arg a
= { .i
= Silent
, .s
= JS_SETUP_INPUT_FOCUS
};
200 if (HISTORY_MAX_ENTRIES
> 0)
207 webview_open_in_new_window_cb(WebKitWebView
*webview
, WebKitWebFrame
*frame
, gpointer user_data
) {
208 Arg a
= { .i
= TargetNew
, .s
= (char*)webkit_web_view_get_uri(webview
) };
209 if (strlen(rememberedURI
) > 0) {
217 webview_new_window_cb(WebKitWebView
*webview
, WebKitWebFrame
*frame
, WebKitNetworkRequest
*request
,
218 WebKitWebNavigationAction
*action
, WebKitWebPolicyDecision
*decision
, gpointer user_data
) {
219 Arg a
= { .i
= TargetNew
, .s
= (char*)webkit_network_request_get_uri(request
) };
221 webkit_web_policy_decision_ignore(decision
);
226 webview_mimetype_cb(WebKitWebView
*webview
, WebKitWebFrame
*frame
, WebKitNetworkRequest
*request
,
227 char *mime_type
, WebKitWebPolicyDecision
*decision
, gpointer user_data
) {
228 if (webkit_web_view_can_show_mime_type(webview
, mime_type
) == FALSE
) {
229 webkit_web_policy_decision_download(decision
);
236 static WebKitWebView
*
237 inspector_inspect_web_view_cb(gpointer inspector
, WebKitWebView
* web_view
) {
238 gchar
* inspector_title
;
239 GtkWidget
* inspector_window
;
240 GtkWidget
* inspector_view
;
242 /* just enough code to show the inspector - no signal handling etc. */
243 inspector_title
= g_strdup_printf("Inspect page - %s - Vimprobable2", webkit_web_view_get_uri(web_view
));
245 inspector_window
= gtk_plug_new(embed
);
247 inspector_window
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
248 gtk_window_set_wmclass(window
, "vimprobable2", "Vimprobable2");
250 gtk_window_set_title(GTK_WINDOW(inspector_window
), inspector_title
);
251 g_free(inspector_title
);
252 inspector_view
= webkit_web_view_new();
253 gtk_container_add(GTK_CONTAINER(inspector_window
), inspector_view
);
254 gtk_widget_show_all(inspector_window
);
255 return WEBKIT_WEB_VIEW(inspector_view
);
259 webview_download_cb(WebKitWebView
*webview
, WebKitDownload
*download
, gpointer user_data
) {
260 const gchar
*filename
;
265 filename
= webkit_download_get_suggested_filename(download
);
266 if (filename
== NULL
|| strlen(filename
) == 0) {
267 filename
= "vimprobable_download";
269 path
= g_build_filename(g_strdup_printf(DOWNLOADS_PATH
), filename
, NULL
);
270 uri
= g_strconcat("file://", path
, NULL
);
271 webkit_download_set_destination_uri(download
, uri
);
273 size
= (uint32_t)webkit_download_get_total_size(download
);
276 a
.s
= g_strdup_printf("Download %s started (expected size: %u bytes)...", filename
, size
);
278 a
.s
= g_strdup_printf("Download %s started (unknown size)...", filename
);
280 activeDownloads
= g_list_prepend(activeDownloads
, download
);
281 g_signal_connect(download
, "notify::progress", G_CALLBACK(download_progress
), NULL
);
282 g_signal_connect(download
, "notify::status", G_CALLBACK(download_progress
), NULL
);
288 download_progress(WebKitDownload
*d
, GParamSpec
*pspec
) {
290 WebKitDownloadStatus status
= webkit_download_get_status(d
);
292 if (status
!= WEBKIT_DOWNLOAD_STATUS_STARTED
&& status
!= WEBKIT_DOWNLOAD_STATUS_CREATED
) {
293 if (status
!= WEBKIT_DOWNLOAD_STATUS_FINISHED
) {
295 a
.s
= g_strdup_printf("Error while downloading %s", webkit_download_get_suggested_filename(d
));
299 a
.s
= g_strdup_printf("Download %s finished", webkit_download_get_suggested_filename(d
));
302 activeDownloads
= g_list_remove(activeDownloads
, d
);
309 process_keypress(GdkEventKey
*event
) {
312 current
= keylistroot
;
313 while (current
!= NULL
) {
314 if (current
->Element
.mask
== CLEAN(event
->state
)
315 && (current
->Element
.modkey
== current_modkey
316 || (!current
->Element
.modkey
&& !current_modkey
)
317 || current
->Element
.modkey
== GDK_VoidSymbol
) /* wildcard */
318 && current
->Element
.key
== event
->keyval
319 && current
->Element
.func
)
320 if (current
->Element
.func(¤t
->Element
.arg
)) {
321 current_modkey
= count
= 0;
325 current
= current
->next
;
331 webview_keypress_cb(WebKitWebView
*webview
, GdkEventKey
*event
) {
332 Arg a
= { .i
= ModeNormal
, .s
= NULL
};
336 if (CLEAN(event
->state
) == 0) {
337 memset(inputBuffer
, 0, 65);
338 if (event
->keyval
== GDK_Escape
) {
342 } else if (current_modkey
== 0 && ((event
->keyval
>= GDK_1
&& event
->keyval
<= GDK_9
)
343 || (event
->keyval
== GDK_0
&& count
))) {
344 count
= (count
? count
* 10 : 0) + (event
->keyval
- GDK_0
);
347 } else if (strchr(modkeys
, event
->keyval
) && current_modkey
!= event
->keyval
) {
348 current_modkey
= event
->keyval
;
354 if (process_keypress(event
) == TRUE
) return TRUE
;
358 if (CLEAN(event
->state
) == 0 && event
->keyval
== GDK_Escape
) {
360 a
.s
= "vimprobable_clearfocus()";
365 case ModePassThrough
:
366 if (CLEAN(event
->state
) == 0 && event
->keyval
== GDK_Escape
) {
377 if (CLEAN(event
->state
) == 0 && event
->keyval
== GDK_Escape
) {
379 a
.s
= "vimprobable_clear()";
383 strncpy(chars
, "0000000000000000000000000000000000000000000000000000000000000000\0", 65);
385 } else if (CLEAN(event
->state
) == 0 && ((event
->keyval
>= GDK_1
&& event
->keyval
<= GDK_9
)
386 || (event
->keyval
>= GDK_KP_1
&& event
->keyval
<= GDK_KP_9
)
387 || ((event
->keyval
== GDK_0
|| event
->keyval
== GDK_KP_0
) && count
))) {
388 /* allow a zero as non-first number */
389 if (event
->keyval
>= GDK_KP_1
&& event
->keyval
<= GDK_KP_9
)
390 count
= (count
? count
* 10 : 0) + (event
->keyval
- GDK_KP_0
);
392 count
= (count
? count
* 10 : 0) + (event
->keyval
- GDK_0
);
393 memset(inputBuffer
, 0, 65);
394 sprintf(inputBuffer
, "%d", count
);
395 a
.s
= g_strconcat("vimprobable_update_hints(", inputBuffer
, ")", NULL
);
397 memset(inputBuffer
, 0, 65);
398 strncpy(chars
, "0000000000000000000000000000000000000000000000000000000000000000\0", 65);
402 } else if ((CLEAN(event
->state
) == 0 && (event
->keyval
>= GDK_a
&& event
->keyval
<= GDK_z
))
403 || (CLEAN(event
->state
) == GDK_SHIFT_MASK
&& (event
->keyval
>= GDK_A
&& event
->keyval
<= GDK_Z
))
404 || ((CLEAN(event
->state
) == 0 || CLEAN(event
->state
) == GDK_SHIFT_MASK
) && (event
->keyval
>= GDK_space
&& event
->keyval
<= GDK_slash
))
405 || ((CLEAN(event
->state
) == 0 || CLEAN(event
->state
) == GDK_SHIFT_MASK
) && (event
->keyval
>= GDK_colon
&& event
->keyval
<= GDK_at
))
406 || ((CLEAN(event
->state
) == 0 || CLEAN(event
->state
) == GDK_SHIFT_MASK
) && (event
->keyval
>= GDK_braceleft
&& event
->keyval
<= GDK_umacron
))
407 || ((CLEAN(event
->state
) == 0 || CLEAN(event
->state
) == GDK_SHIFT_MASK
) && (event
->keyval
>= GDK_Babovedot
&& event
->keyval
<= GDK_ycircumflex
))
408 || ((CLEAN(event
->state
) == 0 || CLEAN(event
->state
) == GDK_SHIFT_MASK
) && (event
->keyval
>= GDK_OE
&& event
->keyval
<= GDK_Ydiaeresis
))
409 || ((CLEAN(event
->state
) == 0 || CLEAN(event
->state
) == GDK_SHIFT_MASK
) && (event
->keyval
>= GDK_overline
&& event
->keyval
<= GDK_semivoicedsound
))
410 || ((CLEAN(event
->state
) == 0 || CLEAN(event
->state
) == GDK_SHIFT_MASK
) && (event
->keyval
>= GDK_Farsi_0
&& event
->keyval
<= GDK_Arabic_9
))
411 || ((CLEAN(event
->state
) == 0 || CLEAN(event
->state
) == GDK_SHIFT_MASK
) && (event
->keyval
>= GDK_Arabic_semicolon
&& event
->keyval
<= GDK_Arabic_sukun
))
412 || ((CLEAN(event
->state
) == 0 || CLEAN(event
->state
) == GDK_SHIFT_MASK
) && (event
->keyval
>= GDK_Arabic_madda_above
&& event
->keyval
<= GDK_Arabic_heh_goal
))
413 || ((CLEAN(event
->state
) == 0 || CLEAN(event
->state
) == GDK_SHIFT_MASK
) && (event
->keyval
>= GDK_Cyrillic_GHE_bar
&& event
->keyval
<= GDK_Cyrillic_u_macron
))
414 || ((CLEAN(event
->state
) == 0 || CLEAN(event
->state
) == GDK_SHIFT_MASK
) && (event
->keyval
>= GDK_Serbian_dje
&& event
->keyval
<= GDK_Korean_Won
))
415 || ((CLEAN(event
->state
) == 0 || CLEAN(event
->state
) == GDK_SHIFT_MASK
) && (event
->keyval
>= GDK_Armenian_ligature_ew
&& event
->keyval
<= GDK_braille_dots_12345678
))) {
416 /* update hints by link text */
417 if (strlen(inputBuffer
) < 65) {
418 memset(inputKey
, 0, 5);
419 /* support multibyte characters */
420 sprintf(inputKey
, "%C", event
->keyval
);
421 strncat(inputBuffer
, inputKey
, 64 - strlen(inputBuffer
));
422 /* remember the number of bytes of each character */
423 for (count
= 0; count
< 64; count
++) {
424 if (strncmp((chars
+ count
), "0", 1) == 0) {
425 sprintf(inputKey
, "%d", (int)strlen(inputKey
));
426 strncpy((chars
+ count
), inputKey
, 1);
430 memset(inputKey
, 0, 5);
433 a
.s
= "vimprobable_cleanup()";
435 a
.s
= g_strconcat("vimprobable_show_hints('", inputBuffer
, "')", NULL
);
441 } else if (CLEAN(event
->state
) == 0 && event
->keyval
== GDK_Return
&& count
) {
442 memset(inputBuffer
, 0, 65);
443 sprintf(inputBuffer
, "%d", count
);
444 a
.s
= g_strconcat("vimprobable_fire(", inputBuffer
, ")", NULL
);
447 memset(inputBuffer
, 0, 65);
449 strncpy(chars
, "0000000000000000000000000000000000000000000000000000000000000000\0", 65);
452 } else if (CLEAN(event
->state
) == 0 && event
->keyval
== GDK_BackSpace
) {
455 memset(inputBuffer
, 0, 65);
456 sprintf(inputBuffer
, "%d", count
);
457 a
.s
= g_strconcat("vimprobable_update_hints(", inputBuffer
, ")", NULL
);
459 memset(inputBuffer
, 0, 65);
462 } else if (count
> 0) {
464 memset(inputBuffer
, 0, 65);
466 a
.s
= "vimprobable_cleanup()";
468 a
.s
= g_strconcat("vimprobable_show_hints()", NULL
);
472 } else if (strlen(inputBuffer
) > 0) {
474 a
.s
= "vimprobable_cleanup()";
476 /* check how many bytes the last character uses */
477 for (count
= 0; count
< 64; count
++) {
478 if (strncmp((chars
+ count
), "0", 1) == 0) {
482 memset(inputKey
, 0, 5);
483 strncpy(inputKey
, (chars
+ count
- 1), 1);
484 strncpy((chars
+ count
- 1), "0", 1);
485 count
= atoi(inputKey
);
486 /* remove the appropriate number of bytes from the string */
487 strncpy((inputBuffer
+ strlen(inputBuffer
) - count
), "\0", 1);
489 a
.s
= g_strconcat("vimprobable_show_hints('", inputBuffer
, "')", NULL
);
502 set_widget_font_and_color(GtkWidget
*widget
, const char *font_str
, const char *bg_color_str
,
503 const char *fg_color_str
) {
506 PangoFontDescription
*font
;
508 font
= pango_font_description_from_string(font_str
);
509 gtk_widget_modify_font(widget
, font
);
510 pango_font_description_free(font
);
513 gdk_color_parse(fg_color_str
, &fg_color
);
515 gdk_color_parse(bg_color_str
, &bg_color
);
517 gtk_widget_modify_text(widget
, GTK_STATE_NORMAL
, fg_color_str
? &fg_color
: NULL
);
518 gtk_widget_modify_base(widget
, GTK_STATE_NORMAL
, bg_color_str
? &bg_color
: NULL
);
524 webview_hoverlink_cb(WebKitWebView
*webview
, char *title
, char *link
, gpointer data
) {
525 const char *uri
= webkit_web_view_get_uri(webview
);
527 memset(rememberedURI
, 0, 128);
529 gtk_label_set_markup(GTK_LABEL(status_url
), g_markup_printf_escaped("<span font=\"%s\">Link: %s</span>", statusfont
, link
));
530 strncpy(rememberedURI
, link
, 128);
536 webview_console_cb(WebKitWebView
*webview
, char *message
, int line
, char *source
, gpointer user_data
) {
539 /* Don't change internal mode if the browser doesn't have focus to prevent inconsistent states */
540 if (gtk_window_has_toplevel_focus(window
)) {
541 if (!strcmp(message
, "hintmode_off") || !strcmp(message
, "insertmode_off")) {
544 } else if (!strcmp(message
, "insertmode_on")) {
553 inputbox_activate_cb(GtkEntry
*entry
, gpointer user_data
) {
555 guint16 length
= gtk_entry_get_text_length(entry
);
559 gboolean success
= FALSE
, forward
= FALSE
, found
= FALSE
;
561 a
.i
= HideCompletion
;
565 text
= (char*)gtk_entry_get_text(entry
);
566 if (text
[0] == ':') {
567 for (i
= 0; i
< LENGTH(commands
); i
++) {
568 len
= strlen(commands
[i
].cmd
);
569 if (length
>= len
&& !strncmp(&text
[1], commands
[i
].cmd
, len
) && (text
[len
+ 1] == ' ' || !text
[len
+ 1])) {
571 a
.i
= commands
[i
].arg
.i
;
572 a
.s
= length
> len
+ 2 ? &text
[len
+ 2] : commands
[i
].arg
.s
;
573 success
= commands
[i
].func(&a
);
578 save_command_history(text
);
582 a
.s
= g_strdup_printf("Not a browser command: %s", &text
[1]);
585 } else if (!success
) {
587 if (error_msg
!= NULL
) {
588 a
.s
= g_strdup_printf("%s", error_msg
);
592 a
.s
= g_strdup_printf("Unknown error. Please file a bug report!");
597 } else if ((forward
= text
[0] == '/') || text
[0] == '?') {
598 webkit_web_view_unmark_text_matches(webview
);
599 #ifdef ENABLE_MATCH_HIGHLITING
600 webkit_web_view_mark_text_matches(webview
, &text
[1], FALSE
, 0);
601 webkit_web_view_set_highlight_text_matches(webview
, TRUE
);
604 #ifndef ENABLE_INCREMENTAL_SEARCH
606 a
.i
= searchoptions
| (forward
? DirectionForward
: DirectionBackwards
);
609 search_direction
= forward
;
610 search_handle
= g_strdup(&text
[1]);
615 gtk_entry_set_text(entry
, "");
616 gtk_widget_grab_focus(GTK_WIDGET(webview
));
620 inputbox_keypress_cb(GtkEntry
*entry
, GdkEventKey
*event
) {
623 switch (event
->keyval
) {
625 a
.i
= HideCompletion
;
636 return commandhistoryfetch(&a
);
640 return commandhistoryfetch(&a
);
642 case GDK_ISO_Left_Tab
:
651 notify_event_cb(GtkWidget
*widget
, GdkEvent
*event
, gpointer user_data
) {
653 if (mode
== ModeNormal
&& event
->type
== GDK_BUTTON_RELEASE
) {
654 /* handle mouse click events */
655 for (i
= 0; i
< LENGTH(mouse
); i
++) {
656 if (mouse
[i
].mask
== CLEAN(event
->button
.state
)
657 && (mouse
[i
].modkey
== current_modkey
658 || (!mouse
[i
].modkey
&& !current_modkey
)
659 || mouse
[i
].modkey
== GDK_VoidSymbol
) /* wildcard */
660 && mouse
[i
].button
== event
->button
.button
662 if (mouse
[i
].func(&mouse
[i
].arg
)) {
663 current_modkey
= count
= 0;
673 static gboolean
inputbox_keyrelease_cb(GtkEntry
*entry
, GdkEventKey
*event
) {
675 guint16 length
= gtk_entry_get_text_length(entry
);
678 a
.i
= HideCompletion
;
686 static gboolean
inputbox_changed_cb(GtkEditable
*entry
, gpointer user_data
) {
687 char *text
= (char*)gtk_entry_get_text(GTK_ENTRY(entry
));
688 guint16 length
= gtk_entry_get_text_length(GTK_ENTRY(entry
));
689 gboolean forward
= FALSE
;
691 /* Update incremental search if the user changes the search text.
693 * Note: gtk_widget_is_focus() is a poor way to check if the change comes
694 * from the user. But if the entry is focused and the text is set
695 * through gtk_entry_set_text() in some asyncrounous operation,
696 * I would consider that a bug.
699 if (gtk_widget_is_focus(GTK_WIDGET(entry
)) && length
> 1 && ((forward
= text
[0] == '/') || text
[0] == '?')) {
700 webkit_web_view_unmark_text_matches(webview
);
701 webkit_web_view_search_text(webview
, &text
[1], searchoptions
& CaseSensitive
, forward
, searchoptions
& Wrapping
);
710 void fill_suggline(char * suggline
, const char * command
, const char *fill_with
) {
711 memset(suggline
, 0, 512);
712 strncpy(suggline
, command
, 512);
713 strncat(suggline
, " ", 1);
714 strncat(suggline
, fill_with
, 512 - strlen(suggline
) - 1);
717 GtkWidget
* fill_eventbox(const char * completion_line
) {
719 GtkWidget
*row_eventbox
, *el
;
723 row
= GTK_BOX(gtk_hbox_new(FALSE
, 0));
724 row_eventbox
= gtk_event_box_new();
725 gdk_color_parse(completionbgcolor
[0], &color
);
726 gtk_widget_modify_bg(row_eventbox
, GTK_STATE_NORMAL
, &color
);
727 el
= gtk_label_new(NULL
);
728 markup
= g_strconcat("<span font=\"", completionfont
[0], "\" color=\"", completioncolor
[0], "\">",
729 g_markup_escape_text(completion_line
, strlen(completion_line
)), "</span>", NULL
);
730 gtk_label_set_markup(GTK_LABEL(el
), markup
);
732 gtk_misc_set_alignment(GTK_MISC(el
), 0, 0);
733 gtk_box_pack_start(row
, el
, TRUE
, TRUE
, 2);
734 gtk_container_add(GTK_CONTAINER(row_eventbox
), GTK_WIDGET(row
));
739 complete(const Arg
*arg
) {
741 const char *filename
;
742 char *str
, *s
, *p
, *markup
, *entry
, *searchfor
, command
[32] = "", suggline
[512] = "", *url
, **suggurls
;
743 size_t listlen
, len
, cmdlen
;
745 gboolean highlight
= FALSE
, finished
= FALSE
;
747 GtkWidget
*row_eventbox
, *el
;
750 static GtkWidget
*table
, **widgets
, *top_border
;
751 static char **suggestions
, *prefix
;
752 static int n
= 0, current
= -1;
754 str
= (char*)gtk_entry_get_text(GTK_ENTRY(inputbox
));
756 if ((len
== 0 || str
[0] != ':') && arg
->i
!= HideCompletion
)
759 if (arg
->i
!= HideCompletion
&& widgets
&& current
!= -1 && !strcmp(&str
[1], suggestions
[current
])) {
760 gdk_color_parse(completionbgcolor
[0], &color
);
761 gtk_widget_modify_bg(widgets
[current
], GTK_STATE_NORMAL
, &color
);
762 current
= (n
+ current
+ (arg
->i
== DirectionPrev
? -1 : 1)) % n
;
763 if ((arg
->i
== DirectionNext
&& current
== 0)
764 || (arg
->i
== DirectionPrev
&& current
== n
- 1))
770 gtk_widget_destroy(GTK_WIDGET(table
));
771 gtk_widget_destroy(GTK_WIDGET(top_border
));
778 if (arg
->i
== HideCompletion
)
781 } else if (arg
->i
== HideCompletion
)
784 prefix
= g_strdup_printf(str
);
785 listlen
= LENGTH(commands
);
786 widgets
= malloc(sizeof(GtkWidget
*) * listlen
);
787 suggestions
= malloc(sizeof(char*) * listlen
);
788 top_border
= gtk_event_box_new();
789 gtk_widget_set_size_request(GTK_WIDGET(top_border
), 0, 1);
790 gdk_color_parse(completioncolor
[2], &color
);
791 gtk_widget_modify_bg(top_border
, GTK_STATE_NORMAL
, &color
);
792 table
= gtk_event_box_new();
793 gdk_color_parse(completionbgcolor
[0], &color
);
794 _table
= GTK_BOX(gtk_vbox_new(FALSE
, 0));
796 if (strchr(str
, ' ') == NULL
) {
797 for (i
= 0; i
< listlen
; i
++) {
798 cmdlen
= strlen(commands
[i
].cmd
);
799 if (!highlight
|| (len
- 1 <= cmdlen
&& !strncmp(&str
[1], commands
[i
].cmd
, len
- 1))) {
800 p
= s
= malloc(sizeof(char*) * (highlight
? sizeof(COMPLETION_TAG_OPEN
) + sizeof(COMPLETION_TAG_CLOSE
) - 1 : 1) + cmdlen
);
802 memcpy(p
, COMPLETION_TAG_OPEN
, sizeof(COMPLETION_TAG_OPEN
) - 1);
803 memcpy((p
+= sizeof(COMPLETION_TAG_OPEN
) - 1), &str
[1], len
- 1);
804 memcpy((p
+= len
- 1), COMPLETION_TAG_CLOSE
, sizeof(COMPLETION_TAG_CLOSE
) - 1);
805 p
+= sizeof(COMPLETION_TAG_CLOSE
) - 1;
807 memcpy(p
, &commands
[i
].cmd
[len
- 1], cmdlen
- len
+ 2);
808 row
= GTK_BOX(gtk_hbox_new(FALSE
, 0));
809 row_eventbox
= gtk_event_box_new();
810 gtk_widget_modify_bg(row_eventbox
, GTK_STATE_NORMAL
, &color
);
811 el
= gtk_label_new(NULL
);
812 markup
= g_strconcat("<span font=\"", completionfont
[0], "\" color=\"", completioncolor
[0], "\">", s
, "</span>", NULL
);
814 gtk_label_set_markup(GTK_LABEL(el
), markup
);
816 gtk_misc_set_alignment(GTK_MISC(el
), 0, 0);
817 gtk_box_pack_start(row
, el
, TRUE
, TRUE
, 2);
818 gtk_container_add(GTK_CONTAINER(row_eventbox
), GTK_WIDGET(row
));
819 gtk_box_pack_start(_table
, GTK_WIDGET(row_eventbox
), FALSE
, FALSE
, 0);
820 suggestions
[n
] = commands
[i
].cmd
;
821 widgets
[n
++] = row_eventbox
;
825 entry
= (char *)malloc(512 * sizeof(char));
827 memset(entry
, 0, 512);
828 suggurls
= malloc(sizeof(char*) * listlen
);
829 if (suggurls
!= NULL
) {
830 spacepos
= strcspn(str
, " ");
831 searchfor
= (str
+ spacepos
+ 1);
832 strncpy(command
, (str
+ 1), spacepos
- 1);
833 if (strlen(command
) == 3 && strncmp(command
, "set", 3) == 0) {
834 /* browser settings */
835 listlen
= LENGTH(browsersettings
);
836 for (i
= 0; i
< listlen
; i
++) {
837 if (strstr(browsersettings
[i
].name
, searchfor
) != NULL
) {
839 fill_suggline(suggline
, command
, browsersettings
[i
].name
);
840 suggurls
[n
] = (char *)malloc(sizeof(char) * 512 + 1);
841 strncpy(suggurls
[n
], suggline
, 512);
842 suggestions
[n
] = suggurls
[n
];
843 row_eventbox
= fill_eventbox(suggline
);
844 gtk_box_pack_start(_table
, GTK_WIDGET(row_eventbox
), FALSE
, FALSE
, 0);
845 widgets
[n
++] = row_eventbox
;
850 /* URL completion using the current command */
851 filename
= g_strdup_printf(BOOKMARKS_STORAGE_FILENAME
);
852 f
= fopen(filename
, "r");
854 while (finished
!= TRUE
) {
855 if ((char *)NULL
== fgets(entry
, 512, f
)) {
856 /* check if end of file was reached / error occured */
860 /* end of file reached */
864 if (strstr(entry
, searchfor
) != NULL
) {
865 /* found in bookmarks */
866 if (strchr(entry
, ' ') != NULL
) {
867 url
= strtok(entry
, " ");
869 url
= strtok(entry
, "\n");
871 fill_suggline(suggline
, command
, url
);
872 suggurls
[n
] = (char *)malloc(sizeof(char) * 512 + 1);
873 strncpy(suggurls
[n
], suggline
, 512);
874 suggestions
[n
] = suggurls
[n
];
875 row_eventbox
= fill_eventbox(suggline
);
876 gtk_box_pack_start(_table
, GTK_WIDGET(row_eventbox
), FALSE
, FALSE
, 0);
877 widgets
[n
++] = row_eventbox
;
886 filename
= g_strdup_printf(HISTORY_STORAGE_FILENAME
);
887 f
= fopen(filename
, "r");
890 while (finished
!= TRUE
) {
891 if ((char *)NULL
== fgets(entry
, 512, f
)) {
892 /* check if end of file was reached / error occured */
896 /* end of file reached */
900 if (strstr(entry
, searchfor
) != NULL
) {
901 /* found in history */
902 if (strchr(entry
, ' ') != NULL
) {
903 url
= strtok(entry
, " ");
905 url
= strtok(entry
, "\n");
907 fill_suggline(suggline
, command
, url
);
908 suggurls
[n
] = (char *)malloc(sizeof(char) * 512 + 1);
909 strncpy(suggurls
[n
], suggline
, 512);
910 suggestions
[n
] = suggurls
[n
];
911 row_eventbox
= fill_eventbox(suggline
);
912 gtk_box_pack_start(_table
, GTK_WIDGET(row_eventbox
), FALSE
, FALSE
, 0);
913 widgets
[n
++] = row_eventbox
;
924 if (suggurls
!= NULL
) {
935 widgets
= realloc(widgets
, sizeof(GtkWidget
*) * n
);
936 suggestions
= realloc(suggestions
, sizeof(char*) * n
);
938 gdk_color_parse(completionbgcolor
[1], &color
);
939 gtk_widget_modify_bg(table
, GTK_STATE_NORMAL
, &color
);
940 el
= gtk_label_new(NULL
);
941 gtk_misc_set_alignment(GTK_MISC(el
), 0, 0);
942 markup
= g_strconcat("<span font=\"", completionfont
[1], "\" color=\"", completioncolor
[1], "\">No Completions</span>", NULL
);
943 gtk_label_set_markup(GTK_LABEL(el
), markup
);
945 gtk_box_pack_start(_table
, GTK_WIDGET(el
), FALSE
, FALSE
, 0);
947 gtk_box_pack_start(box
, GTK_WIDGET(top_border
), FALSE
, FALSE
, 0);
948 gtk_container_add(GTK_CONTAINER(table
), GTK_WIDGET(_table
));
949 gtk_box_pack_start(box
, GTK_WIDGET(table
), FALSE
, FALSE
, 0);
950 gtk_widget_show_all(GTK_WIDGET(window
));
953 current
= arg
->i
== DirectionPrev
? n
- 1 : 0;
956 gdk_color_parse(completionbgcolor
[2], &color
);
957 gtk_widget_modify_bg(GTK_WIDGET(widgets
[current
]), GTK_STATE_NORMAL
, &color
);
958 s
= g_strconcat(":", suggestions
[current
], NULL
);
959 gtk_entry_set_text(GTK_ENTRY(inputbox
), s
);
962 gtk_entry_set_text(GTK_ENTRY(inputbox
), prefix
);
963 gtk_editable_set_position(GTK_EDITABLE(inputbox
), -1);
968 descend(const Arg
*arg
) {
969 char *source
= (char*)webkit_web_view_get_uri(webview
), *p
= &source
[0], *new;
971 count
= count
? count
: 1;
975 if (arg
->i
== Rootdir
) {
976 for (i
= 0; i
< 3; i
++) /* get to the third slash */
977 if (!(p
= strchr(++p
, '/')))
978 return TRUE
; /* if we cannot find it quit */
980 len
= strlen(source
);
981 if (!len
) /* if string is empty quit */
983 p
= source
+ len
; /* start at the end */
984 if (*(p
- 1) == '/') /* /\/$/ is not an additional level */
986 for (i
= 0; i
< count
; i
++)
987 while(*(p
--) != '/' || *p
== '/') /* count /\/+/ as one slash */
988 if (p
== source
) /* if we reach the first char pointer quit */
990 ++p
; /* since we do p-- in the while, we are pointing at
991 the char before the slash, so +1 */
993 len
= p
- source
+ 1; /* new length = end - start + 1 */
994 new = malloc(len
+ 1);
995 memcpy(new, source
, len
);
997 webkit_web_view_load_uri(webview
, new);
1003 echo(const Arg
*arg
) {
1004 int index
= !arg
->s
? 0 : arg
->i
& (~NoAutoHide
);
1006 if (index
< Info
|| index
> Error
)
1009 set_widget_font_and_color(inputbox
, urlboxfont
[index
], urlboxbgcolor
[index
], urlboxcolor
[index
]);
1010 gtk_entry_set_text(GTK_ENTRY(inputbox
), !arg
->s
? "" : arg
->s
);
1016 input(const Arg
*arg
) {
1024 /* Set the colour and font back to the default, so that we don't still
1025 * maintain a red colour from a warning from an end of search indicator,
1028 set_widget_font_and_color(inputbox
, urlboxfont
[index
], urlboxbgcolor
[index
], urlboxcolor
[index
]);
1030 /* to avoid things like :open URL :open URL2 or :open :open URL */
1031 gtk_entry_set_text(GTK_ENTRY(inputbox
), "");
1032 gtk_editable_insert_text(GTK_EDITABLE(inputbox
), arg
->s
, -1, &pos
);
1033 if (arg
->i
& InsertCurrentURL
&& (url
= webkit_web_view_get_uri(webview
)))
1034 gtk_editable_insert_text(GTK_EDITABLE(inputbox
), url
, -1, &pos
);
1035 gtk_widget_grab_focus(inputbox
);
1036 gtk_editable_set_position(GTK_EDITABLE(inputbox
), -1);
1041 navigate(const Arg
*arg
) {
1042 if (arg
->i
& NavigationForwardBack
)
1043 webkit_web_view_go_back_or_forward(webview
, (arg
->i
== NavigationBack
? -1 : 1) * (count
? count
: 1));
1044 else if (arg
->i
& NavigationReloadActions
)
1045 (arg
->i
== NavigationReload
? webkit_web_view_reload
: webkit_web_view_reload_bypass_cache
)(webview
);
1047 webkit_web_view_stop_loading(webview
);
1052 number(const Arg
*arg
) {
1053 const char *source
= webkit_web_view_get_uri(webview
);
1054 char *uri
, *p
, *new;
1055 int number
, diff
= (count
? count
: 1) * (arg
->i
== Increment
? 1 : -1);
1059 uri
= g_strdup_printf(source
); /* copy string */
1061 while(*p
!= '\0') /* goto the end of the string */
1064 while(*p
>= '0' && *p
<= '9') /* go back until non number char is reached */
1066 if (*(++p
) == '\0') { /* if no numbers were found abort */
1070 number
= atoi(p
) + diff
; /* apply diff on number */
1072 new = g_strdup_printf("%s%d", uri
, number
); /* create new uri */
1073 webkit_web_view_load_uri(webview
, new);
1080 open_arg(const Arg
*arg
) {
1082 char *s
= arg
->s
, *p
, *new;
1083 Arg a
= { .i
= NavigationReload
};
1100 else if (arg
->i
== TargetCurrent
) {
1101 len
= strlen(arg
->s
);
1102 new = NULL
, p
= strchr(arg
->s
, ' ');
1103 if (p
) /* check for search engines */
1104 for (i
= 0; i
< LENGTH(searchengines
); i
++)
1105 if (!strncmp(arg
->s
, searchengines
[i
].handle
, p
- arg
->s
)) {
1106 p
= soup_uri_encode(++p
, "&");
1107 new = g_strdup_printf(searchengines
[i
].uri
, p
);
1112 if (len
> 3 && strstr(arg
->s
, "://")) { /* valid url? */
1113 p
= new = g_malloc(len
+ 1);
1114 while(*s
!= '\0') { /* strip whitespaces */
1120 } else if (strcspn(arg
->s
, "/") == 0 || strcspn(arg
->s
, "./") == 0) { /* prepend "file://" */
1121 new = g_malloc(sizeof("file://") + len
);
1122 strcpy(new, "file://");
1123 memcpy(&new[sizeof("file://") - 1], arg
->s
, len
+ 1);
1124 } else if (p
|| !strchr(arg
->s
, '.')) { /* whitespaces or no dot? */
1125 p
= soup_uri_encode(arg
->s
, "&");
1126 new = g_strdup_printf(defsearch
->uri
, p
);
1128 } else { /* prepend "http://" */
1129 new = g_malloc(sizeof("http://") + len
);
1130 strcpy(new, "http://");
1131 memcpy(&new[sizeof("http://") - 1], arg
->s
, len
+ 1);
1134 webkit_web_view_load_uri(webview
, new);
1137 g_spawn_async(NULL
, argv
, NULL
, G_SPAWN_SEARCH_PATH
, NULL
, NULL
, NULL
, NULL
);
1142 yank(const Arg
*arg
) {
1143 const char *url
, *feedback
;
1145 if (arg
->i
& SourceURL
) {
1146 url
= webkit_web_view_get_uri(webview
);
1149 feedback
= g_strconcat("Yanked ", url
, NULL
);
1150 give_feedback(feedback
);
1151 if (arg
->i
& ClipboardPrimary
)
1152 gtk_clipboard_set_text(clipboards
[0], url
, -1);
1153 if (arg
->i
& ClipboardGTK
)
1154 gtk_clipboard_set_text(clipboards
[1], url
, -1);
1156 webkit_web_view_copy_clipboard(webview
);
1161 paste(const Arg
*arg
) {
1162 Arg a
= { .i
= arg
->i
& TargetNew
, .s
= NULL
};
1164 /* If we're over a link, open it in a new target. */
1165 if (strlen(rememberedURI
) > 0) {
1166 Arg new_target
= { .i
= TargetNew
, .s
= arg
->s
};
1167 open_arg(&new_target
);
1171 if (arg
->i
& ClipboardPrimary
)
1172 a
.s
= gtk_clipboard_wait_for_text(clipboards
[0]);
1173 if (!a
.s
&& arg
->i
& ClipboardGTK
)
1174 a
.s
= gtk_clipboard_wait_for_text(clipboards
[1]);
1181 quit(const Arg
*arg
) {
1183 const char *filename
;
1184 const char *uri
= webkit_web_view_get_uri(webview
);
1186 /* write last URL into status file for recreation with "u" */
1187 filename
= g_strdup_printf(CLOSED_URL_FILENAME
);
1188 f
= fopen(filename
, "w");
1190 fprintf(f
, "%s", uri
);
1199 revive(const Arg
*arg
) {
1201 const char *filename
;
1202 char buffer
[512] = "";
1203 Arg a
= { .i
= TargetNew
, .s
= NULL
};
1204 /* get the URL of the window which has been closed last */
1205 filename
= g_strdup_printf(CLOSED_URL_FILENAME
);
1206 f
= fopen(filename
, "r");
1208 fgets(buffer
, 512, f
);
1211 if (strlen(buffer
) > 0) {
1220 gboolean
print_frame(const Arg
*arg
)
1222 WebKitWebFrame
*frame
= webkit_web_view_get_main_frame(webview
);
1223 webkit_web_frame_print (frame
);
1228 search(const Arg
*arg
) {
1229 count
= count
? count
: 1;
1230 gboolean success
, direction
= arg
->i
& DirectionPrev
;
1234 free(search_handle
);
1235 search_handle
= g_strdup_printf(arg
->s
);
1239 if (arg
->i
& DirectionAbsolute
)
1240 search_direction
= direction
;
1242 direction
^= search_direction
;
1244 success
= webkit_web_view_search_text(webview
, search_handle
, arg
->i
& CaseSensitive
, direction
, FALSE
);
1246 if (arg
->i
& Wrapping
) {
1247 success
= webkit_web_view_search_text(webview
, search_handle
, arg
->i
& CaseSensitive
, direction
, TRUE
);
1250 a
.s
= g_strdup_printf("search hit %s, continuing at %s",
1251 direction
? "BOTTOM" : "TOP",
1252 direction
? "TOP" : "BOTTOM");
1263 a
.s
= g_strdup_printf("Pattern not found: %s", search_handle
);
1271 set(const Arg
*arg
) {
1272 Arg a
= { .i
= Info
| NoAutoHide
};
1276 if (search_handle
) {
1277 search_handle
= NULL
;
1278 webkit_web_view_unmark_text_matches(webview
);
1280 gtk_entry_set_text(GTK_ENTRY(inputbox
), "");
1281 gtk_widget_grab_focus(GTK_WIDGET(webview
));
1283 case ModePassThrough
:
1284 a
.s
= "-- PASS THROUGH --";
1288 a
.s
= "-- PASS TROUGH (next) --";
1291 case ModeInsert
: /* should not be called manually but automatically */
1292 a
.s
= "-- INSERT --";
1296 memset(followTarget
, 0, 8);
1297 strncpy(followTarget
, arg
->s
, 8);
1299 a
.s
= "vimprobable_show_hints()";
1310 jsapi_ref_to_string(JSContextRef context
, JSValueRef ref
) {
1311 JSStringRef string_ref
;
1315 string_ref
= JSValueToStringCopy(context
, ref
, NULL
);
1316 length
= JSStringGetMaximumUTF8CStringSize(string_ref
);
1317 string
= g_new(gchar
, length
);
1318 JSStringGetUTF8CString(string_ref
, string
, length
);
1319 JSStringRelease(string_ref
);
1324 jsapi_evaluate_script(const gchar
*script
, gchar
**value
, gchar
**message
) {
1325 WebKitWebFrame
*frame
= webkit_web_view_get_main_frame(webview
);
1326 JSGlobalContextRef context
= webkit_web_frame_get_global_context(frame
);
1328 JSValueRef val
, exception
;
1330 str
= JSStringCreateWithUTF8CString(script
);
1331 val
= JSEvaluateScript(context
, str
, JSContextGetGlobalObject(context
), NULL
, 0, &exception
);
1332 JSStringRelease(str
);
1334 *message
= jsapi_ref_to_string(context
, exception
);
1336 *value
= jsapi_ref_to_string(context
, val
);
1340 quickmark(const Arg
*a
) {
1343 char *fn
= g_strdup_printf(QUICKMARK_FILE
);
1345 fp
= fopen(fn
, "r");
1348 if (fp
!= NULL
&& b
< 10) {
1349 for( i
=0; i
< b
; ++i
) {
1353 fgets(buf
, 100, fp
);
1355 char *ptr
= strrchr(buf
, '\n');
1357 Arg x
= { .s
= buf
};
1358 if ( strlen(buf
)) return open_arg(&x
);
1362 x
.s
= g_strdup_printf("Quickmark %d not defined", b
);
1368 else { return false; }
1372 script(const Arg
*arg
) {
1373 gchar
*value
= NULL
, *message
= NULL
;
1377 set_error("Missing argument.");
1380 jsapi_evaluate_script(arg
->s
, &value
, &message
);
1385 if (arg
->i
!= Silent
&& value
) {
1391 if (strncmp(value
, "fire;", 5) == 0) {
1393 strncpy(chars
, "0000000000000000000000000000000000000000000000000000000000000000", 64);
1394 memset(inputBuffer
, 0, 65);
1395 a
.s
= g_strconcat("vimprobable_fire(", (value
+ 5), ")", NULL
);
1398 } else if (strncmp(value
, "open;", 5) == 0) {
1400 strncpy(chars
, "0000000000000000000000000000000000000000000000000000000000000000", 64);
1401 memset(inputBuffer
, 0, 65);
1404 if (strncmp(followTarget
, "new", 3) == 0)
1407 a
.i
= TargetCurrent
;
1408 memset(followTarget
, 0, 8);
1418 scroll(const Arg
*arg
) {
1419 GtkAdjustment
*adjust
= (arg
->i
& OrientationHoriz
) ? adjust_h
: adjust_v
;
1420 int max
= gtk_adjustment_get_upper(adjust
) - gtk_adjustment_get_page_size(adjust
);
1421 float val
= gtk_adjustment_get_value(adjust
) / max
* 100;
1422 int direction
= (arg
->i
& (1 << 2)) ? 1 : -1;
1424 if ((direction
== 1 && val
< 100) || (direction
== -1 && val
> 0)) {
1425 if (arg
->i
& ScrollMove
)
1426 gtk_adjustment_set_value(adjust
, gtk_adjustment_get_value(adjust
) +
1427 direction
* /* direction */
1428 ((arg
->i
& UnitLine
|| (arg
->i
& UnitBuffer
&& count
)) ? (scrollstep
* (count
? count
: 1)) : (
1429 arg
->i
& UnitBuffer
? gtk_adjustment_get_page_size(adjust
) / 2 :
1430 (count
? count
: 1) * (gtk_adjustment_get_page_size(adjust
) -
1431 (gtk_adjustment_get_page_size(adjust
) > pagingkeep
? pagingkeep
: 0)))));
1433 gtk_adjustment_set_value(adjust
,
1434 ((direction
== 1) ? gtk_adjustment_get_upper
: gtk_adjustment_get_lower
)(adjust
));
1441 zoom(const Arg
*arg
) {
1442 webkit_web_view_set_full_content_zoom(webview
, (arg
->i
& ZoomFullContent
) > 0);
1443 webkit_web_view_set_zoom_level(webview
, (arg
->i
& ZoomOut
) ?
1444 webkit_web_view_get_zoom_level(webview
) +
1445 (((float)(count
? count
: 1)) * (arg
->i
& (1 << 1) ? 1.0 : -1.0) * zoomstep
) :
1446 (count
? (float)count
/ 100.0 : 1.0));
1451 fake_key_event(const Arg
*a
) {
1458 if ( (xdpy
= XOpenDisplay(NULL
)) == NULL
) {
1459 err
.s
= "Couldn't find the XDisplay.";
1466 xk
.subwindow
= None
;
1467 xk
.time
= CurrentTime
;
1468 xk
.same_screen
= True
;
1469 xk
.x
= xk
.y
= xk
.x_root
= xk
.y_root
= 1;
1474 err
.s
= "Zero pointer as argument! Check your config.h";
1480 if( (keysym
= XStringToKeysym(a
->s
)) == NoSymbol
) {
1481 err
.s
= g_strdup_printf("Couldn't translate %s to keysym", a
->s
);
1486 if( (xk
.keycode
= XKeysymToKeycode(xdpy
, keysym
)) == NoSymbol
) {
1487 err
.s
= "Couldn't translate keysym to keycode";
1493 if( !XSendEvent(xdpy
, embed
, True
, KeyPressMask
, (XEvent
*)&xk
) ) {
1494 err
.s
= "XSendEvent failed";
1505 commandhistoryfetch(const Arg
*arg
) {
1506 if (arg
->i
== DirectionPrev
) {
1508 if (commandpointer
< 0)
1509 commandpointer
= maxcommands
- 1;
1512 if (commandpointer
== COMMANDHISTSIZE
|| commandpointer
== maxcommands
)
1516 if (commandpointer
< 0)
1519 gtk_entry_set_text(GTK_ENTRY(inputbox
), commandhistory
[commandpointer
]);
1520 gtk_editable_set_position(GTK_EDITABLE(inputbox
), -1);
1526 bookmark(const Arg
*arg
) {
1528 const char *filename
;
1529 const char *uri
= webkit_web_view_get_uri(webview
);
1530 const char *title
= webkit_web_view_get_title(webview
);
1531 filename
= g_strdup_printf(BOOKMARKS_STORAGE_FILENAME
);
1532 f
= fopen(filename
, "a");
1533 if (uri
== NULL
|| strlen(uri
) == 0) {
1534 set_error("No URI found to bookmark.");
1538 fprintf(f
, "%s", uri
);
1539 if (title
!= NULL
) {
1540 fprintf(f
, "%s", " ");
1541 fprintf(f
, "%s", title
);
1543 if (arg
->s
&& strlen(arg
->s
)) {
1544 build_taglist(arg
, f
);
1546 fprintf(f
, "%s", "\n");
1548 give_feedback( "Bookmark saved" );
1551 set_error("Bookmarks file not found.");
1559 const char *filename
;
1560 const char *uri
= webkit_web_view_get_uri(webview
);
1561 const char *title
= webkit_web_view_get_title(webview
);
1562 char *entry
, buffer
[512], *new;
1564 gboolean finished
= FALSE
;
1566 if (title
!= NULL
) {
1567 entry
= malloc((strlen(uri
) + strlen(title
) + 2) * sizeof(char));
1568 memset(entry
, 0, strlen(uri
) + strlen(title
) + 2);
1570 entry
= malloc((strlen(uri
) + 1) * sizeof(char));
1571 memset(entry
, 0, strlen(uri
) + 1);
1573 if (entry
!= NULL
) {
1574 strncpy(entry
, uri
, strlen(uri
));
1575 if (title
!= NULL
) {
1576 strncat(entry
, " ", 1);
1577 strncat(entry
, title
, strlen(title
));
1580 filename
= g_strdup_printf(HISTORY_STORAGE_FILENAME
);
1581 f
= fopen(filename
, "r");
1583 new = (char *)malloc(HISTORY_MAX_ENTRIES
* 512 * sizeof(char) + 1);
1585 memset(new, 0, HISTORY_MAX_ENTRIES
* 512 * sizeof(char) + 1);
1586 /* newest entries go on top */
1587 strncpy(new, entry
, strlen(entry
));
1588 strncat(new, "\n", 1);
1589 /* retain at most HISTORY_MAX_ENTIRES - 1 old entries */
1590 while (finished
!= TRUE
) {
1591 if ((char *)NULL
== fgets(buffer
, 512, f
)) {
1592 /* check if end of file was reached / error occured */
1596 /* end of file reached */
1600 /* compare line (-1 because of newline character) */
1601 if (n
!= strlen(buffer
) - 1 || strncmp(entry
, buffer
, n
) != 0) {
1602 /* if the URI is already in history; we put it on top and skip it here */
1603 strncat(new, buffer
, 512);
1606 if ((i
+ 1) >= HISTORY_MAX_ENTRIES
) {
1612 f
= fopen(filename
, "w");
1614 fprintf(f
, "%s", new);
1623 if (entry
!= NULL
) {
1632 view_source(const Arg
* arg
) {
1633 gboolean current_mode
= webkit_web_view_get_view_source_mode(webview
);
1634 webkit_web_view_set_view_source_mode(webview
, !current_mode
);
1635 webkit_web_view_reload(webview
);
1640 focus_input(const Arg
*arg
) {
1643 a
.s
= g_strconcat("vimprobable_focus_input()", NULL
);
1651 browser_settings(const Arg
*arg
) {
1654 set_error("Missing argument.");
1657 strncpy(line
, arg
->s
, 254);
1658 if (process_set_line(line
))
1661 set_error("Invalid setting.");
1667 search_word(int whichword
) {
1669 static char word
[240];
1670 char *c
= my_pair
.line
;
1672 while (isspace(*c
) && *c
)
1675 switch (whichword
) {
1677 while (*c
&& !isspace (*c
) && *c
!= '=' && k
< 240) {
1682 strncpy(my_pair
.what
, word
, 20);
1685 while (*c
&& k
< 240) {
1690 strncpy(my_pair
.value
, word
, 240);
1698 process_set_line(char *line
) {
1702 WebKitWebSettings
*settings
;
1704 settings
= webkit_web_view_get_settings(webview
);
1705 my_pair
.line
= line
;
1707 if (!strlen(my_pair
.what
))
1710 while (isspace(*c
) && *c
)
1713 if (*c
== ':' || *c
== '=')
1719 listlen
= LENGTH(browsersettings
);
1720 for (i
= 0; i
< listlen
; i
++) {
1721 if (strlen(browsersettings
[i
].name
) == strlen(my_pair
.what
) && strncmp(browsersettings
[i
].name
, my_pair
.what
, strlen(my_pair
.what
)) == 0) {
1722 /* mandatory argument not provided */
1723 if (strlen(my_pair
.value
) == 0)
1725 /* process qmark? */
1726 if (strlen(my_pair
.what
) == 5 && strncmp("qmark", my_pair
.what
, 5) == 0) {
1727 return (process_save_qmark(my_pair
.value
, webview
));
1729 /* interpret boolean values */
1730 if (browsersettings
[i
].boolval
) {
1731 if (strncmp(my_pair
.value
, "on", 2) == 0 || strncmp(my_pair
.value
, "true", 4) == 0 || strncmp(my_pair
.value
, "ON", 2) == 0 || strncmp(my_pair
.value
, "TRUE", 4) == 0) {
1733 } else if (strncmp(my_pair
.value
, "off", 3) == 0 || strncmp(my_pair
.value
, "false", 5) == 0 || strncmp(my_pair
.value
, "OFF", 3) == 0 || strncmp(my_pair
.value
, "FALSE", 5) == 0) {
1738 } else if (browsersettings
[i
].colourval
) {
1739 /* interpret as hexadecimal colour */
1740 if (!parse_colour(my_pair
.value
)) {
1744 if (browsersettings
[i
].var
!= NULL
) {
1745 /* write value into internal variable */
1746 /*if (browsersettings[i].intval) {
1747 browsersettings[i].var = atoi(my_pair.value);
1749 strncpy(browsersettings
[i
].var
, my_pair
.value
, strlen(my_pair
.value
) + 1);
1752 if (strlen(browsersettings
[i
].webkit
) > 0) {
1753 /* activate appropriate webkit setting */
1754 if (browsersettings
[i
].boolval
) {
1755 g_object_set((GObject
*)settings
, browsersettings
[i
].webkit
, boolval
, NULL
);
1756 } else if (browsersettings
[i
].intval
) {
1757 g_object_set((GObject
*)settings
, browsersettings
[i
].webkit
, atoi(my_pair
.value
), NULL
);
1759 g_object_set((GObject
*)settings
, browsersettings
[i
].webkit
, my_pair
.value
, NULL
);
1761 webkit_web_view_set_settings(webview
, settings
);
1763 /* toggle proxy usage? */
1764 if (strlen(my_pair
.what
) == 5 && strncmp("proxy", my_pair
.what
, 5) == 0) {
1765 toggle_proxy(boolval
);
1768 /* Toggle scrollbars. */
1769 if (strlen(my_pair
.what
) == 10 && strncmp("scrollbars", my_pair
.what
, 10) == 0)
1770 toggle_scrollbars(boolval
);
1773 if (browsersettings
[i
].reload
)
1774 webkit_web_view_reload(webview
);
1782 process_line(char *line
) {
1787 /* Ignore blank lines. */
1790 if (strncmp(c
, "map", 3) == 0) {
1792 return process_map_line(c
);
1793 } else if (strncmp(c
, "set", 3) == 0) {
1795 return process_set_line(c
);
1801 search_tag(const Arg
* a
) {
1803 const char *filename
;
1804 const char *tag
= a
->s
;
1805 char s
[BUFFERSIZE
], foundtag
[40], url
[BUFFERSIZE
];
1809 /* The user must give us something to load up. */
1810 set_error("Bookmark tag required with this option.");
1814 if (strlen(tag
) > MAXTAGSIZE
) {
1815 set_error("Tag too long.");
1819 filename
= g_strdup_printf(BOOKMARKS_STORAGE_FILENAME
);
1820 f
= fopen(filename
, "r");
1822 set_error("Couldn't open bookmarks file.");
1825 while (fgets(s
, BUFFERSIZE
-1, f
)) {
1828 while (isspace(s
[t
]))
1830 if (s
[t
] != ']') continue;
1843 foundtag
[i
++] = s
[k
++];
1845 /* foundtag now contains the tag */
1846 if (strlen(foundtag
) < MAXTAGSIZE
&& strcmp(tag
, foundtag
) == 0) {
1848 while (isspace(s
[i
])) i
++;
1850 while (s
[i
] && !isspace(s
[i
])) url
[k
++] = s
[i
++];
1852 Arg x
= { .i
= TargetNew
, .s
= url
};
1866 toggle_proxy(gboolean onoff
) {
1868 char *filename
, *new;
1871 if (onoff
== FALSE
) {
1872 g_object_set(session
, "proxy-uri", NULL
, NULL
);
1873 give_feedback("Proxy deactivated");
1875 filename
= (char *)g_getenv("http_proxy");
1877 /* Fallthrough to checking HTTP_PROXY as well, since this can also be
1880 if (filename
== NULL
)
1881 filename
= (char *)g_getenv("HTTP_PROXY");
1883 if (filename
!= NULL
&& 0 < (len
= strlen(filename
))) {
1884 if (strstr(filename
, "://") == NULL
) {
1885 /* prepend http:// */
1886 new = g_malloc(sizeof("http://") + len
);
1887 strcpy(new, "http://");
1888 memcpy(&new[sizeof("http://") - 1], filename
, len
+ 1);
1889 proxy_uri
= soup_uri_new(new);
1891 proxy_uri
= soup_uri_new(filename
);
1893 g_object_set(session
, "proxy-uri", proxy_uri
, NULL
);
1894 give_feedback("Proxy activated");
1900 toggle_scrollbars(gboolean onoff
) {
1901 if (onoff
== TRUE
) {
1902 adjust_h
= gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(viewport
));
1903 adjust_v
= gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(viewport
));
1906 adjust_v
= gtk_range_get_adjustment(GTK_RANGE(scroll_v
));
1907 adjust_h
= gtk_range_get_adjustment(GTK_RANGE(scroll_h
));
1909 gtk_widget_set_scroll_adjustments (GTK_WIDGET(webview
), adjust_h
, adjust_v
);
1915 update_url(const char *uri
) {
1916 gboolean ssl
= g_str_has_prefix(uri
, "https://");
1918 #ifdef ENABLE_HISTORY_INDICATOR
1919 char before
[] = " [";
1921 gboolean back
= webkit_web_view_can_go_back(webview
);
1922 gboolean fwd
= webkit_web_view_can_go_forward(webview
);
1925 before
[0] = after
[0] = '\0';
1927 gtk_label_set_markup((GtkLabel
*)status_url
, g_markup_printf_escaped(
1928 #ifdef ENABLE_HISTORY_INDICATOR
1929 "<span font=\"%s\">%s%s%s%s%s</span>", statusfont
, uri
,
1930 before
, back
? "+" : "", fwd
? "-" : "", after
1932 "<span font=\"%s\">%s</span>", statusfont
, uri
1935 gdk_color_parse(ssl
? sslbgcolor
: statusbgcolor
, &color
);
1936 gtk_widget_modify_bg(eventbox
, GTK_STATE_NORMAL
, &color
);
1937 gdk_color_parse(ssl
? sslcolor
: statuscolor
, &color
);
1938 gtk_widget_modify_fg(GTK_WIDGET(status_url
), GTK_STATE_NORMAL
, &color
);
1939 gtk_widget_modify_fg(GTK_WIDGET(status_state
), GTK_STATE_NORMAL
, &color
);
1945 int download_count
= g_list_length(activeDownloads
);
1946 GString
*status
= g_string_new("");
1948 /* construct the status line */
1950 /* count, modkey and input buffer */
1951 g_string_append_printf(status
, "%.0d", count
);
1952 if (current_modkey
) g_string_append_c(status
, current_modkey
);
1953 if (inputBuffer
[0]) g_string_append_printf(status
, " %s", inputBuffer
);
1955 /* the number of active downloads */
1956 if (activeDownloads
) {
1957 g_string_append_printf(status
, " %d active %s", download_count
,
1958 (download_count
== 1) ? "download" : "downloads");
1961 #ifdef ENABLE_WGET_PROGRESS_BAR
1962 /* the progressbar */
1965 char progressbar
[progressbartick
+ 1];
1967 if (activeDownloads
) {
1971 for (ptr
= activeDownloads
; ptr
; ptr
= g_list_next(ptr
)) {
1972 progress
+= 100 * webkit_download_get_progress(ptr
->data
);
1975 progress
/= download_count
;
1977 } else if (webkit_web_view_get_load_status(webview
) != WEBKIT_LOAD_FINISHED
1978 && webkit_web_view_get_load_status(webview
) != WEBKIT_LOAD_FAILED
) {
1980 progress
= webkit_web_view_get_progress(webview
) * 100;
1983 if (progress
>= 0) {
1984 ascii_bar(progressbartick
, progress
* progressbartick
/ 100, progressbar
);
1985 g_string_append_printf(status
, " %c%s%c",
1986 progressborderleft
, progressbar
, progressborderright
);
1991 /* and the current scroll position */
1993 int max
= gtk_adjustment_get_upper(adjust_v
) - gtk_adjustment_get_page_size(adjust_v
);
1994 int val
= (int)(gtk_adjustment_get_value(adjust_v
) / max
* 100);
1997 g_string_append(status
, " All");
1999 g_string_append(status
, " Top");
2000 else if (val
== 100)
2001 g_string_append(status
, " Bot");
2003 g_string_append_printf(status
, " %d%%", val
);
2007 markup
= g_markup_printf_escaped("<span font=\"%s\">%s</span>", statusfont
, status
->str
);
2008 gtk_label_set_markup(GTK_LABEL(status_state
), markup
);
2010 g_string_free(status
, TRUE
);
2016 modkeys
= calloc(LENGTH(keys
) + 1, sizeof(char));
2017 char *ptr
= modkeys
;
2019 for (i
= 0; i
< LENGTH(keys
); i
++)
2020 if (keys
[i
].modkey
&& !strchr(modkeys
, keys
[i
].modkey
))
2021 *(ptr
++) = keys
[i
].modkey
;
2022 modkeys
= realloc(modkeys
, &ptr
[0] - &modkeys
[0] + 1);
2027 scroll_h
= GTK_SCROLLBAR(gtk_hscrollbar_new(NULL
));
2028 scroll_v
= GTK_SCROLLBAR(gtk_vscrollbar_new(NULL
));
2029 adjust_h
= gtk_range_get_adjustment(GTK_RANGE(scroll_h
));
2030 adjust_v
= gtk_range_get_adjustment(GTK_RANGE(scroll_v
));
2032 window
= (GtkWindow
*)gtk_plug_new(embed
);
2034 window
= (GtkWindow
*)gtk_window_new(GTK_WINDOW_TOPLEVEL
);
2035 gtk_window_set_wmclass(GTK_WINDOW(window
), "vimprobable2", "Vimprobable2");
2037 gtk_window_set_default_size(GTK_WINDOW(window
), 640, 480);
2038 box
= GTK_BOX(gtk_vbox_new(FALSE
, 0));
2039 inputbox
= gtk_entry_new();
2040 webview
= (WebKitWebView
*)webkit_web_view_new();
2041 GtkBox
*statusbar
= GTK_BOX(gtk_hbox_new(FALSE
, 0));
2042 eventbox
= gtk_event_box_new();
2043 status_url
= gtk_label_new(NULL
);
2044 status_state
= gtk_label_new(NULL
);
2046 PangoFontDescription
*font
;
2047 GdkGeometry hints
= { 1, 1 };
2048 inspector
= webkit_web_view_get_inspector(WEBKIT_WEB_VIEW(webview
));
2050 clipboards
[0] = gtk_clipboard_get(GDK_SELECTION_PRIMARY
);
2051 clipboards
[1] = gtk_clipboard_get(GDK_NONE
);
2053 gdk_color_parse(statusbgcolor
, &bg
);
2054 gtk_widget_modify_bg(eventbox
, GTK_STATE_NORMAL
, &bg
);
2055 gtk_widget_set_name(GTK_WIDGET(window
), "Vimprobable2");
2056 gtk_window_set_geometry_hints(window
, NULL
, &hints
, GDK_HINT_MIN_SIZE
);
2058 #ifdef DISABLE_SCROLLBAR
2059 viewport
= gtk_scrolled_window_new(NULL
, NULL
);
2060 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(viewport
), GTK_POLICY_NEVER
, GTK_POLICY_NEVER
);
2062 /* Ensure we still see scrollbars. */
2063 GtkWidget
*viewport
= gtk_scrolled_window_new(adjust_h
, adjust_v
);
2067 gtk_container_add(GTK_CONTAINER(viewport
), GTK_WIDGET(webview
));
2069 /* Ensure we set the scroll adjustments now, so that if we're not drawing
2070 * titlebars, we can still scroll.
2072 gtk_widget_set_scroll_adjustments(GTK_WIDGET(webview
), adjust_h
, adjust_v
);
2074 font
= pango_font_description_from_string(urlboxfont
[0]);
2075 gtk_widget_modify_font(GTK_WIDGET(inputbox
), font
);
2076 pango_font_description_free(font
);
2077 gtk_entry_set_inner_border(GTK_ENTRY(inputbox
), NULL
);
2078 gtk_misc_set_alignment(GTK_MISC(status_url
), 0.0, 0.0);
2079 gtk_misc_set_alignment(GTK_MISC(status_state
), 1.0, 0.0);
2080 gtk_box_pack_start(statusbar
, status_url
, TRUE
, TRUE
, 2);
2081 gtk_box_pack_start(statusbar
, status_state
, FALSE
, FALSE
, 2);
2082 gtk_container_add(GTK_CONTAINER(eventbox
), GTK_WIDGET(statusbar
));
2083 gtk_box_pack_start(box
, viewport
, TRUE
, TRUE
, 0);
2084 gtk_box_pack_start(box
, eventbox
, FALSE
, FALSE
, 0);
2085 gtk_entry_set_has_frame(GTK_ENTRY(inputbox
), FALSE
);
2086 gtk_box_pack_end(box
, inputbox
, FALSE
, FALSE
, 0);
2087 gtk_container_add(GTK_CONTAINER(window
), GTK_WIDGET(box
));
2088 gtk_widget_grab_focus(GTK_WIDGET(webview
));
2089 gtk_widget_show_all(GTK_WIDGET(window
));
2094 WebKitWebSettings
*settings
= (WebKitWebSettings
*)webkit_web_settings_new();
2096 char *filename
, *new;
2098 #ifdef ENABLE_COOKIE_SUPPORT
2099 SoupCookieJar
*cookiejar
;
2101 session
= webkit_get_default_session();
2102 g_object_set((GObject
*)settings
, "default-font-size", DEFAULT_FONT_SIZE
, NULL
);
2103 g_object_set((GObject
*)settings
, "enable-scripts", enablePlugins
, NULL
);
2104 g_object_set((GObject
*)settings
, "enable-plugins", enablePlugins
, NULL
);
2105 g_object_set((GObject
*)settings
, "enable-java-applet", enableJava
, NULL
);
2106 filename
= g_strdup_printf(USER_STYLESHEET
);
2107 filename
= g_strdup_printf("file://%s", filename
);
2108 g_object_set((GObject
*)settings
, "user-stylesheet-uri", filename
, NULL
);
2109 g_object_set((GObject
*)settings
, "user-agent", useragent
, NULL
);
2110 g_object_get((GObject
*)settings
, "zoom-step", &zoomstep
, NULL
);
2111 webkit_web_view_set_settings(webview
, settings
);
2112 #ifdef ENABLE_COOKIE_SUPPORT
2113 filename
= g_strdup_printf(COOKIES_STORAGE_FILENAME
);
2114 cookiejar
= soup_cookie_jar_text_new(filename
, COOKIES_STORAGE_READONLY
);
2116 soup_session_add_feature(session
, (SoupSessionFeature
*)cookiejar
);
2119 if (use_proxy
== TRUE
) {
2120 filename
= (char *)g_getenv("http_proxy");
2121 if (filename
!= NULL
&& 0 < (len
= strlen(filename
))) {
2122 if (strstr(filename
, "://") == NULL
) {
2123 /* prepend http:// */
2124 new = g_malloc(sizeof("http://") + len
);
2125 strcpy(new, "http://");
2126 memcpy(&new[sizeof("http://") - 1], filename
, len
+ 1);
2127 proxy_uri
= soup_uri_new(new);
2129 proxy_uri
= soup_uri_new(filename
);
2131 g_object_set(session
, "proxy-uri", proxy_uri
, NULL
);
2139 g_object_connect((GObject
*)window
,
2140 "signal::destroy", (GCallback
)window_destroyed_cb
, NULL
,
2143 g_object_connect((GObject
*)webview
,
2144 "signal::title-changed", (GCallback
)webview_title_changed_cb
, NULL
,
2145 "signal::load-progress-changed", (GCallback
)webview_progress_changed_cb
, NULL
,
2146 "signal::load-committed", (GCallback
)webview_load_committed_cb
, NULL
,
2147 "signal::load-finished", (GCallback
)webview_load_finished_cb
, NULL
,
2148 "signal::navigation-policy-decision-requested", (GCallback
)webview_navigation_cb
, NULL
,
2149 "signal::new-window-policy-decision-requested", (GCallback
)webview_new_window_cb
, NULL
,
2150 "signal::mime-type-policy-decision-requested", (GCallback
)webview_mimetype_cb
, NULL
,
2151 "signal::download-requested", (GCallback
)webview_download_cb
, NULL
,
2152 "signal::key-press-event", (GCallback
)webview_keypress_cb
, NULL
,
2153 "signal::hovering-over-link", (GCallback
)webview_hoverlink_cb
, NULL
,
2154 "signal::console-message", (GCallback
)webview_console_cb
, NULL
,
2155 "signal::create-web-view", (GCallback
)webview_open_in_new_window_cb
, NULL
,
2156 "signal::event", (GCallback
)notify_event_cb
, NULL
,
2158 /* webview adjustment */
2159 g_object_connect((GObject
*)adjust_v
,
2160 "signal::value-changed", (GCallback
)webview_scroll_cb
, NULL
,
2163 g_object_connect((GObject
*)inputbox
,
2164 "signal::activate", (GCallback
)inputbox_activate_cb
, NULL
,
2165 "signal::key-press-event", (GCallback
)inputbox_keypress_cb
, NULL
,
2166 "signal::key-release-event", (GCallback
)inputbox_keyrelease_cb
, NULL
,
2167 #ifdef ENABLE_INCREMENTAL_SEARCH
2168 "signal::changed", (GCallback
)inputbox_changed_cb
, NULL
,
2172 g_signal_connect((GObject
*)inspector
,
2173 "inspect-web-view", (GCallback
)inspector_inspect_web_view_cb
, NULL
);
2177 main(int argc
, char *argv
[]) {
2179 static char url
[256] = "";
2180 static gboolean ver
= false;
2181 static const char *cfile
= NULL
;
2182 static GOptionEntry opts
[] = {
2183 { "version", 'v', 0, G_OPTION_ARG_NONE
, &ver
, "print version", NULL
},
2184 { "embed", 'e', 0, G_OPTION_ARG_STRING
, &winid
, "embedded", NULL
},
2185 { "configfile", 'c', 0, G_OPTION_ARG_STRING
, &cfile
, "config file", NULL
},
2191 /* command line argument: version */
2192 if (!gtk_init_with_args(&argc
, &argv
, "[<uri>]", opts
, NULL
, &err
)) {
2193 g_printerr("can't init gtk: %s\n", err
->message
);
2195 return EXIT_FAILURE
;
2199 printf("%s\n", useragent
);
2200 return EXIT_SUCCESS
;
2204 configfile
= g_strdup_printf(cfile
);
2206 configfile
= g_strdup_printf(RCFILE
);
2208 if (!g_thread_supported())
2209 g_thread_init(NULL
);
2212 embed
= atoi(winid
);
2218 /* read config file */
2219 if (!read_rcfile(configfile
)) {
2222 a
.s
= g_strdup_printf("Error in config file");
2227 /* command line argument: URL */
2229 strncpy(url
, argv
[argc
- 1], 255);
2231 strncpy(url
, startpage
, 255);
2234 a
.i
= TargetCurrent
;
2239 return EXIT_SUCCESS
;